/************************************************************************** OmegaT - Computer Assisted Translation (CAT) tool with fuzzy matching, translation memory, keyword search, glossaries, and translation leveraging into updated projects. Copyright (C) 2015 Aaron Madlon-Kay Home page: http://www.omegat.org/ Support center: http://groups.yahoo.com/group/OmegaT/ This file is part of OmegaT. OmegaT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OmegaT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.omegat.util.gui; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Area; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import javax.swing.border.AbstractBorder; /** * @author Aaron Madlon-Kay */ @SuppressWarnings("serial") public class RoundedCornerBorder extends AbstractBorder { public static final int SIDE_TOP = 0; public static final int SIDE_LEFT = 1; public static final int SIDE_BOTTOM = 2; public static final int SIDE_RIGHT = 3; public static final int SIDE_ALL = 4; private final int radius; private final Color color; private final int side; private final int stroke; private final transient Stroke strokeObj; public RoundedCornerBorder() { this(-1, Color.GRAY, SIDE_ALL); } public RoundedCornerBorder(int radius, Color color, int side) { this(radius, color, side, 1); } public RoundedCornerBorder(int radius, Color color, int side, int stroke) { this.radius = radius; this.color = color; this.side = side; this.stroke = stroke; this.strokeObj = new BasicStroke(stroke); } @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setStroke(strokeObj); int r = radius == -1 ? height - stroke : radius; RoundRectangle2D roundRect = new RoundRectangle2D.Float(x, y, width - (stroke - 0.5f), height - stroke, r, r); Rectangle2D sharpRect = new Rectangle2D.Float(x, y, width, height); Area corners = new Area(sharpRect); corners.subtract(new Area(roundRect)); Color background = c.getParent() == null ? null : c.getParent().getBackground(); if (side == SIDE_ALL) { drawCorners(g2, background, corners, roundRect); g2.dispose(); return; } Shape initialClip = g2.getClip(); Rectangle2D roundedHalfClip; Shape line1; Shape line2; if (side == SIDE_TOP) { roundedHalfClip = new Rectangle2D.Float(x, y, width, height / 2); line1 = new Line2D.Float(x, y, x, y + height); line2 = new Line2D.Float(x + width - 0.5f, y, x + width - 0.5f, y + height); } else if (side == SIDE_LEFT) { roundedHalfClip = new Rectangle2D.Float(x, y, width / 2 + stroke, height); line1 = new Line2D.Float(x, y, x + width, y); line2 = new Line2D.Float(x, y + height - stroke, x + width, y + height - stroke); } else if (side == SIDE_BOTTOM) { roundedHalfClip = new Rectangle2D.Float(x, y + height / 2, width, height / 2 + stroke); line1 = new Line2D.Float(x, y, x, y + height); line2 = new Line2D.Float(x + width - (stroke - 0.5f), y, x + width - (stroke - 0.5f), y + height); } else if (side == SIDE_RIGHT) { roundedHalfClip = new Rectangle2D.Float(x + width / 2, y, width / 2 + stroke, height); line1 = new Line2D.Float(x, y, x + width, y); line2 = new Line2D.Float(x, y + height - stroke, x + width, y + height - stroke); } else { throw new IllegalArgumentException(); } g2.clip(roundedHalfClip); drawCorners(g2, background, corners, roundRect); Area inverseClip = new Area(sharpRect); inverseClip.subtract(new Area(roundedHalfClip)); g2.setClip(initialClip); g2.clip(inverseClip); g2.draw(line1); g2.draw(line2); g2.dispose(); } private void drawCorners(Graphics2D g2, Color background, Area corners, Shape shape) { if (background != null) { g2.setColor(background); g2.fill(corners); } g2.setColor(color); g2.draw(shape); } @Override public Insets getBorderInsets(Component c) { return new Insets(4, 8, 4, 8); } @Override public Insets getBorderInsets(Component c, Insets insets) { insets.set(4, 8, 4, 8); return insets; } }