You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2013/11/08 16:13:31 UTC

svn commit: r1540068 - in /ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin: ./ component/

Author: jawi
Date: Fri Nov  8 15:13:31 2013
New Revision: 1540068

URL: http://svn.apache.org/r1540068
Log:
ACE-334 - provide action-in-selection for targets:

- allow a set of targets to be registered or approved with a single click;
- some cleanups and preparations for adding extra components for a panel.


Modified:
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/VaadinClient.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/ArtifactsPanel.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java
    ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/VaadinClient.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/VaadinClient.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/VaadinClient.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/VaadinClient.java Fri Nov  8 15:13:31 2013
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -85,6 +86,8 @@ import org.osgi.service.useradmin.Author
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
 import com.vaadin.event.ShortcutAction.KeyCode;
 import com.vaadin.event.ShortcutAction.ModifierKey;
 import com.vaadin.service.ApplicationContext;
@@ -93,6 +96,7 @@ import com.vaadin.ui.Button;
 import com.vaadin.ui.Button.ClickEvent;
 import com.vaadin.ui.DragAndDropWrapper;
 import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.HorizontalLayout;
 import com.vaadin.ui.Label;
 import com.vaadin.ui.ProgressIndicator;
 import com.vaadin.ui.Window;
@@ -168,10 +172,10 @@ public class VaadinClient extends com.va
     private GridLayout m_grid;
     private StatusLine m_statusLine;
     private File m_sessionDir; // private folder for session info
-    private Button m_artifactToolbar;
-    private Button m_featureToolbar;
-    private Button m_distributionToolbar;
-    private Button m_targetToolbar;
+    private HorizontalLayout m_artifactToolbar;
+    private HorizontalLayout m_featureToolbar;
+    private HorizontalLayout m_distributionToolbar;
+    private HorizontalLayout m_targetToolbar;
     private Window m_mainWindow;
     private final URL m_obrUrl;
     private final String m_repositoryXML;
