001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2021, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * --------------- 028 * LineBorder.java 029 * --------------- 030 * (C) Copyright 2007-2021, by Christo Zietsman and Contributors. 031 * 032 * Original Author: Christo Zietsman; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 */ 036 037package org.jfree.chart.block; 038 039import java.awt.BasicStroke; 040import java.awt.Color; 041import java.awt.Graphics2D; 042import java.awt.Paint; 043import java.awt.RenderingHints; 044import java.awt.Stroke; 045import java.awt.geom.Line2D; 046import java.awt.geom.Rectangle2D; 047import java.io.IOException; 048import java.io.ObjectInputStream; 049import java.io.ObjectOutputStream; 050import java.io.Serializable; 051import java.util.Objects; 052import org.jfree.chart.ui.RectangleInsets; 053import org.jfree.chart.util.PaintUtils; 054import org.jfree.chart.util.Args; 055import org.jfree.chart.util.SerialUtils; 056 057/** 058 * A line border for any {@link AbstractBlock}. 059 */ 060public class LineBorder implements BlockFrame, Serializable { 061 062 /** For serialization. */ 063 static final long serialVersionUID = 4630356736707233924L; 064 065 /** The line color. */ 066 private transient Paint paint; 067 068 /** The line stroke. */ 069 private transient Stroke stroke; 070 071 /** The insets. */ 072 private RectangleInsets insets; 073 074 /** 075 * Creates a default border. 076 */ 077 public LineBorder() { 078 this(Color.BLACK, new BasicStroke(1.0f), new RectangleInsets(1.0, 1.0, 079 1.0, 1.0)); 080 } 081 082 /** 083 * Creates a new border with the specified color. 084 * 085 * @param paint the color ({@code null} not permitted). 086 * @param stroke the border stroke ({@code null} not permitted). 087 * @param insets the insets ({@code null} not permitted). 088 */ 089 public LineBorder(Paint paint, Stroke stroke, RectangleInsets insets) { 090 Args.nullNotPermitted(paint, "paint"); 091 Args.nullNotPermitted(stroke, "stroke"); 092 Args.nullNotPermitted(insets, "insets"); 093 this.paint = paint; 094 this.stroke = stroke; 095 this.insets = insets; 096 } 097 098 /** 099 * Returns the paint. 100 * 101 * @return The paint (never {@code null}). 102 */ 103 public Paint getPaint() { 104 return this.paint; 105 } 106 107 /** 108 * Returns the insets. 109 * 110 * @return The insets (never {@code null}). 111 */ 112 @Override 113 public RectangleInsets getInsets() { 114 return this.insets; 115 } 116 117 /** 118 * Returns the stroke. 119 * 120 * @return The stroke (never {@code null}). 121 */ 122 public Stroke getStroke() { 123 return this.stroke; 124 } 125 126 /** 127 * Draws the border by filling in the reserved space (in black). 128 * 129 * @param g2 the graphics device. 130 * @param area the area. 131 */ 132 @Override 133 public void draw(Graphics2D g2, Rectangle2D area) { 134 double w = area.getWidth(); 135 double h = area.getHeight(); 136 // if the area has zero height or width, we shouldn't draw anything 137 if (w <= 0.0 || h <= 0.0) { 138 return; 139 } 140 double t = this.insets.calculateTopInset(h); 141 double b = this.insets.calculateBottomInset(h); 142 double l = this.insets.calculateLeftInset(w); 143 double r = this.insets.calculateRightInset(w); 144 double x = area.getX(); 145 double y = area.getY(); 146 double x0 = x + l / 2.0; 147 double x1 = x + w - r / 2.0; 148 double y0 = y + h - b / 2.0; 149 double y1 = y + t / 2.0; 150 g2.setPaint(getPaint()); 151 g2.setStroke(getStroke()); 152 Object saved = g2.getRenderingHint(RenderingHints.KEY_STROKE_CONTROL); 153 g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, 154 RenderingHints.VALUE_STROKE_NORMALIZE); 155 Line2D line = new Line2D.Double(); 156 if (t > 0.0) { 157 line.setLine(x0, y1, x1, y1); 158 g2.draw(line); 159 } 160 if (b > 0.0) { 161 line.setLine(x0, y0, x1, y0); 162 g2.draw(line); 163 } 164 if (l > 0.0) { 165 line.setLine(x0, y0, x0, y1); 166 g2.draw(line); 167 } 168 if (r > 0.0) { 169 line.setLine(x1, y0, x1, y1); 170 g2.draw(line); 171 } 172 g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, saved); 173 } 174 175 /** 176 * Tests this border for equality with an arbitrary instance. 177 * 178 * @param obj the object ({@code null} permitted). 179 * 180 * @return A boolean. 181 */ 182 @Override 183 public boolean equals(Object obj) { 184 if (obj == this) { 185 return true; 186 } 187 if (!(obj instanceof LineBorder)) { 188 return false; 189 } 190 LineBorder that = (LineBorder) obj; 191 if (!PaintUtils.equal(this.paint, that.paint)) { 192 return false; 193 } 194 if (!Objects.equals(this.stroke, that.stroke)) { 195 return false; 196 } 197 if (!this.insets.equals(that.insets)) { 198 return false; 199 } 200 return true; 201 } 202 203 /** 204 * Provides serialization support. 205 * 206 * @param stream the output stream. 207 * 208 * @throws IOException if there is an I/O error. 209 */ 210 private void writeObject(ObjectOutputStream stream) throws IOException { 211 stream.defaultWriteObject(); 212 SerialUtils.writePaint(this.paint, stream); 213 SerialUtils.writeStroke(this.stroke, stream); 214 } 215 216 /** 217 * Provides serialization support. 218 * 219 * @param stream the input stream. 220 * 221 * @throws IOException if there is an I/O error. 222 * @throws ClassNotFoundException if there is a classpath problem. 223 */ 224 private void readObject(ObjectInputStream stream) 225 throws IOException, ClassNotFoundException { 226 stream.defaultReadObject(); 227 this.paint = SerialUtils.readPaint(stream); 228 this.stroke = SerialUtils.readStroke(stream); 229 } 230} 231 232