From a64aa24b528786375fbaa25fa478637b03668753 Mon Sep 17 00:00:00 2001 From: vito Date: Tue, 28 Nov 2023 12:03:01 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-99485=20UI=20demo=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=E6=95=85=E4=BA=8B=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fine/theme/icon/IconResource.java | 4 +- .../com/fine/theme/icon/UrlIconResource.java | 8 +- .../fine/theme/light/ui/laf/FineDarkLaf.java | 37 ++++++++ .../fine/theme/light/ui/laf/FineLightLaf.java | 19 ++++- .../com/fr/design/gui/ibutton/UIHead.java | 2 +- .../fr/design/gui/ibutton/UIHeadGroup.java | 2 +- .../gui/storybook/ButtonStoryBoard.java | 36 ++++++++ .../fr/design/gui/storybook/StoryBoard.java | 30 +++++++ .../gui/storybook/StoryBookComponent.java | 18 ++++ .../fr/design/gui/storybook/Storybook.java | 85 +++++++++++++++++++ .../gui/storybook/ToggleButtonStoryBoard.java | 31 +++++++ .../gui/storybook/UIHeadGroupStoryBoard.java | 65 ++++++++++++++ 12 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java create mode 100644 designer-base/src/test/java/com/fr/design/gui/storybook/ButtonStoryBoard.java create mode 100644 designer-base/src/test/java/com/fr/design/gui/storybook/StoryBoard.java create mode 100644 designer-base/src/test/java/com/fr/design/gui/storybook/StoryBookComponent.java create mode 100644 designer-base/src/test/java/com/fr/design/gui/storybook/Storybook.java create mode 100644 designer-base/src/test/java/com/fr/design/gui/storybook/ToggleButtonStoryBoard.java create mode 100644 designer-base/src/test/java/com/fr/design/gui/storybook/UIHeadGroupStoryBoard.java diff --git a/designer-base/src/main/java/com/fine/theme/icon/IconResource.java b/designer-base/src/main/java/com/fine/theme/icon/IconResource.java index f654a6cf8c..d519601391 100644 --- a/designer-base/src/main/java/com/fine/theme/icon/IconResource.java +++ b/designer-base/src/main/java/com/fine/theme/icon/IconResource.java @@ -1,6 +1,6 @@ package com.fine.theme.icon; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import java.io.InputStream; @@ -18,6 +18,6 @@ public interface IconResource { * * @return 资源流 */ - @Nullable + @NotNull InputStream getInputStream(); } diff --git a/designer-base/src/main/java/com/fine/theme/icon/UrlIconResource.java b/designer-base/src/main/java/com/fine/theme/icon/UrlIconResource.java index 58e53646e2..1684a5464c 100644 --- a/designer-base/src/main/java/com/fine/theme/icon/UrlIconResource.java +++ b/designer-base/src/main/java/com/fine/theme/icon/UrlIconResource.java @@ -3,6 +3,7 @@ package com.fine.theme.icon; import com.fr.general.IOUtils; import com.fr.io.utils.ResourceIOUtils; import com.fr.third.errorprone.annotations.Immutable; +import org.jetbrains.annotations.NotNull; import java.io.InputStream; @@ -27,8 +28,13 @@ public class UrlIconResource implements IconResource { } @Override + @NotNull public InputStream getInputStream() { - return getInputStream(path); + InputStream inputStream = getInputStream(path); + if (inputStream == null) { + throw new IconException("Icon load failed: " + path); + } + return inputStream; } diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java new file mode 100644 index 0000000000..062e818a74 --- /dev/null +++ b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java @@ -0,0 +1,37 @@ +package com.fine.theme.light.ui.laf; + +import com.fine.swing.ui.layout.Layouts; +import com.fine.theme.icon.IconManager; +import com.fine.theme.light.ui.FineLightIconSet; +import com.formdev.flatlaf.FlatDarkLaf; +import com.formdev.flatlaf.util.UIScale; +import com.fr.stable.StringUtils; + +/** + * FineReport designer new look and feel + * + * @author vito + * @since 11.0 + * Created on 2023/9/12 + */ +public class FineDarkLaf extends FlatDarkLaf { + + private static final String USER_SCALE_FACTOR = "userScaleFactor"; + + public static boolean setup() { + IconManager.addSet(new FineLightIconSet("fine-light")); + Layouts.setScaleFactor(UIScale.getUserScaleFactor()); + UIScale.addPropertyChangeListener(evt -> { + if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) { + Layouts.setScaleFactor((float) evt.getNewValue()); + } + }); + return setup(new FineDarkLaf()); + } + + @Override + public String getName() { + return "FineDarkLaf"; + } + +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java index 58442eca58..f18bbcd69b 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java +++ b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java @@ -1,8 +1,11 @@ package com.fine.theme.light.ui.laf; -import com.fine.theme.light.ui.FineLightIconSet; +import com.fine.swing.ui.layout.Layouts; import com.fine.theme.icon.IconManager; +import com.fine.theme.light.ui.FineLightIconSet; import com.formdev.flatlaf.FlatLightLaf; +import com.formdev.flatlaf.util.UIScale; +import com.fr.stable.StringUtils; /** * FineReport designer new look and feel @@ -12,8 +15,22 @@ import com.formdev.flatlaf.FlatLightLaf; * Created on 2023/9/12 */ public class FineLightLaf extends FlatLightLaf { + + public static final String USER_SCALE_FACTOR = "userScaleFactor"; + + /** + * 安装外观 + * + * @return 是否安装成功 + */ public static boolean setup() { IconManager.addSet(new FineLightIconSet("fine-light")); + Layouts.setScaleFactor(UIScale.getUserScaleFactor()); + UIScale.addPropertyChangeListener(evt -> { + if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) { + Layouts.setScaleFactor((float) evt.getNewValue()); + } + }); return setup(new FineLightLaf()); } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHead.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHead.java index e1f91b15a7..9d52c61870 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHead.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHead.java @@ -22,7 +22,7 @@ public class UIHead { this.icon = icon; } - public UIHead(Icon icon, int index, boolean enable) { + public UIHead(Icon icon,boolean enable) { this(icon); this.enable = enable; } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java index 1eeb0bb913..f5560810ec 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java @@ -61,7 +61,7 @@ public class UIHeadGroup extends Row { } private void intiContent() { - setSpacing(4); + setSpacing(2); setOpaque(false); add(buttonGroup()); setUI(new UIHeadGroupUI()); diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/ButtonStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/ButtonStoryBoard.java new file mode 100644 index 0000000000..17646a18dc --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/ButtonStoryBoard.java @@ -0,0 +1,36 @@ +package com.fr.design.gui.storybook; + +import com.fine.theme.icon.LazyIcon; +import com.fr.design.gui.ibutton.UIButton; + +import javax.swing.JButton; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + +/** + * 按钮 + * + * @author vito + * @since 11.0 + * Created on 2023/11/27 + */ +public class ButtonStoryBoard extends StoryBoard { + + public ButtonStoryBoard() { + super("按钮"); + add( + row(10, + cell(new UIButton("按钮")), + cell(new UIButton("保存", new LazyIcon("save"))), + cell(new UIButton(new LazyIcon("multi"))) + ), + row(10, + cell(new JButton("按钮")), + cell(new JButton(new LazyIcon("multi"))) + ), + flex() + ); + } +} diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/StoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/StoryBoard.java new file mode 100644 index 0000000000..ad7f04aa32 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/StoryBoard.java @@ -0,0 +1,30 @@ +package com.fr.design.gui.storybook; + +import com.fine.swing.ui.layout.Column; +import com.fr.design.gui.ilable.UILabel; + +import javax.swing.UIManager; +import java.awt.Font; + +import static com.fine.swing.ui.layout.Layouts.cell; + +/** + * UI 故事板,用于demo + * 展示每个UI组件的能力 + * + * @author vito + * @since 11.0 + * Created on 2023/11/27 + */ +public class StoryBoard extends Column { + + protected static final Font labelFont = UIManager.getFont("Label.font"); + + protected String title; + + public StoryBoard(String title) { + this.title = title; + setSpacing(4); + add(cell(new UILabel(title)).with(it -> it.setFont(labelFont.deriveFont(16f).deriveFont(Font.BOLD)))); + } +} diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/StoryBookComponent.java b/designer-base/src/test/java/com/fr/design/gui/storybook/StoryBookComponent.java new file mode 100644 index 0000000000..8926899aea --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/StoryBookComponent.java @@ -0,0 +1,18 @@ +package com.fr.design.gui.storybook; + +import javax.swing.JComponent; + +/** + * @author vito + * @since 11.0 + * Created on 2023/11/27 + */ +public class StoryBookComponent { + public String name; + public JComponent component; + + public StoryBookComponent(String name, JComponent component) { + this.name = name; + this.component = component; + } +} diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/Storybook.java b/designer-base/src/test/java/com/fr/design/gui/storybook/Storybook.java new file mode 100644 index 0000000000..e6621cddca --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/Storybook.java @@ -0,0 +1,85 @@ +package com.fr.design.gui.storybook; + +import com.fanruan.gui.UiInspector; +import com.fine.theme.light.ui.laf.FineLightLaf; +import com.formdev.flatlaf.util.ScaledEmptyBorder; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Component; +import java.util.ArrayList; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.row; +import static com.fine.theme.utils.FineUIScale.scale; + +/** + * UI 故事书,用于demo + * 展示每个UI组件的能力 + * + * @author vito + * @since 11.0 + * Created on 2023/11/27 + */ +public class Storybook { + + CardLayout cardLayout; + JPanel cards; + + public void start() { + FineLightLaf.setup(); + JFrame jf = new JFrame("Story Book"); + jf.add(row( + cell(new JList<>(components())).with(it -> { + it.setBorder(new ScaledEmptyBorder(10, 10, 10, 10)); + it.setCellRenderer(new MyListCellRenderer()); + it.addListSelectionListener(e -> { + StoryBookComponent[] cs = components(); + cards.removeAll(); + cards.add(cs[it.getSelectedIndex()].component); + cards.revalidate(); + }); + }), + cell(new JScrollPane()).weight(1).with(it -> { + cards = new JPanel(new BorderLayout()); + it.setViewportView(cards); + cards.setBorder(new ScaledEmptyBorder(10, 10, 10, 10)); + cards.add(components()[0].component); + }) + ).getComponent()); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jf.setSize(scale(600), scale(400)); + new UiInspector(); + jf.setVisible(true); + } + + + static class MyListCellRenderer extends DefaultListCellRenderer { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + setText(((StoryBookComponent) value).name); + return this; + } + } + + private StoryBookComponent[] components() { + ArrayList components = new ArrayList<>(); + components.add(new StoryBookComponent("Button", new ButtonStoryBoard())); + components.add(new StoryBookComponent("HeadGroup", new UIHeadGroupStoryBoard())); + components.add(new StoryBookComponent("ToggleButton", new ToggleButtonStoryBoard())); + return components.toArray(new StoryBookComponent[0]); + } + + + public static void main(String... args) { + SwingUtilities.invokeLater(() -> new Storybook().start()); + } + +} diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/ToggleButtonStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/ToggleButtonStoryBoard.java new file mode 100644 index 0000000000..8ef89bc40a --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/ToggleButtonStoryBoard.java @@ -0,0 +1,31 @@ +package com.fr.design.gui.storybook; + +import com.fine.theme.icon.LazyIcon; + +import javax.swing.JToggleButton; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + +/** + * 切换状态按钮 + * + * @author vito + * @since 11.0 + * Created on 2023/11/27 + */ +public class ToggleButtonStoryBoard extends StoryBoard { + + public ToggleButtonStoryBoard() { + super("切换按钮"); + add( + row(10, + cell(new JToggleButton("切换按钮")), + cell(new JToggleButton("长文字保存保存保存保存", new LazyIcon("save"))), + cell(new JToggleButton(new LazyIcon("multi"))) + ), + flex() + ); + } +} diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/UIHeadGroupStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/UIHeadGroupStoryBoard.java new file mode 100644 index 0000000000..887c59e9e4 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/UIHeadGroupStoryBoard.java @@ -0,0 +1,65 @@ +package com.fr.design.gui.storybook; + +import com.fine.theme.icon.LazyIcon; +import com.fr.design.gui.ibutton.UIHead; +import com.fr.design.gui.ibutton.UIHeadGroup; +import com.fr.design.gui.ilable.UILabel; + +import java.util.ArrayList; +import java.util.List; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.flex; + +/** + * 属性面板tab + * + * @author vito + * @since 11.0 + * Created on 2023/11/27 + */ +class UIHeadGroupStoryBoard extends StoryBoard { + + public UIHeadGroupStoryBoard() { + super("属性面板&导入数据集tab"); + add( + cell(new UILabel("文字Tab")).with(it -> it.setFont(labelFont.deriveFont(14f))), + cell(new UIHeadGroup(new String[]{"左按钮", "右按钮"})), + cell(new UILabel("图标Tab")).with(it -> it.setFont(labelFont.deriveFont(14f))), + cell(new UIHeadGroup(iconList())), + cell(new UILabel("文字Tab带禁用")).with(it -> it.setFont(labelFont.deriveFont(14f))), + cell(new UIHeadGroup(iconList2())), + cell(new UILabel("文字图标Tab带禁用")).with(it -> it.setFont(labelFont.deriveFont(14f))), + cell(new UIHeadGroup(iconList3())), + flex() + ); + } + + public static List iconList() { + List uiHeads = new ArrayList<>(); + uiHeads.add(new UIHead(new LazyIcon("cut"))); + uiHeads.add(new UIHead(new LazyIcon("save"))); + return uiHeads; + } + + public static List iconList2() { + List uiHeads = new ArrayList<>(); + uiHeads.add(new UIHead(new LazyIcon("cut"))); + uiHeads.add(new UIHead(new LazyIcon("save"), false)); + return uiHeads; + } + + public static List iconList3() { + List uiHeads = new ArrayList<>(); + uiHeads.add(new UIHead("剪切", new LazyIcon("cut"))); + uiHeads.add(new UIHead("保存", new LazyIcon("save"), false)); + return uiHeads; + } + + public static List iconList4() { + List uiHeads = new ArrayList<>(); + uiHeads.add(new UIHead("剪切剪切剪切剪切剪切剪切剪切剪切剪切", new LazyIcon("cut"))); + uiHeads.add(new UIHead("保存", new LazyIcon("save"), false)); + return uiHeads; + } +}