package jmathlib.core.graphics.axes; import java.awt.*; import jmathlib.core.interpreter.ErrorLogger; import jmathlib.core.graphics.*; import jmathlib.core.graphics.properties.*; import jmathlib.core.graphics.axes.coreObjects.*; /** created and holds the axes of a plot*/ public class AxesObject extends FigureObject implements PropertyListener { protected class AxesComponent extends Component { private AxesObject parent; AxesComponent(AxesObject parent) { this.parent = parent; } public Dimension getPreferredSize() { return getMinimumSize(); } public Dimension getMinimumSize() { return parent.getMinimumSize(); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { parent.paint(g); } } // size of component; protected int dyFrame = 400; protected int dxFrame = 400; /**title of this axis*/ protected TextObject title = null; /**double-buffering data*/ protected Image backBuffer; protected Graphics backGC = null; protected Dimension backSize; protected boolean backEnabled = true; /**internal component*/ protected AxesComponent component; /**axes properties*/ public RadioProperty ActivePositionPropertyP = new RadioProperty(this, "ActivePositionProperty", new String[] {"outerposition", "position"}, "outerposition"); public DoubleStructProperty ALimP = new DoubleStructProperty(this, "ALim", new String[] {"x","y"}, new double[] {-1 , 1}); public RadioProperty ALimModeP = new RadioProperty(this, "ALimMode", new String[] {"auto", "manual"}, "auto"); public ColorProperty AmbientLightColorP = new ColorProperty(this, "AmbientLightColor", Color.white); public BooleanProperty BoxP = new BooleanProperty(this, "Box", true); public DoubleVectorProperty CameraPositionP = new DoubleVectorProperty(this, "CameraPosition", new double[3], 3); public RadioProperty CameraPositionModeP = new RadioProperty(this, "CameraPositionMode", new String[] {"auto", "manual"}, "auto"); public DoubleVectorProperty CameraTargetP = new DoubleVectorProperty(this, "CameraTarget", new double[3], 3); public RadioProperty CameraTargetModeP = new RadioProperty(this, "CameraTargetMode", new String[] {"auto", "manual"}, "auto"); public DoubleVectorProperty CameraUpVectorP = new DoubleVectorProperty(this, "CameraUpVector", new double[3], 3); public RadioProperty CameraUpVectorModeP = new RadioProperty(this, "CameraUpVectorMode", new String[] {"auto", "manual"}, "auto"); public DoubleProperty CameraViewAngleP = new DoubleProperty(this, "CameraViewAngle", 1.0); public RadioProperty CameraViewAngleModeP = new RadioProperty(this, "CameraViewAngleMode", new String[] {"auto", "manual"}, "auto"); public HandleObjectListProperty ChildrenP = new HandleObjectListProperty(this, "Children", -1); public DoubleVectorProperty CLimP = new DoubleVectorProperty(this, "CLim", new double[] {0.0, 1.0}, 2); public RadioProperty CLimModeP = new RadioProperty(this, "CLimMode", new String[] {"auto", "manual"}, "auto"); public ColorProperty ColorP = new ColorProperty(this, "Color", Color.white); public ColormapProperty ColorOrderP = new ColormapProperty(this, "Colormap"); public DoubleVectorProperty CurrentPointP = new DoubleVectorProperty(this, "CurrentPoint", new double[2], 2); public DoubleVectorProperty DataAspectRatioP = new DoubleVectorProperty(this, "DataAspectRatio", new double[3], 3); public RadioProperty DataAspectRatioModeP = new RadioProperty(this, "DataAspectRatioMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty DrawModeP = new RadioProperty(this, "DrawMode", new String[] {"normal", "fast"}, "normal"); public RadioProperty FontAngleP = new RadioProperty(this, "FontAngle", new String[] {"normal", "italic", "oblique"}, "normal"); public StringProperty FontNameP = new StringProperty(this, "FontName", ""); public IntegerProperty FontSizeP = new IntegerProperty(this, "FontSize", 12); public RadioProperty FontUnitsP = new RadioProperty(this, "FontUnits", new String[] {"points", "normalized", "inches", "centimeters", "pixels"}, "points"); public RadioProperty FontWeightP = new RadioProperty(this, "FontWeight", new String[] {"normal", "bold", "light", "demi"}, "normal"); public RadioProperty GridLineStyleP = new RadioProperty(this, "GridLineStyle", new String[] {"-", "- -", ":", "-.", "none"}, "-"); public RadioProperty LayerP = new RadioProperty(this, "Layer", new String[] {"bottom", "top"}, "bottom"); // LineStyleOrder needs LineSpec-Property public DoubleProperty LineWidthP = new DoubleProperty(this, "LineWidth", 1.0); public RadioProperty MinorGridLineStyleP = new RadioProperty(this, "MinorGridLineStyle", new String[] {"-", "- -", ":", "-.", "none"}, "-"); public DoubleVectorProperty OuterPositionP = new DoubleVectorProperty(this, "OuterPosition", new double[3], 3); public DoubleVectorProperty PlotBoxAspectRatioP = new DoubleVectorProperty(this, "PlotBoxAspectRatio", new double[3], 3); public RadioProperty PlotBoxAspectRatioModeP = new RadioProperty(this, "PlotBoxAspectRatioMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty ProjectionP = new RadioProperty(this, "Projection", new String[] {"orthographic", "perspective"}, "orthographic"); public RadioProperty TickDirP = new RadioProperty(this, "TickDir", new String[] {"in", "out"}, "in"); public RadioProperty TickDirModeP = new RadioProperty(this, "TickDirMode", new String[] {"auto", "manual"}, "auto"); public DoubleVectorProperty TickLengthP = new DoubleVectorProperty(this, "TickLength", new double[2], 2); public DoubleVectorProperty TightInsetP = new DoubleVectorProperty(this, "TightInset", new double[4], 4); public StringProperty TitleP = new StringProperty(this, "Title", ""); // UIContextMenuP // UserDataP public RadioProperty XAxisLocationP = new RadioProperty(this, "XAxisLocation", new String[] {"top", "bottom"}, "bottom"); public RadioProperty YAxisLocationP = new RadioProperty(this, "YAxisLocation", new String[] {"left", "right"}, "left"); public RadioProperty ZAxisLocationP = new RadioProperty(this, "ZAxisLocation", new String[] {"left", "right"}, "left"); public ColorProperty XColorP = new ColorProperty(this, "XColor", Color.black); public ColorProperty YColorP = new ColorProperty(this, "YColor", Color.black); public ColorProperty ZColorP = new ColorProperty(this, "ZColor", Color.black); public RadioProperty XDirP = new RadioProperty(this, "XDir", new String[] {"normal", "reverse"}, "normal"); public RadioProperty YDirP = new RadioProperty(this, "YDir", new String[] {"normal", "reverse"}, "normal"); public RadioProperty ZDirP = new RadioProperty(this, "ZDir", new String[] {"normal", "reverse"}, "normal"); public BooleanProperty XGridP = new BooleanProperty(this, "XGrid", false); public BooleanProperty YGridP = new BooleanProperty(this, "YGrid", false); public BooleanProperty ZGridP = new BooleanProperty(this, "ZGrid", false); public TextObject xLabel = null; public TextObject yLabel = null; public TextObject zLabel = null; public DoubleVectorProperty XLimP = new DoubleVectorProperty(this, "XLim", new double[] {0.0, 1.0}, 2); public DoubleVectorProperty YLimP = new DoubleVectorProperty(this, "YLim", new double[] {0.0, 1.0}, 2); public DoubleVectorProperty ZLimP = new DoubleVectorProperty(this, "ZLim", new double[] {-0.5, 0.5}, 2); public RadioProperty XLimModeP = new RadioProperty(this, "XLimMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty YLimModeP = new RadioProperty(this, "YLimMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty ZLimModeP = new RadioProperty(this, "ZLimMode", new String[] {"auto", "manual"}, "auto"); public BooleanProperty XMinorGridP = new BooleanProperty(this, "XMinorGrid", false); public BooleanProperty YMinorGridP = new BooleanProperty(this, "YMinorGrid", false); public BooleanProperty ZMinorGridP = new BooleanProperty(this, "ZMinorGrid", false); public BooleanProperty XMinorTickP = new BooleanProperty(this, "XMinorTick", false); public BooleanProperty YMinorTickP = new BooleanProperty(this, "YMinorTick", false); public BooleanProperty ZMinorTickP = new BooleanProperty(this, "ZMinorTick", false); public RadioProperty XScaleP = new RadioProperty(this, "XScale", new String[] {"linear", "log"}, "linear"); public RadioProperty YScaleP = new RadioProperty(this, "YScale", new String[] {"linear", "log"}, "linear"); public RadioProperty ZScaleP = new RadioProperty(this, "ZScale", new String[] {"linear", "log"}, "linear"); public DoubleVectorProperty XTickP = new DoubleVectorProperty(this, "XTick", new double[0], -1); public DoubleVectorProperty YTickP = new DoubleVectorProperty(this, "YTick", new double[0], -1); public DoubleVectorProperty ZTickP = new DoubleVectorProperty(this, "ZTick", new double[0], -1); public StringArrayProperty XTickLabelP = new StringArrayProperty(this, "XTickLabel", new String[0]); public StringArrayProperty YTickLabelP = new StringArrayProperty(this, "YTickLabel", new String[0]); public StringArrayProperty ZTickLabelP = new StringArrayProperty(this, "ZTickLabel", new String[0]); public RadioProperty XTickModeP = new RadioProperty(this, "XTickMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty YTickModeP = new RadioProperty(this, "YTickMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty ZTickModeP = new RadioProperty(this, "ZTickMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty XTickLabelModeP = new RadioProperty(this, "XTickLabelMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty YTickLabelModeP = new RadioProperty(this, "YTickLabelMode", new String[] {"auto", "manual"}, "auto"); public RadioProperty ZTickLabelModeP = new RadioProperty(this, "ZTickLabelMode", new String[] {"auto", "manual"}, "auto"); public LineStyleProperty XGridStyleP = new LineStyleProperty(this, "XGridStyle", ":"); public LineStyleProperty YGridStyleP = new LineStyleProperty(this, "YGridStyle", ":"); public LineStyleProperty ZGridStyleP = new LineStyleProperty(this, "ZGridStyle", ":"); public AxesObject() { // set type to "axes" TypeP = new TypeProperty(this, "axes"); component = new AxesComponent(this); autoTick(); ActivePositionPropertyP.addPropertyListener(this); ALimP.addPropertyListener(this); ALimModeP.addPropertyListener(this); AmbientLightColorP.addPropertyListener(this); BoxP.addPropertyListener(this); CameraPositionP.addPropertyListener(this); CameraPositionModeP.addPropertyListener(this); CameraTargetP.addPropertyListener(this); CameraTargetModeP.addPropertyListener(this); CameraTargetModeP.addPropertyListener(this); CameraUpVectorModeP.addPropertyListener(this); CameraViewAngleP.addPropertyListener(this); CameraViewAngleModeP.addPropertyListener(this); ChildrenP.addPropertyListener(this); CLimP.addPropertyListener(this); CLimModeP.addPropertyListener(this); ColorP.addPropertyListener(this); ColorOrderP.addPropertyListener(this); CurrentPointP.addPropertyListener(this); DataAspectRatioP.addPropertyListener(this); DataAspectRatioModeP.addPropertyListener(this); DrawModeP.addPropertyListener(this); FontAngleP.addPropertyListener(this); FontNameP.addPropertyListener(this); FontUnitsP.addPropertyListener(this); FontSizeP.addPropertyListener(this); FontWeightP.addPropertyListener(this); GridLineStyleP.addPropertyListener(this); LayerP.addPropertyListener(this); LineWidthP.addPropertyListener(this); MinorGridLineStyleP.addPropertyListener(this); OuterPositionP.addPropertyListener(this); PlotBoxAspectRatioP.addPropertyListener(this); PlotBoxAspectRatioModeP.addPropertyListener(this); ProjectionP.addPropertyListener(this); TickDirP.addPropertyListener(this); TickDirModeP.addPropertyListener(this); TickLengthP.addPropertyListener(this); TightInsetP.addPropertyListener(this); TitleP.addPropertyListener(this); XAxisLocationP.addPropertyListener(this); YAxisLocationP.addPropertyListener(this); ZAxisLocationP.addPropertyListener(this); XColorP.addPropertyListener(this); YColorP.addPropertyListener(this); ZColorP.addPropertyListener(this); XDirP.addPropertyListener(this); YDirP.addPropertyListener(this); ZDirP.addPropertyListener(this); XGridP.addPropertyListener(this); YGridP.addPropertyListener(this); ZGridP.addPropertyListener(this); //XLabel.addPropertyListener(this); //YLabel.addPropertyListener(this); //ZLabel.addPropertyListener(this); XLimP.addPropertyListener(this); YLimP.addPropertyListener(this); ZLimP.addPropertyListener(this); XLimModeP.addPropertyListener(this); YLimModeP.addPropertyListener(this); ZLimModeP.addPropertyListener(this); XMinorGridP.addPropertyListener(this); YMinorGridP.addPropertyListener(this); ZMinorGridP.addPropertyListener(this); XMinorTickP.addPropertyListener(this); YMinorTickP.addPropertyListener(this); ZMinorTickP.addPropertyListener(this); XScaleP.addPropertyListener(this); YScaleP.addPropertyListener(this); ZScaleP.addPropertyListener(this); XTickP.addPropertyListener(this); YTickP.addPropertyListener(this); ZTickP.addPropertyListener(this); XTickLabelP.addPropertyListener(this); YTickLabelP.addPropertyListener(this); ZTickLabelP.addPropertyListener(this); XTickModeP.addPropertyListener(this); YTickModeP.addPropertyListener(this); ZTickModeP.addPropertyListener(this); XTickLabelModeP.addPropertyListener(this); YTickLabelModeP.addPropertyListener(this); ZTickLabelModeP.addPropertyListener(this); XGridStyleP.addPropertyListener(this); YGridStyleP.addPropertyListener(this); ZGridStyleP.addPropertyListener(this); } public Component getComponent() { return component; } private synchronized void newBackBuffer() { backBuffer = component.createImage(getSize().width, getSize().height); if (backGC != null) { backGC.dispose(); } if (backBuffer != null) backGC = backBuffer.getGraphics(); backSize = getSize(); } protected Graphics initBackBuffer(Graphics g) { if (backEnabled) { if (backGC == null) { backBuffer = component.createImage(getSize().width, getSize().height); backGC = backBuffer.getGraphics(); backSize = getSize(); } else if (!backSize.equals(getSize())) newBackBuffer(); backGC.setColor(component.getBackground()); backGC.fillRect(0, 0, getSize().width, getSize().height); return backGC; } else { //g.clearRect(0, 0, getSize().width, getSize().height); return g; } } protected void flushBackBuffer(Graphics g, Graphics backGC) { if (backEnabled) g.drawImage(backBuffer, 0, 0, component); } /** add a line to the current plot */ public void addLine(double[] _x, double[] _y) { addLine(_x, _y, "r", "-", "none"); } public void addLine(double[] _x, double[] _y, String color, String lineStyle, String marker) { if (NextPlotP.is("replace")) ChildrenP.removeAllElements(); if (lineStyle.equals(" ")) lineStyle = "-"; if (marker.equals(" ")) marker = "none"; LineObject line = new LineObject(_x, _y, color, lineStyle, marker); line.setParent(this); ChildrenP.addElement(line); autoScale(); repaint(); } /** add lines to the current plot */ public void addLines(double[] _x, double[][] _y, String color, String lineStyle, String marker) { if (NextPlotP.is("replace")) ChildrenP.removeAllElements(); if (lineStyle.equals(" ")) lineStyle = "-"; if (marker.equals(" ")) marker = "none"; for (int n=0; n<_y.length; n++) { LineObject line = new LineObject(_x, _y[n], color, lineStyle, marker); line.setParent(this); ChildrenP.addElement(line); } autoScale(); repaint(); } /** add a title to the current axes */ public void setTitle(String _title) { title = new TextObject(_title, TextObject.H_CENTER, TextObject.V_BOTTOM); } /** add text to the x-axis of this axes*/ public void setXLabel(String _xLabel) { xLabel = new TextObject(_xLabel, TextObject.H_CENTER, TextObject.V_TOP); } /** add text to the y-axis of this axes*/ public void setYLabel(String _yLabel) { yLabel = new TextObject(_yLabel, TextObject.H_CENTER, TextObject.V_BOTTOM); yLabel.setRotation(-90); } /** add text to the z-axis of this axes*/ public void setZLabel(String _zLabel) { zLabel = new TextObject(_zLabel, TextObject.H_CENTER, TextObject.V_BOTTOM); zLabel.setRotation(-90); } /** Indicate wether calls to addLine() will add lines or clear the axes before adding new lines */ public void setHold(boolean _holdSwitch) { NextPlotP.update(_holdSwitch ? "add" : "replace"); } public Dimension getMinimumSize() { //ErrorLogger.debugLine("AxesObject getMinimumSize"); return new Dimension(dyFrame,dyFrame); } public Dimension getSize() { return component.getSize(); } public void repaint() { component.repaint(); } public void setBackBuffer(boolean flag) { backEnabled = flag; } protected void autoScale() { autoScaleX(); autoScaleY(); autoScaleZ(); } protected void autoScaleX() { double xmin, xmax; if (XLimModeP.is("auto") && ChildrenP.size() > 0) { xmin = ((GraphicalObject)ChildrenP.elementAt(0)).getXMin(); xmax = ((GraphicalObject)ChildrenP.elementAt(0)).getXMax(); for (int i=1; i<ChildrenP.size(); i++) { double _xmin = ((GraphicalObject)ChildrenP.elementAt(i)).getXMin(); double _xmax = ((GraphicalObject)ChildrenP.elementAt(i)).getXMax(); if (_xmin < xmin) xmin = _xmin; if (_xmax > xmax) xmax = _xmax; } if (XScaleP.is("linear")) { // linear axis double dx = xmax-xmin; if (dx > 10) { xmin = Math.floor(xmin); xmax = Math.ceil(xmax); } else if (dx == 0) { xmin--; xmax++; } } else { // log axis if (xmax/xmin > 10) { xmin = Math.floor(xmin); xmax = Math.ceil(xmax); } else { // ???? xmin--; xmax++; } } XLimP.update(new double[] {xmin, xmax}); autoTickX(); } } protected void autoScaleY() { double ymin, ymax; if (YLimModeP.is("auto") && ChildrenP.size() > 0) { ymin = ((GraphicalObject)ChildrenP.elementAt(0)).getYMin(); ymax = ((GraphicalObject)ChildrenP.elementAt(0)).getYMax(); for (int i=1; i<ChildrenP.size(); i++) { double _ymin = ((GraphicalObject)ChildrenP.elementAt(i)).getYMin(); double _ymax = ((GraphicalObject)ChildrenP.elementAt(i)).getYMax(); if (_ymin < ymin) ymin = _ymin; if (_ymax > ymax) ymax = _ymax; } double dy = ymax-ymin; if (dy > 10) { // nice numbers on axis ymin = Math.floor(ymin); ymax = Math.ceil(ymax); } else if (dy == 0) { ymin--; ymax++; } YLimP.update(new double[] {ymin, ymax}); autoTickY(); } } protected void autoScaleZ() { double zmin, zmax; if (ZLimModeP.is("auto") && ChildrenP.size() > 0) { zmin = ((GraphicalObject)ChildrenP.elementAt(0)).getZMin(); zmax = ((GraphicalObject)ChildrenP.elementAt(0)).getZMax(); for (int i=1; i<ChildrenP.size(); i++) { double _zmin = ((GraphicalObject)ChildrenP.elementAt(i)).getZMin(); double _zmax = ((GraphicalObject)ChildrenP.elementAt(i)).getZMax(); if (_zmin < zmin) zmin = _zmin; if (_zmax > zmax) zmax = _zmax; } double dz = zmax-zmin; if (dz > 10) { zmin = Math.floor(zmin); zmax = Math.ceil(zmax); } else if (dz == 0) { zmin--; zmax++; } ZLimP.update(new double[] {zmin, zmax}); autoTickZ(); } } protected void autoTick() { autoTickX(); autoTickY(); autoTickZ(); } protected void autoTickX() { if (XTickModeP.is("auto")) { double xmin = XLimP.getArray()[0]; double xmax = XLimP.getArray()[1]; double[] ticks = new double[5]; for (int i=0; i<ticks.length; i++) ticks[i] = xmin + i * (xmax - xmin) / (ticks.length - 1); XTickP.update(ticks); } autoTickLabelX(); } protected void autoTickY() { if (YTickModeP.is("auto")) { double ymin = YLimP.getArray()[0]; double ymax = YLimP.getArray()[1]; double[] ticks = new double[5]; for (int i=0; i<ticks.length; i++) ticks[i] = ymin + i * (ymax - ymin) / (ticks.length - 1); YTickP.update(ticks); } autoTickLabelY(); } protected void autoTickZ() { if (ZTickModeP.is("auto")) { double zmin = ZLimP.getArray()[0]; double zmax = ZLimP.getArray()[1]; double[] ticks = new double[5]; for (int i=0; i<ticks.length; i++) ticks[i] = zmin + i * (zmax - zmin) / (ticks.length - 1); ZTickP.update(ticks); } autoTickLabelZ(); } protected void autoTickLabel() { autoTickLabelX(); autoTickLabelY(); autoTickLabelZ(); } protected void autoTickLabelX() { double[] ticks = XTickP.getArray(); String[] labels = new String[ticks.length]; for (int i=0; i<ticks.length; i++) { double val = ((double)Math.round(ticks[i]*100))/100; labels[i] = new Double(val).toString(); } XTickLabelP.update(labels); } protected void autoTickLabelY() { double[] ticks = YTickP.getArray(); String[] labels = new String[ticks.length]; for (int i=0; i<ticks.length; i++) { double val = ((double)Math.round(ticks[i]*100))/100; labels[i] = new Double(val).toString(); } YTickLabelP.update(labels); } protected void autoTickLabelZ() { double[] ticks = ZTickP.getArray(); String[] labels = new String[ticks.length]; for (int i=0; i<ticks.length; i++) { double val = ((double)Math.round(ticks[i]*100))/100; labels[i] = new Double(val).toString(); } ZTickLabelP.update(labels); } public void paint(Graphics _g) { ErrorLogger.debugLine("AxesObject: paint"); Graphics g = initBackBuffer(_g); Graphics2D g2d = (Graphics2D)g; //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); //System.out.println("width = "+this.getSize().width+" height = "+this.getSize().height); dyFrame = this.getSize().height; dxFrame = this.getSize().width; //ErrorLogger.debugLine("AxesObject dxFrame="+dxFrame+" dyFframe="+dyFrame); //ErrorLogger.debugLine("AxesObject getX="+this.getX()+" getY="+this.getY()); //ErrorLogger.debugLine("AxesObject getLocation.x="+this.getLocation().x); // size of curves int dyCurves = (int)(dyFrame*3/4); int dxCurves = (int)(dxFrame*3/4); // Origin of curves int dyOrig = (dyFrame-dyCurves)/2; int dxOrig = (dxFrame-dxCurves)/2; // fonts FontMetrics fM = g.getFontMetrics(); int sAscent = fM.getAscent(); int sDescent = fM.getDescent(); // Find range of x-axis and y-axis double xmin, xmax, ymin, ymax, dx, dy; // X axis xmin = XLimP.getArray()[0]; xmax = XLimP.getArray()[1]; dx = xmax-xmin; // Y axis ymin = YLimP.getArray()[0]; ymax = YLimP.getArray()[1]; dy = ymax-ymin; // add rectangle as background g.setColor( ((ColorProperty)getProperty("Color")).getColor() ); g.fillRect(dxOrig, dyOrig, dxCurves, dyCurves); Stroke normS = g2d.getStroke(); int yLabMinX = dxOrig; int xLabMinY = dyOrig+dxCurves; // X Grid double[] xticks = XTickP.getArray(); String[] xticklabels = XTickLabelP.getArray(); Stroke xS = XGridStyleP.getStroke(1); g2d.setColor(XColorP.getColor()); ErrorLogger.debugLine("doXGrid xticks.length " + xticks.length); for (int i=0; i<xticks.length; i++) { int xt = dxOrig + (int)((xticks[i] - xmin) / (xmax - xmin) * dxCurves); if (xt < dxOrig || xt > (dxFrame-dxOrig)) continue; // grid line if (XGridP.isSet() && !XGridStyleP.is("none")) { g2d.setStroke(xS); g.drawLine(xt, dyOrig, xt, dyOrig+dyCurves); g2d.setStroke(normS); } // tick mark g.drawLine(xt, dyOrig, xt, dyOrig+5); g.drawLine(xt, dyOrig+dyCurves, xt, dyOrig+dyCurves-5); // tick text if (i < xticklabels.length) { int sXWidth = fM.stringWidth(xticklabels[i]); g.drawString( xticklabels[i], xt-sXWidth/2, dyFrame-dyOrig+5+sAscent); } } // Y Grid double[] yticks = YTickP.getArray(); String[] yticklabels = YTickLabelP.getArray(); Stroke yS = YGridStyleP.getStroke(1); g2d.setColor(YColorP.getColor()); for (int i=0; i<yticks.length; i++) { int yt = dyFrame - dyOrig - (int)((yticks[i] - ymin) / (ymax - ymin) * dyCurves); if (yt < dyOrig || yt > (dyFrame-dyOrig)) continue; // grid line if (YGridP.isSet() && !YGridStyleP.is("none")) { g2d.setStroke(yS); g.drawLine(dxOrig, yt, dxOrig+dxCurves, yt); g2d.setStroke(normS); } // tick mark g.drawLine(dxOrig, yt, dxOrig+5, yt); g.drawLine(dxOrig+dxCurves, yt, dxOrig+dxCurves-5, yt); // tick text if (i < yticklabels.length) { int sYWidth = fM.stringWidth(yticklabels[i]); g.drawString( yticklabels[i], dxOrig - 5 - sYWidth, (int)(yt+(sAscent/2)) ); if (dxOrig-5-sYWidth < yLabMinX) yLabMinX = dxOrig-5-sYWidth; } } // draw borders if (BoxP.isSet()) { g.setColor(XColorP.getColor()); g.drawLine( dxOrig, dyOrig+dyCurves, dxOrig+dxCurves, dyOrig+dyCurves); g.drawLine( dxOrig, dyOrig, dxOrig+dxCurves, dyOrig); g.setColor(YColorP.getColor()); g.drawLine( dxOrig+dxCurves, dyOrig+dyCurves, dxOrig+dxCurves, dyOrig); g.drawLine( dxOrig, dyOrig, dxOrig, dyOrig+dyCurves); g.setColor(Color.black); } // Add title if (title != null) { title.setPlotArea(dxOrig+dxCurves/2, dyOrig-5, 0, 0); title.paint(g); } // Add label of x-axis if (xLabel != null) { xLabel.setPlotArea(dxOrig+dxCurves/2, dyFrame-dyOrig+5+sAscent+sDescent, 0, 0); xLabel.paint(g); } // Add label of y-axis if (yLabel != null) { yLabel.setPlotArea(yLabMinX-5, dyFrame/2, 0, 0); yLabel.paint(g); } // plot line objects Shape clip = g.getClip(); g.clipRect(dxOrig+1, dyOrig+1, dxCurves-1, dyCurves-1); for(int n = 0; n < ChildrenP.size(); n++) { ((LineObject)ChildrenP.elementAt(n)).setAxesBoundaries(xmin, xmax, ymin, ymax); ((LineObject)ChildrenP.elementAt(n)).setPlotArea(dxOrig,dyFrame-dyOrig,dxCurves,dyCurves); ((LineObject)ChildrenP.elementAt(n)).paint(g); } g.setClip(clip); flushBackBuffer(_g, g); } public void propertyChanged(Property p) { ErrorLogger.debugLine("Axesobject property changed: "+ p.getName()); if (p == XLimP) { XLimModeP.update("manual"); autoTickX(); } else if (p == YLimP) { YLimModeP.update("manual"); autoTickY(); } else if (p == ZLimP) { ZLimModeP.update("manual"); autoTickZ(); } else if (p == XLimModeP) { if (XLimModeP.is("auto")) autoScaleX(); } else if (p == YLimModeP) { if (YLimModeP.is("auto")) autoScaleY(); } else if (p == ZLimModeP) { if (ZLimModeP.is("auto")) autoScaleZ(); } else if (p == XTickP) XTickModeP.update("manual"); else if (p == YTickP) YTickModeP.update("manual"); else if (p == ZTickP) ZTickModeP.update("manual"); else if (p == XTickModeP) { if (XTickModeP.is("auto")) autoTickX(); } else if (p == YTickModeP) { if (YTickModeP.is("auto")) autoTickY(); } else if (p == ZTickModeP) { if (ZTickModeP.is("auto")) autoTickZ(); } else if (p == XTickLabelP) XTickLabelModeP.update("manual"); else if (p == YTickLabelP) YTickLabelModeP.update("manual"); else if (p == ZTickLabelP) ZTickLabelModeP.update("manual"); else if (p == XTickLabelModeP) { if (XTickLabelModeP.is("auto")) autoTickLabelX(); } else if (p == YTickLabelModeP) { if (YTickLabelModeP.is("auto")) autoTickLabelY(); } else if (p == ZTickLabelModeP) { if (ZTickLabelModeP.is("auto")) autoTickLabelZ(); } repaint(); } public void clearAxes() { ChildrenP.removeAllElements(); } }