Package org.fusesource.ide.camel.editor.provider

Source Code of org.fusesource.ide.camel.editor.provider.AbstractAddNodeMenuFactory

/*******************************************************************************
* Copyright (c) 2013 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Red Hat, Inc. - initial API and implementation
******************************************************************************/

package org.fusesource.ide.camel.editor.provider;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.ICustomContext;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.tb.ContextMenuEntry;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.fusesource.ide.camel.editor.AbstractNodes;
import org.fusesource.ide.camel.editor.Activator;
import org.fusesource.ide.camel.editor.EditorMessages;
import org.fusesource.ide.camel.editor.Messages;
import org.fusesource.ide.camel.editor.commands.DiagramOperations;
import org.fusesource.ide.camel.editor.editor.RiderDesignEditor;
import org.fusesource.ide.camel.editor.features.custom.CreateNodeConnectionFeature;
import org.fusesource.ide.camel.model.AbstractNode;
import org.fusesource.ide.camel.model.Endpoint;
import org.fusesource.ide.camel.model.RouteContainer;
import org.fusesource.ide.camel.model.RouteSupport;
import org.fusesource.ide.camel.model.generated.Bean;
import org.fusesource.ide.camel.model.generated.Route;
import org.fusesource.ide.commons.util.Strings;


public abstract class AbstractAddNodeMenuFactory {

  protected static final String DEFAULT_IMAGE_KEY = "org.fusesource.demo.icons.generic.png_small";
  private AbstractNode selectedNode;
  private RiderDesignEditor editor;

  // Graphiti context menu

  /**
   * setup the menu structure for the addNode context menu
   *
   * @param rootMenu  the root menu entry (addNode)
   * @param context  the context
   * @param fp    the feature provider
   */
  public void setupMenuStructure(ContextMenuEntry rootMenu, ICustomContext context, IFeatureProvider fp) {
    AbstractNode selectedNode = getSelectedNode(context, fp);
    boolean onlyEndpoints = false;
    if (selectedNode instanceof Route || selectedNode == null) {
      // commented out as we already have a "add route" menu entry
      //addMenuItem(rootMenu, Messages.paletteRouteTitle, Messages.paletteRouteDescription, Route.class, context, fp);
      onlyEndpoints = true;
    }

    ContextMenuEntry endpointsEntry = new ContextMenuEntry(null, null);
    endpointsEntry.setText(Messages.endpointsDrawerTitle);
    endpointsEntry.setSubmenu(true);

    ContextMenuEntry routingEntry = new ContextMenuEntry(null, context);
    routingEntry.setText(Messages.routingDrawerTitle);
    routingEntry.setSubmenu(true);

    ContextMenuEntry controlFlowEntry = new ContextMenuEntry(null, context);
    controlFlowEntry.setText(Messages.controlFlowDrawerTitle);
    controlFlowEntry.setSubmenu(true);

    ContextMenuEntry transformationEntry = new ContextMenuEntry(null, context);
    transformationEntry.setText(Messages.transformationDrawerTitle);
    transformationEntry.setSubmenu(true);

    ContextMenuEntry miscEntry = new ContextMenuEntry(null, context);
    miscEntry.setText(Messages.miscellaneousDrawerTitle);
    miscEntry.setSubmenu(true);

    // then we need to fill the shelves menus
    fillEndpointsContextMenu(endpointsEntry, context, fp);
    if (!onlyEndpoints) {
      fillRoutingContextMenu(routingEntry, context, fp);
      fillControlFlowContextMenu(controlFlowEntry, context, fp);
      fillTransformationContextMenu(transformationEntry, context, fp);
      fillMiscellaneousContextMenu(miscEntry, context, fp);
    }

    // lets find what endpoints are available...
    if (selectedNode != null) {
      Set<Endpoint> endpoints = AbstractNodes.getAllEndpoints(selectedNode);
      Map<String, String> beans = AbstractNodes.getAllBeans(selectedNode);
      if (endpoints.size() > 0 || beans.size() > 0) {
        /*
        // TODO add a separator...
        ContextMenuEntry menuEntry = new ContextMenuEntry(null, null);
        menuEntry.setSubmenu(false);
        // add entry to parent
        endpointsEntry.add(menuEntry);
         */
      }
      if (endpoints.size() > 0) {
        boolean useChildMenu = false;
        if (useChildMenu) {
          ContextMenuEntry values = new ContextMenuEntry(null, null);
          values.setText(Messages.endpointsDrawerTitle);
          values.setSubmenu(true);

          addEndpointInstances(values, endpoints, context, fp);
          endpointsEntry.add(values);
        } else {
          addEndpointInstances(endpointsEntry, endpoints, context, fp);
        }
      }
      if (beans.size() > 0) {
        boolean useChildMenu = false;
        if (useChildMenu) {
          ContextMenuEntry values = new ContextMenuEntry(null, null);
          values.setText(Messages.endpointsDrawerTitle);
          values.setSubmenu(true);

          addBeanInstances(values, beans, context, fp);
          endpointsEntry.add(values);
        } else {
          addBeanInstances(endpointsEntry, beans, context, fp);
        }
      }
    }

    // and finally we add the shelves entries to the parent menu
    rootMenu.add(endpointsEntry);
    rootMenu.add(routingEntry);
    rootMenu.add(controlFlowEntry);
    rootMenu.add(transformationEntry);
    rootMenu.add(miscEntry);
  }


  protected void addBeanInstances(ContextMenuEntry menu, Map<String, String> beans, ICustomContext context,
      IFeatureProvider fp) {
    ArrayList<String> processedBeans = new ArrayList<String>();
   
    for (Map.Entry<String,String> entry : beans.entrySet()) {
      final String name = entry.getKey();
      final String aClass = entry.getValue();
      if (Strings.isBlank(name) && Strings.isBlank(aClass)) {
        continue;
      }
      if (processedBeans.contains(name)) continue;
      processedBeans.add(name);
     
      String description = "bean '" + name + "' of type " + aClass;
      addMenuItem(menu, name, description, Bean.class, context, fp, new CreateNodeConnectionFeature(fp, Bean.class) {

        @Override
        protected AbstractNode createNode() throws Exception {
          Bean bean = new Bean();
          bean.setName(name);
          bean.setRef(name);
          bean.setBeanType(aClass);
          return bean;
        }
      });
    }

  }


  protected void addEndpointInstances(ContextMenuEntry menu, Set<Endpoint> endpoints, ICustomContext context, IFeatureProvider fp) {
    SortedMap<String,Endpoint> map = new TreeMap<String,Endpoint>();
    ArrayList<String> processedURIs = new ArrayList<String>();
    for (Endpoint endpoint : endpoints) {
      map.put(endpoint.getDisplayText(), endpoint);
    }

    for (final Endpoint endpoint : map.values()) {
      String id = endpoint.getId();
      String url = endpoint.getUri();
      if (Strings.isBlank(id) && Strings.isBlank(url)) {
        continue;
      }
      if (processedURIs.contains(url)) continue;
      processedURIs.add(url);
      String description = endpoint.getDescription();
      String title = endpoint.getDisplayText();

      addMenuItem(menu, title, description, Endpoint.class, context, fp, new CreateNodeConnectionFeature(fp, Endpoint.class) {

        @Override
        protected AbstractNode createNode() throws Exception {
          return new Endpoint(endpoint);
        }
      });
    }
  }




  /**
   * creates a new menu item and adds it to the parent menu
   *
   * @param parent    the parent menu
   * @param label      the menu label
   * @param description  the menu description
   * @param clazz      the class which is created by that menu item
   * @param context    the custom context
   * @param fp      the feature provider
   */
  protected void addMenuItem(ContextMenuEntry parent, String label, String description, Class<? extends AbstractNode> clazz, ICustomContext context, IFeatureProvider fp) {
    // check if we can actually connect to the current selection
    CreateNodeConnectionFeature feature = new CreateNodeConnectionFeature(fp, clazz);
    addMenuItem(parent, label, description, clazz, context, fp, feature);
  }


  protected void addMenuItem(ContextMenuEntry parent, String label, String description,
      Class<? extends AbstractNode> clazz, ICustomContext context, IFeatureProvider fp,
      CreateNodeConnectionFeature feature) {
    AbstractNode selectedNode = getSelectedNode(context, fp);
    Object newObject = newInstance(clazz);
    if (newObject instanceof AbstractNode) {
      AbstractNode newNode = (AbstractNode) newObject;

      // TODO change to allow us to add any new item to the selection...
      //if (newNode instanceof RouteSupport || (selectedNode != null && selectedNode.canConnectTo(newNode))) {

      // create a sub-menu for all AddNode operations
      ContextMenuEntry menuEntry = new ContextMenuEntry(feature, context);
      // set the menu label
      menuEntry.setText(label);
      // set the description
      menuEntry.setDescription(description);
      try {
        // set the image
        AbstractNode node = clazz.newInstance();
        String iconName = node.getIconName();
        menuEntry.setIconId(ImageProvider.getKeyForSmallIcon(iconName));
      } catch (Exception ex) {
        menuEntry.setIconId(DEFAULT_IMAGE_KEY);
      }
      // display sub-menu hierarchical or flat
      menuEntry.setSubmenu(false);
      // add entry to parent
      parent.add(menuEntry);
      //}
    }
  }




  public static AbstractNode getSelectedNode(ICustomContext context, IFeatureProvider fp) {
    AbstractNode selectedNode = null;
    PictogramElement[] elements = context.getPictogramElements();
    if (elements != null && elements.length > 0) {
      Object bo = fp.getBusinessObjectForPictogramElement(elements[0]);
      if (bo instanceof AbstractNode) {
        selectedNode = (AbstractNode) bo;
      }
    }
    if (selectedNode == null){
      RiderDesignEditor editor = RiderDesignEditor.toRiderDesignEditor(fp);
      if (editor != null) {
        selectedNode = editor.getSelectedRoute();
      }
    }
    return selectedNode;
  }


  // MenuManager creation

  public void fillMenu(RiderDesignEditor editor, Menu menu) {
    this.editor = editor;
    this.selectedNode = editor.getSelectedNode();
    List<MenuManager> menus = new ArrayList<MenuManager>();
    if ((selectedNode instanceof RouteContainer) && !(selectedNode instanceof RouteSupport)) {
      // lets just add a new route
      MenuManager subMenu = new MenuManager(EditorMessages.paletteRouteTitle, "org.fusesource.ide.actions.add.routes");
      addMenuItem(subMenu, EditorMessages.addRouteTitle, EditorMessages.addRouteDescription, Route.class);

      addMenu(menus, subMenu);
    } else {
      MenuManager subMenu = new MenuManager(Messages.endpointsDrawerTitle, "org.fusesource.ide.actions.add.endpoints");
      fillEndpointsMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.routingDrawerTitle, "org.fusesource.ide.actions.add.routing");
      fillRoutingMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.controlFlowDrawerTitle, "org.fusesource.ide.actions.add.control");
      fillControlFlowMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.transformationDrawerTitle, "org.fusesource.ide.actions.add.transformation");
      fillTransformationMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.miscellaneousDrawerTitle, "org.fusesource.ide.actions.add.miscellaneous");
      fillMiscellaneousMenu(subMenu);
      addMenu(menus, subMenu);
    }

    int index = menu.getItemCount();
    if (menus.size() == 1) {
      // lets remove the items and move them directly onto the menu
      // directly
      MenuManager childMenu = menus.get(0);
      IContributionItem[] items = childMenu.getItems();
      childMenu.removeAll();
      for (IContributionItem item : items) {
        item.fill(menu, index++);
      }
    } else if (menus.size() > 1) {
      for (MenuManager childMenu : menus) {
        childMenu.fill(menu, menu.getItemCount());
      }
    }
  }

  /*
  public void fillMenu2(RiderDesignEditor editor, IMenuManager menu) {
    AbstractNode selected = editor.getSelectedNode();
    fillMenu(editor, menu, selected);
  }
   */

  public void fillMenu(RiderDesignEditor editor, MenuManager menu, AbstractNode node) {
    this.editor = editor;
    this.selectedNode = node;
    List<MenuManager> menus = new ArrayList<MenuManager>();
    if ((selectedNode instanceof RouteContainer) && !(selectedNode instanceof RouteSupport)) {
      // lets just add a new route
      MenuManager subMenu = new MenuManager(EditorMessages.paletteRouteTitle, "org.fusesource.ide.actions.add.routes");
      addMenuItem(subMenu, EditorMessages.addRouteTitle, EditorMessages.addRouteDescription, Route.class);

      addMenu(menus, subMenu);
    } else {
      MenuManager subMenu = new MenuManager(Messages.endpointsDrawerTitle, "org.fusesource.ide.actions.add.endpoints");
      fillEndpointsMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.routingDrawerTitle, "org.fusesource.ide.actions.add.routing");
      fillRoutingMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.controlFlowDrawerTitle, "org.fusesource.ide.actions.add.control");
      fillControlFlowMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.transformationDrawerTitle, "org.fusesource.ide.actions.add.transformation");
      fillTransformationMenu(subMenu);
      addMenu(menus, subMenu);

      subMenu = new MenuManager(Messages.miscellaneousDrawerTitle, "org.fusesource.ide.actions.add.miscellaneous");
      fillMiscellaneousMenu(subMenu);
      addMenu(menus, subMenu);
    }

    if (menus.size() == 1) {
      // lets remove the items and move them directly onto the menu
      // directly
      MenuManager childMenu = menus.get(0);
      IContributionItem[] items = childMenu.getItems();
      childMenu.removeAll();
      for (IContributionItem item : items) {
        menu.add(item);
      }
    } else if (menus.size() > 1) {
      for (MenuManager childMenu : menus) {
        menu.add(childMenu);
      }
    }
  }

  protected void addMenu(List<MenuManager> menus, MenuManager subMenu) {
    IContributionItem[] items = subMenu.getItems();
    if (items != null && items.length > 0) {
      menus.add(subMenu);
    }
  }


  protected void addMenuItem(IMenuManager menu, final String title, final String description, final Class<? extends AbstractNode> aClass) {
    // lets decide if we can actually add this kind of node first...
    Object newObject = newInstance(aClass);
    if (newObject instanceof AbstractNode) {
      final AbstractNode newNode = (AbstractNode) newObject;
      if (newNode instanceof RouteSupport || (selectedNode != null && selectedNode.canConnectTo(newNode))) {
        final AbstractNode node = selectedNode;
        Action action = new Action() {
          @Override
          public void runWithEvent(Event event) {
            if (newNode instanceof Route) {
              editor.addNewRoute();
            } else {
              DiagramOperations.addNode(editor, aClass, node);
            }

            /*

            Object newObject = newInstance(aClass);
            if (newObject instanceof AbstractNode) {
              final AbstractNode newNode = (AbstractNode) newObject;
              RouteContainer parent = selectedNode.getParent();
              RouteSupport route = null;
              if (selectedNode instanceof RouteSupport) {
                route = (RouteSupport) selectedNode;
                parent = route;
              } else if (selectedNode instanceof RouteContainer && parent == null) {
                parent = (RouteContainer) selectedNode;
              } else if (parent instanceof RouteSupport) {
                route = (RouteSupport) parent;
              }
              newNode.setParent(parent);
              RouteContainer root = null;
              if (route != null) {
                Activator.getLogger().debug("Creating a new: " + title + " on selected node: " + selectedNode);

                // lets figure out a reasonable x, y based being
                // bigger by some margin that biggest X and max
                // y
                root = route.getParent();
                if (root == null) {
                  root = route;
                }
              } else {
                root = parent;
              }

              Rectangle bounds = newNode.getLayout();
              Set<AbstractNode> descendents = root.getDescendents();
              for (AbstractNode descendant : descendents) {
                Rectangle layout = descendant.getLayout();
                if (layout.x > bounds.x) {
                  bounds.x = layout.x;
                }
                if (layout.y > bounds.y) {
                  bounds.y = layout.y;
                }
              }
              bounds.x += NEWNODE_X_OFFSET;
              bounds.y = selectedNode.getLayout().y;

              // lets force the route to be big too
              if (route != null) {
                Rectangle routeLayout = route.getLayout();
                if (routeLayout.width < bounds.x + ROUTE_WIDTH_MARGIN) {
                  routeLayout.width = bounds.x + ROUTE_WIDTH_MARGIN;
                  route.setLayout(routeLayout);
                }
                newNode.setLayout(bounds);
              }

              CompoundCommand command = new CompoundCommand("Add " + title);

              if (newNode instanceof RouteSupport) {
                RouteCreateCommand nodeCommand = new RouteCreateCommand((RouteSupport) newNode, parent, bounds);
                command.add(nodeCommand);
              } else {
                AbstractNodeCreateCommand nodeCommand = new AbstractNodeCreateCommand(newNode, route,
                    bounds);
                command.add(nodeCommand);
              }

              if (selectedNode instanceof Container) {
                // no flow when adding to a container
              } else {
                FlowCreateCommand flowCommand = new FlowCreateCommand(selectedNode);
                flowCommand.setTarget(newNode);
                command.add(flowCommand);
              }

              command.add(new Command(NLS.bind(EditorMessages.selectCommandLabel, title)) {

                @Override
                public void execute() {
                  // lets force the viewer to refresh...
                  editor.autoLayoutRoute();
                  nodeViewer.setSelectedNode(newNode);
                }

                @Override
                public void redo() {
                  execute();
                }
              });

              editor.getCommandStack().execute(command);
          } else {
            Activator.getLogger().error("No parent available for new node: " + newObject + " selected node: "
                + selectedNode);
          }
             */
          }
        };
        action.setId("org.fusesource.ide.actions.add." + newNode.getPatternName());
        action.setText(title);
        action.setToolTipText(description);
        action.setDescription(description);
        action.setImageDescriptor(getImageDescriptor(newNode.getSmallIconName()));
        menu.add(action);
      }
    }
  }


  protected Object newInstance(final Class<?> aClass) {
    try {
      return aClass.newInstance();
    } catch (Exception e) {
      Activator.getLogger().warning("Failed to create instance of " + aClass.getName() + ". " + e, e);
      return null;
    }
  }

  public ImageDescriptor getImageDescriptor(String key) {
    return org.fusesource.ide.camel.model.Activator.getDefault().getImageDescriptor(key);
  }


  protected abstract void fillTransformationContextMenu(ContextMenuEntry menu, ICustomContext context, IFeatureProvider fp);

  protected abstract void fillControlFlowContextMenu(ContextMenuEntry menu, ICustomContext context, IFeatureProvider fp);

  protected abstract void fillRoutingContextMenu(ContextMenuEntry menu, ICustomContext context, IFeatureProvider fp);

  protected abstract void fillEndpointsContextMenu(ContextMenuEntry menu, ICustomContext context, IFeatureProvider fp);

  protected abstract void fillMiscellaneousContextMenu(ContextMenuEntry menu, ICustomContext context, IFeatureProvider fp);


  protected abstract void fillTransformationMenu(IMenuManager menu);

  protected abstract void fillControlFlowMenu(IMenuManager menu);

  protected abstract void fillRoutingMenu(IMenuManager menu);

  protected abstract void fillEndpointsMenu(IMenuManager menu);

  protected abstract void fillMiscellaneousMenu(IMenuManager menu);

}
TOP

Related Classes of org.fusesource.ide.camel.editor.provider.AbstractAddNodeMenuFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.