/*- * @(#)ExtendedJBorder.java * * Copyright: Yokogawa, All rights reserved. * YOKOGAWA PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * Author: C. Horevoorts * * ---------------------------------------------------------------------------- * Changes .... * ---------------------------------------------------------------------------- * Who When Change What * ---------------------------------------------------------------------------- * HVS Feb-08 e9435 First version documented * BNL Apr-09 i10199 Correct hit detection for border top, bottom and text * BNL Mar-11 e10468 732 Correct hit detection for empty border with text * HVS Jun-20 e12272 Port to JViews 2017.2 * */ package fasttools.jwui.ilv.graphic; import fasttools.jwui.common.property.JBorderType; import fasttools.jwui.ilv.swing.INonRectangularJComponent; import fasttools.jwui.ilv.swing.IJComponentTagger; import ilog.views.IlvPoint; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.LineBorder; import javax.swing.border.TitledBorder; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** * Extends the ExtendedJBorder to be usable in the {@link ExtendedJComponent} container. */ public class ExtendedJBorder extends JPanel implements IJComponentTagger, INonRectangularJComponent { private String cLabel = ""; private Border cBorder = JBorderType.NATIVE_BORDER; public ExtendedJBorder() { setOpaque(false); setBorder(cBorder); } /** * Sets the label. * * @param label The label */ public void setLabelText(String label) { if (label == null) { label = ""; } if (!cLabel.equals(label)) { cLabel = label; createBorder(); } } /** * Returns the label. * * @return The label */ public String getLabelText() { return cLabel; } /** * Sets the border type. * * @param borderType The border type */ public void setBorderType(JBorderType borderType) { Border mBorder = borderType.getBorder(); if (mBorder != cBorder) { cBorder = mBorder; createBorder(); } } /** * Returns the border type. * * @return The border type */ public JBorderType getBorderType() { return new JBorderType(cBorder); } /** * Override to update the border. * * @param color The color */ public void setForeground(Color color) { super.setForeground(color); createBorder(); } /** * Override to update the border. * * @param font The font */ public void setFont(Font font) { super.setFont(font); createBorder(); } /** * Recreate the border. */ private void createBorder() { if (cLabel != null) { Border mBorder = cBorder; if (mBorder instanceof LineBorder) { mBorder = new LineBorder(getForeground()); } if (cLabel.length() > 0) { mBorder = new TitledBorder(mBorder, cLabel, TitledBorder.LEADING, TitledBorder.TOP, getFont(), getForeground()); } setBorder(mBorder); } } public boolean contains(Point2D p, AffineTransform t, GraphicHelper graphicHelper, float zoomFactor, boolean zoomEnabled) { // TODO: Shearing is not taken into consideration, so sheared borders won't hit-detect correctly. Shape mShape = graphicHelper.getShape(); if (isOpaque()) { return mShape.contains(p); } if (!mShape.contains(p)) { return false; } Point2D mTopLeft = graphicHelper.getXYNull(); Point2D mTopRight = graphicHelper.getXYWidth(); double mRotation = GraphicHelper.getRotationAngleInDegrees((IlvPoint) mTopLeft, (IlvPoint) mTopRight); String mLabel = getLabelText(); if (mLabel != null && !mLabel.equals("")) { Graphics2D g = (Graphics2D) getGraphics(); FontRenderContext mFontRenderingContext = g.getFontRenderContext(); Font mFont = getFont(); TextLayout mActualText = new TextLayout(mLabel, mFont, mFontRenderingContext); TextLayout mHeightText = new TextLayout("abcdefghijklmnopqrstuvwxyz", mFont, mFontRenderingContext); Rectangle2D mBounds = mActualText.getBounds(); Rectangle2D mHeightBounds = mHeightText.getBounds(); double mZoomFactor = zoomFactor / (zoomEnabled ? 1.0 : t.getScaleX()); double mTextHeight = mHeightBounds.getHeight() * mZoomFactor; // NOTE: The width in mBounds is too long for reasons that I've given up trying to figure out. Multiplying by 0.75 gives us a value that's good enough for now. double mTextWidth = mBounds.getWidth() * mZoomFactor * 0.75; double mLeftInset = 5.0 * mZoomFactor; Point2D mTextTopLeft = getPointFrom((IlvPoint) mTopLeft, mLeftInset, mRotation); Point2D mTextTopRight = getPointFrom((IlvPoint) mTextTopLeft, mTextWidth, mRotation); Point2D mTextBottomLeft = getPointFrom((IlvPoint) mTextTopLeft, mTextHeight, mRotation + 90.0); Point2D mTextBottomRight = getPointFrom((IlvPoint) mTextBottomLeft, mTextWidth, mRotation); Path2D.Double mTextShapeRectangle = new Path2D.Double(Path2D.WIND_NON_ZERO, 4); mTextShapeRectangle.moveTo(mTextTopLeft.getX(), mTextTopLeft.getY()); mTextShapeRectangle.lineTo(mTextTopRight.getX(), mTextTopRight.getY()); mTextShapeRectangle.lineTo(mTextBottomRight.getX(), mTextBottomRight.getY()); mTextShapeRectangle.lineTo(mTextBottomLeft.getX(), mTextBottomLeft.getY()); if (mTextShapeRectangle.contains(p)) { return true; } } if (!getBorderType().equals(new JBorderType(JBorderType.EMPTY))) { double mBorderWidth = 6.0 * zoomFactor; if (!zoomEnabled && t != null) { mBorderWidth /= t.getScaleX(); } Point2D mBottomLeft = graphicHelper.getXYHeight(); Point2D mBottomRight = graphicHelper.getXYWidthHeight(); mTopLeft = getPointFrom((IlvPoint) mTopLeft, mBorderWidth, mRotation + 45.0); mTopRight = getPointFrom((IlvPoint) mTopRight, mBorderWidth, mRotation + 135.0); mBottomRight = getPointFrom((IlvPoint) mBottomRight, mBorderWidth, mRotation + 225.0); mBottomLeft = getPointFrom((IlvPoint) mBottomLeft, mBorderWidth, mRotation + 315.0); Path2D.Double mInsideShape = new Path2D.Double(Path2D.WIND_NON_ZERO, 4); mInsideShape.moveTo(mTopLeft.getX(), mTopLeft.getY()); mInsideShape.lineTo(mTopRight.getX(), mTopRight.getY()); mInsideShape.lineTo(mBottomRight.getX(), mBottomRight.getY()); mInsideShape.lineTo(mBottomLeft.getX(), mBottomLeft.getY()); if (!mInsideShape.contains(p)) { return true; } } return false; } private Point2D getPointFrom(IlvPoint point, double distance, double angle) { IlvPoint mMidPoint = GraphicHelper.getPointRotatedFrom(point, angle - 45.0, distance); return GraphicHelper.getPointRotatedFrom(mMidPoint, angle + 45.0, distance); } }