Package org.apache.airavata.xbaya.ui.graph

Source Code of org.apache.airavata.xbaya.ui.graph.NodeGUI

/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* 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.apache.airavata.xbaya.ui.graph;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.airavata.workflow.model.graph.DataPort;
import org.apache.airavata.workflow.model.graph.Node;
import org.apache.airavata.workflow.model.graph.Node.NodeObserver;
import org.apache.airavata.workflow.model.graph.Node.NodeUpdateType;
import org.apache.airavata.workflow.model.graph.Port;
import org.apache.airavata.xbaya.XBayaEngine;
import org.apache.airavata.xbaya.graph.controller.NodeController;
import org.apache.airavata.xbaya.ui.monitor.MonitorEventHandler.NodeState;
import org.apache.airavata.xbaya.ui.utils.DrawUtils;

public abstract class NodeGUI implements GraphPieceGUI, NodeObserver {

    /**
     * BREAK_POINT_BORDER_COLOR
     */
    protected static final Color BREAK_POINT_BORDER_COLOR = new Color(53, 103, 157);

    /**
     * The minimum width of the node.
     */
    protected static final int MINIMUM_WIDTH = 100;

    /**
     * The minimum height of the node
     */
    protected static final int MINIMUM_HEIGHT = 37;

    protected static final int TEXT_GAP_X = 5;

    protected static final int TEXT_GAP_Y = 2;

    protected static final Color TEXT_COLOR = Color.black;

    protected static final int PORT_GAP = 13;

    protected static final int PORT_INITIAL_GAP = 10;

    protected static final Color EDGE_COLOR = Color.GRAY;

    protected static final Color DEFAULT_HEAD_COLOR = Color.white;

    protected static final Color SELECTED_HEAD_COLOR = Color.pink;

    /**
     * The default body color.
     */
    public static final Color DEFAULT_BODY_COLOR = new Color(250, 220, 100);

    protected static final Color DRAGGED_BODY_COLOR = Color.lightGray;

    protected static final Color BREAK_POINT_COLOR = new Color(174, 197, 221);

    protected Node node;

    protected Dimension dimension;

    protected int headHeight;

    protected boolean selected = false;

    protected boolean dragged = false;

    protected Color headColor;

    protected Color bodyColor;

    protected List<Paintable> paintables;
   
    /**
     * @param node
     */
    public NodeGUI(Node node) {
        this.node = node;
        this.bodyColor = DEFAULT_BODY_COLOR;
        this.headColor = DEFAULT_HEAD_COLOR;
        // The followings are just to make sure that it has some size.
        this.dimension = new Dimension(MINIMUM_WIDTH, MINIMUM_HEIGHT);
        this.paintables = new LinkedList<Paintable>();
        node.registerObserver(this);
    }

    /**
     * Sets the color of the body.
     *
     * @param color
     *            The color
     */
    public void setBodyColor(Color color) {
        this.bodyColor = color;
    }

    /**
     * @return The color of the body.
     */
    public Color getBodyColor() {
        return this.bodyColor;
    }

    /**
     * Sets the color of the head.
     *
     * @param color
     *            The color to set
     */
    public void setHeadColor(Color color) {
        this.headColor = color;
    }

    /**
     * @see org.apache.airavata.xbaya.ui.graph.GraphPieceGUI#mouseClicked(java.awt.event.MouseEvent,
     *      org.apache.airavata.xbaya.XBayaEngine)
     */
    public void mouseClicked(MouseEvent event, XBayaEngine engine) {
        // Nothing by default
    }

    /**
     * @param paintable
     */
    public void addPaintable(Paintable paintable) {
        this.paintables.add(paintable);
    }

    /**
     * @param paintable
     */
    public void removePaintable(Paintable paintable) {
        this.paintables.remove(paintable);
    }

    /**
     * @param flag
     */
    protected void setSelectedFlag(boolean flag) {
        this.selected = flag;
        if (this.selected) {
            this.headColor = SELECTED_HEAD_COLOR;
        } else {
            this.headColor = DEFAULT_HEAD_COLOR;
        }
    }

    /**
     * @param flag
     */
    protected void setDraggedFlag(boolean flag) {
        this.dragged = flag;
    }

    /**
     * Returns the position of the node.
     *
     * @return the position of the node
     */
    protected Point getPosition() {
        return getNode().getPosition();
    }

    /**
     * Gets the bounding Rectangle of this Node.
     *
     * @return A rectangle indicating this component's bounds
     */
    protected Rectangle getBounds() {
        return new Rectangle(getNode().getPosition(), this.dimension);
    }

    /**
     * Checks if a user's click is to select the node.
     *
     * @param point
     *            The location.
     * @return true if the user's click is to select the node; false otherwise
     */
    protected boolean isIn(Point point) {
        Rectangle bounds = getBounds();
        return bounds.contains(point);
    }

    /**
     * Checks if a user's click is to select the configuration
     *
     * @param point
     * @return true if the user's click is to select the node, false otherwise
     */
    @SuppressWarnings("unused")
    protected boolean isInConfig(Point point) {
        return false;
    }

    /**
     * Calculates the width of the node and x-coordinate of the ports. This method has to be called before painting any
     * parts of the graph.
     *
     * @param g
     */
    protected void calculatePositions(Graphics g) {
        Font oldFont = g.getFont();
        g.setFont(new Font(oldFont.getFontName(),Font.BOLD,oldFont.getSize()));
        FontMetrics fm = g.getFontMetrics();

        this.headHeight = fm.getHeight() + TEXT_GAP_Y * 2;

        int maxNumPort = Math.max(getNode().getOutputPorts().size(), getNode().getInputPorts().size());
        this.dimension.height = Math.max(this.headHeight + PORT_INITIAL_GAP + PORT_GAP * maxNumPort, MINIMUM_HEIGHT);
        this.dimension.width = Math.max(MINIMUM_WIDTH, fm.stringWidth(getNode().getID()) + TEXT_GAP_X * 5);

        /* Calculates the position of ports */
        setPortPositions();
        g.setFont(oldFont);
    }

    /**
     * @param g
     */
    protected void paint(Graphics2D g) {
        Shape componentShape = getComponentShape();
       
        // Draws the body.
        drawBody(g, componentShape, getComponentBodyColor());
       
        // Draws the head.
    drawHeader(g, getComponentHeaderShape(), getComponentHeaderText(), getComponentHeaderColor());
       
        // Draw a small circle to indicate the break
        drawBreaks(g, getNode().getPosition());

        // Edge
    drawEdge(g, componentShape, getComponentEdgeColor());

        // Paint all ports
        drawPorts(g, getAllPorts());

        // Paint extras
        drawExtras(g);
    }
   
    /** Following functions need to be overridden for if the component shape/text/color is different **/
 
  protected final Collection<? extends Port> getAllPorts() {
    return getNode().getAllPorts();
  }

  protected Node getNode() {
    return this.node;
  }

  protected final Color getComponentEdgeColor() {
    return EDGE_COLOR;
  }

  protected Color getComponentHeaderColor() {
    return this.headColor;
  }

  protected Shape getComponentHeaderShape() {
    Point position = getNode().getPosition();
    RoundRectangle2D headerBoundaryRect = new RoundRectangle2D.Double(position.x, position.y, this.dimension.width, this.headHeight,DrawUtils.ARC_SIZE, DrawUtils.ARC_SIZE);
    return headerBoundaryRect;
  }

  protected final Color getComponentBodyColor() {
    Color paintBodyColor;
        if (this.dragged) {
          paintBodyColor=DRAGGED_BODY_COLOR;
        } else {
          paintBodyColor=this.bodyColor;
        }
    return paintBodyColor;
  }

  protected Shape getComponentShape() {
    Point position = getNode().getPosition();
        RoundRectangle2D completeComponentBoundaryRect = new RoundRectangle2D.Float(position.x, position.y, this.dimension.width, this.dimension.height, DrawUtils.ARC_SIZE, DrawUtils.ARC_SIZE);
    return completeComponentBoundaryRect;
  }

  protected String getComponentHeaderText() {
    // XXX it's debatable if we should show the ID or the name.
        // String headerText = this.node.getName();
        String headerText = getNode().getID();
    return headerText;
  }

  /**---------------------------------------------------------------------------------**/
 
  protected void drawBody(Graphics2D g,
      Shape shape, Color paintBodyColor) {
    DrawUtils.initializeGraphics2D(g);
    AffineTransform affineTransform = new AffineTransform();
    affineTransform.translate(5,5);
    Shape shadow = affineTransform.createTransformedShape(shape);
    Composite oldComposite = g.getComposite();
    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.65F));
    g.setColor(Color.GRAY);
    g.fill(shadow);
    g.setComposite(oldComposite);
    DrawUtils.gradientFillShape(g, getEndColor(paintBodyColor), paintBodyColor, shape);
  }

  protected void drawBreaks(Graphics2D g, Point position) {
    if (getNode().isBreak()) {
      DrawUtils.initializeGraphics2D(g);
            g.setColor(BREAK_POINT_COLOR);
            int r = this.headHeight / 4;
            g.fillOval(position.x + this.dimension.width - 3 * r, position.y + r, 2 * r, 2 * r);
            g.setColor(BREAK_POINT_BORDER_COLOR);
            g.drawOval(position.x + this.dimension.width - 3 * r, position.y + r, 2 * r, 2 * r);
        }
  }

  protected void drawExtras(Graphics2D g) {
    DrawUtils.initializeGraphics2D(g);
    for (Paintable paintable : this.paintables) {
            paintable.paint(g, getNode().getPosition());
        }
  }

  protected void drawPorts(Graphics2D g, Collection<? extends Port> ports) {
    DrawUtils.initializeGraphics2D(g);
    for (Port port : ports) {
            NodeController.getGUI(port).paint(g);
        }
  }
 
  protected void drawPorts(Graphics2D g, Node node) {
    drawPorts(g, node.getAllPorts());
  }

  protected void drawEdge(Graphics2D g,
      Shape completeComponentBoundaryShape, Color edgeColor) {
    DrawUtils.initializeGraphics2D(g);
    g.setColor(edgeColor);
    //uncomment the commented lines to enable a double line edge
//    g.setStroke(new BasicStroke(4.0f));
        g.draw(completeComponentBoundaryShape);
//        g.setColor(Color.white);
//        g.setStroke(new BasicStroke(3.0f));
//        g.draw(completeComponentBoundaryShape);
  }
  protected void drawHeader(Graphics2D g, Shape shape,
      String headerText, Color headColor, boolean lowerBorderflat) {
    drawHeader(g, shape, headerText, headColor, shape, lowerBorderflat);
  }
 
  protected void drawHeader(Graphics2D g, Shape shape,
      String headerText, Color headColor) {
    drawHeader(g, shape, headerText, headColor, true);
  }
 
  protected void drawHeader(Graphics2D g, Shape shape,
      String headerText, Color headColor,
      Shape headerDrawBoundaryShape) {
    drawHeader(g, shape, headerText, headColor, headerDrawBoundaryShape, true);
  }
 
  protected void drawHeader(Graphics2D g, Shape shape,
      String headerText, Color headColor,
      Shape headerDrawBoundaryShape, boolean lowerBorderflat) {
    DrawUtils.initializeGraphics2D(g);
        if (lowerBorderflat) {
        g.setColor(getEndColor(headColor));
        Rectangle rect=new Rectangle((int) shape.getBounds().getX()+1, (int) (shape.getBounds()
          .getY() + shape.getBounds().getHeight() - DrawUtils.ARC_SIZE),
          (int) shape.getBounds().getWidth(), DrawUtils.ARC_SIZE);
      DrawUtils.gradientFillShape(g, getEndColor(headColor), headColor, rect);
    }
        DrawUtils.gradientFillShape(g, getEndColor(headColor), headColor, headerDrawBoundaryShape);
       
        // Text
        g.setColor(TEXT_COLOR);
        Font oldFont = g.getFont();
    g.setFont(new Font(oldFont.getFontName(),Font.BOLD,oldFont.getSize()));
        Rectangle2D bounds = g.getFontMetrics().getStringBounds(headerText, g);
        g.drawString(headerText, (int)(shape.getBounds().getX() + (shape.getBounds().getWidth()-bounds.getWidth())/2),
    (int)(shape.getBounds().getY() + (shape.getBounds().getHeight()+bounds.getHeight())/2));
        g.setFont(oldFont);
  }

    /**
     * Sets up the position of ports
     */
    protected void setPortPositions() {
        // inputs
        List<? extends Port> inputPorts = getNode().getInputPorts();
        for (int i = 0; i < inputPorts.size(); i++) {
            Port port = inputPorts.get(i);
            Point offset = new Point(PortGUI.DATA_PORT_SIZE / 2, this.headHeight + PORT_INITIAL_GAP + PORT_GAP * i);
            NodeController.getGUI(port).setOffset(offset);
        }

        // outputs
        List<? extends Port> outputPorts = getNode().getOutputPorts();
        for (int i = 0; i < outputPorts.size(); i++) {
            Port port = outputPorts.get(i);
            // Use getBounds() instead of this.dimension because subclass might
            // overwrite getBounds() to have different shape.
            Point offset = new Point(this.getBounds().width - PortGUI.DATA_PORT_SIZE / 2, this.headHeight
                    + PORT_INITIAL_GAP + PORT_GAP * i);
            NodeController.getGUI(port).setOffset(offset);
        }

        // control-in
        Port controlInPort = getNode().getControlInPort();
        if (controlInPort != null) {
          NodeController.getGUI(controlInPort).setOffset(new Point(0, 0));
        }

        // control-outs
        for (Port controlOutPort : getNode().getControlOutPorts()) {
            // By default, all ports will be drawn at the same place. Subclass
            // should rearrange them if there are more than one control-out
            // ports.
          NodeController.getGUI(controlOutPort).setOffset(new Point(getBounds().width, getBounds().height));
        }
    }

    /**
     * @param workflowName
     * @param state
     */
    public void setToken(String workflowName, NodeState state) {
        List<DataPort> inputPorts = getNode().getInputPorts();
        switch (state) {
        case EXECUTING:

            for (DataPort dataPort : inputPorts) {
              NodeController.getGUI(((DataPort) dataPort.getFromPort())).removeToken(workflowName);
              NodeController.getGUI(dataPort).addToken(workflowName);
            }
            break;
        case FINISHED:
            for (DataPort dataPort : inputPorts) {
              NodeController.getGUI(dataPort).removeToken(workflowName);
            }

            List<DataPort> outputPorts = getNode().getOutputPorts();
            for (DataPort dataPort : outputPorts) {
              NodeController.getGUI(dataPort).addToken(workflowName);
            }
            break;
        case FAILED:

            break;

        }

    }

    /**
   *
   */
    public void resetTokens() {

        List<DataPort> inputPorts = getNode().getInputPorts();
        for (DataPort dataPort : inputPorts) {
            NodeController.getGUI(dataPort).reset();
        }
        List<DataPort> outputPorts = getNode().getOutputPorts();
        for (DataPort dataPort : outputPorts) {
            NodeController.getGUI(dataPort).reset();
        }
    }
   
    protected Color getEndColor(Color bodyColor){
      return Color.white;
    }
   
    @Override
    public void nodeUpdated(NodeUpdateType type) {
      switch(type){
      case STATE_CHANGED:
        updateNodeColor();
        break;
    default:
      break;
      }
     
    }

  private void updateNodeColor() {
    switch(node.getState()){
    case WAITING:
      setBodyColor(NodeState.DEFAULT.color); break;
    case EXECUTING:
      setBodyColor(NodeState.EXECUTING.color); break;
    case FAILED:
      setBodyColor(NodeState.FAILED.color); break;
    case FINISHED:
      setBodyColor(NodeState.FINISHED.color); break;
    }
  }
}
TOP

Related Classes of org.apache.airavata.xbaya.ui.graph.NodeGUI

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.