@@ -541,7 +545,7 @@ public class VaadinClient extends com.va
      * @return Button
      */
     private Button createAddArtifactButton() {
-        Button button = new Button("Add artifact...");
+        Button button = new Button("+");
         addCrossPlatformAddShortcut(button, KeyCode.A, "Add a new artifact");
         button.addListener(new Button.ClickListener() {
             public void buttonClick(ClickEvent event) {
@@ -560,7 +564,7 @@ public class VaadinClient extends com.va
      * @return the add-distribution button instance.
      */
     private Button createAddDistributionButton() {
-        Button button = new Button("Add Distribution...");
+        Button button = new Button("+");
         addCrossPlatformAddShortcut(button, KeyCode.D, "Add a new distribution");
         button.addListener(new Button.ClickListener() {
             public void buttonClick(ClickEvent event) {
@@ -590,7 +594,7 @@ public class VaadinClient extends com.va
      * @return the add-feature button instance.
      */
     private Button createAddFeatureButton() {
-        Button button = new Button("Add Feature...");
+        Button button = new Button("+");
         addCrossPlatformAddShortcut(button, KeyCode.F, "Add a new feature");
         button.addListener(new Button.ClickListener() {
             public void buttonClick(ClickEvent event) {
@@ -619,7 +623,7 @@ public class VaadinClient extends com.va
      * @return the add-target button instance.
      */
     private Button createAddTargetButton() {
-        Button button = new Button("Add target...");
+        Button button = new Button("+");
         addCrossPlatformAddShortcut(button, KeyCode.G, "Add a new target");
         button.addListener(new Button.ClickListener() {
             public void buttonClick(ClickEvent event) {
@@ -648,6 +652,41 @@ public class VaadinClient extends com.va
         return button;
     }
 
+    /**
+     * @return a button to approve one or more targets.
+     */
+    private Button createApproveTargetsButton() {
+        final Button button = new Button("A");
+        button.setDisableOnClick(true);
+        button.setImmediate(true);
+        button.setEnabled(false);
+        button.addListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                m_targetsPanel.approveSelectedTargets();
+            }
+        });
+        m_targetsPanel.addListener(new ValueChangeListener() {
+            @Override
+            public void valueChange(ValueChangeEvent event) {
+                TargetsPanel targetsPanel = (TargetsPanel) event.getProperty();
+
+                Collection<?> itemIDs = (Collection<?>) targetsPanel.getValue();
+
+                boolean enabled = false;
+                for (Object itemID : itemIDs) {
+                    if (targetsPanel.isItemApproveNeeded(itemID)) {
+                        enabled = true;
+                        break;
+                    }
+                }
+
+                button.setEnabled(enabled);
+            }
+        });
+        return button;
+    }
+
     private ArtifactsPanel createArtifactsPanel() {
         return new ArtifactsPanel(m_associations, this, m_cacheRate, m_pageLength) {
             @Override
@@ -678,6 +717,13 @@ public class VaadinClient extends com.va
         };
     }
 
+    private HorizontalLayout createArtifactToolbar() {
+        HorizontalLayout result = new HorizontalLayout();
+        result.setSpacing(true);
+        result.addComponent(createAddArtifactButton());
+        return result;
+    }
+
     private DistributionsPanel createDistributionsPanel() {
         return new DistributionsPanel(m_associations, this) {
             @Override
@@ -708,6 +754,13 @@ public class VaadinClient extends com.va
         };
     }
 
+    private HorizontalLayout createDistributionToolbar() {
+        HorizontalLayout result = new HorizontalLayout();
+        result.setSpacing(true);
+        result.addComponent(createAddDistributionButton());
+        return result;
+    }
+
     private FeaturesPanel createFeaturesPanel() {
         return new FeaturesPanel(m_associations, this) {
             @Override
@@ -738,6 +791,45 @@ public class VaadinClient extends com.va
         };
     }
 
+    private HorizontalLayout createFeatureToolbar() {
+        HorizontalLayout result = new HorizontalLayout();
+        result.setSpacing(true);
+        result.addComponent(createAddFeatureButton());
+        return result;
+    }
+
+    private Button createRegisterTargetsButton() {
+        final Button button = new Button("R");
+        button.setDisableOnClick(true);
+        button.setImmediate(true);
+        button.setEnabled(false);
+        button.addListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                m_targetsPanel.registerSelectedTargets();
+            }
+        });
+        m_targetsPanel.addListener(new ValueChangeListener() {
+            @Override
+            public void valueChange(ValueChangeEvent event) {
+                TargetsPanel targetsPanel = (TargetsPanel) event.getProperty();
+
+                Collection<?> itemIDs = (Collection<?>) targetsPanel.getValue();
+
+                boolean enabled = false;
+                for (Object itemID : itemIDs) {
+                    if (targetsPanel.isItemRegistrationNeeded(itemID)) {
+                        enabled = true;
+                        break;
+                    }
+                }
+
+                button.setEnabled(enabled);
+            }
+        });
+        return button;
+    }
+
     private TargetsPanel createTargetsPanel() {
         return new TargetsPanel(m_associations, this) {
             @Override
@@ -793,6 +885,15 @@ public class VaadinClient extends com.va
         };
     }
 
+    private HorizontalLayout createTargetToolbar() {
+        HorizontalLayout result = new HorizontalLayout();
+        result.setSpacing(true);
+        result.addComponent(createAddTargetButton());
+        result.addComponent(createRegisterTargetsButton());
+        result.addComponent(createApproveTargetsButton());
+        return result;
+    }
+
     private GridLayout createToolbar() {
         return new MainActionToolbar(m_useAuth) {
             @Override
@@ -1011,7 +1112,7 @@ public class VaadinClient extends com.va
         m_grid.addComponent(m_mainToolbar, 0, 0, count - 1, 0);
 
         m_artifactsPanel = createArtifactsPanel();
-        m_artifactToolbar = createAddArtifactButton();
+        m_artifactToolbar = createArtifactToolbar();
 
         final DragAndDropWrapper artifactsPanelWrapper = new DragAndDropWrapper(m_artifactsPanel);
         artifactsPanelWrapper.setDropHandler(new ArtifactDropHandler(uploadHandler));
@@ -1026,7 +1127,7 @@ public class VaadinClient extends com.va
         }
 
         m_featuresPanel = createFeaturesPanel();
-        m_featureToolbar = createAddFeatureButton();
+        m_featureToolbar = createFeatureToolbar();
 
         if (auth.hasRole("viewFeature")) {
             m_grid.addComponent(m_featuresPanel, count, 2);
@@ -1035,7 +1136,7 @@ public class VaadinClient extends com.va
         }
 
         m_distributionsPanel = createDistributionsPanel();
-        m_distributionToolbar = createAddDistributionButton();
+        m_distributionToolbar = createDistributionToolbar();
 
         if (auth.hasRole("viewDistribution")) {
             m_grid.addComponent(m_distributionsPanel, count, 2);
@@ -1044,7 +1145,7 @@ public class VaadinClient extends com.va
         }
 
         m_targetsPanel = createTargetsPanel();
-        m_targetToolbar = createAddTargetButton();
+        m_targetToolbar = createTargetToolbar();
 
         if (auth.hasRole("viewTarget")) {
             m_grid.addComponent(m_targetsPanel, count, 2);
@@ -1075,8 +1176,8 @@ public class VaadinClient extends com.va
         m_distributionsPanel.setAssociatedTables(m_featuresPanel, m_targetsPanel);
         m_targetsPanel.setAssociatedTables(m_distributionsPanel, null);
 
-        addListener(m_statusLine, RepositoryObject.PUBLIC_TOPIC_ROOT.concat(RepositoryObject.TOPIC_ALL_SUFFIX));
-        addListener(m_mainToolbar, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
+        addListener(m_statusLine, StatefulTargetObject.TOPIC_ALL, RepositoryObject.PUBLIC_TOPIC_ROOT.concat(RepositoryObject.TOPIC_ALL_SUFFIX));
+        addListener(m_mainToolbar, StatefulTargetObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
         addListener(m_artifactsPanel, ArtifactObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
         addListener(m_featuresPanel, FeatureObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);
         addListener(m_distributionsPanel, DistributionObject.TOPIC_ALL, RepositoryAdmin.TOPIC_STATUSCHANGED, RepositoryAdmin.TOPIC_LOGIN, RepositoryAdmin.TOPIC_REFRESH);

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/ArtifactsPanel.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/ArtifactsPanel.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/ArtifactsPanel.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/ArtifactsPanel.java Fri Nov  8 15:13:31 2013
@@ -118,10 +118,10 @@ public abstract class ArtifactsPanel ext
     protected void handleEvent(String topic, RepositoryObject entity, org.osgi.service.event.Event event) {
         ArtifactObject artifact = (ArtifactObject) entity;
         if (ArtifactObject.TOPIC_ADDED.equals(topic)) {
-            add(artifact);
+            addToTable(artifact);
         }
         if (ArtifactObject.TOPIC_REMOVED.equals(topic)) {
-            remove(artifact);
+            removeFromTable(artifact);
         }
         if (ArtifactObject.TOPIC_CHANGED.equals(topic) || RepositoryAdmin.TOPIC_STATUSCHANGED.equals(topic)) {
             update(artifact);
@@ -137,8 +137,8 @@ public abstract class ArtifactsPanel ext
     protected void populateItem(ArtifactObject artifact, Item item) {
         item.getItemProperty(OBJECT_NAME).setValue(getDisplayName(artifact));
         item.getItemProperty(OBJECT_DESCRIPTION).setValue(artifact.getDescription());
-        item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(artifact));
-        item.getItemProperty(ACTION_DELETE).setValue(new RemoveItemButton(artifact));
+        item.getItemProperty(ACTION_UNLINK).setValue(createRemoveLinkButton(artifact));
+        item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(artifact));
     }
 
     private String getVersion(ArtifactObject artifact) {

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/BaseObjectPanel.java Fri Nov  8 15:13:31 2013
@@ -66,71 +66,6 @@ import com.vaadin.ui.Window.Notification
  */
 abstract class BaseObjectPanel<REPO_OBJ extends RepositoryObject, REPO extends ObjectRepository<REPO_OBJ>, LEFT_ASSOC_REPO_OBJ extends RepositoryObject, RIGHT_ASSOC_REPO_OBJ extends RepositoryObject> extends TreeTable implements EventHandler,
     CellStyleGenerator, ValueChangeListener {
-    /**
-     * Provides a generic remove item button.
-     */
-    protected class RemoveItemButton extends Button {
-        public RemoveItemButton(final REPO_OBJ object) {
-            setIcon(createIconResource("trash"));
-            setStyleName("small tiny");
-            setDescription("Delete " + getDisplayName(object));
-
-            addListener(new Button.ClickListener() {
-                public void buttonClick(ClickEvent event) {
-                    // Give some clue that this click is being processed...
-                    event.getButton().setEnabled(false);
-
-                    try {
-                        getRepository().remove(object);
-                    }
-                    catch (Exception e) {
-                        // ACE-246: notify user when the removal failed!
-                        getWindow().showNotification("Failed to remove item!", "<br/>Reason: " + e.getMessage(),
-                            Notification.TYPE_ERROR_MESSAGE);
-                    }
-                }
-            });
-        }
-    }
-
-    /**
-     * Provides a generic remove-link (or association) button.
-     */
-    protected class RemoveLinkButton extends Button {
-        public RemoveLinkButton(final REPO_OBJ object) {
-            this(object, null);
-        }
-
-        public RemoveLinkButton(final REPO_OBJ object, String parentId) {
-            setIcon(createIconResource("unlink"));
-            setStyleName("small tiny");
-            setData(object.getDefinition());
-            setDescription("Unlink " + getDisplayName(object));
-            // Only enable this button when actually selected...
-            setEnabled(false);
-
-            addListener(new Button.ClickListener() {
-                public void buttonClick(ClickEvent event) {
-                    // Give some clue that this click is being processed...
-                    event.getButton().setEnabled(false);
-
-                    Set<?> selection = m_associations.getActiveSelection();
-                    if (selection != null) {
-                        if (m_associations.isActiveTable(m_leftTable)) {
-                            for (Object itemId : selection) {
-                                removeLeftSideAssociation(m_leftTable.getFromId(itemId), object);
-                            }
-                        }
-                        else if (m_associations.isActiveTable(m_rightTable)) {
-                            for (Object itemId : selection) {
-                                removeRightSideAssocation(object, m_rightTable.getFromId(itemId));
-                            }
-                        }
-                    }
-                }
-            });
-        }
-    }
 
     /**
      * Drop handler for associations.
@@ -433,7 +368,7 @@ abstract class BaseObjectPanel<REPO_OBJ 
     public void populate() {
         removeAllItems();
         for (REPO_OBJ object : getAllRepositoryObjects()) {
-            add(object);
+            addToTable(object);
         }
         // Ensure the table is properly sorted...
         sort();
@@ -572,7 +507,7 @@ abstract class BaseObjectPanel<REPO_OBJ 
      * @param object
      *            the repository object to add, cannot be <code>null</code>.
      */
-    protected final void add(REPO_OBJ object) {
+    protected final void addToTable(REPO_OBJ object) {
         String itemId = object.getDefinition();
         String parentId = getParentId(object);
 
@@ -654,6 +589,89 @@ abstract class BaseObjectPanel<REPO_OBJ 
     }
 
     /**
+     * Creates a remove-item button for the given repository object.
+     * 
+     * @param object
+     *            the object to create a remove-item button, cannot be <code>null</code>.
+     * @return a remove-item button, never <code>null</code>.
+     */
+    protected final Button createRemoveItemButton(REPO_OBJ object) {
+        return createRemoveItemButton(object, getDisplayName(object));
+    }
+
+    /**
+     * Creates a remove-item button for the given repository object.
+     * 
+     * @param object
+     *            the object to create a remove-item button, cannot be <code>null</code>;
+     * @param displayName
+     *            the display name for the description of the button, cannot be <code>null</code>.
+     * @return a remove-item button, never <code>null</code>.
+     */
+    protected final Button createRemoveItemButton(RepositoryObject object, String displayName) {
+        Button result = new Button();
+        result.setIcon(createIconResource("trash"));
+        result.setData(object.getDefinition());
+        result.setStyleName("small tiny");
+        result.setDescription("Delete " + displayName);
+        result.setDisableOnClick(true);
+
+        result.addListener(new Button.ClickListener() {
+            public void buttonClick(Button.ClickEvent event) {
+                try {
+                    handleItemRemoveObject(event.getButton().getData());
+                }
+                catch (Exception e) {
+                    // ACE-246: notify user when the removal failed!
+                    getWindow().showNotification("Failed to remove item!", "<br/>Reason: " + e.getMessage(), Notification.TYPE_ERROR_MESSAGE);
+                }
+            }
+        });
+
+        return result;
+    }
+
+    /**
+     * Creates a remove-link button for the given repository object.
+     * 
+     * @param object
+     *            the object to create a remove-link button, cannot be <code>null</code>.
+     * @return a remove-link button, never <code>null</code>.
+     */
+    protected final Button createRemoveLinkButton(REPO_OBJ object) {
+        return createRemoveLinkButton(object, getDisplayName(object));
+    }
+
+    /**
+     * Creates a remove-link button for the given repository object.
+     * 
+     * @param object
+     *            the object to create a remove-link button, cannot be <code>null</code>;
+     * @param displayName
+     *            the display name for the description of the button, cannot be <code>null</code>.
+     * @return a remove-link button, never <code>null</code>.
+     */
+    protected final Button createRemoveLinkButton(RepositoryObject object, String displayName) {
+        Button result = new Button();
+        result.setIcon(createIconResource("unlink"));
+        result.setStyleName("small tiny");
+        result.setData(object.getDefinition());
+        result.setDescription("Unlink " + displayName);
+        // Only enable this button when actually selected...
+        result.setEnabled(false);
+        result.setDisableOnClick(true);
+
+        result.addListener(new Button.ClickListener() {
+            public void buttonClick(Button.ClickEvent event) {
+                handleItemRemoveLink(event.getButton().getData());
+            }
+
+        });
+
+        return result;
+    }
+
+    /**
      * Defines the table columns for this panel.
      */
     protected void defineTableColumns() {
@@ -839,6 +857,38 @@ abstract class BaseObjectPanel<REPO_OBJ 
     }
 
     /**
+     * Called by the remove-link button to remove a link.
+     * 
+     * @param itemID
+     *            the ID of the item to remove from the repository, cannot be <code>null</code>.
+     */
+    protected void handleItemRemoveLink(Object itemID) {
+        Set<?> selection = m_associations.getActiveSelection();
+        if (selection != null) {
+            if (m_associations.isActiveTable(m_leftTable)) {
+                for (Object itemId : selection) {
+                    removeLeftSideAssociation(m_leftTable.getFromId(itemId), getFromId(itemID));
+                }
+            }
+            else if (m_associations.isActiveTable(m_rightTable)) {
+                for (Object itemId : selection) {
+                    removeRightSideAssocation(getFromId(itemID), m_rightTable.getFromId(itemId));
+                }
+            }
+        }
+    }
+
+    /**
+     * Called by the remove-item button to remove a repository object from the repository.
+     * 
+     * @param itemID
+     *            the ID of the item to remove from the repository, cannot be <code>null</code>.
+     */
+    protected void handleItemRemoveObject(Object itemID) {
+        getRepository().remove(getFromId(itemID));
+    }
+
+    /**
      * Returns whether the given {@link RepositoryObject} can be handled by this panel.
      * 
      * @param entity
@@ -900,7 +950,7 @@ abstract class BaseObjectPanel<REPO_OBJ 
      * @param object
      *            the repository object to remove, cannot be <code>null</code>.
      */
-    protected final void remove(REPO_OBJ object) {
+    protected final void removeFromTable(RepositoryObject object) {
         String itemID = object.getDefinition();
         Object parentID = getParent(itemID);
 

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/DistributionsPanel.java Fri Nov  8 15:13:31 2013
@@ -87,10 +87,10 @@ public abstract class DistributionsPanel
     protected void handleEvent(String topic, RepositoryObject entity, org.osgi.service.event.Event event) {
         DistributionObject distribution = (DistributionObject) entity;
         if (DistributionObject.TOPIC_ADDED.equals(topic)) {
-            add(distribution);
+            addToTable(distribution);
         }
         if (DistributionObject.TOPIC_REMOVED.equals(topic)) {
-            remove(distribution);
+            removeFromTable(distribution);
         }
         if (DistributionObject.TOPIC_CHANGED.equals(topic) || RepositoryAdmin.TOPIC_STATUSCHANGED.equals(topic)) {
             update(distribution);
@@ -106,7 +106,7 @@ public abstract class DistributionsPanel
     protected void populateItem(DistributionObject distribution, Item item) {
         item.getItemProperty(OBJECT_NAME).setValue(distribution.getName());
         item.getItemProperty(OBJECT_DESCRIPTION).setValue(distribution.getDescription());
-        item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(distribution));
-        item.getItemProperty(ACTION_DELETE).setValue(new RemoveItemButton(distribution));
+        item.getItemProperty(ACTION_UNLINK).setValue(createRemoveLinkButton(distribution));
+        item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(distribution));
     }
 }

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/FeaturesPanel.java Fri Nov  8 15:13:31 2013
@@ -87,10 +87,10 @@ public abstract class FeaturesPanel exte
     protected void handleEvent(String topic, RepositoryObject entity, org.osgi.service.event.Event event) {
         FeatureObject feature = (FeatureObject) entity;
         if (FeatureObject.TOPIC_ADDED.equals(topic)) {
-            add(feature);
+            addToTable(feature);
         }
         if (FeatureObject.TOPIC_REMOVED.equals(topic)) {
-            remove(feature);
+            removeFromTable(feature);
         }
         if (FeatureObject.TOPIC_CHANGED.equals(topic) || RepositoryAdmin.TOPIC_STATUSCHANGED.equals(topic)) {
             update(feature);
@@ -106,7 +106,7 @@ public abstract class FeaturesPanel exte
     protected void populateItem(FeatureObject feature, Item item) {
         item.getItemProperty(OBJECT_NAME).setValue(feature.getName());
         item.getItemProperty(OBJECT_DESCRIPTION).setValue(feature.getDescription());
-        item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(feature));
-        item.getItemProperty(ACTION_DELETE).setValue(new RemoveItemButton(feature));
+        item.getItemProperty(ACTION_UNLINK).setValue(createRemoveLinkButton(feature));
+        item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(feature));
     }
 }

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/MainActionToolbar.java Fri Nov  8 15:13:31 2013
@@ -299,9 +299,7 @@ public abstract class MainActionToolbar 
             modified = getRepositoryAdmin().isModified();
         }
         catch (IOException e) {
-            getWindow().showNotification("Communication failed!",
-                "Failed to communicate with the server.<br />Reason: " + e.getMessage(),
-                Notification.TYPE_ERROR_MESSAGE);
+            showError("Communication failed!", "Failed to communicate with the server.", e);
         }
 
         // always enabled...

Modified: ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java?rev=1540068&r1=1540067&r2=1540068&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java (original)
+++ ace/trunk/org.apache.ace.webui.vaadin/src/org/apache/ace/webui/vaadin/component/TargetsPanel.java Fri Nov  8 15:13:31 2013
@@ -18,8 +18,10 @@
  */
 package org.apache.ace.webui.vaadin.component;
 
+import java.util.Collection;
 import java.util.List;
 
+import org.apache.ace.client.repository.RepositoryAdmin;
 import org.apache.ace.client.repository.RepositoryObject;
 import org.apache.ace.client.repository.RepositoryObject.WorkingState;
 import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
@@ -27,6 +29,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.TargetObject;
 import org.apache.ace.client.repository.repository.TargetRepository;
 import org.apache.ace.client.repository.stateful.StatefulTargetObject;
+import org.apache.ace.client.repository.stateful.StatefulTargetObject.ApprovalState;
 import org.apache.ace.client.repository.stateful.StatefulTargetRepository;
 import org.apache.ace.webui.NamedObject;
 import org.apache.ace.webui.UIExtensionFactory;
@@ -60,20 +63,87 @@ public abstract class TargetsPanel exten
     }
 
     /**
-     * Called to populate this table.
+     * Approves all selected targets in a single go.
+     * 
+     * @return <code>true</code> if at least one target of the current selection was approved, <code>false</code>
+     *         otherwise.
+     */
+    public boolean approveSelectedTargets() {
+        Collection<?> selection = (Collection<?>) getValue();
+
+        boolean result = false;
+        for (Object itemID : selection) {
+            StatefulTargetObject sto = getStatefulTargetFromId(itemID);
+            if (needsApproval(sto)) {
+                sto.approve();
+                result = true;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Tests whether a target with the given identifier needs approval.
+     * 
+     * @param itemID
+     *            the identifier of the object that should be checked, cannot be <code>null</code>.
+     * @return <code>true</code> if the target represented by the given identifier needs approval, <code>false</code>
+     *         otherwise.
+     */
+    public boolean isItemApproveNeeded(Object itemID) {
+        return needsApproval(getStatefulTargetFromId(itemID));
+    }
+
+    /**
+     * Tests whether a target with the given identifier needs be registered.
+     * 
+     * @param itemID
+     *            the identifier of the object that should be checked, cannot be <code>null</code>.
+     * @return <code>true</code> if the target represented by the given identifier needs registration,
+     *         <code>false</code> otherwise.
+     */
+    public boolean isItemRegistrationNeeded(Object itemID) {
+        return needsRegistration(getStatefulTargetFromId(itemID));
+    }
+
+    /**
+     * Called to populate this table, which is overridden in order to show unregistered targets (if needed).
      */
     public void populate() {
         removeAllItems();
         // All unregistered items aren't yet present in our TargetRepo, so we must add them explicitly...
         for (StatefulTargetObject object : getStatefulTargetRepository().get()) {
             if (!object.isRegistered()) {
-                Item item = addItem(object.getDefinition());
-                populateItem(object, item);
+                addToTable(object);
             }
         }
         for (TargetObject object : getRepository().get()) {
-            add(object);
+            addToTable(object);
         }
+        // Ensure the table is properly sorted...
+        sort();
+    }
+
+    /**
+     * Registers all selected targets in a single go.
+     * 
+     * @return <code>true</code> if at least one target of the current selection was registered, <code>false</code>
+     *         otherwise.
+     */
+    public boolean registerSelectedTargets() {
+        Collection<?> selection = (Collection<?>) getValue();
+
+        boolean result = false;
+        for (Object itemID : selection) {
+            StatefulTargetObject sto = getStatefulTargetFromId(itemID);
+            if (needsRegistration(sto)) {
+                sto.register();
+                result = true;
+            }
+        }
+
+        return result;
     }
 
     protected void defineTableColumns() {
@@ -121,7 +191,7 @@ public abstract class TargetsPanel exten
     @Override
     protected WorkingState getWorkingState(RepositoryObject object) {
         final StatefulTargetObject statefulTarget = asStatefulTargetObject(object);
-        if (statefulTarget.isRegistered()) {
+        if (statefulTarget != null && statefulTarget.isRegistered()) {
             return super.getWorkingState(statefulTarget.getTargetObject());
         }
         return WorkingState.Unchanged;
@@ -129,31 +199,35 @@ public abstract class TargetsPanel exten
 
     @Override
     protected void handleEvent(String topic, RepositoryObject entity, org.osgi.service.event.Event event) {
-        try {
-            TargetObject target = asTargetObject(entity);
+        if (entity instanceof StatefulTargetObject) {
+            StatefulTargetObject target = (StatefulTargetObject) entity;
+            if (StatefulTargetObject.TOPIC_ADDED.equals(topic)) {
+                addToTable(target);
+            }
+            if (StatefulTargetObject.TOPIC_REMOVED.equals(topic)) {
+                removeFromTable(target);
+            }
+            if (StatefulTargetObject.TOPIC_CHANGED.equals(topic) || RepositoryAdmin.TOPIC_STATUSCHANGED.equals(topic)) {
+                update(target);
+            }
+        }
+        else {
+            TargetObject target = (TargetObject) entity;
             if (TargetObject.TOPIC_ADDED.equals(topic)) {
-                add(target);
+                addToTable(target);
             }
             if (TargetObject.TOPIC_REMOVED.equals(topic)) {
-                remove(target);
+                removeFromTable(target);
             }
-            if (topic.endsWith("CHANGED")) {
+            if (TargetObject.TOPIC_CHANGED.equals(topic) || RepositoryAdmin.TOPIC_STATUSCHANGED.equals(topic)) {
                 update(target);
             }
         }
-        catch (IllegalStateException exception) {
-            // Ignore...
-        }
     }
 
-    /**
-     * Called whenever the user double clicks on a row.
-     * 
-     * @param itemId
-     *            the row/item ID of the double clicked item.
-     */
+    @Override
     protected void handleItemDoubleClick(Object itemId) {
-        StatefulTargetObject object = getStatefulTargetRepository().get((String) itemId);
+        StatefulTargetObject object = getStatefulTargetFromId(itemId);
 
         NamedObject namedObject = NamedObjectFactory.getNamedObject(object);
         if (namedObject != null) {
@@ -162,13 +236,46 @@ public abstract class TargetsPanel exten
     }
 
     @Override
+    protected void handleItemRemoveObject(Object itemId) {
+        StatefulTargetObject object = getStatefulTargetFromId(itemId);
+        if (object != null) {
+            getStatefulTargetRepository().remove(object);
+        }
+    }
+
+    @Override
     protected boolean isSupportedEntity(RepositoryObject entity) {
         return (entity instanceof StatefulTargetObject) || (entity instanceof TargetObject);
     }
 
     protected void populateItem(TargetObject target, Item item) {
-        StatefulTargetObject statefulTarget = asStatefulTargetObject(target);
-        populateItem(statefulTarget, item);
+        StatefulTargetObject sto = asStatefulTargetObject(target);
+
+        item.getItemProperty(OBJECT_NAME).setValue(target.getID());
+        if (sto != null) {
+            item.getItemProperty(REGISTRATION_STATE_ICON).setValue(getRegistrationStateIcon(sto));
+            item.getItemProperty(STORE_STATE_ICON).setValue(getStoreStateIcon(sto));
+            item.getItemProperty(PROVISIONING_STATE_ICON).setValue(getProvisioningStateIcon(sto));
+        }
+        item.getItemProperty(ACTION_UNLINK).setValue(createRemoveLinkButton(target));
+        item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(target));
+    }
+
+    /**
+     * Adds a given repository object to this table.
+     * 
+     * @param object
+     *            the repository object to add, cannot be <code>null</code>.
+     */
+    private void addToTable(StatefulTargetObject object) {
+        String itemId = object.getDefinition();
+
+        Item item = addItem(itemId);
+        if (item != null) {
+            populateItem(object, item);
+        }
+
+        setChildrenAllowed(itemId, false);
     }
 
     private StatefulTargetObject asStatefulTargetObject(RepositoryObject entity) {
@@ -178,11 +285,8 @@ public abstract class TargetsPanel exten
         return getStatefulTargetRepository().get(((TargetObject) entity).getDefinition());
     }
 
-    private TargetObject asTargetObject(RepositoryObject entity) {
-        if (entity instanceof TargetObject) {
-            return (TargetObject) entity;
-        }
-        return ((StatefulTargetObject) entity).getTargetObject();
+    private String getDisplayName(StatefulTargetObject object) {
+        return object.getID();
     }
 
     private Embedded getProvisioningStateIcon(StatefulTargetObject object) {
@@ -197,22 +301,53 @@ public abstract class TargetsPanel exten
         return createIcon(name, res);
     }
 
+    /**
+     * @param itemID
+     *            the target definition of the stateful target representation to get, cannot be <code>null</code>.
+     * @return the stateful target representation, can be <code>null</code>.
+     */
+    private StatefulTargetObject getStatefulTargetFromId(Object itemID) {
+        return getStatefulTargetRepository().get((String) itemID);
+    }
+
     private Embedded getStoreStateIcon(StatefulTargetObject object) {
         String name = object.getStoreState().name();
         Resource res = createIconResource("target_store_" + name);
         return createIcon(name, res);
     }
 
+    private boolean needsApproval(StatefulTargetObject target) {
+        return (target != null) && !target.getAutoApprove() && target.needsApprove() && (target.getApprovalState() != ApprovalState.Approved);
+    }
+
+    private boolean needsRegistration(StatefulTargetObject target) {
+        return (target != null) && !target.isRegistered();
+    }
+
     private void populateItem(StatefulTargetObject statefulTarget, Item item) {
         item.getItemProperty(OBJECT_NAME).setValue(statefulTarget.getID());
         item.getItemProperty(REGISTRATION_STATE_ICON).setValue(getRegistrationStateIcon(statefulTarget));
         item.getItemProperty(STORE_STATE_ICON).setValue(getStoreStateIcon(statefulTarget));
         item.getItemProperty(PROVISIONING_STATE_ICON).setValue(getProvisioningStateIcon(statefulTarget));
-        if (statefulTarget.isRegistered()) {
-            TargetObject targetObject = statefulTarget.getTargetObject();
+        item.getItemProperty(ACTION_UNLINK).setValue(createRemoveLinkButton(statefulTarget, getDisplayName(statefulTarget)));
+        item.getItemProperty(ACTION_DELETE).setValue(createRemoveItemButton(statefulTarget, getDisplayName(statefulTarget)));
+    }
 
-            item.getItemProperty(ACTION_UNLINK).setValue(new RemoveLinkButton(targetObject));
-            item.getItemProperty(ACTION_DELETE).setValue(new RemoveItemButton(targetObject));
+    /**
+     * Updates a given repository object in this table.
+     * 
+     * @param object
+     *            the repository object to update, cannot be <code>null</code>.
+     */
+    private void update(StatefulTargetObject object) {
+        if (object != null) {
+            String definition = object.getDefinition();
+            if (definition != null) {
+                Item item = getItem(definition);
+                if (item != null) {
+                    populateItem(object, item);
+                }
+            }
         }
     }
 }