gt:         List<String> ids = new ArrayList<String>(steps.size());
context: /**
   * Licensed to JumpMind Inc under one or more contributor
   * license agreements.  See the NOTICE file distributed
   * with this work for additional information regarding
   * copyright ownership.  JumpMind Inc licenses this file
   * to you under the GNU General Public License, version 3.0 (GPLv3)
   * (the "License"); you may not use this file except in compliance
   * with the License.
   *
   * You should have received a copy of the GNU General Public License,
   * version 3.0 (GPLv3) along with this library; if not, see
   * <http://www.gnu.org/licenses/>.
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  package org.jumpmind.metl.ui.views.design;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import org.jumpmind.metl.core.model.AbstractObject;
  import org.jumpmind.metl.core.model.Agent;
  import org.jumpmind.metl.core.model.AgentDeploy;
  import org.jumpmind.metl.core.model.Component;
  import org.jumpmind.metl.core.model.Flow;
  import org.jumpmind.metl.core.model.FlowName;
  import org.jumpmind.metl.core.model.FlowStep;
  import org.jumpmind.metl.core.model.FlowStepLink;
  import org.jumpmind.metl.core.model.Folder;
  import org.jumpmind.metl.core.model.FolderType;
  import org.jumpmind.metl.core.model.Privilege;
  import org.jumpmind.metl.core.model.Setting;
  import org.jumpmind.metl.core.model.UserSetting;
  import org.jumpmind.metl.core.persist.IConfigurationService;
  import org.jumpmind.metl.core.plugin.IDefinitionFactory;
  import org.jumpmind.metl.core.plugin.XMLComponentDefinition;
  import org.jumpmind.metl.core.runtime.AgentRuntime;
  import org.jumpmind.metl.core.runtime.IAgentManager;
  import org.jumpmind.metl.core.runtime.MisconfiguredException;
  import org.jumpmind.metl.core.runtime.component.AbstractComponentRuntime;
  import org.jumpmind.metl.ui.common.ApplicationContext;
  import org.jumpmind.metl.ui.common.ButtonBar;
  import org.jumpmind.metl.ui.common.IFlowRunnable;
  import org.jumpmind.metl.ui.common.Icons;
  import org.jumpmind.metl.ui.common.TabbedPanel;
  import org.jumpmind.metl.ui.common.UiUtils;
  import org.jumpmind.metl.ui.definition.XMLComponentUI;
  import org.jumpmind.metl.ui.diagram.Diagram;
  import org.jumpmind.metl.ui.diagram.LinkEvent;
  import org.jumpmind.metl.ui.diagram.LinkSelectedEvent;
  import org.jumpmind.metl.ui.diagram.Node;
  import org.jumpmind.metl.ui.diagram.NodeDoubleClickedEvent;
  import org.jumpmind.metl.ui.diagram.NodeMovedEvent;
  import org.jumpmind.metl.ui.diagram.NodeSelectedEvent;
  import org.jumpmind.metl.ui.views.manage.ExecutionRunPanel;
  import org.jumpmind.util.AppUtils;
  import org.jumpmind.vaadin.ui.common.IUiPanel;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import com.vaadin.event.dd.DragAndDropEvent;
  import com.vaadin.event.dd.acceptcriteria.AcceptAll;
  import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
  import com.vaadin.server.FontAwesome;
  import com.vaadin.server.Resource;
  import com.vaadin.ui.AbstractLayout;
  import com.vaadin.ui.AbstractSplitPanel;
  import com.vaadin.ui.Button;
  import com.vaadin.ui.DragAndDropWrapper;
  import com.vaadin.ui.DragAndDropWrapper.WrapperTargetDetails;
  import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable;
  import com.vaadin.ui.HorizontalLayout;
  import com.vaadin.ui.HorizontalSplitPanel;
  import com.vaadin.ui.Panel;
  import com.vaadin.ui.VerticalLayout;
  import com.vaadin.ui.VerticalSplitPanel;
  import com.vaadin.ui.themes.ValoTheme;
  
  @SuppressWarnings("serial")
  public class EditFlowPanel extends HorizontalLayout implements IUiPanel, IFlowRunnable {
  
      final Logger log = LoggerFactory.getLogger(getClass());
  
      ApplicationContext context;
  
      Flow flow;
  
      boolean readOnly;
  
      PropertySheet propertySheet;
  
      DesignNavigator designNavigator;
  
      EditFlowPalette componentPalette;
  
      TabbedPanel tabs;
  
      Diagram diagram;
  
      Panel flowPanel;
  
      AbstractLayout diagramLayout;
  
      Button runButton;
  
      Button copyButton;
  
      Button delButton;
      
      Button advancedEditButton;
  
      Button settingsButton;
  
      List<AbstractObject> selected = new ArrayList<AbstractObject>();
  
      IConfigurationService configurationService;
      
      VerticalLayout rightLayout;
      AbstractSplitPanel vSplit;
      AbstractSplitPanel hSplit;
      Boolean isVerticalView = null;
  
      float lastPos = 70;
      
      final static float MAX_PANEL_POSITION = 99;
  
      public EditFlowPanel(ApplicationContext context, String flowId, DesignNavigator designNavigator, TabbedPanel tabs) {
          this.configurationService = context.getConfigurationService();
          this.flow = configurationService.findFlow(flowId);
          this.readOnly = context.isReadOnly(configurationService.findProjectVersion(flow.getProjectVersionId()), Privilege.DESIGN);
          this.context = context;
          this.tabs = tabs;
          this.designNavigator = designNavigator;
  
          this.propertySheet = new PropertySheet(context, tabs, readOnly);
          this.propertySheet.setListener((components) -> {
              List<FlowStep> steps = new ArrayList<FlowStep>();
              for (Component c : components) {
                  steps.add(EditFlowPanel.this.flow.findFlowStepWithComponentId(c.getId()));
              }
              refreshStepOnDiagram(steps);
          });
          propertySheet.setCaption("Property Sheet");
  
          componentPalette = new EditFlowPalette(this, context, flow.getProjectVersionId());
  
          addComponent(componentPalette);
  
          
          rightLayout = new VerticalLayout();
          rightLayout.setSizeFull();
  
          rightLayout.addComponent(buildButtonBar());
  
          // Create two different layouts for the user to toggle between.
          vSplit = new VerticalSplitPanel();
          vSplit.setSizeFull();
          vSplit.setSplitPosition(MAX_PANEL_POSITION, Unit.PERCENTAGE);
          hSplit = new HorizontalSplitPanel();
          hSplit.setSizeFull();
          hSplit.setSplitPosition(MAX_PANEL_POSITION, Unit.PERCENTAGE);
           
          diagramLayout = new VerticalLayout();
          diagramLayout.setWidth(10000, Unit.PIXELS);
          diagramLayout.setHeight(10000, Unit.PIXELS);
  
          DragAndDropWrapper wrapper = new DragAndDropWrapper(diagramLayout);
          wrapper.setSizeUndefined();
          wrapper.setDropHandler(new DropHandler());
          flowPanel = new Panel();
          flowPanel.setSizeFull();
          flowPanel.addStyleName(ValoTheme.PANEL_WELL);
          flowPanel.setContent(wrapper);
  
          if (isVerticalView()) {
              vSplit.addComponent(flowPanel);
              vSplit.addComponent(propertySheet);
              rightLayout.addComponent(vSplit);
              rightLayout.setExpandRatio(vSplit, 1);
          } else {
              hSplit.addComponent(flowPanel);
              hSplit.addComponent(propertySheet);
              rightLayout.addComponent(hSplit);
              rightLayout.setExpandRatio(hSplit, 1);
          }
  
          addComponent(rightLayout);
          setExpandRatio(rightLayout, 1);
  
          redrawFlow();
      }
  
      protected HorizontalLayout buildButtonBar() {
          ButtonBar buttonBar = new ButtonBar();
          if (!readOnly) {
              runButton = buttonBar.addButton("Run", Icons.RUN);
              runButton.addClickListener((event)->runFlow());
          }
  
          settingsButton = buttonBar.addButton("Settings", FontAwesome.GEARS);
          settingsButton.addClickListener((event) -> new EditFlowSettingsDialog(context, flow, readOnly).showAtSize(.75));        
  
          if (!readOnly) {
              Button selectAllButton = buttonBar.addButton("Select All", FontAwesome.CROSSHAIRS);
              selectAllButton.addClickListener((event)->setSelectedAll());
  
              copyButton = buttonBar.addButton("Copy", FontAwesome.COPY);
              copyButton.addClickListener((event)->copySelected());
              copyButton.setEnabled(false);
  
              delButton = buttonBar.addButton("Remove", FontAwesome.TRASH_O);
              delButton.addClickListener((event)->deleteSelected());
              delButton.setEnabled(false);;
  
          }
          
          advancedEditButton = buttonBar.addButton("Advanced Edit", FontAwesome.EDIT, e->openAdvancedEditor());
          advancedEditButton.setEnabled(false);
  
          Button exportButton = buttonBar.addButtonRight("Capture", FontAwesome.CAMERA, (event)->export());
          exportButton.setId("exportButton");
          
          buttonBar.addButtonRight("Layout", FontAwesome.COLUMNS, (event)->toggleView());
          
          return buttonBar;
      }
      
      private void export() {
          // There is an issue with the html2canvas library not writing 
          // component anchors correctly when the scroll panel is scrolled down.
          // Reset scrolling first.
          flowPanel.setScrollLeft(0);
          flowPanel.setScrollTop(0);
          new ImagePreviewDialog(diagram).showAtSize(.75);
      }
      
      private void toggleView() {
          if (isVerticalView()) {
              hSplit.addComponent(flowPanel);
              hSplit.addComponent(propertySheet);
              rightLayout.replaceComponent(vSplit, hSplit);
              rightLayout.setExpandRatio(hSplit, 1);
              setVerticalView(false);
          } else {
              vSplit.addComponent(flowPanel);
              vSplit.addComponent(propertySheet);
              rightLayout.replaceComponent(hSplit, vSplit);
              rightLayout.setExpandRatio(vSplit, 1);
              setVerticalView(true);
          }
      }
  
      protected Button createToolButton(String name, Resource icon) {
          Button button = new Button(name, icon);
          button.addStyleName(ValoTheme.BUTTON_SMALL);
          button.addStyleName(ValoTheme.BUTTON_ICON_ALIGN_TOP);
          button.addStyleName(ValoTheme.BUTTON_BORDERLESS_COLORED);
          return button;
      }
  
      @Override
      public boolean closing() {
          FlowName flowName = new FlowName(flow);
          configurationService.save(flowName);
          return true;
      }
  
      @Override
      public void selected() {
          context.setCurrentFlow(new FlowName(flow));
          propertySheet.setSource(propertySheet.getValue());
      }
  
      public Flow getFlow() {
          return flow;
      }
  
      protected void refreshStepOnDiagram(List<FlowStep> steps) {
  