All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.visualization.renderers.BasicNodeLabelRenderer Maven / Gradle / Ivy

/*
 * Copyright (c) 2005, The JUNG Authors
 * All rights reserved.
 *
 * This software is open-source under the BSD license; see either "license.txt"
 * or https://github.com/jrtom/jung/blob/master/LICENSE for a description.
 *
 * Created on Aug 23, 2005
 */
package edu.uci.ics.jung.visualization.renderers;

import edu.uci.ics.jung.layout.model.LayoutModel;
import edu.uci.ics.jung.layout.model.Point;
import edu.uci.ics.jung.visualization.MultiLayerTransformer.Layer;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationModel;
import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer;
import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer;
import edu.uci.ics.jung.visualization.transform.shape.TransformingGraphics;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

public class BasicNodeLabelRenderer implements Renderer.NodeLabel {

  protected Position position = Position.SE;
  private Positioner positioner = new OutsidePositioner();

  /** @return the position */
  public Position getPosition() {
    return position;
  }

  /** @param position the position to set */
  public void setPosition(Position position) {
    this.position = position;
  }

  public Component prepareRenderer(
      RenderContext renderContext,
      LayoutModel layoutModel,
      NodeLabelRenderer graphLabelRenderer,
      Object value,
      boolean isSelected,
      N node) {
    return renderContext
        .getNodeLabelRenderer()
        .getNodeLabelRendererComponent(
            renderContext.getScreenDevice(),
            value,
            renderContext.getNodeFontFunction().apply(node),
            isSelected,
            node);
  }

  /**
   * Labels the specified node with the specified label. Uses the font specified by this instance's
   * NodeFontFunction. (If the font is unspecified, the existing font for the graphics
   * context is used.) If node label centering is active, the label is centered on the position of
   * the node; otherwise the label is offset slightly.
   */
  public void labelNode(
      RenderContext renderContext,
      VisualizationModel visualizationModel,
      N v,
      String label) {
    if (!renderContext.getNodeIncludePredicate().test(v)) {
      return;
    }
    LayoutModel layoutModel = visualizationModel.getLayoutModel();
    Point pt = layoutModel.apply(v);
    Point2D pt2d =
        renderContext
            .getMultiLayerTransformer()
            .transform(Layer.LAYOUT, new Point2D.Double(pt.x, pt.y));

    float x = (float) pt2d.getX();
    float y = (float) pt2d.getY();

    Component component =
        prepareRenderer(
            renderContext,
            layoutModel,
            renderContext.getNodeLabelRenderer(),
            label,
            renderContext.getPickedNodeState().isPicked(v),
            v);
    GraphicsDecorator g = renderContext.getGraphicsContext();
    Dimension d = component.getPreferredSize();
    AffineTransform xform = AffineTransform.getTranslateInstance(x, y);

    Shape shape = renderContext.getNodeShapeFunction().apply(v);
    shape = xform.createTransformedShape(shape);
    if (renderContext.getGraphicsContext() instanceof TransformingGraphics) {
      BidirectionalTransformer transformer =
          ((TransformingGraphics) renderContext.getGraphicsContext()).getTransformer();
      if (transformer instanceof ShapeTransformer) {
        ShapeTransformer shapeTransformer = (ShapeTransformer) transformer;
        shape = shapeTransformer.transform(shape);
      }
    }
    Rectangle2D bounds = shape.getBounds2D();

    Point p = null;
    if (position == Position.AUTO) {
      Dimension vvd = renderContext.getScreenDevice().getSize();
      if (vvd.width == 0 || vvd.height == 0) {
        vvd = renderContext.getScreenDevice().getPreferredSize();
      }
      p = getAnchorPoint(bounds, d, positioner.getPosition(x, y, vvd));
    } else {
      p = getAnchorPoint(bounds, d, position);
    }

    Paint fillPaint = renderContext.getNodeLabelDrawPaintFunction().apply(v);
    if (fillPaint != null) {
      Paint oldPaint = component.getForeground();
      component.setForeground((Color) fillPaint);
      g.draw(
          component,
          renderContext.getRendererPane(),
          (int) p.x,
          (int) p.y,
          d.width,
          d.height,
          true);
      component.setForeground((Color) oldPaint);
    } else {
      g.draw(
          component,
          renderContext.getRendererPane(),
          (int) p.x,
          (int) p.y,
          d.width,
          d.height,
          true);
    }
  }

  protected Point getAnchorPoint(Rectangle2D nodeBounds, Dimension labelSize, Position position) {
    double x;
    double y;
    int offset = 5;
    switch (position) {
      case N:
        x = nodeBounds.getCenterX() - labelSize.width / 2;
        y = nodeBounds.getMinY() - offset - labelSize.height;
        return Point.of(x, y);

      case NE:
        x = nodeBounds.getMaxX() + offset;
        y = nodeBounds.getMinY() - offset - labelSize.height;
        return Point.of(x, y);

      case E:
        x = nodeBounds.getMaxX() + offset;
        y = nodeBounds.getCenterY() - labelSize.height / 2;
        return Point.of(x, y);

      case SE:
        x = nodeBounds.getMaxX() + offset;
        y = nodeBounds.getMaxY() + offset;
        return Point.of(x, y);

      case S:
        x = nodeBounds.getCenterX() - labelSize.width / 2;
        y = nodeBounds.getMaxY() + offset;
        return Point.of(x, y);

      case SW:
        x = nodeBounds.getMinX() - offset - labelSize.width;
        y = nodeBounds.getMaxY() + offset;
        return Point.of(x, y);

      case W:
        x = nodeBounds.getMinX() - offset - labelSize.width;
        y = nodeBounds.getCenterY() - labelSize.height / 2;
        return Point.of(x, y);

      case NW:
        x = nodeBounds.getMinX() - offset - labelSize.width;
        y = nodeBounds.getMinY() - offset - labelSize.height;
        return Point.of(x, y);

      case CNTR:
        x = nodeBounds.getCenterX() - labelSize.width / 2;
        y = nodeBounds.getCenterY() - labelSize.height / 2;
        return Point.of(x, y);

      default:
        return Point.ORIGIN;
    }
  }

  public static class InsidePositioner implements Positioner {
    public Position getPosition(float x, float y, Dimension d) {
      int cx = d.width / 2;
      int cy = d.height / 2;
      if (x > cx && y > cy) {
        return Position.NW;
      }
      if (x > cx && y < cy) {
        return Position.SW;
      }
      if (x < cx && y > cy) {
        return Position.NE;
      }
      return Position.SE;
    }
  }

  public static class OutsidePositioner implements Positioner {
    public Position getPosition(float x, float y, Dimension d) {
      int cx = d.width / 2;
      int cy = d.height / 2;
      if (x > cx && y > cy) {
        return Position.SE;
      }
      if (x > cx && y < cy) {
        return Position.NE;
      }
      if (x < cx && y > cy) {
        return Position.SW;
      }
      return Position.NW;
    }
  }
  /** @return the positioner */
  public Positioner getPositioner() {
    return positioner;
  }

  /** @param positioner the positioner to set */
  public void setPositioner(Positioner positioner) {
    this.positioner = positioner;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy