changeset 1310:6e5580aa0165

Decorators for Icons (Decorators part II) review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-November/008678.html reviewed-by: omajid
author Mario Torre <neugens.limasoftware@gmail.com>
date Fri, 08 Nov 2013 14:23:26 +0100
parents e66baba3918e
children 5bb638ad064d
files client/core/src/main/java/com/redhat/thermostat/client/ui/Decorator.java client/core/src/main/java/com/redhat/thermostat/client/ui/DecoratorProvider.java client/core/src/main/java/com/redhat/thermostat/client/ui/PlatformIcon.java client/core/src/main/java/com/redhat/thermostat/client/ui/ReferenceFieldIconDecorator.java client/core/src/main/java/com/redhat/thermostat/client/ui/ReferenceFieldLabelDecorator.java client/living-vm-filter/swing/pom.xml client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/IconUtils.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/DeadVMDecoratorProvider.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/DeadVMIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LivingVMDecoratorProvider.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMLabelDecorator.java client/living-vm-filter/swing/src/main/resources/deadvm.png client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java client/swing/src/main/java/com/redhat/thermostat/client/swing/ReferenceFieldDecoratorLayout.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/BaseIcon.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/CompositeIcon.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/FontAwesomeIcon.java client/swing/src/main/java/com/redhat/thermostat/client/swing/components/Icon.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/HostIconDecoratorProvider.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/HostTreeDecoratorRegistry.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/RegistryFactory.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/VMTreeDecoratorRegistry.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/components/DecoratedDefaultMutableTreeNode.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryController.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryFactory.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/IconDecoratorRegistry.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/BaseIcon.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/ReferenceComponent.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/ReferenceTitle.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorListener.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorManager.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorProviderExtensionListener.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeController.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/LabelDecoratorListener.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/HostIconDecoratorProviderTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImplTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryControllerTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeControllerTest.java
diffstat 47 files changed, 1029 insertions(+), 1396 deletions(-) [+]
line wrap: on
line diff
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/Decorator.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012, 2013 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;
-
-/**
- * A {@link Decorator} allows plugins to install special visual clues on
- * selected components.
- * 
- * <br /><br />
- * 
- * A {@link Decorator} itself is not an entry point.
- */
-public interface Decorator {
-
-    public static enum Quadrant {
-        TOP_LEFT,
-        BOTTOM_LEFT,
-        MAIN
-    }
-    
-    String getLabel(String originalLabel);
-    IconDescriptor getIconDescriptor();
-    Quadrant getQuadrant();
-}
-
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/DecoratorProvider.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012, 2013 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 com.redhat.thermostat.annotations.ExtensionPoint;
-import com.redhat.thermostat.common.Filter;
-import com.redhat.thermostat.storage.core.Ref;
-
-/**
- * This interface allows plugins to install a custom {@link Decorator} into
- * the Reference List view.
- * 
- * <br /><br />
- * 
- * Active {@link Decorator}s are first queried against their filters
- * and then installed into the view if the filter passes. 
- */
-@ExtensionPoint
-public interface DecoratorProvider<T extends Ref> {
-
-    Decorator getDecorator();
-    Filter<T> getFilter();
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/PlatformIcon.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012, 2013 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;
+
+/**
+ * An opaque type representing an Icon in the underlying UI toolkit.
+ * Plugins can cast this type to the concrete implementation provided by each
+ * client implementation. 
+ */
+public interface PlatformIcon {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/ReferenceFieldIconDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012, 2013 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 com.redhat.thermostat.common.Ordered;
+import com.redhat.thermostat.storage.core.Ref;
+
+public interface ReferenceFieldIconDecorator extends Ordered {
+
+    public static final String ID = "ReferenceFieldIconDecorator_ID";
+    
+    /**
+     * The passed {@link PlatformIcon} my be null, indicating no plugin has
+     * set the icon.
+     */
+    PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference);
+    
+    /**
+     * The passed {@link PlatformIcon} my be null, indicating no plugin has
+     * set the icon.
+     */
+    PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference);
+
+}
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/ReferenceFieldLabelDecorator.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/ReferenceFieldLabelDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -36,14 +36,18 @@
 
 package com.redhat.thermostat.client.ui;
 
+import com.redhat.thermostat.common.Ordered;
 import com.redhat.thermostat.storage.core.Ref;
 
 /**
  *
  */
-public interface ReferenceFieldLabelDecorator {
+public interface ReferenceFieldLabelDecorator extends Ordered {
 
     public static final String ID = "ReferenceFieldLabelDecorator_ID";
     
+    /**
+     * The passed label my be null, indicating no plugin has set the label.
+     */
     String getLabel(String originalLabel, Ref reference);
 }
--- a/client/living-vm-filter/swing/pom.xml	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/living-vm-filter/swing/pom.xml	Fri Nov 08 14:23:26 2013 +0100
@@ -67,6 +67,12 @@
     </dependency>
 
     <dependency>
+      <groupId>net.java.openjdk.cacio</groupId>
+      <artifactId>cacio-tta</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
       <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012, 2013 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.filter.host.swing;
+
+import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.Palette;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+
+public class DeadHostIconDecorator implements ReferenceFieldIconDecorator {
+
+    public static final Icon UNCONNECTED = new FontAwesomeIcon('\uf127', 12, Palette.THERMOSTAT_RED.getColor());
+    public static final Icon UNCONNECTED_SELECTED = new FontAwesomeIcon('\uf127', 12, Palette.THERMOSTAT_RED.getColor());
+
+    private HostInfoDAO dao;
+    
+    public DeadHostIconDecorator(HostInfoDAO dao) {
+        this.dao = dao;
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP + 100;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        return doOverlay(originalIcon, reference, UNCONNECTED);
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        return doOverlay(originalIcon, reference, UNCONNECTED_SELECTED);
+    }
+    
+    public PlatformIcon doOverlay(PlatformIcon originalIcon, Ref reference, Icon overlay) {
+        
+        if (!(reference instanceof HostRef)) {
+            return originalIcon;
+        }
+        
+        if (dao.isAlive((HostRef) reference)) {
+            return originalIcon;
+        }
+        
+        Icon canvas = (Icon) originalIcon;
+        int y = canvas.getIconHeight() - overlay.getIconHeight();
+        
+        return IconUtils.overlay(canvas, overlay, 0, y);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012, 2013 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.filter.host.swing;
+
+import com.redhat.thermostat.client.swing.IconResource;
+import com.redhat.thermostat.client.swing.components.CompositeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+
+public class HostIconDecorator implements ReferenceFieldIconDecorator {
+    
+    private static final Icon ICON = IconUtils.resizeIcon(IconResource.HOST_24.getIcon());
+    private static final Icon SELECTED = CompositeIcon.createDefaultComposite(ICON, true);
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof HostRef) {
+            return ICON;
+        } else {
+            return originalIcon;
+        }
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof HostRef) {
+            return SELECTED;
+        } else {
+            return originalIcon;
+        }
+    }
+}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostLabelDecorator.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostLabelDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -53,6 +53,11 @@
     }
     
     @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP;
+    }
+    
+    @Override
     public String getLabel(String originalLabel, Ref reference) {
         
         if (!(reference instanceof HostRef)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/IconUtils.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012, 2013 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.filter.host.swing;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import com.redhat.thermostat.client.swing.components.EmptyIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+
+public class IconUtils {
+    public static Icon resizeIcon(Icon source) {
+        Icon canvas = new EmptyIcon(32, 32);
+        
+        float v1 = canvas.getIconWidth() / 2;
+        float v0 = source.getIconWidth() / 2; 
+                
+        int x = (int) (v1 - v0 + 0.5);
+                
+        v1 = canvas.getIconHeight() / 2;
+        v0 = source.getIconHeight() / 2; 
+        
+        int y = (int) (v1 - v0 + 0.5);
+
+        BufferedImage image = new BufferedImage(canvas.getIconWidth(),
+                                                canvas.getIconHeight(),
+                                                BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics = (Graphics2D) image.getGraphics();
+        graphics.drawImage(source.getImage(), x, y, null);
+        
+        return new Icon(image);
+    }
+
+    public static Icon overlay(Icon canvas, Icon overlay, int x, int y) {
+        BufferedImage image = new BufferedImage(canvas.getIconWidth(),
+                                                canvas.getIconHeight(),
+                                                BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics = (Graphics2D) image.getGraphics();
+        canvas.paintIcon(null, graphics, 0, 0);
+        
+        graphics.drawImage(overlay.getImage(), x, y, null);
+        graphics.dispose();
+        
+        return new Icon(image);
+    }
+}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/DeadVMDecoratorProvider.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012, 2013 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.filter.vm.swing;
-
-import java.io.IOException;
-
-import com.redhat.thermostat.common.Filter;
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.client.ui.IconDescriptor;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class DeadVMDecoratorProvider implements DecoratorProvider<VmRef> {
-    
-    private class DeadVMDecorator implements Decorator {
-        @Override
-        public IconDescriptor getIconDescriptor() {
-            try {
-                return IconDescriptor.loadIcon(getClass().getClassLoader(), "deadvm.png");
-            } catch (IOException e) {
-                e.printStackTrace();
-                return null;
-            }
-        }
-        
-        @Override
-        public String getLabel(String originalLabel) {
-            return "[not running] " + originalLabel;
-        }
-        
-        @Override
-        public Quadrant getQuadrant() {
-            return Quadrant.BOTTOM_LEFT;
-        }
-    }
-
-    private Filter<VmRef> decoratorFilter;
-    private DeadVMDecorator decorator;
-    
-    public DeadVMDecoratorProvider(final VmInfoDAO dao) {
-        decorator = new DeadVMDecorator();
-        decoratorFilter = new Filter<VmRef>() {
-            @Override
-            public boolean matches(VmRef vm) {
-                VmInfo vmInfo = dao.getVmInfo(vm);
-
-                return !vmInfo.isAlive();
-            }
-        };
-    }
-    
-    @Override
-    public Decorator getDecorator() {
-        return decorator;
-    }
-    
-    @Override
-    public Filter<VmRef> getFilter() {
-        return decoratorFilter;
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/DeadVMIconDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012, 2013 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.filter.vm.swing;
+
+import com.redhat.thermostat.client.filter.host.swing.IconUtils;
+import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.Palette;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class DeadVMIconDecorator implements ReferenceFieldIconDecorator {
+
+    public static final Icon DEAD = new FontAwesomeIcon('\uf00d', 12, Palette.THERMOSTAT_RED.getColor());
+    public static final Icon DEAD_SELECTED = new FontAwesomeIcon('\uf00d', 12, Palette.THERMOSTAT_RED.getColor());
+
+    private VmInfoDAO vmDao;
+    private HostInfoDAO hostDao;
+    
+    public DeadVMIconDecorator(VmInfoDAO vmDao, HostInfoDAO hostDao) {
+        this.vmDao = vmDao;
+        this.hostDao = hostDao;
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP + 100;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        return doOverlay(originalIcon, reference, DEAD);
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        return doOverlay(originalIcon, reference, DEAD_SELECTED);
+    }
+    
+    public PlatformIcon doOverlay(PlatformIcon originalIcon, Ref reference, Icon overlay) {
+        
+        if (!(reference instanceof VmRef)) {
+            return originalIcon;
+        }
+        
+        boolean match = true;
+        
+        VmRef vm = (VmRef) reference;
+        if (hostDao.isAlive(vm.getHostRef())) {
+            VmInfo vmInfo = vmDao.getVmInfo(vm);
+            match = !vmInfo.isAlive();
+            
+        } else {
+            match = true;
+        }
+     
+        PlatformIcon result = originalIcon;
+        if (match) {
+            Icon canvas = (Icon) originalIcon;
+            int y = canvas.getIconHeight() - overlay.getIconHeight();
+            result = IconUtils.overlay(canvas, overlay, 0, y);            
+        }
+        
+        return result;
+    }
+}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LivingVMDecoratorProvider.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012, 2013 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.filter.vm.swing;
-
-import java.io.IOException;
-
-import com.redhat.thermostat.common.Filter;
-import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
-import com.redhat.thermostat.client.swing.IconResource;
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.client.ui.IconDescriptor;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-public class LivingVMDecoratorProvider implements DecoratorProvider<VmRef> {
-    
-    private class LivingVMDecorator implements Decorator {
-        @Override
-        public IconDescriptor getIconDescriptor() {
-            IconDescriptor icon = null;
-            try {
-                icon = IconResource.JAVA_APPLICATION_24.toIconDescriptor();
-            } catch (IOException ioe) {
-                ioe.printStackTrace();
-                Logger.getLogger(LivingVMDecoratorProvider.class.getName()).log(Level.SEVERE, ioe.getMessage(), ioe);
-            }
-            return icon;
-        }
-        
-        @Override
-        public String getLabel(String originalLabel) {
-            return originalLabel;
-        }
-        
-        @Override
-        public Quadrant getQuadrant() {
-            return Quadrant.MAIN;
-        }
-    }
-
-    private com.redhat.thermostat.client.filter.vm.core.LivingVMFilter decoratorFilter;
-    private LivingVMDecorator decorator;
-    
-    public LivingVMDecoratorProvider(VmInfoDAO vmDao, HostInfoDAO hostDao) {
-        decorator = new LivingVMDecorator();
-        decoratorFilter = new LivingVMFilter(vmDao, hostDao);
-    }
-    
-    @Override
-    public Decorator getDecorator() {
-        return decorator;
-    }
-    
-    @Override
-    public Filter<VmRef> getFilter() {
-        return decoratorFilter;
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -48,13 +48,14 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
+import com.redhat.thermostat.client.filter.host.swing.DeadHostIconDecorator;
+import com.redhat.thermostat.client.filter.host.swing.HostIconDecorator;
 import com.redhat.thermostat.client.filter.host.swing.HostLabelDecorator;
 import com.redhat.thermostat.client.swing.ReferenceFieldDecoratorLayout;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
 import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
 import com.redhat.thermostat.common.Constants;
 import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
@@ -96,19 +97,7 @@
                 VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
                 HostInfoDAO hostDao = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
 
-                LivingVMDecoratorProvider decorator = new LivingVMDecoratorProvider(vmDao, hostDao);
-                DeadVMDecoratorProvider deadDecorator = new DeadVMDecoratorProvider(vmDao);
-                
                 Dictionary<String, String> decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(Constants.GENERIC_SERVICE_CLASSNAME, VmRef.class.getName());
-                
-                registration = context.registerService(DecoratorProvider.class.getName(),
-                                                       deadDecorator, decoratorProperties);
-                registeredServices.add(registration);
-
-                registration = context.registerService(DecoratorProvider.class.getName(),
-                                                       decorator, decoratorProperties);
-                registeredServices.add(registration);
                 
                 VMLabelDecorator vmLabelDecorator = new VMLabelDecorator(vmDao);
                 decoratorProperties = new Hashtable<>();
@@ -117,6 +106,8 @@
                 registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
                         vmLabelDecorator, decoratorProperties);
                 
+                registeredServices.add(registration);
+                
                 NetworkInterfaceInfoDAO networkDao = (NetworkInterfaceInfoDAO)
                             services.get(NetworkInterfaceInfoDAO.class.getName());
                 
@@ -125,8 +116,39 @@
                 decoratorProperties.put(ReferenceFieldLabelDecorator.ID, ReferenceFieldDecoratorLayout.LABEL_INFO.name());
                 
                 registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
-                        hostLabelDecorator, decoratorProperties);
+                                                       hostLabelDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                HostIconDecorator hostIconDecorator = new HostIconDecorator();
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID, ReferenceFieldDecoratorLayout.ICON_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       hostIconDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                DeadHostIconDecorator deadHostIconDecorator = new DeadHostIconDecorator(hostDao);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID, ReferenceFieldDecoratorLayout.ICON_MAIN.name());
                 
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       deadHostIconDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                VMIconDecorator livingVMIconDecorator = new VMIconDecorator();
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID, ReferenceFieldDecoratorLayout.ICON_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       livingVMIconDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                DeadVMIconDecorator deadVMIconDecorator = new DeadVMIconDecorator(vmDao, hostDao);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID, ReferenceFieldDecoratorLayout.ICON_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       deadVMIconDecorator, decoratorProperties);
                 registeredServices.add(registration);
             }
         });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMIconDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, 2013 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.filter.vm.swing;
+
+import com.redhat.thermostat.client.filter.host.swing.IconUtils;
+import com.redhat.thermostat.client.swing.IconResource;
+import com.redhat.thermostat.client.swing.components.CompositeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+
+public class VMIconDecorator implements ReferenceFieldIconDecorator {
+
+    private static final Icon ICON = IconUtils.resizeIcon(IconResource.JAVA_APPLICATION_24.getIcon());
+    private static final Icon SELECTED = CompositeIcon.createDefaultComposite(ICON, true);
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof VmRef) {
+            return ICON;
+        } else {
+            return originalIcon;
+        }
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof VmRef) {
+            return SELECTED;
+        } else {
+            return originalIcon;
+        }
+    }
+}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMLabelDecorator.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMLabelDecorator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -37,7 +37,6 @@
 package com.redhat.thermostat.client.filter.vm.swing;
 
 import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
-import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.Ref;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
@@ -55,6 +54,11 @@
     }
     
     @Override
+    public int getOrderValue() {
+        return ORDER_CPU_GROUP;
+    }
+    
+    @Override
     public String getLabel(String originalLabel, Ref reference) {
         
         if (!(reference instanceof VmRef)) {
Binary file client/living-vm-filter/swing/src/main/resources/deadvm.png has changed
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Fri Nov 08 14:23:26 2013 +0100
@@ -41,8 +41,10 @@
 
 import org.junit.Test;
 
+import com.redhat.thermostat.client.filter.host.swing.DeadHostIconDecorator;
+import com.redhat.thermostat.client.filter.host.swing.HostIconDecorator;
 import com.redhat.thermostat.client.filter.host.swing.HostLabelDecorator;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
 import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
@@ -65,10 +67,14 @@
         ctx.registerService(HostInfoDAO.class, hostDao, null);
         ctx.registerService(NetworkInterfaceInfoDAO.class, netDao, null);
 
-        assertTrue(ctx.isServiceRegistered(DecoratorProvider.class.getName(), LivingVMDecoratorProvider.class));
-        assertTrue(ctx.isServiceRegistered(DecoratorProvider.class.getName(), DeadVMDecoratorProvider.class));
-        
         assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), VMLabelDecorator.class));
         assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), HostLabelDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), HostIconDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), DeadHostIconDecorator.class));
+
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), VMIconDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), DeadVMIconDecorator.class));
+
+        
     }
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/ReferenceFieldDecoratorLayout.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/ReferenceFieldDecoratorLayout.java	Fri Nov 08 14:23:26 2013 +0100
@@ -40,7 +40,5 @@
     LABEL_MAIN,
     LABEL_INFO,
     
-    ICON_TOP,
     ICON_MAIN,
-    ICON_BOTTOM;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/BaseIcon.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012, 2013 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.swing.components;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.image.BufferedImage;
+import java.beans.Transient;
+
+import com.redhat.thermostat.client.swing.GraphicsUtils;
+import com.redhat.thermostat.client.swing.internal.vmlist.UIDefaults;
+
+@SuppressWarnings("serial")
+class BaseIcon extends Icon {
+
+    private boolean selected;
+    private Icon source;
+    
+    public BaseIcon(boolean selected, Icon source) {
+        this.selected = selected;
+        this.source = source;
+    }
+    
+    @Override
+    public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
+        GraphicsUtils utils = GraphicsUtils.getInstance();
+        Graphics2D graphics = utils.createAAGraphics(g);
+        graphics.setPaint(getPaint());
+        graphics.fillRect(x, y, getIconWidth(), getIconHeight());
+        graphics.dispose();
+    }
+    
+    @Override
+    public int getIconHeight() {
+        return source.getIconHeight();
+    }
+    
+    @Override
+    public int getIconWidth() {
+        return source.getIconWidth();
+    }
+    
+    private Paint getPaint() {
+        UIDefaults palette = UIDefaults.getInstance();
+        Color color = palette.getComponentFGColor();
+        if (selected) {
+            color = palette.getSelectedComponentFGColor();
+        }
+        return color;
+    }
+}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/CompositeIcon.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/CompositeIcon.java	Fri Nov 08 14:23:26 2013 +0100
@@ -40,7 +40,9 @@
 import java.awt.Component;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.Image;
 import java.awt.image.BufferedImage;
+import java.beans.Transient;
 
 import com.redhat.thermostat.client.swing.GraphicsUtils;
 import com.redhat.thermostat.client.ui.IconDescriptor;
@@ -90,4 +92,12 @@
         graphics.drawImage(imageBuffer, x, y, null);
         graphics.dispose();
     }
+     
+    /**
+     * Creates a default composite icon suitable for highlight.
+     * The default colours are defined based on the underlying look and feel. 
+     */
+    public static Icon createDefaultComposite(Icon source, boolean selected) {
+        return new CompositeIcon(source, new BaseIcon(true, source));
+    }
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/FontAwesomeIcon.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/FontAwesomeIcon.java	Fri Nov 08 14:23:26 2013 +0100
@@ -43,6 +43,7 @@
 import java.awt.FontMetrics;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.Image;
 import java.awt.RenderingHints;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
@@ -143,6 +144,11 @@
     }
 
     @Override
+    public Image getImage() {
+        return super.getImage();
+    }
+    
+    @Override
     public int getIconHeight() {
         return size;
     }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/Icon.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/Icon.java	Fri Nov 08 14:23:26 2013 +0100
@@ -37,14 +37,20 @@
 package com.redhat.thermostat.client.swing.components;
 
 import com.redhat.thermostat.client.ui.IconDescriptor;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+
 import javax.swing.ImageIcon;
+
 import java.awt.Dimension;
+import java.awt.Graphics2D;
 import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.beans.Transient;
 
 /**
  */
 @SuppressWarnings("serial")
-public class Icon extends ImageIcon {
+public class Icon extends ImageIcon implements PlatformIcon {
 
     public Icon(IconDescriptor descriptor) {
         super(descriptor.getData().array());
@@ -62,6 +68,16 @@
         super(image);
     }
     
+    @Override
+    @Transient
+    public Image getImage() {
+        BufferedImage image = new BufferedImage(getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g = (Graphics2D) image.getGraphics();
+        paintIcon(null, g, 0, 0);
+        g.dispose();
+        return image;
+    }
+    
     /**
      * Returns a {@link Dimension} object with this {@link Icon}
      * {@code width} and {@code height}.
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/HostIconDecoratorProvider.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal;
-
-import java.io.IOException;
-
-import com.redhat.thermostat.common.Filter;
-import com.redhat.thermostat.client.core.NameMatchingRefFilter;
-import com.redhat.thermostat.client.swing.IconResource;
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.client.ui.IconDescriptor;
-import com.redhat.thermostat.storage.core.HostRef;
-
-public class HostIconDecoratorProvider implements DecoratorProvider<HostRef> {
-
-    private final Filter<HostRef> anyHost = new NameMatchingRefFilter<HostRef>();
-
-    @Override
-    public Decorator getDecorator() {
-        return new IconDecorator();
-    }
-
-    @Override
-    public Filter<HostRef> getFilter() {
-        return anyHost;
-    }
-
-    private static class IconDecorator implements Decorator {
-
-        private final IconDescriptor icon;
-
-        public IconDecorator() {
-            IconDescriptor icon = null;
-            try {
-                icon = IconResource.HOST_24.toIconDescriptor();
-            } catch (IOException ioe) {
-                ioe.printStackTrace();
-            }
-            this.icon = icon;
-        }
-
-        @Override
-        public String getLabel(String originalLabel) {
-            return originalLabel;
-        }
-
-        @Override
-        public IconDescriptor getIconDescriptor() {
-            return icon;
-        }
-
-        @Override
-        public Quadrant getQuadrant() {
-            return Quadrant.MAIN;
-        }
-
-    }
-
-}
-
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/HostTreeDecoratorRegistry.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.common.ThermostatExtensionRegistry;
-import com.redhat.thermostat.storage.core.HostRef;
-
-@SuppressWarnings("rawtypes")
-class HostTreeDecoratorRegistry extends ThermostatExtensionRegistry<DecoratorProvider> {
-
-    private static final String FILTER = "(&(" + Constants.OBJECTCLASS + "=" +
-            DecoratorProvider.class.getName() + ")(" +
-            com.redhat.thermostat.common.Constants.GENERIC_SERVICE_CLASSNAME + "=" +
-            HostRef.class.getName() + "))";
-
-    public HostTreeDecoratorRegistry(BundleContext context) throws InvalidSyntaxException {
-        super(context, FILTER, DecoratorProvider.class);
-    }
-}
-
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImpl.java	Fri Nov 08 14:23:26 2013 +0100
@@ -62,7 +62,6 @@
 import com.redhat.thermostat.client.swing.internal.registry.decorator.DecoratorRegistryController;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.ContextActionController;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.ContextHandler;
-import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorProviderExtensionListener;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.FilterManager;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.HostTreeController;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.HostTreeController.ReferenceSelection;
@@ -159,9 +158,6 @@
         }
     };
 
-    private HostTreeDecoratorRegistry hostDecoratorRegistry;
-    private VMTreeDecoratorRegistry vmDecoratorRegistry;
-
     private VMInformationRegistry vmInfoRegistry;
     private ActionListener<ThermostatExtensionRegistry.Action> vmInfoRegistryListener =
             new ActionListener<ThermostatExtensionRegistry.Action> ()
@@ -200,10 +196,7 @@
             vmFilterRegistry = registryFactory.createVmFilterRegistry();
             hostFilterRegistry = registryFactory.createHostFilterRegistry();
             
-            hostDecoratorRegistry = registryFactory.createHostTreeDecoratorRegistry();
-            vmDecoratorRegistry = registryFactory.createVMTreeDecoratorRegistry();
             menuRegistry = registryFactory.createMenuRegistry();
-            
             vmInfoRegistry = registryFactory.createVMInformationRegistry();
             
         } catch (InvalidSyntaxException e) {
@@ -389,16 +382,6 @@
 
         filterManager.start();
         
-        DecoratorProviderExtensionListener<HostRef> hostDecoratorListener =
-                hostTreeController.getHostDecoratorListener();
-        hostDecoratorRegistry.addActionListener(hostDecoratorListener);
-        hostDecoratorRegistry.start();
-        
-        DecoratorProviderExtensionListener<VmRef> vmDecoratorListener =
-                hostTreeController.getVmDecoratorListener();
-        vmDecoratorRegistry.addActionListener(vmDecoratorListener);
-        vmDecoratorRegistry.start();
-
         vmInfoRegistry.addActionListener(vmInfoRegistryListener);
         vmInfoRegistry.start();
 
@@ -429,19 +412,6 @@
         menuRegistry.stop();
 
         filterManager.stop();
-        
-        HostTreeController hostTreeController = view.getHostTreeController();
-        
-        DecoratorProviderExtensionListener<HostRef> hostDecoratorListener =
-                hostTreeController.getHostDecoratorListener();
-        hostDecoratorRegistry.removeActionListener(hostDecoratorListener);
-        hostDecoratorRegistry.stop();
-
-        DecoratorProviderExtensionListener<VmRef> vmDecoratorListener =
-                hostTreeController.getVmDecoratorListener();
-        vmDecoratorRegistry.removeActionListener(vmDecoratorListener);
-        vmDecoratorRegistry.stop();
-
         decoratorController.stop();
         
         vmInfoRegistry.removeActionListener(vmInfoRegistryListener);
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/RegistryFactory.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/RegistryFactory.java	Fri Nov 08 14:23:26 2013 +0100
@@ -50,14 +50,6 @@
         this.context = context;
     }
 
-    HostTreeDecoratorRegistry createHostTreeDecoratorRegistry() throws InvalidSyntaxException {
-        return new HostTreeDecoratorRegistry(context);
-    }
-    
-    VMTreeDecoratorRegistry createVMTreeDecoratorRegistry() throws InvalidSyntaxException {
-        return new VMTreeDecoratorRegistry(context);
-    }
-    
     HostFilterRegistry createHostFilterRegistry() throws InvalidSyntaxException {
         return new HostFilterRegistry(context);
     }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/VMTreeDecoratorRegistry.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.common.ThermostatExtensionRegistry;
-import com.redhat.thermostat.storage.core.VmRef;
-
-@SuppressWarnings("rawtypes")
-class VMTreeDecoratorRegistry extends ThermostatExtensionRegistry<DecoratorProvider> {
-
-    private static final String FILTER = "(&(" + Constants.OBJECTCLASS + "=" +
-            DecoratorProvider.class.getName() + ")(" +
-            com.redhat.thermostat.common.Constants.GENERIC_SERVICE_CLASSNAME + "=" +
-            VmRef.class.getName() + "))";
-
-    public VMTreeDecoratorRegistry(BundleContext context) throws InvalidSyntaxException {
-        super(context, FILTER, DecoratorProvider.class);
-    }
-}
-
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/components/DecoratedDefaultMutableTreeNode.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal.components;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.tree.DefaultMutableTreeNode;
-
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.storage.core.Ref;
-
-public class DecoratedDefaultMutableTreeNode  extends DefaultMutableTreeNode {
-    
-    private List<Decorator> decorators;
-    
-    public DecoratedDefaultMutableTreeNode(Ref ref) {
-        super(ref);
-        decorators = new ArrayList<>();
-    }
-    
-    public void addDecorator(Decorator decorator) {
-        decorators.add(decorator);
-    }
-    
-    public void setDecorators(List<Decorator> decorators) {
-        this.decorators = decorators;
-    }
-    
-    public List<Decorator> getDecorators() {
-        return decorators;
-    }
-}
-
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java	Fri Nov 08 14:23:26 2013 +0100
@@ -36,8 +36,6 @@
 
 package com.redhat.thermostat.client.swing.internal.osgi;
 
-import java.util.Dictionary;
-import java.util.Hashtable;
 import java.util.Map;
 
 import org.osgi.framework.BundleActivator;
@@ -49,21 +47,17 @@
 import com.redhat.thermostat.client.core.views.SummaryViewProvider;
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
 import com.redhat.thermostat.client.swing.internal.GUIClientCommand;
-import com.redhat.thermostat.client.swing.internal.HostIconDecoratorProvider;
 import com.redhat.thermostat.client.swing.internal.Main;
 import com.redhat.thermostat.client.swing.internal.views.SwingAgentInformationViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingClientConfigurationViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingHostInformationViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingSummaryViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingVmInformationViewProvider;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
 import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Constants;
 import com.redhat.thermostat.common.MultipleServiceTracker;
 import com.redhat.thermostat.common.MultipleServiceTracker.Action;
 import com.redhat.thermostat.common.cli.CommandRegistry;
 import com.redhat.thermostat.common.cli.CommandRegistryImpl;
-import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.utils.keyring.Keyring;
 
 public class ThermostatActivator implements BundleActivator {
@@ -74,11 +68,6 @@
     @Override
     public void start(final BundleContext context) throws Exception {
         
-        HostIconDecoratorProvider hostDecorator = new HostIconDecoratorProvider();
-        Dictionary<String, String> decoratorProperties = new Hashtable<>();
-        decoratorProperties.put(Constants.GENERIC_SERVICE_CLASSNAME, HostRef.class.getName());
-        context.registerService(DecoratorProvider.class.getName(), hostDecorator, decoratorProperties);
-        
         // Host views
         HostInformationViewProvider infoProvider = new SwingHostInformationViewProvider();
         context.registerService(HostInformationViewProvider.class.getName(), infoProvider, null);
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryController.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryController.java	Fri Nov 08 14:23:26 2013 +0100
@@ -38,27 +38,29 @@
 
 import org.osgi.framework.InvalidSyntaxException;
 
+import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorManager;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.HostTreeController;
 
 public class DecoratorRegistryController {
 
     private DecoratorRegistryFactory registryFactory;
-    private HostTreeController hostController;
+    private DecoratorManager decoratorManager;
 
     private InfoLabelDecoratorRegistry infoLabel;
     private MainLabelDecoratorRegistry mainLabel;
-    
+    private IconDecoratorRegistry iconDecorator;
+
     public DecoratorRegistryController(DecoratorRegistryFactory registryFactory) {
         this.registryFactory = registryFactory;
     }
 
     public void init(HostTreeController hostController) {
-        this.hostController = hostController;
+        this.decoratorManager = hostController.getDecoratorManager();
         
         try {
-           
             infoLabel = registryFactory.createInfoLabelDecoratorRegistry();
             mainLabel = registryFactory.createMainLabelDecoratorRegistry();
+            iconDecorator = registryFactory.createIconDecoratorRegistry();
             
         } catch (InvalidSyntaxException e) {
             throw new RuntimeException(e);
@@ -66,18 +68,24 @@
     }
     
     public void start() {
-        infoLabel.addActionListener(hostController.getInfoLabelDecoratorListener());
+        infoLabel.addActionListener(decoratorManager.getInfoLabelDecoratorListener());
         infoLabel.start();
         
-        mainLabel.addActionListener(hostController.getMainLabelDecoratorListener());
+        mainLabel.addActionListener(decoratorManager.getMainLabelDecoratorListener());
         mainLabel.start();
+        
+        iconDecorator.addActionListener(decoratorManager.getIconDecoratorListener());
+        iconDecorator.start();
     }
 
     public void stop() {
-        infoLabel.removeActionListener(hostController.getInfoLabelDecoratorListener());
+        infoLabel.removeActionListener(decoratorManager.getInfoLabelDecoratorListener());
         infoLabel.stop();
         
-        mainLabel.removeActionListener(hostController.getMainLabelDecoratorListener());
+        mainLabel.removeActionListener(decoratorManager.getMainLabelDecoratorListener());
         mainLabel.stop();
+        
+        iconDecorator.removeActionListener(decoratorManager.getIconDecoratorListener());
+        iconDecorator.stop();
     }
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryFactory.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryFactory.java	Fri Nov 08 14:23:26 2013 +0100
@@ -53,4 +53,8 @@
     MainLabelDecoratorRegistry createMainLabelDecoratorRegistry() throws InvalidSyntaxException {
         return new MainLabelDecoratorRegistry(context);
     }
+    
+    IconDecoratorRegistry createIconDecoratorRegistry() throws InvalidSyntaxException {
+        return new IconDecoratorRegistry(context);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/registry/decorator/IconDecoratorRegistry.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012, 2013 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.swing.internal.registry.decorator;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+
+import com.redhat.thermostat.client.swing.ReferenceFieldDecoratorLayout;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+
+import com.redhat.thermostat.common.ThermostatExtensionRegistry;
+
+public class IconDecoratorRegistry extends ThermostatExtensionRegistry<ReferenceFieldIconDecorator> {
+    private static final String FILTER = "(&(" +
+            Constants.OBJECTCLASS + "=" + ReferenceFieldIconDecorator.class.getName() +
+            ")(" +
+            ReferenceFieldIconDecorator.ID + "=" + ReferenceFieldDecoratorLayout.ICON_MAIN +
+            "))";
+
+    public IconDecoratorRegistry(BundleContext context) throws InvalidSyntaxException {
+        super(context, FILTER, ReferenceFieldIconDecorator.class);
+    }
+}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/BaseIcon.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal.vmlist;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.Paint;
-import java.awt.image.BufferedImage;
-import java.beans.Transient;
-
-import com.redhat.thermostat.client.swing.GraphicsUtils;
-import com.redhat.thermostat.client.swing.components.Icon;
-
-@SuppressWarnings("serial")
-class BaseIcon extends Icon {
-
-    private boolean selected;
-    private Icon source;
-    
-    public BaseIcon(boolean selected, Icon source) {
-        this.selected = selected;
-        this.source = source;
-    }
-    
-    @Override
-    public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
-        GraphicsUtils utils = GraphicsUtils.getInstance();
-        Graphics2D graphics = utils.createAAGraphics(g);
-        graphics.setPaint(getPaint());
-        graphics.fillRect(x, y, getIconWidth(), getIconHeight());
-        graphics.dispose();
-    }
-    
-    @Override
-    public int getIconHeight() {
-        return source.getIconHeight();
-    }
-    
-    @Override
-    public int getIconWidth() {
-        return source.getIconWidth();
-    }
-    
-    private Paint getPaint() {
-        UIDefaults palette = UIDefaults.getInstance();
-        Color color = palette.getComponentFGColor();
-        if (selected) {
-            color = palette.getSelectedComponentFGColor();
-        }
-        return color;
-    }
-    
-    @Override
-    @Transient
-    public Image getImage() {
-        BufferedImage image = new BufferedImage(getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB);
-        Graphics2D g = (Graphics2D) image.getGraphics();
-        paintIcon(null, g, 0, 0);
-        g.dispose();
-        return image;
-    }
-}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/ReferenceComponent.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/ReferenceComponent.java	Fri Nov 08 14:23:26 2013 +0100
@@ -46,7 +46,6 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 
-import com.redhat.thermostat.client.swing.components.CompositeIcon;
 import com.redhat.thermostat.client.swing.components.Icon;
 import com.redhat.thermostat.client.swing.components.ShadowLabel;
 
@@ -108,6 +107,8 @@
             Component gap = Box.createRigidArea(new Dimension(gapSize, gapSize));
             add(gap, BorderLayout.WEST);
         }
+        
+        setState();
     }
 
     @Override
@@ -166,15 +167,19 @@
         painter.paint((Graphics2D) g, this, getWidth(), getHeight());
     }
     
-    public void setIcon(Icon icon) {
+    public void setIcon(Icon icon, Icon selectedIcon) {
         this.icon = icon;
-        this.selectedIcon = new CompositeIcon(icon, new BaseIcon(true, icon));
+        this.selectedIcon = selectedIcon;
         setState();
     }
 
     public Icon getIcon() {
         return icon;
     }
+
+    public Icon getSelectedIcon() {
+        return selectedIcon;
+    }
     
     private class PainterPanel extends JPanel {
         @Override
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/ReferenceTitle.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/ReferenceTitle.java	Fri Nov 08 14:23:26 2013 +0100
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.client.swing.internal.vmlist;
 
-import com.redhat.thermostat.client.swing.components.Icon;
 import com.redhat.thermostat.client.swing.internal.accordion.TitledPane;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.Ref;
@@ -57,10 +56,6 @@
     public Ref getReference() {
         return ref;
     }
-
-    public void setIcon(Icon icon) {
-        ((ReferenceComponent) getTitleComponent()).setIcon(icon);
-    }
     
     public ReferenceComponent getReferenceComponent() {
         return (ReferenceComponent) getTitleComponent();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorListener.java	Fri Nov 08 14:23:26 2013 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012, 2013 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.swing.internal.vmlist.controller;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.Ordered;
+import com.redhat.thermostat.common.OrderedComparator;
+import com.redhat.thermostat.common.ThermostatExtensionRegistry;
+import com.redhat.thermostat.common.ThermostatExtensionRegistry.Action;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ *
+ */
+public class DecoratorListener<D extends Ordered> extends DecoratorNotifier
+    implements ActionListener<ThermostatExtensionRegistry.Action>
+{
+    private static final Logger logger =
+            LoggingUtils.getLogger(DecoratorListener.class);
+    
+    private CopyOnWriteArrayList<D> decorators;
+    private Class<D> type;
+    
+    public DecoratorListener(Class<D> type) {
+        decorators = new CopyOnWriteArrayList<>();
+        this.type = type;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent<Action> actionEvent) {
+        Object payload = actionEvent.getPayload();
+        if (!type.isAssignableFrom(payload.getClass())) {
+            // be permissive, but log this
+            logger.log(Level.WARNING, "Dropping unexpected payload type: " +
+                                      payload.getClass().getName());
+        } else {
+            
+            @SuppressWarnings("unchecked")
+            D labelDecorator = (D) payload;
+            decorators.add(labelDecorator);
+            
+            switch (actionEvent.getActionId()) {
+            case SERVICE_ADDED:
+                fireDecorationAdded();
+                break;
+                
+            case SERVICE_REMOVED:
+                fireDecorationRemoved();
+                break;
+                
+            default:
+                fireDecorationChanged();
+                break;
+            }
+        }
+    }
+
+    public List<D> getDecorators() {
+        
+        List<D> result = new ArrayList<>(decorators);
+        Collections.sort(result, new OrderedComparator<D>());
+        return result;
+    }
+}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorManager.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorManager.java	Fri Nov 08 14:23:26 2013 +0100
@@ -36,96 +36,43 @@
 
 package com.redhat.thermostat.client.swing.internal.vmlist.controller;
 
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.redhat.thermostat.client.swing.components.EmptyIcon;
 import com.redhat.thermostat.client.swing.components.Icon;
 import com.redhat.thermostat.client.swing.internal.vmlist.ReferenceComponent;
 import com.redhat.thermostat.client.swing.internal.vmlist.ReferenceTitle;
-import com.redhat.thermostat.client.swing.internal.vmlist.UIDefaults;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorNotifier.DecorationEvent;
-import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorProviderExtensionListener.Action;
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.client.ui.IconDescriptor;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
 import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
 
 public class DecoratorManager {
 
-    private DecoratorProviderExtensionListener<HostRef> hostDecorator = new DecoratorProviderExtensionListener<>();
-    private DecoratorProviderExtensionListener<VmRef> vmDecorator = new DecoratorProviderExtensionListener<>();
-    
-    private LabelDecoratorListener infoLabelDecorator = new LabelDecoratorListener();
-    private LabelDecoratorListener mainLabelDecorator = new LabelDecoratorListener();
+    private class Icons {
+        Icon main;
+        Icon selected;
+    }
     
-    private Map<Decorator, Icon> decoratorsCache = new HashMap<>();
-    
+    private DecoratorListener<ReferenceFieldLabelDecorator> infoLabelDecorator =
+            new DecoratorListener<>(ReferenceFieldLabelDecorator.class);
+    private DecoratorListener<ReferenceFieldLabelDecorator> mainLabelDecorator =
+            new DecoratorListener<>(ReferenceFieldLabelDecorator.class);
+
+    private DecoratorListener<ReferenceFieldIconDecorator> iconDecorator =
+            new DecoratorListener<>(ReferenceFieldIconDecorator.class);
+
     public void registerAndSetIcon(final ReferenceComponent component) {
-        VmRef ref = (VmRef) component.getReference();
-        component.setIcon(createIcon(vmDecorator, ref));
+        Ref ref = component.getReference();
         component.setInfoLabelText(createComponentLabel(infoLabelDecorator, ref,
                                                         component.getInfoLabelText()));
         component.setMainLabelText(createComponentLabel(mainLabelDecorator, ref,
                                                         component.getMainLabelText()));
-        
-        // FIXME: this is a leak
-        vmDecorator.addDecoratorChangeListener(new ActionListener<DecoratorProviderExtensionListener.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                VmRef ref = (VmRef) component.getReference();
-                component.setIcon(createIcon(vmDecorator, ref));
-            }
-        });
+        setIcons(component);
         
         // FIXME: this is a leak
         infoLabelDecorator.addDecoratorChangeListener(new ActionListener<DecoratorNotifier.DecorationEvent>() {
             @Override
             public void actionPerformed(ActionEvent<DecorationEvent> actionEvent) {
-                VmRef ref = (VmRef) component.getReference();
-                component.setInfoLabelText(createComponentLabel(infoLabelDecorator, ref,
-                                                                component.getInfoLabelText()));
-            }
-        });
-        mainLabelDecorator.addDecoratorChangeListener(new ActionListener<DecoratorNotifier.DecorationEvent>() {
-            @Override
-            public void actionPerformed(ActionEvent<DecorationEvent> actionEvent) {
-                VmRef ref = (VmRef) component.getReference();
-                component.setMainLabelText(createComponentLabel(mainLabelDecorator, ref,
-                                                                component.getMainLabelText()));
-            }
-        });
-    }
-
-    public void registerAndSetIcon(final ReferenceTitle pane) {
-        
-        HostRef ref = (HostRef) pane.getReference();
-        final ReferenceComponent component = pane.getReferenceComponent();
-        
-        pane.setIcon(createIcon(hostDecorator, ref));
-        component.setInfoLabelText(createComponentLabel(infoLabelDecorator, ref,
-                                                        component.getInfoLabelText()));
-        component.setMainLabelText(createComponentLabel(mainLabelDecorator, ref,
-                                                        component.getMainLabelText()));
-        
-        // FIXME: this is a leak
-        hostDecorator.addDecoratorChangeListener(new ActionListener<DecoratorProviderExtensionListener.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                pane.setIcon(createIcon(hostDecorator, (HostRef) pane.getReference()));
-            }
-        });
-        
-        infoLabelDecorator.addDecoratorChangeListener(new ActionListener<DecoratorNotifier.DecorationEvent>() {
-            @Override
-            public void actionPerformed(ActionEvent<DecorationEvent> actionEvent) {
                 component.setInfoLabelText(createComponentLabel(infoLabelDecorator,
                                                                 component.getReference(),
                                                                 component.getInfoLabelText()));
@@ -139,9 +86,39 @@
                                                                 component.getMainLabelText()));
             }
         });
+        iconDecorator.addDecoratorChangeListener(new ActionListener<DecoratorNotifier.DecorationEvent>() {
+            @Override
+            public void actionPerformed(ActionEvent<DecorationEvent> actionEvent) {
+                setIcons(component);
+            }
+        });
+    }
+
+    private void setIcons(final ReferenceComponent component) {
+        Icons icons = new Icons();
+        icons.main = component.getIcon();
+        icons.selected = component.getSelectedIcon();
+        icons = createComponentIcon(iconDecorator, component.getReference(), icons);
+        
+        component.setIcon(icons.main, icons.selected);
     }
     
-    private <R extends Ref> String createComponentLabel(LabelDecoratorListener listener,
+    public void registerAndSetIcon(final ReferenceTitle pane) {
+        registerAndSetIcon(pane.getReferenceComponent());
+    }
+    
+    private <R extends Ref> Icons createComponentIcon(DecoratorListener<ReferenceFieldIconDecorator> listener,
+                                                      R reference,
+                                                      Icons originalIcons)
+    {
+        for (ReferenceFieldIconDecorator decorator : listener.getDecorators()) {
+            originalIcons.main = (Icon) decorator.getIcon(originalIcons.main, reference);
+            originalIcons.selected = (Icon) decorator.getSelectedIcon(originalIcons.selected, reference);
+        }
+        return originalIcons;
+    }
+
+    private <R extends Ref> String createComponentLabel(DecoratorListener<ReferenceFieldLabelDecorator> listener,
                                                         R reference,
                                                         String label)
     {        
@@ -151,102 +128,15 @@
         return label;
     }
     
-    private <R extends Ref> Icon createIcon(DecoratorProviderExtensionListener<R> listener, R ref)
-    {
-        UIDefaults uiDefaults = UIDefaults.getInstance();
-        int size = uiDefaults.getIconSize();
-        Icon canvas = new EmptyIcon(size, size);
-        
-        // FIXME: this logic is broken, since we simply iterate over
-        // icon locations, instead we need to at least sort them
-        // in painter's order
-        for (DecoratorProvider<R> provider : listener.getDecorators()) {
-            
-            if (!provider.getFilter().matches(ref)) {
-                continue;
-            }
-            
-            Decorator decorator = provider.getDecorator();
-            Icon icon = getIconFromCache(decorator);
-            if (icon == null) {
-                continue;
-            }
-            
-            switch (decorator.getQuadrant()) {
-            case MAIN:
-                canvas = createCustomIcon(canvas, icon);
-                break;
-                
-            case TOP_LEFT:
-                canvas = createCustomIcon(canvas, icon, 0, 0);
-                break;
-
-            case BOTTOM_LEFT:
-                int y = canvas.getIconHeight() - icon.getIconHeight();
-                canvas = createCustomIcon(canvas, icon, 0, y);
-                break;
-                
-            default:
-                // FIXME: log me?
-                break;
-            }
-
-        }
-        
-        return canvas;
-    }
-    
-    Icon getIconFromCache(Decorator decorator) {
-        Icon icon = decoratorsCache.get(decorator);
-        if (icon == null) {
-            IconDescriptor iconDescriptor = decorator.getIconDescriptor();
-            if (iconDescriptor != null) {
-                icon = new Icon(iconDescriptor);
-                decoratorsCache.put(decorator, icon);
-            }
-        }
-        return icon;
-    }
-  
-    private Icon createCustomIcon(Icon source, Icon newIcon) {
-        float v1 = source.getIconWidth() / 2;
-        float v2 = newIcon.getIconWidth() / 2; 
-        
-        int x = (int) (v1 - v2 + 0.5);;
-        
-        v1 = source.getIconHeight() / 2;
-        v2 = newIcon.getIconHeight() / 2; 
-        
-        int y = (int) (v1 - v2 + 0.5);
-        return createCustomIcon(source, newIcon, x, y);
-    }
-    
-    private Icon createCustomIcon(Icon source, Icon newIcon, int x, int y) {
-        BufferedImage image = new BufferedImage(source.getIconWidth(),
-                                                source.getIconHeight(),
-                                                BufferedImage.TYPE_INT_ARGB);
-        Graphics2D graphics = (Graphics2D) image.getGraphics();
-        source.paintIcon(null, graphics, 0, 0);
-        graphics.drawImage(newIcon.getImage(), x, y, null);
-        
-        return new Icon(image);
-    }
-    
-    @Deprecated
-    DecoratorProviderExtensionListener<HostRef> getHostDecoratorListener() {
-        return hostDecorator;
-    }
-    
-    @Deprecated
-    DecoratorProviderExtensionListener<VmRef> getVmDecoratorListener() {
-        return vmDecorator;
-    }
-
-    public LabelDecoratorListener getInfoLabelDecoratorListener() {
+    public DecoratorListener<ReferenceFieldLabelDecorator> getInfoLabelDecoratorListener() {
         return infoLabelDecorator;
     }
 
-    public LabelDecoratorListener getMainLabelDecoratorListener() {
+    public DecoratorListener<ReferenceFieldLabelDecorator> getMainLabelDecoratorListener() {
         return mainLabelDecorator;
     }
+    
+    public DecoratorListener<ReferenceFieldIconDecorator> getIconDecoratorListener() {
+        return iconDecorator;
+    }
 }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/DecoratorProviderExtensionListener.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal.vmlist.controller;
-
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.client.ui.DecoratorProvider;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.common.ThermostatExtensionRegistry;
-import com.redhat.thermostat.storage.core.Ref;
-
-/*
- * Provide an implementation of a listener for Registry update. This listener
- * is only to be used to listen for DecoratorProvider changes and its sole
- * purpose is to re-route the generic VmRef or HostRef DecoratorProvider
- * changes to the actual Decoration Manager.
- */
-@Deprecated
-public class DecoratorProviderExtensionListener<T extends Ref> implements ActionListener<ThermostatExtensionRegistry.Action>
-{
-    public enum Action {
-        DECORATOR_ADDED,
-        DECORATOR_REMOVED,
-        DECORATION_CHANGED,
-    }
-    
-    private final ActionNotifier<Action> decoratorChangeNotifier;
-
-    private Logger logger = Logger.getLogger(DecoratorProviderExtensionListener.class.getSimpleName());    
-
-    private CopyOnWriteArrayList<DecoratorProvider<T>> decorators;
-
-    public DecoratorProviderExtensionListener() {
-        this.decoratorChangeNotifier = new ActionNotifier<>(this);
-        decorators = new CopyOnWriteArrayList<>();
-    }
-
-    public void addDecoratorChangeListener(ActionListener<Action> listener) {
-        decoratorChangeNotifier.addActionListener(listener);
-    }
-    
-    public void removeDecoratorChangeListener(ActionListener<Action> listener) {
-        decoratorChangeNotifier.removeActionListener(listener);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void actionPerformed(ActionEvent<com.redhat.thermostat.common.
-                                ThermostatExtensionRegistry.Action> actionEvent)
-    {
-        Object payload = actionEvent.getPayload();
-        if (! (payload instanceof DecoratorProvider)) {
-            throw new IllegalArgumentException("unexpected payload type. " +
-                                               payload.getClass().getName() +
-                                               " not allowed here.");
-        }
-
-        decorators.add((DecoratorProvider<T>) payload);
-        
-        switch (actionEvent.getActionId()) {
-        case SERVICE_ADDED:
-            decoratorChangeNotifier.fireAction(Action.DECORATOR_ADDED, payload);
-            break;
-
-        case SERVICE_REMOVED:
-            decoratorChangeNotifier.fireAction(Action.DECORATOR_REMOVED, payload);
-            break;
-
-        default:
-            logger.log(Level.WARNING, "received unknown event from ExtensionRegistry: " +
-                                       actionEvent.getActionId());
-            break;
-        }
-    }
-    
-    CopyOnWriteArrayList<DecoratorProvider<T>> getDecorators() {
-        return decorators;
-    }
-
-    public void decorationChanged() {
-        decoratorChangeNotifier.fireAction(Action.DECORATION_CHANGED);
-    }
-}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeController.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeController.java	Fri Nov 08 14:23:26 2013 +0100
@@ -43,6 +43,7 @@
 
 import com.redhat.thermostat.client.core.vmlist.HostFilter;
 import com.redhat.thermostat.client.core.vmlist.VMFilter;
+
 import com.redhat.thermostat.client.swing.internal.accordion.Accordion;
 import com.redhat.thermostat.client.swing.internal.accordion.AccordionComponent;
 import com.redhat.thermostat.client.swing.internal.accordion.AccordionComponentEvent;
@@ -51,13 +52,17 @@
 import com.redhat.thermostat.client.swing.internal.accordion.AccordionModel;
 import com.redhat.thermostat.client.swing.internal.accordion.AccordionModelChangeListener;
 import com.redhat.thermostat.client.swing.internal.accordion.ItemSelectedEvent;
+
 import com.redhat.thermostat.client.swing.internal.vmlist.HostTreeComponentFactory;
 import com.redhat.thermostat.client.swing.internal.vmlist.ReferenceProvider;
+
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.common.ActionNotifier;
+
 import com.redhat.thermostat.common.Filter;
 import com.redhat.thermostat.common.Filter.FilterEvent;
+
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.Ref;
 import com.redhat.thermostat.storage.core.VmRef;
@@ -159,8 +164,7 @@
             public void run() {
                 if (filter(hostFilters, host)) {
                     proxyModel.removeHeader(host);
-                }                
-                decoratorManager.getHostDecoratorListener().decorationChanged();
+                }
                 fireDecoratorChanged();
             }
         });
