private void applyCustomGraphics(
      final VisualProperty<?> vp, final CyCustomGraphics<CustomGraphicLayer> customGraphics) {
    Set<CustomGraphicLayer> dCustomGraphicsSet = cgMap.get(vp);

    if (dCustomGraphicsSet == null) dCustomGraphicsSet = new HashSet<CustomGraphicLayer>();

    for (final CustomGraphicLayer cg : dCustomGraphicsSet) removeCustomGraphic(cg);

    dCustomGraphicsSet.clear();

    if (customGraphics == null || customGraphics instanceof NullCustomGraphics) return;

    final List<CustomGraphicLayer> layers = customGraphics.getLayers(graphView, this);

    // No need to update
    if (layers == null || layers.size() == 0) return;

    // Check dependency. Sync size or not.
    final VisualProperty<Double> cgSizeVP = DVisualLexicon.getAssociatedCustomGraphicsSizeVP(vp);
    boolean sync = syncToNode();

    final VisualProperty<ObjectPosition> cgPositionVP =
        DVisualLexicon.getAssociatedCustomGraphicsPositionVP(vp);
    final ObjectPosition positionValue = getVisualProperty(cgPositionVP);
    final Double customSize = getVisualProperty(cgSizeVP);

    for (CustomGraphicLayer newCG : layers) {
      // Assume it's a Ding layer
      CustomGraphicLayer finalCG = newCG;

      if (sync) {
        // System.out.println("Synching size to "+this.getWidth()+"x"+this.getHeight());
        // Size is locked to node size.
        finalCG = syncSize(customGraphics, newCG, this.getWidth(), this.getHeight());
      } else if (customSize != null) {
        // System.out.println("Synching size to "+customSize);
        // Size should be set to customSize
        finalCG = syncSize(customGraphics, newCG, customSize, customSize);
      }
      finalCG = moveCustomGraphicsToNewPosition(finalCG, positionValue);

      addCustomGraphic(finalCG);
      dCustomGraphicsSet.add(finalCG);
    }

    cgMap.put(vp, dCustomGraphicsSet);
  }
  private CustomGraphicLayer syncSize(
      CyCustomGraphics<CustomGraphicLayer> graphics,
      final CustomGraphicLayer cg,
      double width,
      double height) {
    // final double nodeW = this.getWidth();
    // final double nodeH = this.getHeight();

    final Rectangle2D originalBounds = cg.getBounds2D();
    // If this is just a paint, getBounds2D will return null and
    // we can use our own width and height
    if (originalBounds == null) return cg;

    if (width == 0.0 || height == 0.0) return cg;

    final double cgW = originalBounds.getWidth();
    final double cgH = originalBounds.getHeight();

    // In case size is same, return the original.
    if (width == cgW && height == cgH) return cg;

    final AffineTransform scale;
    final float fit = graphics.getFitRatio();

    // Case 1: if custom graphic is a vector fit width and length
    if (cg instanceof PaintedShape || cg instanceof Cy2DGraphicLayer) {
      scale = AffineTransform.getScaleInstance(fit * width / cgW, fit * height / cgH);
    } else {
      double scaleW = width / cgW;
      double scaleH = height / cgH;
      // Case 2: node height value is larger than width
      if (scaleW >= scaleH) {
        scale = AffineTransform.getScaleInstance(fit * scaleH, fit * scaleH);
        // scale = AffineTransform.getScaleInstance(fit * (width / cgW) * (height / width), fit *
        // height / cgH);
      } else {
        scale = AffineTransform.getScaleInstance(fit * scaleW, fit * scaleW);
        // scale = AffineTransform.getScaleInstance(fit * (width / cgW) * (height / width), fit *
        // height / cgH);
      }
    }

    return cg.transform(scale);
  }
 private void printList() {
   for (CyCustomGraphics cg : graphics) {
     System.out.println(cg.getClass().getCanonicalName() + ": " + cg.getDisplayName());
   }
 }