⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 periodaxis.java

📁 java图形利器
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
        }
        else if (edge == RectangleEdge.TOP) {
            delta1 = this.labelInfo[band].getPadding().calculateBottomOutset(
                    fm.getHeight());   
        }
        state.moveCursor(delta1, edge);
        long axisMin = this.first.getFirstMillisecond(this.calendar);
        long axisMax = this.last.getLastMillisecond(this.calendar);
        g2.setFont(this.labelInfo[band].getLabelFont());
        g2.setPaint(this.labelInfo[band].getLabelPaint());

        // work out the number of periods to skip for labelling
        RegularTimePeriod p1 = this.labelInfo[band].createInstance(
                new Date(axisMin), this.timeZone);
        RegularTimePeriod p2 = this.labelInfo[band].createInstance(
                new Date(axisMax), this.timeZone);
        String label1 = this.labelInfo[band].getDateFormat().format(
                new Date(p1.getMiddleMillisecond(this.calendar)));
        String label2 = this.labelInfo[band].getDateFormat().format(
                new Date(p2.getMiddleMillisecond(this.calendar)));
        Rectangle2D b1 = TextUtilities.getTextBounds(label1, g2, 
                g2.getFontMetrics());
        Rectangle2D b2 = TextUtilities.getTextBounds(label2, g2, 
                g2.getFontMetrics());
        double w = Math.max(b1.getWidth(), b2.getWidth());
        long ww = Math.round(java2DToValue(dataArea.getX() + w + 5.0, 
                dataArea, edge)) - axisMin;
        long length = p1.getLastMillisecond(this.calendar) 
                      - p1.getFirstMillisecond(this.calendar);
        int periods = (int) (ww / length) + 1;
        
        RegularTimePeriod p = this.labelInfo[band].createInstance(
                new Date(axisMin), this.timeZone);
        Rectangle2D b = null;
        long lastXX = 0L;
        float y = (float) (state.getCursor());
        TextAnchor anchor = TextAnchor.TOP_CENTER;
        float yDelta = (float) b1.getHeight();
        if (edge == RectangleEdge.TOP) {
            anchor = TextAnchor.BOTTOM_CENTER;
            yDelta = -yDelta;
        }
        while (p.getFirstMillisecond(this.calendar) <= axisMax) {
            float x = (float) valueToJava2D(p.getMiddleMillisecond(
                    this.calendar), dataArea, edge);
            DateFormat df = this.labelInfo[band].getDateFormat();
            String label = df.format(new Date(p.getMiddleMillisecond(
                    this.calendar)));
            long first = p.getFirstMillisecond(this.calendar);
            long last = p.getLastMillisecond(this.calendar);
            if (last > axisMax) {
                // this is the last period, but it is only partially visible 
                // so check that the label will fit before displaying it...
                Rectangle2D bb = TextUtilities.getTextBounds(label, g2, 
                        g2.getFontMetrics());
                if ((x + bb.getWidth() / 2) > dataArea.getMaxX()) {
                    float xstart = (float) valueToJava2D(Math.max(first, 
                            axisMin), dataArea, edge);
                    if (bb.getWidth() < (dataArea.getMaxX() - xstart)) {
                        x = ((float) dataArea.getMaxX() + xstart) / 2.0f;   
                    }
                    else {
                        label = null;
                    }
                }
            }
            if (first < axisMin) {
                // this is the first period, but it is only partially visible 
                // so check that the label will fit before displaying it...
                Rectangle2D bb = TextUtilities.getTextBounds(label, g2, 
                        g2.getFontMetrics());
                if ((x - bb.getWidth() / 2) < dataArea.getX()) {
                    float xlast = (float) valueToJava2D(Math.min(last, 
                            axisMax), dataArea, edge);
                    if (bb.getWidth() < (xlast - dataArea.getX())) {
                        x = (xlast + (float) dataArea.getX()) / 2.0f;   
                    }
                    else {
                        label = null;
                    }
                }
                
            }
            if (label != null) {
                g2.setPaint(this.labelInfo[band].getLabelPaint());
                b = TextUtilities.drawAlignedString(label, g2, x, y, anchor);
            }
            if (lastXX > 0L) {
                if (this.labelInfo[band].getDrawDividers()) {
                    long nextXX = p.getFirstMillisecond(this.calendar);
                    long mid = (lastXX + nextXX) / 2;
                    float mid2d = (float) valueToJava2D(mid, dataArea, edge);
                    g2.setStroke(this.labelInfo[band].getDividerStroke());
                    g2.setPaint(this.labelInfo[band].getDividerPaint());
                    g2.draw(new Line2D.Float(mid2d, y, mid2d, y + yDelta));
                }
            }
            lastXX = last;
            for (int i = 0; i < periods; i++) {
                p = p.next();   
            }
        }
        double used = 0.0;
        if (b != null) {
            used = b.getHeight();
            // work out the trailing gap
            if (edge == RectangleEdge.BOTTOM) {
                used += this.labelInfo[band].getPadding().calculateBottomOutset(
                        fm.getHeight());   
            }
            else if (edge == RectangleEdge.TOP) {
                used += this.labelInfo[band].getPadding().calculateTopOutset(
                        fm.getHeight());   
            }
        }
        state.moveCursor(used, edge);        
        return state;    
    }

    /**
     * Calculates the positions of the ticks for the axis, storing the results
     * in the tick list (ready for drawing).
     *
     * @param g2  the graphics device.
     * @param state  the axis state.
     * @param dataArea  the area inside the axes.
     * @param edge  the edge on which the axis is located.
     * 
     * @return The list of ticks.
     */
    public List refreshTicks(Graphics2D g2, 
                             AxisState state,
                             Rectangle2D dataArea,
                             RectangleEdge edge) {
        return Collections.EMPTY_LIST;
    }
    
    /**
     * Converts a data value to a coordinate in Java2D space, assuming that the
     * axis runs along one edge of the specified dataArea.
     * <p>
     * Note that it is possible for the coordinate to fall outside the area.
     *
     * @param value  the data value.
     * @param area  the area for plotting the data.
     * @param edge  the edge along which the axis lies.
     *
     * @return The Java2D coordinate.
     */
    public double valueToJava2D(double value,
                                Rectangle2D area,
                                RectangleEdge edge) {
        
        double result = Double.NaN;
        double axisMin = this.first.getFirstMillisecond(this.calendar);
        double axisMax = this.last.getLastMillisecond(this.calendar);
        if (RectangleEdge.isTopOrBottom(edge)) {
            double minX = area.getX();
            double maxX = area.getMaxX();
            if (isInverted()) {
                result = maxX + ((value - axisMin) / (axisMax - axisMin)) 
                         * (minX - maxX);
            }
            else {
                result = minX + ((value - axisMin) / (axisMax - axisMin)) 
                         * (maxX - minX);
            }
        }
        else if (RectangleEdge.isLeftOrRight(edge)) {
            double minY = area.getMinY();
            double maxY = area.getMaxY();
            if (isInverted()) {
                result = minY + (((value - axisMin) / (axisMax - axisMin)) 
                         * (maxY - minY));
            }
            else {
                result = maxY - (((value - axisMin) / (axisMax - axisMin)) 
                         * (maxY - minY));
            }
        }
        return result;
        
    }

    /**
     * Converts a coordinate in Java2D space to the corresponding data value,
     * assuming that the axis runs along one edge of the specified dataArea.
     *
     * @param java2DValue  the coordinate in Java2D space.
     * @param area  the area in which the data is plotted.
     * @param edge  the edge along which the axis lies.
     *
     * @return The data value.
     */
    public double java2DToValue(double java2DValue,
                                Rectangle2D area,
                                RectangleEdge edge) {

        double result = Double.NaN;
        double min = 0.0;
        double max = 0.0;
        double axisMin = this.first.getFirstMillisecond(this.calendar);
        double axisMax = this.last.getLastMillisecond(this.calendar);
        if (RectangleEdge.isTopOrBottom(edge)) {
            min = area.getX();
            max = area.getMaxX();
        }
        else if (RectangleEdge.isLeftOrRight(edge)) {
            min = area.getMaxY();
            max = area.getY();
        }
        if (isInverted()) {
             result = axisMax - ((java2DValue - min) / (max - min) 
                      * (axisMax - axisMin));
        }
        else {
             result = axisMin + ((java2DValue - min) / (max - min) 
                      * (axisMax - axisMin));
        }
        return result;
    }

    /**
     * Rescales the axis to ensure that all data is visible.
     */
    protected void autoAdjustRange() {

        Plot plot = getPlot();
        if (plot == null) {
            return;  // no plot, no data
        }

        if (plot instanceof ValueAxisPlot) {
            ValueAxisPlot vap = (ValueAxisPlot) plot;

            Range r = vap.getDataRange(this);
            if (r == null) {
                r = getDefaultAutoRange();
            }
            
            long upper = Math.round(r.getUpperBound());
            long lower = Math.round(r.getLowerBound());
            this.first = createInstance(this.autoRangeTimePeriodClass, 
                    new Date(lower), this.timeZone);
            this.last = createInstance(this.autoRangeTimePeriodClass, 
                    new Date(upper), this.timeZone);
            setRange(r, false, false);
        }

    }
    
    /**
     * Tests the axis for equality with an arbitrary object.
     * 
     * @param obj  the object (<code>null</code> permitted).
     * 
     * @return A boolean.
     */
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;   
        }
        if (obj instanceof PeriodAxis && super.equals(obj)) {
            PeriodAxis that = (PeriodAxis) obj;
            if (!this.first.equals(that.first)) {
                return false;   
            }
            if (!this.last.equals(that.last)) {
                return false;   
            }
            if (!this.timeZone.equals(that.timeZone)) {
                return false;   
            }
            if (!this.autoRangeTimePeriodClass.equals(
                    that.autoRangeTimePeriodClass)) {
                return false;   
            }
            if (!(isMinorTickMarksVisible() 
                    == that.isMinorTickMarksVisible())) {
                return false;
            }
            if (!this.majorTickTimePeriodClass.equals(
                    that.majorTickTimePeriodClass)) {
                return false;
            }
            if (!this.minorTickTimePeriodClass.equals(
                    that.minorTickTimePeriodClass)) {
                return false;
            }
            if (!this.minorTickMarkPaint.equals(that.minorTickMarkPaint)) {
                return false;
            }
            if (!this.minorTickMarkStroke.equals(that.minorTickMarkStroke)) {
                return false;
            }
            if (!Arrays.equals(this.labelInfo, that.labelInfo)) {
                return false;   
            }
            return true;   
        }
        return false;
    }

    /**
     * Returns a hash code for this object.
     * 
     * @return A hash code.
     */
    public int hashCode() {
        if (getLabel() != null) {
            return getLabel().hashCode();
        }
        else {
            return 0;
        }
    }
    
    /**
     * Returns a clone of the axis.
     * 
     * @return A clone.
     * 
     * @throws CloneNotSupportedException  this class is cloneable, but 
     *         subclasses may not be.
     */
    public Object clone() throws CloneNotSupportedException {
        PeriodAxis clone = (PeriodAxis) super.clone();
        clone.timeZone = (TimeZone) this.timeZone.clone();
        clone.labelInfo = new PeriodAxisLabelInfo[this.labelInfo.length];
        for (int i = 0; i < this.labelInfo.length; i++) {
            clone.labelInfo[i] = this.labelInfo[i];  // copy across references 
                                                     // to immutable objs 
        }
        return clone;
    }
    
    /**
     * A utility method used to create a particular subclass of the 
     * {@link RegularTimePeriod} class that includes the specified millisecond, 
     * assuming the specified time zone.
     * 
     * @param periodClass  the class.
     * @param millisecond  the time.
     * @param zone  the time zone.
     * 
     * @return The time period.
     */
    private RegularTimePeriod createInstance(Class periodClass, 
                                             Date millisecond, TimeZone zone) {
        RegularTimePeriod result = null;
        try {
            Constructor c = periodClass.getDeclaredConstructor(new Class[] {
                    Date.class, TimeZone.class});
            result = (RegularTimePeriod) c.newInstance(new Object[] {
                    millisecond, zone});   
        }
        catch (Exception e) {
            // do nothing            
        }
        return result;
    }
    
    /**
     * Provides serialization support.
     *
     * @param stream  the output stream.
     *
     * @throws IOException  if there is an I/O error.
     */
    private void writeObject(ObjectOutputStream stream) throws IOException {
        stream.defaultWriteObject();
        SerialUtilities.writeStroke(this.minorTickMarkStroke, stream);
        SerialUtilities.writePaint(this.minorTickMarkPaint, stream);
    }

    /**
     * Provides serialization support.
     *
     * @param stream  the input stream.
     *
     * @throws IOException  if there is an I/O error.
     * @throws ClassNotFoundException  if there is a classpath problem.
     */
    private void readObject(ObjectInputStream stream) 
        throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        this.minorTickMarkStroke = SerialUtilities.readStroke(stream);
        this.minorTickMarkPaint = SerialUtilities.readPaint(stream);
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -