Package org.timepedia.chronoscope.client.render

Source Code of org.timepedia.chronoscope.client.render.RangeAxisPanel

package org.timepedia.chronoscope.client.render;

import org.timepedia.chronoscope.client.Chart;
import org.timepedia.chronoscope.client.Cursor;
import org.timepedia.chronoscope.client.axis.RangeAxis;
import org.timepedia.chronoscope.client.canvas.Bounds;
import org.timepedia.chronoscope.client.canvas.Layer;
import org.timepedia.chronoscope.client.canvas.View;
import org.timepedia.chronoscope.client.gss.GssElement;
import org.timepedia.chronoscope.client.gss.GssProperties;
import org.timepedia.chronoscope.client.render.CompositeAxisPanel.Position;
import org.timepedia.chronoscope.client.util.MathUtil;

/**
* Renders a vertical range axis.
*/
public class RangeAxisPanel extends AxisPanel {

  public RangeAxisPanel() {
    new RuntimeException().printStackTrace();
  }

  public enum TickPosition {
    INSIDE, OUTSIDE;

    public static TickPosition is(String s) {
      try {
        return valueOf(s.trim().toUpperCase());
      } catch (Exception e) {
        return INSIDE;
      }
    }
    public String toString(){
        return name().toLowerCase();
    }
  }
  public enum TickAlignment {
    ABOVE, MIDDLE, BELOW;

    public static TickAlignment is(String s) {
      try {
        return valueOf(s.trim().toUpperCase());
      } catch (Exception e) {
        return ABOVE;
      }
    }
    public String toString(){
        return name().toLowerCase();
    }
  }

  private boolean boundsSet;
  private double axisLabelWidth, maxLabelWidth, maxLabelHeight;
  private double rotationAngle;
  private Bounds drawBounds = new Bounds();

  private GssProperties gridProperties, tickProperties;
  private RangeAxis rangeAxis;

  public void dispose() {
    super.dispose();
    gridProperties = null;
    tickProperties = null;
    rangeAxis = null;
  }

  public void remove(Panel panel) {
    return; // no sub panels
  }

  public void computeLabelWidths(View view) {
    log ("computeLabelWidths bounds "+bounds);
    if (null == layer) {
      layer = parent.getLayer();
    }

    final String valueAxisLabel = valueAxis.getLabel();
    // TODO - really walk the ticklabels and compute the max width
    layer.save();

    maxLabelWidth = StringSizer.getWidth(layer, getDummyLabel(), gssProperties)+1;
    maxLabelHeight = StringSizer.getHeight(layer, getDummyLabel(), gssProperties)+2;
    axisLabelWidth = StringSizer.getRotatedWidth(layer, valueAxisLabel, gssProperties, rotationAngle);

    layer.restore();
  }

  public void draw() {
    bounds.copyTo(drawBounds);
    log("draw bounds:"+bounds + " layerOffsetX:"+getLayerOffsetX() + " layerOffsetY:"+getLayerOffsetY());
    // drawBounds.x += getLayerOffsetX();
    // drawBounds.y += getLayerOffsetY();

    double tickPositions[] = rangeAxis.calcTickPositions();

    layer.save();

    if (!GRID_ONLY) {
      // layer.clear(); // (layer, drawBounds);
      drawLine(layer, drawBounds);
    }
    drawAxisLabel(layer, drawBounds, plot.getChart());

    layer.setTransparency((float)gssProperties.transparency);
    layer.setFillColor(gssProperties.bgColor);
    layer.setStrokeColor(gssProperties.color);

    final double axisInterval = valueAxis.getExtrema().length();
    for (int i = 0; i < tickPositions.length; i++) {
      drawTick(layer, tickPositions[i], tickPositions[0], axisInterval, drawBounds, GRID_ONLY);
    }

    layer.restore();
  }

//  public String formatLegendLabel(double value) {
//    return rangeAxis.getFormattedLabel(value);
//  }

  public double getMaxLabelHeight() {
    return maxLabelHeight;
  }

  public double getMaxLabelWidth() {
    return maxLabelWidth;
  }

  public String getType() {
    return "axis";
  }

  public String getTypeClass() {
    return "range a" + ((RangeAxis) valueAxis).getAxisIndex();
  }

  @Override
  public void layout() {
    computeLabelWidths(view);
    bounds.width = calcWidth();
    setBounds(bounds);
    // height not calculated -- it must be dictated by some external entity
  }

  @Override
  protected void initHook() {
    rangeAxis = (RangeAxis) this.valueAxis;
    GssElement tickGssElem = new GssElementImpl("tick", this);
    GssElement gridGssElem = new GssElementImpl("grid", this);
    tickProperties = view.getGssProperties(tickGssElem, "");
    gridProperties = view.getGssProperties(gridGssElem, "");

    if (getParentPosition() == Position.RIGHT) {
      rotationAngle = Math.PI / 2;
    } else {
      rotationAngle = -(Math.PI / 2);
    }
  }

  // TODO - not as variable as height, but axisLabelWidth is per axis, unlike maxLabelWidth
  private double calcWidth() {
    double w = 0.0;
    final double widthBuffer = 4;
    final double computedAxisLabelWidth = labelProperties.visible ?
        axisLabelWidth + widthBuffer : 0;

    boolean isLeft = getParentPosition() == Position.LEFT;
    if (isInnerMost(isLeft)) {
      if (getTickPosition() == RangeAxisPanel.TickPosition.INSIDE) {
        w = computedAxisLabelWidth;
      } else {
        w = maxLabelWidth + widthBuffer + computedAxisLabelWidth;
      }
    } else {
      w = maxLabelWidth + widthBuffer + computedAxisLabelWidth;
    }

    return w;
  }

/*
  private void clearAxis(Layer layer, Bounds bounds) {
    layer.save();
    if (!boundsSet) {
      layer.setTextLayerBounds(textLayerName, bounds);
      boundsSet = true;
    }
    layer.clearTextLayer(textLayerName);
    layer.setFillColor(gssProperties.bgColor);
    //layer.setShadowBlur(0);
    //layer.setShadowOffsetX(0);
    //layer.setShadowOffsetY(0);
    //layer.translate(bounds.x - 1, bounds.y - 1);
    // layer.scale(bounds.width + 1, bounds.height + 1);
    //layer.fillRect(0, 0, 1, 1);
    layer.restore();
  }
*/

  private void drawAxisLabel(Layer layer, Bounds bounds, Chart chart) {
    if (labelProperties.visible) {
      boolean isLeft = getParentPosition() == Position.LEFT;
      boolean isInnerMost = isInnerMost(isLeft);

      double x = isLeft ?
           (isInnerMost ? layer.getWidth() - axisLabelWidth : axisLabelWidth) + 5:
           (isInnerMost ? layer.getWidth() - axisLabelWidth : maxLabelWidth + 2) - 1;
      String label = valueAxis.getLabel();

      layer.save();
      int labelHeight = StringSizer.getRotatedHeight(layer, label, gssProperties, rotationAngle);
      // double y = bounds.y + ((bounds.height - maxLabelHeight) / 2) + (labelHeight / 2);
      double y = ((bounds.height - maxLabelHeight) / 2) + (labelHeight / 2);
      layer.setStrokeColor(labelProperties.color);

      layer.drawRotatedText(x, y, rotationAngle, label, gssProperties.fontFamily,
              gssProperties.fontWeight, gssProperties.fontSize, textLayerName, chart);
      layer.restore();
    }
  }

  private void drawLabel(Layer layer, double y, Bounds bounds, double value) {
    log(layer.getLayerId()+" drawLabel "+value +" "+bounds);
    String label = rangeAxis.getFormattedLabel(value);
//    double labelWidth = layer.stringWidth(label,
//            gssProperties.fontFamily, gssProperties.fontWeight, gssProperties.fontSize);
//    double labelHeight = layer.stringHeight(label,
//            gssProperties.fontFamily, gssProperties.fontWeight, gssProperties.fontSize);
    boolean isLeft = getParentPosition() == Position.LEFT;
    double dir = (isLeft ? -5 - maxLabelWidth : 5 - bounds.width);
    if (TickPosition.INSIDE == TickPosition.is(gssProperties.tickPosition)) {
      dir = isLeft ? 5 : -maxLabelWidth - 5;
    }
    double alignAdjust = Math.floor(-maxLabelHeight / 2.0);
    if (TickAlignment.ABOVE == TickAlignment.is(labelProperties.tickAlign)) {
      // alignAdjust = -maxLabelHeight;
      alignAdjust = -2;
      dir = 1;

      if (isInnerMost(isLeft)) {
        layer = plot.getPlotRangeLayer();
        layer.setFillColor(getTickProps(tickProperties).color);
        layer.setTransparency(1);
        dir = isLeft ? -bounds.width + 1 :  - maxLabelWidth + 1;
        drawLabelText(layer, bounds.width + dir, y + alignAdjust, label);
      } else {
        dir = isLeft ? (-maxLabelWidth + 2)
            : (-maxLabelWidth - axisLabelWidth - 10);
        drawLabelText(layer, bounds.width + dir, y + alignAdjust, label);
      }
    }
/*
    log(layer.getLayerId() + layer.getBounds()+"drawText isBounded("+y+", "+0+", "+bounds.height);
    if (MathUtil.isBounded(y, 0, bounds.height)) {
      // layer.drawText(bounds.rightX() + dir, y + alignAdjust, label,
      drawLabelText(layer, bounds.width + dir, y + alignAdjust, label);

    } else {
      log (layer.getLayerId() + layer.getBounds()+"drawText not bounded("+y+", "+0+", "+bounds.height);
    }
*/


  }


  private void drawLabelText(Layer layer, double x, double y, String text) {
    log(layer.getLayerId() + " drawLabelText "+x+", "+ y + " " + text);
    layer.save();
    // layer.setTransparency(1);
    layer.setStrokeColor(getTickProps(labelProperties).color);
    layer.setFillColor(labelProperties.bgColor);
    // layer.fillRect(bounds.rightX()+dir, y + alignAdjust,
    // bounds.rightX()+dir+labelWidth, y+alignAdjust+labelHeight);
    layer.drawText(x, y, text,
        gssProperties.fontFamily, gssProperties.fontWeight,
        gssProperties.fontSize, textLayerName, Cursor.CONTRASTED);

    layer.restore();
  }

  private void drawLine(Layer layer, Bounds bounds) {
    log(layer.getLayerId() + " drawLine "+ bounds);
    GssProperties tprop = getTickProps(tickProperties);
    log("drawLine setFill "+tprop.color);
    layer.setFillColor(tprop.color);
    boolean isLeft = getParentPosition() == Position.LEFT;
    double dir = (isLeft ? bounds.width : 0);
    if (TickPosition.INSIDE == TickPosition.is(gssProperties.tickPosition)) {
      if (isInnerMost(isLeft)) {
        dir = isLeft ? layer.getBounds().width - tickProperties.lineThickness : 0;
      } else {
        dir = isLeft ? bounds.width - maxLabelWidth-: layer.getBounds().width - maxLabelWidth - 21;
      }
    }
    // layer.fillRect(bounds.x + dir, maxLabelHeight, tickProperties.lineThickness, bounds.height-maxLabelHeight);
    layer.fillRect(dir, maxLabelHeight, tickProperties.lineThickness, bounds.height);
    }

  private GssProperties getTickProps(GssProperties defprop) {
    GssProperties tprop = defprop;
    if (false && !plot.isMultiaxis()) {
      int dIdx = plot.getFocus() != null ? plot.getFocus().getDatasetIndex()
          : -1;

      if (dIdx != -1) {
        GssProperties cprop = plot.getDatasetRenderer(dIdx).getCurveProperties()
            ;
        if (cprop != null) {
          tprop = cprop;
        }
      }
    }
    return tprop;
  }

  private void drawTick(Layer layer, double range, double rangeLow,
      double rangeInterval, Bounds bounds, boolean gridOnly) {

    // Determines the horizontal length (in pixels) of each range axis tick
    final int tickWidth = 5;
    double tickPixelHeight = ((range - rangeLow) / rangeInterval) * (bounds.height);
    // double uy = Math.round(bounds.y + maxLabelHeight + (bounds.height - tickPixelHeight));
    double uy = Math.min( bounds.height -1, Math.round(maxLabelHeight + (bounds.height - tickPixelHeight)));

    boolean isLeft = getParentPosition() == Position.LEFT;
    double dir = (isLeft ? (bounds.width - tickWidth) : 0);
    if (TickPosition.INSIDE == TickPosition.is(gssProperties.tickPosition)) {
      if (isInnerMost(isLeft)) {
        // if INSIDE the plot then use plotAxesLayer instead of the axis layer (outside plot area)
        layer = plot.getPlotRangeLayer();
        bounds = layer.getBounds();
        // dir = isLeft ? (bounds.width + 1) : -tickWidth;
        dir = isLeft ? 0 : bounds.width - tickWidth;
      } else {
        dir = isLeft ? (bounds.width - maxLabelWidth - 1)
            : (maxLabelWidth + tickWidth + 1);
      }
    }
    layer.setFillColor(getTickProps(tickProperties).color);
    layer.setTransparency(1);

    layer.save();
    layer.setFillColor(getTickProps(tickProperties).color);
    layer.setTransparency(1);
    if (!gridOnly) {
      drawLabel(layer, uy, bounds, range);
    }
    layer.restore();

    // double ux = Math.round(bounds.x + dir);
    double ux = dir;
    log(layer.getLayerId() + " fillRect "+ux + ", "+uy+", "+tickWidth+", "+tickProperties.lineThickness);
    layer.fillRect(ux, uy, tickWidth, tickProperties.lineThickness);
    if (gridProperties.visible && uy != bounds.height) {
      Layer gridlayer = plot.getOverlayLayer(); // TODO - should be background
      gridlayer.save();
      gridlayer.setFillColor(gridProperties.color);
      gridlayer.setTransparency((float) gridProperties.transparency);
      gridlayer.fillRect(0, uy, gridlayer.getBounds().width, gridProperties.lineThickness);
      gridlayer.restore();
    }
  }

  private String getDummyLabel() {
    int maxDig = RangeAxis.MAX_DIGITS;
    return "0" + ((maxDig == 1) ? "" : "." + "000000000".substring(0, maxDig - 1));
  }

  private TickPosition getTickPosition() {
      return TickPosition.is(gssProperties.tickPosition);
  }

  private TickAlignment getTickAlignment() {
      return TickAlignment.is(gssProperties.tickAlign);
  }

  private boolean isInnerMost(boolean isLeftPanel) {
    CompositeAxisPanel parentContainer = (CompositeAxisPanel) this.parent;

    return parentContainer.indexOf(this) == (isLeftPanel ?
        parentContainer.getChildCount() - 1 : 0);
  }

  private Position getParentPosition() {
    return ((CompositeAxisPanel) parent).getPosition();
  }


  private static void log(Object msg) {
    System.out.println("RangeAxisPanel> " + msg);
  }
}
TOP

Related Classes of org.timepedia.chronoscope.client.render.RangeAxisPanel

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.