Browse Source

REPORT-107973 主页及组件视觉样式翻新

【问题原因】rt
【改动思路】翻新带标签带滑块
newui
Leo.Qin 1 year ago
parent
commit
022b18ae6d
  1. 344
      designer-base/src/main/java/com/fine/theme/light/ui/FineSliderUI.java
  2. 7
      designer-base/src/main/java/com/fr/design/mainframe/JFormSliderPane.java
  3. 3
      designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties
  4. 11
      designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties
  5. 20
      designer-base/src/test/java/com/fr/design/gui/storybook/components/SliderStoryBoard.java

344
designer-base/src/main/java/com/fine/theme/light/ui/FineSliderUI.java

@ -0,0 +1,344 @@
package com.fine.theme.light.ui;
import com.fine.theme.utils.FineUIUtils;
import com.formdev.flatlaf.ui.FlatSliderUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.UIScale;
import com.fr.stable.AssistUtils;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Dictionary;
import java.util.Enumeration;
/**
* 滑块slider UI类
*
* @author Leo.Qin
* @since 11.0
* Created on 2023/12/15
*/
public class FineSliderUI extends FlatSliderUI {
private final int DEFAULT_LABEL_HEIGHT = 13;
private Color defaultForeground;
private int defaultLabelHeight;
/**
* 创建UI
*/
public static ComponentUI createUI(JComponent c) {
return new FineSliderUI();
}
@Override
protected void installDefaults(JSlider slider) {
super.installDefaults(slider);
defaultForeground = UIManager.getColor("Slider.foreground");
defaultLabelHeight = FineUIUtils.getAndScaleInt("Slider.labelHeight", DEFAULT_LABEL_HEIGHT);
}
@Override
protected void calculateLabelRect() {
if (slider.getPaintLabels()) {
calLabelRectWhenPaint();
} else {
calLabelRectWhenNotPaint();
}
}
private void calLabelRectWhenPaint() {
labelRect.y = 0;
if (slider.getOrientation() == JSlider.HORIZONTAL) {
labelRect.x = tickRect.x - trackBuffer;
labelRect.width = tickRect.width + (trackBuffer * 2);
labelRect.height = getHeightOfTallestLabel();
} else {
if (isLeftToRight(slider)) {
labelRect.x = tickRect.x + tickRect.width;
labelRect.width = getWidthOfWidestLabel();
} else {
labelRect.width = getWidthOfWidestLabel();
labelRect.x = tickRect.x - labelRect.width;
}
labelRect.height = tickRect.height + (trackBuffer * 2);
}
}
private void calLabelRectWhenNotPaint() {
labelRect.y = 0;
if (slider.getOrientation() == JSlider.HORIZONTAL) {
labelRect.x = tickRect.x;
labelRect.width = tickRect.width;
labelRect.height = 0;
} else {
if (isLeftToRight(slider)) {
labelRect.x = tickRect.x + tickRect.width;
} else {
labelRect.x = tickRect.x;
}
labelRect.width = 0;
labelRect.height = tickRect.height;
}
}
@Override
protected void calculateTrackRect() {
if (slider.getOrientation() == JSlider.HORIZONTAL) {
calHorizontalTrackRect();
} else {
calVerticalTrackRect();
}
}
private void calVerticalTrackRect() {
int centerSpacing;
centerSpacing = thumbRect.width;
if (isLeftToRight(slider)) {
if (slider.getPaintTicks()) {
centerSpacing += getTickLength();
}
if (slider.getPaintLabels()) {
centerSpacing += getWidthOfWidestLabel();
}
} else {
if (slider.getPaintTicks()) {
centerSpacing -= getTickLength();
}
if (slider.getPaintLabels()) {
centerSpacing -= getWidthOfWidestLabel();
}
}
trackRect.x = contentRect.x + getWidthOfWidestLabel() + (contentRect.width - centerSpacing - 1) / 2;
trackRect.y = contentRect.y + trackBuffer;
trackRect.width = thumbRect.width;
trackRect.height = contentRect.height - (trackBuffer * 2);
}
private void calHorizontalTrackRect() {
int centerSpacing;
centerSpacing = thumbRect.height;
if (slider.getPaintTicks()) {
centerSpacing += getTickLength();
}
if (slider.getPaintLabels()) {
centerSpacing += getHeightOfTallestLabel();
}
trackRect.x = contentRect.x + trackBuffer;
trackRect.y = contentRect.y + getHeightOfTallestLabel() + (contentRect.height - centerSpacing - 1) / 2;
trackRect.width = contentRect.width - (trackBuffer * 2);
trackRect.height = thumbRect.height;
}
@Override
protected int getHeightOfTallestLabel() {
Dictionary dictionary = slider.getLabelTable();
int tallest = 0;
if (dictionary != null) {
Enumeration keys = dictionary.keys();
while (keys.hasMoreElements()) {
JComponent label = (JComponent) dictionary.get(keys.nextElement());
tallest = Math.max(label.getPreferredSize().height, tallest);
}
}
return Math.min(tallest, defaultLabelHeight);
}
@Override
protected int getWidthOfWidestLabel() {
Dictionary dictionary = slider.getLabelTable();
int widest = 0;
if (dictionary != null) {
Enumeration keys = dictionary.keys();
while (keys.hasMoreElements()) {
JComponent label = (JComponent) dictionary.get(keys.nextElement());
widest = Math.max(label.getPreferredSize().width, widest);
}
}
return Math.min(widest, defaultLabelHeight);
}
/**
* Convenience function for determining ComponentOrientation. Helps us
* avoid having Munge directives throughout the code.
*/
static boolean isLeftToRight(Component c) {
return c.getComponentOrientation().isLeftToRight();
}
@Override
public void paintThumb(Graphics g) {
Color thumbColor = getThumbColor();
Color color = stateColor(slider, thumbHover, thumbPressed, thumbColor, disabledThumbColor, null, hoverThumbColor, pressedThumbColor);
color = FlatUIUtils.deriveColor(color, thumbColor);
Color foreground = slider.getForeground();
Color borderColor = (thumbBorderColor != null && foreground == defaultForeground) ? stateColor(slider, false, false, thumbBorderColor, disabledThumbBorderColor, focusedThumbBorderColor, null, null) : null;
Color focusedColor = FlatUIUtils.deriveColor(this.focusedColor, (foreground != defaultForeground) ? foreground : focusBaseColor);
paintThumb(g, slider, thumbRect, isRoundThumb(), color, borderColor, focusedColor, thumbBorderWidth, focusWidth);
}
/**
* Paints the thumb.
*
* @param g the graphics context
* @param slider the slider
* @param thumbRect the thumb rectangle
* @param roundThumb whether the thumb should be round
* @param thumbColor the thumb color
* @param thumbBorderColor the thumb border color
* @param focusedColor the focused color
* @param thumbBorderWidth the thumb border width
* @param focusWidth the focus width
*/
public static void paintThumb(Graphics g, JSlider slider, Rectangle thumbRect, boolean roundThumb, Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, int focusWidth) {
double systemScaleFactor = UIScale.getSystemScaleFactor((Graphics2D) g);
int scaleFactor2 = 2;
if (systemScaleFactor != 1 && systemScaleFactor != scaleFactor2) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x((Graphics2D) g, thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height, (g2d, x2, y2, width2, height2, scaleFactor) -> {
paintThumbImpl(g, slider, x2, y2, width2, height2, roundThumb, thumbColor, thumbBorderColor, focusedColor, (float) (thumbBorderWidth * scaleFactor), (float) (focusWidth * scaleFactor));
});
return;
}
paintThumbImpl(g, slider, thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height, roundThumb, thumbColor, thumbBorderColor, focusedColor, thumbBorderWidth, focusWidth);
}
private static void paintThumbImpl(Graphics g, JSlider slider, int x, int y, int width, int height, boolean roundThumb, Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, float focusWidth) {
int fw = Math.round(UIScale.scale(focusWidth));
int tx = x + fw;
int ty = y + fw;
int tw = width - fw - fw;
int th = height - fw - fw;
boolean focused = FlatUIUtils.isPermanentFocusOwner(slider);
if (roundThumb) {
paintRoundThumb(g, x, y, width, height, thumbColor, thumbBorderColor, focusedColor, thumbBorderWidth, focused, tx, ty, tw, th);
} else {
paintDirectionalThumb(g, slider, x, y, width, height, thumbColor, thumbBorderColor, focusedColor, thumbBorderWidth, tw, th, focused, fw);
}
}
private static void paintDirectionalThumb(Graphics g, JSlider slider, int x, int y, int width, int height, Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, int tw, int th, boolean focused, int fw) {
Graphics2D g2 = (Graphics2D) g.create();
try {
g2.translate(x, y);
if (slider.getOrientation() == JSlider.VERTICAL) {
if (slider.getComponentOrientation().isLeftToRight()) {
g2.translate(0, height);
g2.rotate(Math.toRadians(270));
} else {
g2.translate(width, 0);
g2.rotate(Math.toRadians(90));
}
// rotate thumb width/height
int temp = tw;
tw = th;
th = temp;
}
paintDirectionalThumbImpl(thumbColor, thumbBorderColor, focusedColor, thumbBorderWidth, tw, th, focused, fw, g2);
} finally {
g2.dispose();
}
}
private static void paintDirectionalThumbImpl(Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, int tw, int th, boolean focused, int fw, Graphics2D g2) {
// paint thumb focus border
if (focused) {
g2.setColor(focusedColor);
g2.fill(createDirectionalThumbShape(0, 0, tw + fw + fw, th + fw + fw + (fw * 0.4142f), fw));
}
if (thumbBorderColor != null) {
// paint thumb border
g2.setColor(thumbBorderColor);
g2.fill(createDirectionalThumbShape(fw, fw, tw, th, 0));
// paint thumb background
float lw = UIScale.scale(thumbBorderWidth);
g2.setColor(thumbColor);
g2.fill(createDirectionalThumbShape(fw + lw, fw + lw, tw - lw - lw, th - lw - lw - (lw * 0.4142f), 0));
} else {
// paint thumb background
g2.setColor(thumbColor);
g2.fill(createDirectionalThumbShape(fw, fw, tw, th, 0));
}
}
private static void paintRoundThumb(Graphics g, int x, int y, int width, int height, Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, boolean focused, int tx, int ty, int tw, int th) {
// paint thumb focus border
if (focused) {
g.setColor(focusedColor);
((Graphics2D) g).fill(createRoundThumbShape(x, y, width, height));
}
if (thumbBorderColor != null) {
// paint thumb border
g.setColor(thumbBorderColor);
((Graphics2D) g).fill(createRoundThumbShape(tx, ty, tw, th));
// paint thumb background
float lw = UIScale.scale(thumbBorderWidth);
g.setColor(thumbColor);
((Graphics2D) g).fill(createRoundThumbShape(tx + lw, ty + lw, tw - lw - lw, th - lw - lw));
} else {
// paint thumb background
g.setColor(thumbColor);
((Graphics2D) g).fill(createRoundThumbShape(tx, ty, tw, th));
}
}
/**
* 无标签下创建圆形Thumb形状
*/
public static Shape createRoundThumbShape(float x, float y, float w, float h) {
if (AssistUtils.equals(w, h)) {
return new Ellipse2D.Float(x, y, w, h);
} else {
float arc = Math.min(w, h);
return new RoundRectangle2D.Float(x, y, w, h, arc, arc);
}
}
/**
* 有标签下创建Thumb形状
*/
public static Shape createDirectionalThumbShape(float x, float y, float w, float h, float arc) {
float wh = w / 2;
Path2D path = new Path2D.Float(Path2D.WIND_NON_ZERO, 9);
path.moveTo(x + wh, y); // 移到反转后的位置
path.lineTo(x, y + wh); // 线到反转后的位置
path.lineTo(x, y + h - arc); // 线到反转后的位置
path.quadTo(x, y + h, x + arc, y + h); // 贝塞尔曲线到反转后的位置
path.lineTo(x + (w - arc), y + h); // 线到反转后的位置
path.quadTo(x + w, y + h, x + w, y + h - arc); // 贝塞尔曲线到反转后的位置
path.lineTo(x + w, y + wh); // 线到反转后的位置
path.closePath(); // 关闭路径
return path;
}
}

7
designer-base/src/main/java/com/fr/design/mainframe/JFormSliderPane.java

@ -1,6 +1,7 @@
package com.fr.design.mainframe; package com.fr.design.mainframe;
import com.fine.theme.icon.LazyIcon; import com.fine.theme.icon.LazyIcon;
import com.fine.theme.utils.FineUIScale;
import com.formdev.flatlaf.FlatDarculaLaf; import com.formdev.flatlaf.FlatDarculaLaf;
import com.fr.base.BaseUtils; import com.fr.base.BaseUtils;
import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButton;
@ -48,8 +49,6 @@ public class JFormSliderPane extends JPanel {
private static final int HUNDRED = 100; private static final int HUNDRED = 100;
private static final int TWO_HUNDRED = 200; private static final int TWO_HUNDRED = 200;
private static final int FOUR_HUNDRED = 400; private static final int FOUR_HUNDRED = 400;
private static final int SHOWVALBUTTON_WIDTH = 40;
private static final int SHOWVALBUTTON_HEIGHTH = 20;
private static final String SUFFIX = "%"; private static final String SUFFIX = "%";
private static final int TOOLTIP_Y = 30; private static final int TOOLTIP_Y = 30;
private static final Color BACK_COLOR = new Color(245, 245, 247); private static final Color BACK_COLOR = new Color(245, 245, 247);
@ -93,7 +92,6 @@ public class JFormSliderPane extends JPanel {
}; };
slider.setValue(HALF_HUNDRED); slider.setValue(HALF_HUNDRED);
slider.addChangeListener(listener); slider.addChangeListener(listener);
slider.setPreferredSize(new Dimension(220, 20));
//去掉虚线框 //去掉虚线框
slider.setFocusable(false); slider.setFocusable(false);
slider.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Scale_Slider")); slider.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Scale_Slider"));
@ -124,7 +122,8 @@ public class JFormSliderPane extends JPanel {
private void initShowValField() { private void initShowValField() {
showValField = new UINumberField(); showValField = new UINumberField();
showValField.setValue(showValue); showValField.setValue(showValue);
showValField.setPreferredSize(new Dimension(SHOWVALBUTTON_WIDTH, SHOWVALBUTTON_HEIGHTH)); Dimension dimension = new Dimension(UIManager.getInt("FormSliderPane.showValueWidth"), UIManager.getInt("FormSliderPane.showValueHeight"));
showValField.setPreferredSize(FineUIScale.scale(dimension));
showValField.addKeyListener(new KeyListener() { showValField.addKeyListener(new KeyListener() {
@Override @Override
public void keyTyped(KeyEvent e) { public void keyTyped(KeyEvent e) {

3
designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties

@ -28,7 +28,7 @@ RootPaneUI=com.formdev.flatlaf.ui.FlatRootPaneUI
ScrollBarUI=com.formdev.flatlaf.ui.FlatScrollBarUI ScrollBarUI=com.formdev.flatlaf.ui.FlatScrollBarUI
ScrollPaneUI=com.formdev.flatlaf.ui.FlatScrollPaneUI ScrollPaneUI=com.formdev.flatlaf.ui.FlatScrollPaneUI
SeparatorUI=com.formdev.flatlaf.ui.FlatSeparatorUI SeparatorUI=com.formdev.flatlaf.ui.FlatSeparatorUI
SliderUI=com.formdev.flatlaf.ui.FlatSliderUI SliderUI=com.fine.theme.light.ui.FineSliderUI
SpinnerUI=com.formdev.flatlaf.ui.FlatSpinnerUI SpinnerUI=com.formdev.flatlaf.ui.FlatSpinnerUI
SplitPaneUI=com.formdev.flatlaf.ui.FlatSplitPaneUI SplitPaneUI=com.formdev.flatlaf.ui.FlatSplitPaneUI
TabbedPaneUI=com.formdev.flatlaf.ui.FlatTabbedPaneUI TabbedPaneUI=com.formdev.flatlaf.ui.FlatTabbedPaneUI
@ -46,4 +46,3 @@ ViewportUI=com.formdev.flatlaf.ui.FlatViewportUI
HeadGroupUI=com.fine.theme.light.ui.FineHeadGroupUI HeadGroupUI=com.fine.theme.light.ui.FineHeadGroupUI
ButtonGroupUI= com.fine.theme.light.ui.FineButtonGroupUI ButtonGroupUI= com.fine.theme.light.ui.FineButtonGroupUI
SelectBoxUI= com.fine.theme.light.ui.FineSelectBoxUI SelectBoxUI= com.fine.theme.light.ui.FineSelectBoxUI

11
designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties

@ -688,17 +688,24 @@ Separator.foreground = shade(@background,15%)
Slider.focusInsets = 0,0,0,0 Slider.focusInsets = 0,0,0,0
Slider.trackWidth = 2 Slider.trackWidth = 2
Slider.thumbSize = 12,12 Slider.thumbSize = 12,12
Slider.focusWidth = 4 Slider.focusWidth=0
Slider.trackValueColor=$brand.normal Slider.trackValueColor=$brand.normal
Slider.trackColor=$border.divider Slider.trackColor=$border.divider
Slider.thumbColor=$fill.normal Slider.thumbColor=$fill.normal
Slider.thumbBorderColor=$border.divider Slider.thumbBorderColor=$border.divider
Slider.tickColor = @disabledForeground Slider.tickColor = @disabledForeground
Slider.focusedColor = fade(changeLightness($Component.focusColor,75%,derived),50%,derived) Slider.focusedColor=$border.divider
Slider.focusedThumbBorderColor=$border.divider
Slider.hoverThumbColor=$fill.hover Slider.hoverThumbColor=$fill.hover
Slider.pressedThumbColor=$fill.hover Slider.pressedThumbColor=$fill.hover
Slider.disabledTrackColor = darken(@background,13%) Slider.disabledTrackColor = darken(@background,13%)
Slider.disabledThumbColor = $Slider.disabledTrackColor Slider.disabledThumbColor = $Slider.disabledTrackColor
Slider.labelHeight=13
#---- FormSliderPane ----
FormSliderPane.showValueWidth=40
FormSliderPane.showValueHeight=20
FormSliderPane.sliderWidth=220
FormSliderPane.sliderHeight=20
#---- Spinner ---- #---- Spinner ----

20
designer-base/src/test/java/com/fr/design/gui/storybook/components/SliderStoryBoard.java

@ -1,8 +1,9 @@
package com.fr.design.gui.storybook.components; package com.fr.design.gui.storybook.components;
import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.islider.UISlider;
import com.fr.design.gui.storybook.Story;
import com.fr.design.gui.storybook.StoryBoard; import com.fr.design.gui.storybook.StoryBoard;
import com.fr.design.mainframe.JFormSliderPane;
import static com.fine.swing.ui.layout.Layouts.*; import static com.fine.swing.ui.layout.Layouts.*;
@ -13,12 +14,25 @@ import static com.fine.swing.ui.layout.Layouts.*;
* @since 11.0 * @since 11.0
* Created on 2023/12/14 * Created on 2023/12/14
*/ */
@Story
public class SliderStoryBoard extends StoryBoard { public class SliderStoryBoard extends StoryBoard {
public SliderStoryBoard() { public SliderStoryBoard() {
super("滑块"); super("滑块");
add( add(
cell(new UILabel("面板缩放滑块")).with(this::h3), cell(new UILabel("无标签滑块")).with(this::h3),
row(cell(new JFormSliderPane())) row(cell(new UISlider()).with(it -> {
it.setValue(50);
it.setMaximum(100);
it.setMinimum(0);
})),
cell(new UILabel("带标签滑块")).with(this::h3),
row(cell(new UISlider()).with(it -> {
it.setPaintLabels(true);
it.setMajorTickSpacing(90);
it.setValue(40);
it.setMaximum(90);
it.setMinimum(-90);
}))
); );
} }
} }

Loading…
Cancel
Save