|
|
@ -16,7 +16,6 @@ import java.awt.geom.RoundRectangle2D; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class BubbleBorder extends AbstractBorder { |
|
|
|
public class BubbleBorder extends AbstractBorder { |
|
|
|
|
|
|
|
|
|
|
|
private final static double PAD_OFFSET = 0.2; |
|
|
|
|
|
|
|
private final Insets insets; |
|
|
|
private final Insets insets; |
|
|
|
private Alignment pointerSide = Alignment.NORTH; |
|
|
|
private Alignment pointerSide = Alignment.NORTH; |
|
|
|
private Color color; |
|
|
|
private Color color; |
|
|
@ -25,7 +24,6 @@ public class BubbleBorder extends AbstractBorder { |
|
|
|
private int pointerSize; |
|
|
|
private int pointerSize; |
|
|
|
private int pointerWidth; |
|
|
|
private int pointerWidth; |
|
|
|
private BasicStroke stroke; |
|
|
|
private BasicStroke stroke; |
|
|
|
private double pointerPadPercent = 0.5; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -212,28 +210,11 @@ public class BubbleBorder extends AbstractBorder { |
|
|
|
public BubbleBorder setPointerSide(final Alignment side) { |
|
|
|
public BubbleBorder setPointerSide(final Alignment side) { |
|
|
|
this.pointerSide = side; |
|
|
|
this.pointerSide = side; |
|
|
|
setPointerSize(pointerSize); |
|
|
|
setPointerSize(pointerSize); |
|
|
|
switch (pointerSide) { |
|
|
|
|
|
|
|
case NORTH: |
|
|
|
|
|
|
|
case SOUTH: |
|
|
|
|
|
|
|
case EAST: |
|
|
|
|
|
|
|
case WEST: |
|
|
|
|
|
|
|
case CENTER: |
|
|
|
|
|
|
|
pointerPadPercent = 0.5; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case NORTH_EAST: |
|
|
|
|
|
|
|
case SOUTH_EAST: |
|
|
|
|
|
|
|
pointerPadPercent = 1.0 - PAD_OFFSET; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case NORTH_WEST: |
|
|
|
|
|
|
|
case SOUTH_WEST: |
|
|
|
|
|
|
|
pointerPadPercent = PAD_OFFSET; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public int getOffset(final int w, final int h) { |
|
|
|
public int getOffset(final int w, final int h) { |
|
|
|
return (int) calculatePointerPad(w, h, PAD_OFFSET) + 2 * thickness; |
|
|
|
return (int) calculatePointerPad(w, h, Alignment.NORTH_WEST); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -256,15 +237,31 @@ public class BubbleBorder extends AbstractBorder { |
|
|
|
return getBorderInsets(c); |
|
|
|
return getBorderInsets(c); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Area getInnerArea(final int x, final int y, final int width, final int height) { |
|
|
|
@Contract(pure = true) |
|
|
|
var bubble = calculateBubbleRect(x, y, width, height); |
|
|
|
private double calculatePointerPad(final int width, final int height, final Alignment side) { |
|
|
|
final Area area = new Area(bubble); |
|
|
|
double pointerPad; |
|
|
|
if (pointerSide != Alignment.CENTER) { |
|
|
|
switch (side) { |
|
|
|
double pointerPad = calculatePointerPad(width, height, pointerPadPercent); |
|
|
|
case WEST: |
|
|
|
Path2D pointer = creatPointerShape(pointerPad, bubble); |
|
|
|
case EAST: |
|
|
|
area.add(new Area(pointer)); |
|
|
|
pointerPad = radius + (height - insets.top - insets.bottom - 2 * radius) / 2.0; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case NORTH_WEST: |
|
|
|
|
|
|
|
case SOUTH_WEST: |
|
|
|
|
|
|
|
pointerPad = radius + insets.left + pointerWidth; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case NORTH_EAST: |
|
|
|
|
|
|
|
case SOUTH_EAST: |
|
|
|
|
|
|
|
pointerPad = width - radius - insets.right - pointerWidth; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case SOUTH: |
|
|
|
|
|
|
|
case NORTH: |
|
|
|
|
|
|
|
pointerPad = radius + (0.5 * (width - insets.left - insets.right - 2 * radius)); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
pointerPad = 0; |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return area; |
|
|
|
return pointerPad; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void paintBorder(final Graphics g, final Area innerArea) { |
|
|
|
public void paintBorder(final Graphics g, final Area innerArea) { |
|
|
@ -283,27 +280,15 @@ public class BubbleBorder extends AbstractBorder { |
|
|
|
height - insets.top - insets.bottom, radius, radius); |
|
|
|
height - insets.top - insets.bottom, radius, radius); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Contract(pure = true) |
|
|
|
public Area getInnerArea(final int x, final int y, final int width, final int height) { |
|
|
|
private double calculatePointerPad(final int width, final int height, final double percent) { |
|
|
|
var bubble = calculateBubbleRect(x, y, width, height); |
|
|
|
double pointerPad; |
|
|
|
final Area area = new Area(bubble); |
|
|
|
switch (pointerSide) { |
|
|
|
if (pointerSide != Alignment.CENTER) { |
|
|
|
case WEST: |
|
|
|
double pointerPad = calculatePointerPad(width, height, pointerSide); |
|
|
|
case EAST: |
|
|
|
Path2D pointer = creatPointerShape(pointerPad, bubble); |
|
|
|
pointerPad = radius + (height - insets.top - insets.bottom - 2 * radius) / 2.0; |
|
|
|
area.add(new Area(pointer)); |
|
|
|
break; |
|
|
|
|
|
|
|
case NORTH: |
|
|
|
|
|
|
|
case NORTH_WEST: |
|
|
|
|
|
|
|
case NORTH_EAST: |
|
|
|
|
|
|
|
case SOUTH: |
|
|
|
|
|
|
|
case SOUTH_WEST: |
|
|
|
|
|
|
|
case SOUTH_EAST: |
|
|
|
|
|
|
|
pointerPad = radius + (percent * (width - insets.left - insets.right - 2 * radius)); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
pointerPad = 0; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return pointerPad; |
|
|
|
return area; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@NotNull |
|
|
|
@NotNull |
|
|
|