@@ -274,7 +278,6 @@
                 if (filter(vmFilters, vm)) {
                     proxyModel.removeComponent(vm.getHostRef(), vm);
                 }
-                decoratorManager.getVmDecoratorListener().decorationChanged();
                 fireDecoratorChanged();
             }
         });
@@ -283,6 +286,7 @@
     private void fireDecoratorChanged() {
         decoratorManager.getInfoLabelDecoratorListener().fireDecorationChanged();
         decoratorManager.getMainLabelDecoratorListener().fireDecorationChanged();
+        decoratorManager.getIconDecoratorListener().fireDecorationChanged();
     }
             
     public void addHostFilter(HostFilter filter) {
@@ -379,20 +383,8 @@
     }
     
     // decorator accessors
-    
-    public DecoratorProviderExtensionListener<HostRef> getHostDecoratorListener() {
-        return decoratorManager.getHostDecoratorListener();
-    }
-    
-    public DecoratorProviderExtensionListener<VmRef> getVmDecoratorListener() {
-        return decoratorManager.getVmDecoratorListener();
-    }
 
-    public LabelDecoratorListener getInfoLabelDecoratorListener() {
-        return decoratorManager.getInfoLabelDecoratorListener();
-    }
-    
-    public LabelDecoratorListener getMainLabelDecoratorListener() {
-        return decoratorManager.getMainLabelDecoratorListener();
+    public DecoratorManager getDecoratorManager() {
+        return decoratorManager;
     }
 }
\ No newline at end of file
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/LabelDecoratorListener.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal.vmlist.controller;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ThermostatExtensionRegistry;
-import com.redhat.thermostat.common.ThermostatExtensionRegistry.Action;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.Ref;
-
-/**
- *
- */
-public class LabelDecoratorListener extends DecoratorNotifier
-    implements ActionListener<ThermostatExtensionRegistry.Action>
-{
-    private static final Logger logger =
-            LoggingUtils.getLogger(LabelDecoratorListener.class);
-    
-    private CopyOnWriteArrayList<ReferenceFieldLabelDecorator> decorators;
-    
-    public LabelDecoratorListener() {
-        decorators = new CopyOnWriteArrayList<>();
-    }
-    
-    @Override
-    public void actionPerformed(ActionEvent<Action> actionEvent) {
-        Object payload = actionEvent.getPayload();
-        if (! (payload instanceof ReferenceFieldLabelDecorator)) {
-            // be permissive, but log this
-            logger.log(Level.WARNING, "Dropping unexpected payload type: " +
-                                      payload.getClass().getName());
-        } else {
-            @SuppressWarnings("unchecked")
-            ReferenceFieldLabelDecorator labelDecorator =
-                    (ReferenceFieldLabelDecorator) payload;
-            decorators.add(labelDecorator);
-            
-            switch (actionEvent.getActionId()) {
-            case SERVICE_ADDED:
-                fireDecorationAdded();
-                break;
-                
-            case SERVICE_REMOVED:
-                fireDecorationRemoved();
-                break;
-                
-            default:
-                fireDecorationChanged();
-                break;
-            }
-        }
-    }
-
-    public List<ReferenceFieldLabelDecorator> getDecorators() {
-        return decorators;
-    }
-}
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/HostIconDecoratorProviderTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright 2012, 2013 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.swing.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-
-import javax.imageio.ImageIO;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.Filter;
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.storage.core.HostRef;
-
-public class HostIconDecoratorProviderTest {
-
-    @Test
-    public void verifyFilter() {
-        HostIconDecoratorProvider decorator = new HostIconDecoratorProvider();
-
-        Filter<HostRef> filter = decorator.getFilter();
-        HostRef aHost = mock(HostRef.class);
-
-        assertTrue(filter.matches(aHost));
-    }
-
-    @Test
-    public void verifyHostDecoratorDoesNotModifyLabel() {
-        HostIconDecoratorProvider iconDecorator = new HostIconDecoratorProvider();
-
-        Decorator decorator = iconDecorator.getDecorator();
-
-        String INPUT = "testfoobarbaz";
-
-        assertEquals(INPUT, decorator.getLabel(INPUT));
-    }
-
-    @Test
-    public void verifyHostDecoratorHasAnIcon() throws IOException {
-        HostIconDecoratorProvider iconDecorator = new HostIconDecoratorProvider();
-
-        Decorator decorator = iconDecorator.getDecorator();
-
-        BufferedImage icon = ImageIO.read(new ByteArrayInputStream(decorator.getIconDescriptor().getData().array()));
-
-        assertNotNull(icon);
-    }
-}
-
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImplTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowControllerImplTest.java	Fri Nov 08 14:23:26 2013 +0100
@@ -36,15 +36,13 @@
 
 package com.redhat.thermostat.client.swing.internal;
 
-import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.isA;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.times;
 
 import java.util.concurrent.CountDownLatch;
 
@@ -56,7 +54,6 @@
 import org.mockito.ArgumentCaptor;
 import org.osgi.framework.BundleException;
 
-import com.redhat.thermostat.common.Filter;
 import com.redhat.thermostat.client.core.progress.ProgressNotifier;
 import com.redhat.thermostat.client.core.views.AgentInformationViewProvider;
 import com.redhat.thermostat.client.core.views.ClientConfigViewProvider;
@@ -68,8 +65,6 @@
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
 import com.redhat.thermostat.client.swing.internal.registry.decorator.DecoratorRegistryController;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.ContextActionController;
-import com.redhat.thermostat.client.swing.internal.vmlist.controller.ContextHandler;
-import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorProviderExtensionListener;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.HostTreeController;
 import com.redhat.thermostat.client.ui.HostContextAction;
 import com.redhat.thermostat.client.ui.MenuAction;
@@ -78,6 +73,7 @@
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Filter;
 import com.redhat.thermostat.common.ThermostatExtensionRegistry;
 import com.redhat.thermostat.common.ThermostatExtensionRegistry.Action;
 import com.redhat.thermostat.common.Timer;
@@ -113,8 +109,7 @@
 
     private HostFilterRegistry hostFilterRegistry;
     private VmFilterRegistry vmFilterRegistry;
-    private HostTreeDecoratorRegistry hostDecoratorRegistry;
-    private VMTreeDecoratorRegistry vmDecoratorRegistry;
+
     private VMInformationRegistry vmInfoRegistry;
     private MenuRegistry menus;
 
@@ -126,9 +121,6 @@
     
     private HostTreeController treeController;
     private DecoratorRegistryController decoratorController;
-
-    private DecoratorProviderExtensionListener<HostRef> hostDecorators;
-    private DecoratorProviderExtensionListener<VmRef> vmDecorators;
     
     private ContextActionController contextController;
     
@@ -197,14 +189,9 @@
         contextController = mock(ContextActionController.class);
         when(view.getContextActionController()).thenReturn(contextController);
         
-        hostDecorators = mock(DecoratorProviderExtensionListener.class);
-        vmDecorators = mock(DecoratorProviderExtensionListener.class);
-        
         treeController = mock(HostTreeController.class);
         ArgumentCaptor<ActionListener> hostTreeCaptor = ArgumentCaptor.forClass(ActionListener.class);
         when(view.getHostTreeController()).thenReturn(treeController);
-        when(treeController.getHostDecoratorListener()).thenReturn(hostDecorators);
-        when(treeController.getVmDecoratorListener()).thenReturn(vmDecorators);
         
         doNothing().when(treeController).addReferenceSelectionChangeListener(hostTreeCaptor.capture());
 
@@ -214,8 +201,7 @@
         RegistryFactory registryFactory = mock(RegistryFactory.class);
         hostFilterRegistry = mock(HostFilterRegistry.class);
         vmFilterRegistry = mock(VmFilterRegistry.class);
-        hostDecoratorRegistry = mock(HostTreeDecoratorRegistry.class);
-        vmDecoratorRegistry = mock(VMTreeDecoratorRegistry.class);
+
         vmInfoRegistry = mock(VMInformationRegistry.class);
         menus = mock(MenuRegistry.class);
         shutdown = mock(CountDownLatch.class);
@@ -223,8 +209,6 @@
         decoratorController = mock(DecoratorRegistryController.class);
         
         when(registryFactory.createMenuRegistry()).thenReturn(menus);
-        when(registryFactory.createHostTreeDecoratorRegistry()).thenReturn(hostDecoratorRegistry);
-        when(registryFactory.createVMTreeDecoratorRegistry()).thenReturn(vmDecoratorRegistry);
         when(registryFactory.createHostFilterRegistry()).thenReturn(hostFilterRegistry);
         when(registryFactory.createVmFilterRegistry()).thenReturn(vmFilterRegistry);
         when(registryFactory.createVMInformationRegistry()).thenReturn(vmInfoRegistry);
@@ -235,9 +219,6 @@
 
         ArgumentCaptor<ActionListener> grabVmFiltersListener = ArgumentCaptor.forClass(ActionListener.class);
         doNothing().when(vmFilterRegistry).addActionListener(grabVmFiltersListener.capture());
-
-        ArgumentCaptor<ActionListener> grabDecoratorsListener = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(vmDecoratorRegistry).addActionListener(grabDecoratorsListener.capture());
         
         ArgumentCaptor<ActionListener> grabInfoRegistry = ArgumentCaptor.forClass(ActionListener.class);
         doNothing().when(vmInfoRegistry).addActionListener(grabInfoRegistry.capture());
@@ -307,32 +288,6 @@
     }
     
     @Test
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public void verifyDecoratorsRegisteredAndStarted() {
-
-        ArgumentCaptor<ActionListener> captor1 = ArgumentCaptor.forClass(ActionListener.class);
-        ArgumentCaptor<ActionListener> captor2 = ArgumentCaptor.forClass(ActionListener.class);
-
-        verify(view, atLeastOnce()).getHostTreeController();
-        verify(treeController).getHostDecoratorListener();
-        verify(treeController).getVmDecoratorListener();
-        
-        verify(hostDecoratorRegistry).addActionListener(captor1.capture());
-        verify(vmDecoratorRegistry).addActionListener(captor2.capture());
-        
-        verify(hostDecoratorRegistry).start();
-        verify(vmDecoratorRegistry).start();
-
-        ActionListener l1 = captor1.getValue();
-        ActionListener l2 = captor2.getValue();
-        
-        assertEquals(hostDecorators, l1);
-        assertEquals(vmDecorators, l2);
-        
-        verify(contextController).addContextActionListener(any(ContextHandler.class));
-    }
-    
-    @Test
     public void verifyShowMainWindowActuallyCallsView() {
         controller.showMainMainWindow();
         verify(view).showMainWindow();
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java	Fri Nov 08 14:23:26 2013 +0100
@@ -38,18 +38,10 @@
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JRadioButtonMenuItem;
 
@@ -69,15 +61,10 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
-import com.redhat.thermostat.client.ui.Decorator;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.Filter;
 import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.HostsVMsLoader;
 
 @RunWith(CacioFESTRunner.class)
 public class MainWindowTest {
@@ -116,44 +103,6 @@
         l = null;
     }
 
-    //@Category(GUITest.class)
-    //@Test
-    public void testHostVmDecoratorsAdded() throws InterruptedException {
-        
-        List<DecoratorProvider<HostRef>> decorators = new ArrayList<>();
-        @SuppressWarnings("unchecked")
-        DecoratorProvider<HostRef> refDecorator = mock(DecoratorProvider.class);
-        final Decorator decorator = mock(Decorator.class);
-        when(decorator.getLabel(anyString())).thenReturn("fluff");
-        
-        when(refDecorator.getDecorator()).thenReturn(decorator);
-        
-        @SuppressWarnings("unchecked")
-        Filter<HostRef> filter = mock(Filter.class);
-        when(filter.matches(isA(HostRef.class))).thenReturn(false).thenReturn(true);
-
-        when(refDecorator.getFilter()).thenReturn(filter);
-        
-        decorators.add(refDecorator);
-        
-        HostsVMsLoader hostsVMsLoader = mock(HostsVMsLoader.class);
-        Collection<HostRef> expectedHosts = new ArrayList<>();
-        expectedHosts.add(new HostRef("123", "fluffhost1"));
-        expectedHosts.add(new HostRef("456", "fluffhost2"));
-        
-        when(hostsVMsLoader.getHosts()).thenReturn(expectedHosts);
-        
-        //window.updateTree(null, null, decorators, null, hostsVMsLoader);
-
-        Thread.sleep(50);
-        
-        frameFixture.show();
-        frameFixture.requireVisible();
-        
-        verify(decorator, times(0)).getLabel("fluffhost1");
-        verify(decorator, atLeastOnce()).getLabel("fluffhost2");
-    }
-    
     @Category(GUITest.class)
     @Test
     public void verifyThatCloseFiresShutdownEvent() {
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java	Fri Nov 08 14:23:26 2013 +0100
@@ -46,13 +46,11 @@
 import com.redhat.thermostat.client.core.views.HostInformationViewProvider;
 import com.redhat.thermostat.client.core.views.SummaryViewProvider;
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
-import com.redhat.thermostat.client.swing.internal.HostIconDecoratorProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingAgentInformationViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingClientConfigurationViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingHostInformationViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingSummaryViewProvider;
 import com.redhat.thermostat.client.swing.internal.views.SwingVmInformationViewProvider;
-import com.redhat.thermostat.client.ui.DecoratorProvider;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
 public class ThermostatActivatorTest {
@@ -65,14 +63,13 @@
 
         activator.start(ctx);
 
-        assertTrue(ctx.isServiceRegistered(DecoratorProvider.class.getName(), HostIconDecoratorProvider.class));
         assertTrue(ctx.isServiceRegistered(SummaryViewProvider.class.getName(), SwingSummaryViewProvider.class));
         assertTrue(ctx.isServiceRegistered(HostInformationViewProvider.class.getName(), SwingHostInformationViewProvider.class));
         assertTrue(ctx.isServiceRegistered(VmInformationViewProvider.class.getName(), SwingVmInformationViewProvider.class));
         assertTrue(ctx.isServiceRegistered(AgentInformationViewProvider.class.getName(), SwingAgentInformationViewProvider.class));
         assertTrue(ctx.isServiceRegistered(ClientConfigViewProvider.class.getName(), SwingClientConfigurationViewProvider.class));
         
-        assertEquals(6, ctx.getAllServices().size());
+        assertEquals(5, ctx.getAllServices().size());
 
         // FIXME add more tests for the service tracker used by ThermostatActivator
     }
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryControllerTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/registry/decorator/DecoratorRegistryControllerTest.java	Fri Nov 08 14:23:26 2013 +0100
@@ -44,8 +44,9 @@
 import org.junit.Test;
 import org.osgi.framework.InvalidSyntaxException;
 
+import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorManager;
 import com.redhat.thermostat.client.swing.internal.vmlist.controller.HostTreeController;
-import com.redhat.thermostat.client.swing.internal.vmlist.controller.LabelDecoratorListener;
+import com.redhat.thermostat.client.swing.internal.vmlist.controller.DecoratorListener;
 
 /**
  *
@@ -55,29 +56,41 @@
     private DecoratorRegistryFactory registryFactory;
     private HostTreeController hostController;
 
-    private LabelDecoratorListener l0;
-    private LabelDecoratorListener l1;
-    
+    private DecoratorListener l0;
+    private DecoratorListener l1;
+    private DecoratorListener l2;
+
     private InfoLabelDecoratorRegistry infoLabel;
     private MainLabelDecoratorRegistry mainLabel;
+    private IconDecoratorRegistry icon;
 
+    private DecoratorManager manager;
+    
     @Before
     public void setUp() throws InvalidSyntaxException {
         
+        manager = mock(DecoratorManager.class);
+        
         infoLabel = mock(InfoLabelDecoratorRegistry.class);
         mainLabel = mock(MainLabelDecoratorRegistry.class);
-       
+        icon = mock(IconDecoratorRegistry.class);
+
         registryFactory = mock(DecoratorRegistryFactory.class);
         
         when(registryFactory.createInfoLabelDecoratorRegistry()).thenReturn(infoLabel);
         when(registryFactory.createMainLabelDecoratorRegistry()).thenReturn(mainLabel);
-        
-        l0 = mock(LabelDecoratorListener.class);
-        l1 = mock(LabelDecoratorListener.class);
+        when(registryFactory.createIconDecoratorRegistry()).thenReturn(icon);
+
+        l0 = mock(DecoratorListener.class);
+        l1 = mock(DecoratorListener.class);
+        l2 = mock(DecoratorListener.class);
+
+        hostController = mock(HostTreeController.class);
+        when(hostController.getDecoratorManager()).thenReturn(manager);
         
-        hostController = mock(HostTreeController.class);
-        when(hostController.getInfoLabelDecoratorListener()).thenReturn(l0);
-        when(hostController.getMainLabelDecoratorListener()).thenReturn(l1);
+        when(manager.getInfoLabelDecoratorListener()).thenReturn(l0);
+        when(manager.getMainLabelDecoratorListener()).thenReturn(l1);
+        when(manager.getIconDecoratorListener()).thenReturn(l2);
     }
     
     @Test
@@ -88,6 +101,8 @@
         
         verify(registryFactory).createInfoLabelDecoratorRegistry();
         verify(registryFactory).createMainLabelDecoratorRegistry();
+        verify(registryFactory).createIconDecoratorRegistry();
+
     }
 
     @Test
@@ -109,6 +124,9 @@
         
         verify(mainLabel).addActionListener(l1);
         verify(mainLabel).start();
+        
+        verify(icon).addActionListener(l2);
+        verify(icon).start();
     }
 
     @Test
@@ -133,5 +151,8 @@
         
         verify(mainLabel).removeActionListener(l1);
         verify(mainLabel).stop();
+        
+        verify(icon).removeActionListener(l2);
+        verify(icon).stop();
     } 
 }
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeControllerTest.java	Fri Nov 08 14:22:51 2013 +0100
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeControllerTest.java	Fri Nov 08 14:23:26 2013 +0100
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.client.swing.internal.vmlist.controller;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
 
@@ -58,6 +59,8 @@
 import com.redhat.thermostat.client.swing.internal.accordion.Accordion;
 import com.redhat.thermostat.client.swing.internal.accordion.AccordionModel;
 import com.redhat.thermostat.client.swing.internal.vmlist.HostTreeComponentFactory;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
 
@@ -67,8 +70,11 @@
     private DecoratorManager decoratorManager;
     private HostTreeComponentFactory componentFactory;
     private AccordionModel<HostRef, VmRef> proxyModel;
-    private DecoratorProviderExtensionListener hostDecoratorListener;
-    private DecoratorProviderExtensionListener vmDecoratorListener;
+
+    private DecoratorListener<ReferenceFieldLabelDecorator> mainLabelDecorators;
+    private DecoratorListener<ReferenceFieldLabelDecorator> infoLabelDecorators;
+    
+    private DecoratorListener<ReferenceFieldIconDecorator> iconDecorators;
     
     @BeforeClass
     public static void setUpOnce() {
@@ -87,10 +93,13 @@
         proxyModel = new AccordionModel<>();
         when(accordion.getModel()).thenReturn(proxyModel);
         
-        hostDecoratorListener = mock(DecoratorProviderExtensionListener.class);
-        vmDecoratorListener = mock(DecoratorProviderExtensionListener.class);
-        when(decoratorManager.getVmDecoratorListener()).thenReturn(vmDecoratorListener);
-        when(decoratorManager.getHostDecoratorListener()).thenReturn(hostDecoratorListener);
+        mainLabelDecorators = mock(DecoratorListener.class);
+        infoLabelDecorators = mock(DecoratorListener.class);
+        iconDecorators = mock(DecoratorListener.class);
+        
+        when(decoratorManager.getMainLabelDecoratorListener()).thenReturn(mainLabelDecorators);
+        when(decoratorManager.getInfoLabelDecoratorListener()).thenReturn(infoLabelDecorators);
+        when(decoratorManager.getIconDecoratorListener()).thenReturn(iconDecorators);
     }
     
     private void waitForSwing() {
@@ -246,13 +255,17 @@
         
         waitForSwing();
 
-        verify(vmDecoratorListener).decorationChanged();
-        
+        verify(mainLabelDecorators).fireDecorationChanged();
+        verify(infoLabelDecorators).fireDecorationChanged();
+        verify(iconDecorators).fireDecorationChanged();
+
         controller.updateHostStatus(host0);
 
         waitForSwing();
         
-        verify(hostDecoratorListener).decorationChanged();
+        verify(mainLabelDecorators, times(2)).fireDecorationChanged();
+        verify(infoLabelDecorators, times(2)).fireDecorationChanged();
+        verify(iconDecorators, times(2)).fireDecorationChanged();
     }
     
     @Test