Leo.Qin
1 year ago
8 changed files with 394 additions and 102 deletions
@ -0,0 +1,294 @@ |
|||||||
|
package com.fine.theme.light.ui; |
||||||
|
|
||||||
|
import com.fine.theme.utils.FineUIUtils; |
||||||
|
import com.fr.design.style.background.gradient.GradientBar; |
||||||
|
import com.fr.design.style.background.gradient.SelectColorPointBtn; |
||||||
|
import com.fr.stable.AssistUtils; |
||||||
|
import com.fr.stable.os.OperatingSystem; |
||||||
|
|
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.UIManager; |
||||||
|
import javax.swing.plaf.ComponentUI; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.Graphics; |
||||||
|
import java.awt.Graphics2D; |
||||||
|
import java.awt.LinearGradientPaint; |
||||||
|
import java.awt.RenderingHints; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.awt.event.MouseListener; |
||||||
|
import java.awt.event.MouseMotionAdapter; |
||||||
|
import java.awt.geom.Path2D; |
||||||
|
import java.awt.geom.Point2D; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 渐变色滑块 UI类 |
||||||
|
* |
||||||
|
* @author Leo.Qin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/12/19 |
||||||
|
*/ |
||||||
|
public class FineGradientBarUI extends ComponentUI { |
||||||
|
|
||||||
|
private int directionalShapeSize; |
||||||
|
private int recHeight; |
||||||
|
private int width; |
||||||
|
private int height; |
||||||
|
private int borderWidth; |
||||||
|
private Color borderColor; |
||||||
|
private Color thumbBorderColor; |
||||||
|
private Color hoverThumbColor; |
||||||
|
private Color pressedThumbColor; |
||||||
|
|
||||||
|
private MouseMotionAdapter mouseMotionListener; |
||||||
|
|
||||||
|
GradientBar gradientBar; |
||||||
|
private List<SelectColorPointBtn> list; |
||||||
|
private SelectColorPointBtn p1; |
||||||
|
private SelectColorPointBtn p2; |
||||||
|
private MouseListener mouseListener; |
||||||
|
private double offset = 0.0001; |
||||||
|
|
||||||
|
boolean[] hoverStatus; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 创建UI |
||||||
|
* |
||||||
|
* @param c 组件 |
||||||
|
* @return UI |
||||||
|
*/ |
||||||
|
public static ComponentUI createUI(JComponent c) { |
||||||
|
return new FineGradientBarUI(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void installUI(JComponent c) { |
||||||
|
super.installUI(c); |
||||||
|
installDefaults(c); |
||||||
|
|
||||||
|
gradientBar = (GradientBar) c; |
||||||
|
list = gradientBar.getList(); |
||||||
|
p1 = gradientBar.getSelectColorPointBtnP1(); |
||||||
|
p2 = gradientBar.getSelectColorPointBtnP2(); |
||||||
|
hoverStatus = new boolean[list.size()]; |
||||||
|
mouseMotionListener = new TrackMotionListener(); |
||||||
|
mouseListener = new TrackMouseListener(); |
||||||
|
gradientBar.addMouseMotionListener(mouseMotionListener); |
||||||
|
gradientBar.addMouseListener(mouseListener); |
||||||
|
} |
||||||
|
|
||||||
|
private void installDefaults(JComponent c) { |
||||||
|
directionalShapeSize = FineUIUtils.getAndScaleInt("GradientBar.thumbWidth", 12); |
||||||
|
recHeight = FineUIUtils.getAndScaleInt("GradientBar.recHeight", 30); |
||||||
|
width = FineUIUtils.getAndScaleInt("GradientBar.recWidth", 160); |
||||||
|
height = recHeight + directionalShapeSize; |
||||||
|
borderWidth = FineUIUtils.getAndScaleInt("GradientBar.borderWidth", 1); |
||||||
|
borderColor = UIManager.getColor("GradientBar.borderColor"); |
||||||
|
thumbBorderColor = UIManager.getColor("GradientBar.thumbBorderColor"); |
||||||
|
hoverThumbColor = UIManager.getColor("GradientBar.hoverThumbColor"); |
||||||
|
pressedThumbColor = UIManager.getColor("GradientBar.pressedThumbColor"); |
||||||
|
} |
||||||
|
|
||||||
|
private class TrackMouseListener extends MouseAdapter { |
||||||
|
@Override |
||||||
|
public void mouseExited(MouseEvent e) { |
||||||
|
for (int i = 0; i < list.size(); i++) { |
||||||
|
SelectColorPointBtn selectColorPointBtn = list.get(i); |
||||||
|
selectColorPointBtn.setHover(false); |
||||||
|
hoverStatus[i] = false; |
||||||
|
} |
||||||
|
|
||||||
|
gradientBar.repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseEntered(MouseEvent e) { |
||||||
|
checkHoverStatus(e); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mousePressed(MouseEvent e) { |
||||||
|
for (SelectColorPointBtn btn : list) { |
||||||
|
boolean hover = isOverBtn(e, btn); |
||||||
|
btn.setPressed(hover); |
||||||
|
} |
||||||
|
|
||||||
|
gradientBar.repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseReleased(MouseEvent e) { |
||||||
|
for (SelectColorPointBtn btn : list) { |
||||||
|
btn.setPressed(false); |
||||||
|
} |
||||||
|
|
||||||
|
gradientBar.repaint(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private class TrackMotionListener extends MouseMotionAdapter { |
||||||
|
int index; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseDragged(MouseEvent e) { |
||||||
|
if (!gradientBar.isDraggable()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
index = getSelectedIndex(e, index); |
||||||
|
int halfSize = directionalShapeSize / 2; |
||||||
|
boolean x = e.getX() <= gradientBar.getWidth() - halfSize && e.getX() >= halfSize; |
||||||
|
if (x) { |
||||||
|
list.get(index).setX(e.getX()); |
||||||
|
list.get(index).setStartPosition((double) (e.getX() - halfSize) / (gradientBar.getWidth() - directionalShapeSize)); |
||||||
|
gradientBar.repaint(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private int getSelectedIndex(MouseEvent e, int index) { |
||||||
|
int oldIndex = index; |
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) { |
||||||
|
if (list.get(i).contains(e.getX(), e.getY())) { |
||||||
|
index = i; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (OperatingSystem.isLinux() && AssistUtils.equals(oldIndex, index)) { |
||||||
|
if (Math.abs(p1.getX() - e.getX()) > Math.abs(p2.getX() - e.getX())) { |
||||||
|
index = 1; |
||||||
|
} else { |
||||||
|
index = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
return index; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseMoved(MouseEvent e) { |
||||||
|
checkHoverStatus(e); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void checkHoverStatus(MouseEvent e) { |
||||||
|
boolean repaint = false; |
||||||
|
for (int i = 0; i < list.size(); i++) { |
||||||
|
SelectColorPointBtn btn = list.get(i); |
||||||
|
boolean hover = isOverBtn(e, btn); |
||||||
|
if (hoverStatus[i] != hover) { |
||||||
|
repaint = true; |
||||||
|
hoverStatus[i] = hover; |
||||||
|
btn.setHover(hover); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (repaint) { |
||||||
|
gradientBar.repaint(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isOverBtn(MouseEvent e, SelectColorPointBtn btn) { |
||||||
|
return btn.contains(e.getX(), e.getY()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g, JComponent c) { |
||||||
|
Graphics2D g2 = (Graphics2D) g; |
||||||
|
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||||
|
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); |
||||||
|
|
||||||
|
GradientBar component = (GradientBar) c; |
||||||
|
List<SelectColorPointBtn> btnList = component.getList(); |
||||||
|
Collections.sort(btnList); |
||||||
|
|
||||||
|
|
||||||
|
paintBorder(g2, component); |
||||||
|
paintContent(g2, component); |
||||||
|
paintButton(g2, btnList); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 实际绘制区域x范围(directionalShapeSize / 2, width - directionalShapeSize) |
||||||
|
*/ |
||||||
|
private void paintContent(Graphics2D g2d, GradientBar c) { |
||||||
|
List<SelectColorPointBtn> btnList = c.getList(); |
||||||
|
|
||||||
|
int halfSize = directionalShapeSize / 2; |
||||||
|
Point2D start = new Point2D.Float(halfSize, 0); |
||||||
|
Point2D end = new Point2D.Float(c.getWidth() - halfSize, 0); |
||||||
|
|
||||||
|
|
||||||
|
Collections.sort(btnList); |
||||||
|
Color[] colors = new Color[btnList.size()]; |
||||||
|
for (int i = 0; i < btnList.size(); i++) { |
||||||
|
colors[i] = btnList.get(i).getColorInner(); |
||||||
|
} |
||||||
|
|
||||||
|
float[] dist = new float[btnList.size()]; |
||||||
|
for (int i = 0; i < btnList.size(); i++) { |
||||||
|
if (btnList.get(i).getStartPosition() < 0) { |
||||||
|
dist[i] = 0; |
||||||
|
} else if (btnList.get(i).getStartPosition() > 1) { |
||||||
|
dist[i] = 1; |
||||||
|
} else { |
||||||
|
dist[i] = (float) btnList.get(i).getStartPosition(); |
||||||
|
} |
||||||
|
|
||||||
|
btnList.get(i).setX(dist[i] * (c.getWidth() - directionalShapeSize) + (double) directionalShapeSize / 2); |
||||||
|
} |
||||||
|
|
||||||
|
float dist1 = dist[btnList.size() - 1]; |
||||||
|
float dist2 = dist[btnList.size() - 2]; |
||||||
|
if (AssistUtils.equals(dist1, dist2)) { |
||||||
|
dist[btnList.size() - 1] = (float) (dist2 + offset); |
||||||
|
} |
||||||
|
LinearGradientPaint paint = new LinearGradientPaint(start, end, dist, colors); |
||||||
|
g2d.setPaint(paint); |
||||||
|
g2d.fillRect(halfSize + borderWidth, borderWidth, c.getWidth() - directionalShapeSize - borderWidth * 2, recHeight - borderWidth * 2); |
||||||
|
} |
||||||
|
|
||||||
|
private void paintBorder(Graphics2D g2d, GradientBar c) { |
||||||
|
int halfSize = directionalShapeSize / 2; |
||||||
|
if (borderColor == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
g2d.setColor(borderColor); |
||||||
|
g2d.fillRect(halfSize, 0, c.getWidth() - directionalShapeSize, recHeight); |
||||||
|
} |
||||||
|
|
||||||
|
private void paintButton(Graphics2D g2d, List<SelectColorPointBtn> list) { |
||||||
|
|
||||||
|
for (SelectColorPointBtn selectColorPointBtn : list) { |
||||||
|
Path2D directionalThumbShape = FineSliderUI.createDirectionalThumbShape((float) selectColorPointBtn.getX() - (float) directionalShapeSize / 2, (float) selectColorPointBtn.getY(), directionalShapeSize, directionalShapeSize, 0); |
||||||
|
if (selectColorPointBtn.isHover() && hoverThumbColor != null) { |
||||||
|
g2d.setColor(hoverThumbColor); |
||||||
|
g2d.fill(directionalThumbShape); |
||||||
|
} else if (selectColorPointBtn.isPressed() && pressedThumbColor != null) { |
||||||
|
g2d.setColor(pressedThumbColor); |
||||||
|
g2d.fill(directionalThumbShape); |
||||||
|
} else if (thumbBorderColor != null) { |
||||||
|
g2d.setColor(thumbBorderColor); |
||||||
|
g2d.fill(directionalThumbShape); |
||||||
|
} |
||||||
|
selectColorPointBtn.updatePath(directionalThumbShape); |
||||||
|
|
||||||
|
Path2D innerThumbShape = FineSliderUI.createDirectionalThumbShape((float) selectColorPointBtn.getX() - (float) directionalShapeSize / 2 + borderWidth, (float) selectColorPointBtn.getY() + borderWidth, directionalShapeSize - borderWidth * 2, directionalShapeSize - borderWidth * 2, 0); |
||||||
|
g2d.setColor(selectColorPointBtn.getColorInner()); |
||||||
|
g2d.fill(innerThumbShape); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Dimension getPreferredSize(JComponent c) { |
||||||
|
return new Dimension(width, height); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue