Browse Source

Pull request #13397: REPORT-99485 设计器模版tab和工具栏绘制

Merge in DESIGN/design from ~VITO/c-design:newui to newui

* commit '487ad3609844c38b396b99de86f3629412fb9a0c':
  无jira任务 代码质量
  REPORT-99485 设计器模版tab和工具栏绘制
  REPORT-99485 buttonui
newui
vito-刘恒霖 11 months ago committed by Leo.Qin-覃宇攀
parent
commit
26061e4468
  1. 42
      designer-base/src/main/java/com/fine/theme/light/ui/FineButtonBorder.java
  2. 114
      designer-base/src/main/java/com/fine/theme/light/ui/FineButtonUI.java
  3. 90
      designer-base/src/main/java/com/fine/theme/light/ui/FineCombinationButtonUI.java
  4. 2
      designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java
  5. 407
      designer-base/src/main/java/com/fine/theme/light/ui/FineTemplateTabPaneUI.java
  6. 77
      designer-base/src/main/java/com/fine/theme/utils/FineClientProperties.java
  7. 128
      designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java
  8. 655
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java
  9. 132
      designer-base/src/main/java/com/fr/design/gui/ibutton/UICombinationButton.java
  10. 1
      designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java
  11. 1
      designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java
  12. 47
      designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java
  13. 2
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  14. 6
      designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java
  15. 11
      designer-base/src/main/resources/com/fine/theme/icon/clear_hover.svg
  16. 3
      designer-base/src/main/resources/com/fine/theme/icon/toolbar/more.svg
  17. 3
      designer-base/src/main/resources/com/fine/theme/icon/toolbar/more_disable.svg
  18. 4
      designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties
  19. 126
      designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties
  20. 126
      designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonStoryBoard.java
  21. 42
      designer-base/src/test/java/com/fr/design/gui/storybook/components/JTestTemplate.java
  22. 36
      designer-base/src/test/java/com/fr/design/gui/storybook/components/TemplateTabStoryBoard.java
  23. 3
      designer-form/src/main/java/com/fr/design/mainframe/JForm.java
  24. 3
      designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java
  25. 84
      designer-realize/src/main/java/com/fr/start/MainDesigner.java

42
designer-base/src/main/java/com/fine/theme/light/ui/FineButtonBorder.java

@ -0,0 +1,42 @@
package com.fine.theme.light.ui;
import com.fine.theme.utils.FineUIUtils;
import com.formdev.flatlaf.ui.FlatButtonBorder;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import static com.fine.theme.light.ui.FineButtonUI.isPartRoundButton;
/**
* 按钮边框
*
* @author vito
* @since 11.0
* Created on 2023/12/20
*/
public class FineButtonBorder extends FlatButtonBorder {
public FineButtonBorder() {
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
if (isPartRoundButton(c)) {
Graphics2D g2 = (Graphics2D) g.create();
Paint borderPaint = getBorderColor(c);
if (borderPaint == null) {
return;
}
g2.setPaint(borderPaint);
FineUIUtils.paintPartRoundButtonBorder(c, g2, x, y, width, height, borderWidth, (float) getArc(c));
} else {
super.paintBorder(c, g, x, y, width, height);
}
}
}

114
designer-base/src/main/java/com/fine/theme/light/ui/FineButtonUI.java

@ -0,0 +1,114 @@
package com.fine.theme.light.ui;
import com.fine.theme.utils.FineClientProperties;
import com.fine.theme.utils.FineUIUtils;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import static com.formdev.flatlaf.FlatClientProperties.BUTTON_TYPE;
/**
* 按钮UI
*
* @author vito
* @since 11.0
* Created on 2023/12/20
*/
public class FineButtonUI extends FlatButtonUI {
/**
* @param shared
* @since 2
*/
protected FineButtonUI(boolean shared) {
super(shared);
}
/**
* 是否左圆角矩形
*
* @param c 组件
* @return 是否左圆角矩形
*/
public static boolean isLeftRoundButton(Component c) {
return c instanceof JButton
&& FineClientProperties.BUTTON_TYPE_LEFT_ROUND_RECT.equals(getButtonTypeStr((JButton) c));
}
/**
* 是否右圆角矩形
*
* @param c 组件
* @return 是否右圆角矩形
*/
public static boolean isRightRoundButton(Component c) {
return c instanceof JButton
&& FineClientProperties.BUTTON_TYPE_RIGHT_ROUND_RECT.equals(getButtonTypeStr((JButton) c));
}
/**
* 是否部分圆角矩形
*
* @param c 组件
* @return 是否部分圆角矩形
*/
public static boolean isPartRoundButton(Component c) {
return isLeftRoundButton(c) || isRightRoundButton(c);
}
protected void paintBackground(Graphics g, JComponent c) {
if (isPartRoundButton(c)) {
Color background = getBackground(c);
if (background == null) {
return;
}
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints(g2);
float arc = FlatUIUtils.getBorderArc(c);
int width = c.getWidth();
int height = c.getHeight();
g2.setColor(FlatUIUtils.deriveColor(background, getBackgroundBase(c, false)));
Path2D path2DLeft;
if (isLeftRoundButton(c)) {
path2DLeft = FineUIUtils.createLeftRoundRectangle(0, 0, width, height, arc);
} else {
path2DLeft = FineUIUtils.createRightRoundRectangle(0, 0, width, height, arc);
}
g2.fill(path2DLeft);
} finally {
g2.dispose();
}
} else {
super.paintBackground(g, c);
}
}
/**
* 创建UI
*/
public static ComponentUI createUI(JComponent c) {
return new FineButtonUI(false);
}
static String getButtonTypeStr(AbstractButton c) {
Object value = c.getClientProperty(BUTTON_TYPE);
if (value instanceof String) {
return (String) value;
}
return null;
}
}

90
designer-base/src/main/java/com/fine/theme/light/ui/FineCombinationButtonUI.java

@ -0,0 +1,90 @@
package com.fine.theme.light.ui;
import com.fine.theme.utils.FineClientProperties;
import com.fine.theme.utils.FineUIUtils;
import com.formdev.flatlaf.ui.FlatPanelUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.fr.design.gui.ibutton.UICombinationButton;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import java.awt.Color;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import static com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
/**
* 双组件按钮UI
*
* @author vito
* @since 11.0
* Created on 2023/12/21
*/
public class FineCombinationButtonUI extends FlatPanelUI {
@Styleable(dot = true)
protected Color background;
@Styleable(dot = true)
protected int arc;
@Styleable(dot = true)
protected Color borderColor;
/**
* @param shared
* @since 2
*/
protected FineCombinationButtonUI(boolean shared) {
super(shared);
}
/**
* 创建UI
*
* @param c 组件
* @return ComponentUI
*/
public static ComponentUI createUI(JComponent c) {
return new FineCombinationButtonUI(false);
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
background = FineUIUtils.getUIColor("CombinationButton.background", "desktop");
borderColor = FineUIUtils.getUIColor("CombinationButton.borderColor", "CombinationButton.secondary.background");
arc = FineUIUtils.getUIInt("CombinationButton.arc", "Component.arc");
}
@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
}
@Override
public void paint(Graphics g, JComponent c) {
paintBackground(g, c);
super.paint(g, c);
}
protected void paintBackground(Graphics g, JComponent c) {
FlatUIUtils.setRenderingHints(g);
g.setColor(background);
g.fillRoundRect(0, 0, c.getWidth(), c.getHeight(), arc, arc);
}
@Override
public void propertyChange(PropertyChangeEvent e) {
super.propertyChange(e);
switch (e.getPropertyName()) {
case FineClientProperties.STYLE_CLASS:
UICombinationButton b = (UICombinationButton) e.getSource();
b.setPrimary();
b.repaint();
break;
default:
break;
}
}
}

2
designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java

@ -165,6 +165,7 @@ public class FineLightIconSet extends AbstractIconSet {
new SvgIconSource("chart_line", "com/fine/theme/icon/chart/chart_line.svg", true), new SvgIconSource("chart_line", "com/fine/theme/icon/chart/chart_line.svg", true),
new SvgIconSource("popup", "com/fine/theme/icon/popup/popup.svg", true), new SvgIconSource("popup", "com/fine/theme/icon/popup/popup.svg", true),
new SvgIconSource("clear", "com/fine/theme/icon/clear.svg", true), new SvgIconSource("clear", "com/fine/theme/icon/clear.svg", true),
new SvgIconSource("clear_hover", "com/fine/theme/icon/clear_hover.svg", true),
// 工具栏 // 工具栏
new SvgIconSource("tool_copy", "com/fine/theme/icon/toolbar/copy.svg", true), new SvgIconSource("tool_copy", "com/fine/theme/icon/toolbar/copy.svg", true),
@ -172,6 +173,7 @@ public class FineLightIconSet extends AbstractIconSet {
new SvgIconSource("move_up", "com/fine/theme/icon/toolbar/move_up.svg", true), new SvgIconSource("move_up", "com/fine/theme/icon/toolbar/move_up.svg", true),
new SvgIconSource("tool_edit", "com/fine/theme/icon/toolbar/edit.svg", true), new SvgIconSource("tool_edit", "com/fine/theme/icon/toolbar/edit.svg", true),
new SvgIconSource("tool_edit_white", "com/fine/theme/icon/toolbar/edit_white.svg", true), new SvgIconSource("tool_edit_white", "com/fine/theme/icon/toolbar/edit_white.svg", true),
new SvgIconSource("tool_more", "com/fine/theme/icon/toolbar/more.svg", true),
// 参数面板 // 参数面板
new SvgIconSource("param_edit", "com/fine/theme/icon/param/edit.svg", true, 24), new SvgIconSource("param_edit", "com/fine/theme/icon/param/edit.svg", true, 24),

407
designer-base/src/main/java/com/fine/theme/light/ui/FineTemplateTabPaneUI.java

@ -0,0 +1,407 @@
package com.fine.theme.light.ui;
import com.fine.theme.icon.LazyIcon;
import com.fine.theme.utils.FineClientProperties;
import com.fine.theme.utils.FineUIUtils;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.fr.base.GraphHelper;
import com.fr.base.vcs.DesignerMode;
import com.fr.design.file.MultiTemplateTabPane;
import com.fr.stable.collections.combination.Pair;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.PanelUI;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import static com.fine.theme.utils.FineUIScale.scale;
import static com.fine.theme.utils.FineUIUtils.paintRoundTabBorder;
import static com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
/**
* 文件Tab栏UI
*
* @author vito
* @since 11.0
* Created on 2023/12/27
*/
public class FineTemplateTabPaneUI extends PanelUI {
private MultiTemplateTabPane tabPane;
private static final String ELLIPSIS = "...";
private static final int ICON_TEXT_GAP = 4;
private static final int LEADING_WIDTH = 0;
private static final int TRAILING_WIDTH = 34;
@Styleable(dot = true)
protected Color background;
@Styleable(dot = true)
protected Color selectedBackground;
@Styleable(dot = true)
protected Color hoverColor;
@Styleable(dot = true)
protected Color closeIconHoverBackground;
@Styleable(dot = true)
protected Color closeHoverBackground;
@Styleable(dot = true)
protected Color borderColor;
@Styleable(dot = true)
protected int tabHeight;
@Styleable(dot = true)
protected int separatorHeight;
@Styleable(dot = true)
protected int borderWidth;
@Styleable(dot = true)
protected int tabArc;
@Styleable(dot = true)
protected Insets tabInsets;
protected Icon fileIcon;
protected Icon moreAction;
protected Icon addAction;
protected Icon moreHoverAction;
private Icon closeIcon;
private Icon closeHoverIcon;
private int leadingWidth;
private int trailingWidth;
protected FineTemplateTabPaneUI() {
}
/**
* 创建UI
*
* @param c 组件
* @return ComponentUI
*/
public static ComponentUI createUI(JComponent c) {
return new FineTemplateTabPaneUI();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
this.tabPane = (MultiTemplateTabPane) c;
closeIcon = new LazyIcon("clear");
closeHoverIcon = new LazyIcon("clear_hover");
addAction = new LazyIcon("add_worksheet");
moreAction = new LazyIcon("tool_more");
moreHoverAction = new LazyIcon("clear_hover");
fileIcon = new LazyIcon("cpt_icon");
FineClientProperties.setStyle(tabPane, "Default");
leadingWidth = scale(LEADING_WIDTH);
trailingWidth = scale(TRAILING_WIDTH);
borderWidth = FineUIUtils.getUIInt("TemplateTabPane.borderWidth", "TemplateTabPane.borderWidth");
tabArc = FineUIUtils.getUIInt("TemplateTabPane.tabArc", "TemplateTabPane.tabArc");
background = FineUIUtils.getUIColor("TemplateTabPane.background", "TabbedPane.background");
selectedBackground = FineUIUtils.getUIColor("TemplateTabPane.selectedBackground", "TemplateTabPane.selectedBackground");
closeHoverBackground = FineUIUtils.getUIColor("TemplateTabPane.closeHoverBackground", "TemplateTabPane.closeHoverBackground");
borderColor = FineUIUtils.getUIColor("TemplateTabPane.borderColor", "TabbedPane.tabSeparatorColor");
hoverColor = FineUIUtils.getUIColor("TemplateTabPane.hoverColor", "TemplateTabPane.hoverColor");
closeIconHoverBackground = FineUIUtils.getUIColor("TemplateTabPane.icon.hoverBackground ", "TemplateTabPane.icon.hoverBackground ");
// ---- scaled ----
tabInsets = FineUIUtils.getAndScaleUIInsets("TemplateTabPane.tabInsets", new Insets(4, 6, 4, 6));
tabHeight = FineUIUtils.getAndScaleInt("TemplateTabPane.tabHeight", "TabbedPane.tabHeight");
separatorHeight = FineUIUtils.getAndScaleInt("TemplateTabPane.separatorHeight", "TemplateTabPane.separatorHeight");
}
@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
}
@Override
public void update(Graphics g, JComponent c) {
super.update(g, c);
double maxWidth = c.getWidth() - leadingWidth - trailingWidth;
Graphics2D g2d = (Graphics2D) g;
paintDefaultBackground(g2d);
paintPaneUnderLine(c.getWidth(), g2d);
paintTabs(g2d, maxWidth);
}
private void paintDefaultBackground(Graphics2D g2d) {
//画默认背景
g2d.setPaint(new GradientPaint(0, 0, tabPane.getBackground(), 1, (float) (tabHeight), tabPane.getBackground()));
g2d.fillRect(0, 0, tabPane.getWidth(), tabHeight);
}
private void paintPaneUnderLine(float w, Graphics2D g2d) {
g2d.setPaint(borderColor);
float h = (float) tabHeight;
int t = scale(borderWidth);
Path2D border = new Path2D.Float(Path2D.WIND_EVEN_ODD);
border.append(FlatUIUtils.createComponentRectangle(0, 0, w, h, 0), false);
border.append(FlatUIUtils.createComponentRectangle(0, 0, w, h - t, 0), false);
g2d.fill(border);
}
private void paintTabs(Graphics2D g2d, double maxWidth) {
int maxStringlength = calculateStringMaxLength();
if (tabPane.getSelectedIndex() >= tabPane.getTabCount()) {
tabPane.setSelectedIndex(tabPane.getTabCount() - 1);
}
if (tabPane.getSelectedIndex() < 0) {
tabPane.setSelectedIndex(0);
}
double templateStartX = leadingWidth;
//从可以开始展示在tab面板上的tab开始画
Pair<Integer, Integer> viewRange = tabPane.getViewRange();
for (int i = viewRange.getFirst(); i <= viewRange.getSecond(); i++) {
Icon icon = tabPane.getTemplateIconByIndex(i);
String name = tabPane.getTemplateShowNameByIndex(i);
//如果tab名字的长度大于最大能显示的英文字符长度,则进行省略号处理
if (getStringWidth(name) > maxStringlength) {
name = getEllipsisName(name, maxStringlength);
}
Icon tabcloseIcon = tabPane.isCloseCurrent(i) ? closeHoverIcon : closeIcon;
if (i == tabPane.getSelectedIndex()) {
paintSelectedTab(g2d, icon, templateStartX, name, tabcloseIcon);
} else {
paintUnSelectedTab(g2d, icon, templateStartX, name, tabcloseIcon,
tabPane.getHoverIndex(), i);
}
templateStartX += tabPane.getTabWidth();
}
paintSeparators(g2d);
if (!DesignerMode.isVcsMode()) {
paintTrailingAction(g2d, maxWidth);
}
}
private void paintSeparators(Graphics2D g2d) {
g2d.setPaint(borderColor);
float x = leadingWidth;
Pair<Integer, Integer> viewRange = tabPane.getViewRange();
for (int i = viewRange.getFirst(); i <= viewRange.getSecond(); i++) {
if (i != tabPane.getSelectedIndex()
&& i + 1 != tabPane.getSelectedIndex()) {
paintSeparator(g2d, x);
}
x += tabPane.getTabWidth();
}
}
private void paintLeadingAction(Graphics2D g2d, double tabPaneWidth) {
int x = (leadingWidth - addAction.getIconWidth()) / 2;
int y = (tabHeight - addAction.getIconHeight()) / 2;
if (tabPane.isHoverMoreAction()) {
closeHoverIcon.paintIcon(tabPane, g2d, x, y);
} else {
addAction.paintIcon(tabPane, g2d, x, y);
}
}
private void paintTrailingAction(Graphics2D g2d, double tabPaneWidth) {
int x = leadingWidth + (int) tabPaneWidth + (trailingWidth - moreAction.getIconWidth()) / 2;
int y = (tabHeight - moreAction.getIconHeight()) / 2;
if (tabPane.isHoverMoreAction()) {
closeHoverIcon.paintIcon(tabPane, g2d, x, y);
} else {
moreAction.paintIcon(tabPane, g2d, x, y);
}
}
/**
* 判断tab文字的长度大于能装下的最大文字长度要用省略号
*
* @param name
* @param maxStringlength
* @return
*/
private String getEllipsisName(String name, int maxStringlength) {
int ellipsisWidth = getStringWidth(ELLIPSIS);
int leftkeyPoint = 0;
int rightKeyPoint = name.length() - 1;
int leftStrWidth = 0;
int rightStrWidth = 0;
while (leftStrWidth + rightStrWidth + ellipsisWidth < maxStringlength) {
if (leftStrWidth <= rightStrWidth) {
leftkeyPoint++;
} else {
rightKeyPoint--;
}
leftStrWidth = getStringWidth(name.substring(0, leftkeyPoint));
rightStrWidth = getStringWidth(name.substring(rightKeyPoint));
if (leftStrWidth + rightStrWidth + ellipsisWidth > maxStringlength) {
if (leftStrWidth <= rightStrWidth) {
rightKeyPoint++;
} else {
leftkeyPoint--;
}
break;
}
}
return name.substring(0, leftkeyPoint) + ELLIPSIS + name.substring(rightKeyPoint);
}
/**
* 计算过长度之后的每个tab的能接受的文字的英文字符数
*
* @return
*/
private int calculateStringMaxLength() {
return tabPane.getTabWidth()
- tabInsets.left - tabInsets.right
- ICON_TEXT_GAP * 2
- fileIcon.getIconWidth() - closeIcon.getIconWidth();
}
private int getStringWidth(String str) {
FontMetrics fm = GraphHelper.getFontMetrics(tabPane.getFont());
int size = 0;
for (int i = 0; i < str.length(); i++) {
size += fm.charWidth(str.codePointAt(i));
}
return size;
}
/**
* 画选中的tab
*
* @param g2d
* @param sheeticon
* @param templateStartX
* @param sheetName
* @param closeIcon
* @return
*/
private void paintSelectedTab(Graphics2D g2d, Icon sheeticon, double templateStartX, String sheetName, Icon closeIcon) {
Object[] oriRenderingHints = FlatUIUtils.setRenderingHints(g2d);
// 绘制选中背景
g2d.setPaint(selectedBackground);
Path2D tabShape = FineUIUtils.createTopRoundRectangle(templateStartX, 0,
tabPane.getTabWidth(), tabHeight, tabArc);
g2d.fill(tabShape);
// 绘制选中边框
g2d.setPaint(borderColor);
paintRoundTabBorder(g2d, templateStartX, 0,
tabPane.getTabWidth(), tabHeight, borderWidth, (float) tabArc);
FlatUIUtils.resetRenderingHints(g2d, oriRenderingHints);
// 绘制图标
int sheetIconY = (tabHeight - sheeticon.getIconHeight()) / 2;
sheeticon.paintIcon(tabPane, g2d, (int) templateStartX + tabInsets.left, sheetIconY);
// 绘制字符
g2d.setPaint(tabPane.getForeground());
Point2D.Double textPoint = calTextPoint(templateStartX, sheeticon.getIconWidth());
g2d.drawString(sheetName, (int) textPoint.x, (int) textPoint.y);
int closePosition = (int) templateStartX + tabPane.getTabWidth()
- this.closeIcon.getIconWidth() - tabInsets.right;
int closeY = (tabHeight - closeIcon.getIconHeight()) / 2;
if (!DesignerMode.isVcsMode()) {
closeIcon.paintIcon(tabPane, g2d, closePosition, closeY);
}
}
private Point2D.Double calTextPoint(double x, int iconWidth) {
FontMetrics fm = tabPane.getFontMetrics(tabPane.getFont());
int ascent = fm.getAscent();
int gap = (tabHeight - tabInsets.top - tabInsets.bottom - ascent) / 2;
double y = tabInsets.top + ascent + gap;
return new Point2D.Double(x + iconWidth + tabInsets.left + ICON_TEXT_GAP, y);
}
/**
* 画没有选中的tab
*
* @param g2d
* @param sheeticon
* @param templateStartX
* @param sheetName
* @param closeIcon
*/
private void paintUnSelectedTab(Graphics2D g2d, Icon sheeticon, double templateStartX, String sheetName, Icon closeIcon, int mouseOveredIndex, int selfIndex) {
if (selfIndex == mouseOveredIndex) {
g2d.setPaint(hoverColor);
} else {
g2d.setPaint(background);
}
Object[] oriRenderingHints = FlatUIUtils.setRenderingHints(g2d);
Path2D tabShape = FineUIUtils.createTopRoundRectangle(templateStartX, 0,
tabPane.getTabWidth(), tabHeight - scale(borderWidth), tabArc);
g2d.fill(tabShape);
FlatUIUtils.resetRenderingHints(g2d, oriRenderingHints);
int sheetIconY = (tabHeight - sheeticon.getIconHeight()) / 2;
sheeticon.paintIcon(tabPane, g2d, (int) templateStartX + tabInsets.left, sheetIconY);
// 画字符
g2d.setPaint(tabPane.getForeground());
Point2D.Double textPoint = calTextPoint(templateStartX, sheeticon.getIconWidth());
g2d.drawString(sheetName, (int) textPoint.x, (int) textPoint.y);
int closeY = (tabHeight - closeIcon.getIconHeight()) / 2;
int closePosition = (int) templateStartX + tabPane.getTabWidth()
- this.closeIcon.getIconWidth() - tabInsets.right;
if (!DesignerMode.isVcsMode()) {
closeIcon.paintIcon(tabPane, g2d, closePosition, closeY);
}
}
private void paintSeparator(Graphics2D g2d, float templateStartX) {
float x = templateStartX + tabPane.getTabWidth();
float gap = (tabHeight - separatorHeight) / 2.0f;
g2d.fill(new Rectangle2D.Float(x, gap, scale(borderWidth), tabHeight - gap * 2));
}
@Override
public Dimension getPreferredSize(JComponent c) {
return new Dimension(c.getWidth(), tabHeight);
}
@Override
public Dimension getMinimumSize(JComponent c) {
return new Dimension(0, tabHeight);
}
@Override
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
}

77
designer-base/src/main/java/com/fine/theme/utils/FineClientProperties.java

@ -1,7 +1,10 @@
package com.fine.theme.utils; package com.fine.theme.utils;
import com.finebi.cbb.utils.StringUtils;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import javax.swing.JComponent;
/** /**
* FR-UI中使用的各类属性 * FR-UI中使用的各类属性
* *
@ -13,4 +16,78 @@ public interface FineClientProperties extends FlatClientProperties {
String BUTTON_TYPE_GROUP = "group"; String BUTTON_TYPE_GROUP = "group";
String STYLE_PRIMARY = "primary";
String STYLE_SECONDARY = "secondary";
String STYLE_SIZE_MEDIUM = "medium";
String STYLE_SIZE_SMALL = "small";
String BUTTON_TYPE_LEFT_ROUND_RECT = "leftRoundRect";
String BUTTON_TYPE_RIGHT_ROUND_RECT = "rightRoundRect";
/**
* 添加组件的样式类类似css该方法会接在原样式后方
* <code>
* FineClientProperties.appendStyle("primary small")
* </code>
*
* @param it 组件
* @param styleClass 样式字符串支持连续添加类用空格
*/
static void appendStyle(JComponent it, String styleClass) {
Object oriProperty = it.getClientProperty(FineClientProperties.STYLE_CLASS);
if (oriProperty instanceof String && StringUtils.isNotBlank((String) oriProperty)) {
styleClass = oriProperty + " " + styleClass;
}
it.putClientProperty(FineClientProperties.STYLE_CLASS, styleClass);
}
/**
* 设置组件的样式类类似css该方法会替换原样式
* <code>
* FineClientProperties.setStyle("primary small")
* </code>
*
* @param jComponent 组件
* @param styleClass 样式字符串支持连续添加类用空格
*/
static void setStyle(JComponent jComponent, String styleClass) {
jComponent.putClientProperty(FineClientProperties.STYLE_CLASS, styleClass);
}
/**
* 样式组合
*
* @param styleClasses 所有样式
* @return 样式列表
*/
static String join(String... styleClasses) {
final StringBuilder sb = new StringBuilder();
for (final String style : styleClasses) {
if (style == null) {
continue;
}
if (sb.length() > 0) {
sb.append(" ");
}
sb.append(style);
}
return sb.toString();
}
/**
* 包含样式
*
* @param jComponent 组件
* @param styleClass 样式
* @return 是否包含指定的样式
*/
static boolean hasStyle(JComponent jComponent, String styleClass) {
Object style = jComponent.getClientProperty(FineClientProperties.STYLE_CLASS);
if (style instanceof String && StringUtils.isNotBlank((String) style)) {
return ((String) style).contains(styleClass);
}
return false;
}
} }

128
designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java

@ -6,15 +6,20 @@ import com.fr.value.AtomicClearableLazyValue;
import javax.swing.UIManager; import javax.swing.UIManager;
import java.awt.Color; import java.awt.Color;
import java.awt.Component;
import java.awt.Composite; import java.awt.Composite;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.Insets; import java.awt.Insets;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import static com.fine.theme.light.ui.FineButtonUI.isLeftRoundButton;
import static com.formdev.flatlaf.util.UIScale.scale;
/** /**
* UI绘制的一些常用方法 * UI绘制的一些常用方法
* *
@ -178,4 +183,127 @@ public class FineUIUtils {
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
} }
/**
* 绘制部分圆角矩形边框
*
* @param g2 Graphics2D
* @param x x坐标
* @param y y坐标
* @param width 宽度
* @param height 高度
* @param borderWidth 边框宽度
* @param arc 圆角
*/
public static void paintPartRoundButtonBorder(Component c, Graphics2D g2, int x, int y, int width, int height,
float borderWidth, float arc) {
FlatUIUtils.setRenderingHints(g2);
arc = scale(arc);
float t = scale(borderWidth);
float t2x = t * 2;
Path2D path2D = new Path2D.Float(Path2D.WIND_EVEN_ODD);
if (isLeftRoundButton(c)) {
path2D.append(createLeftRoundRectangle(x, y, width, height, arc), false);
path2D.append(createLeftRoundRectangle(x + t, y + t, width - t, height - t2x, arc - t), false);
} else {
path2D.append(createRightRoundRectangle(x, y, width, height, arc), false);
path2D.append(createRightRoundRectangle(x, y + t, width - t, height - t2x, arc - t), false);
}
g2.fill(path2D);
}
/**
* 绘制圆角tab边框
*
* @param g2 Graphics2D
* @param x x坐标
* @param y y坐标
* @param width 宽度
* @param height 高度
* @param borderWidth 边框宽度
* @param arc 圆角
*/
public static void paintRoundTabBorder(Graphics2D g2, double x, double y, double width, double height,
float borderWidth, float arc) {
FlatUIUtils.setRenderingHints(g2);
arc = scale(arc);
float t = scale(borderWidth);
float t2x = t * 2;
Path2D path2D = new Path2D.Float(Path2D.WIND_EVEN_ODD);
path2D.append(createTopRoundRectangle(x, y, width, height, arc), false);
path2D.append(createTopRoundRectangle(x + t, y + t, width - t2x, height - t, arc - t), false);
g2.fill(path2D);
}
/**
* 创建一个左圆角矩形路径
*
* @param x x坐标
* @param y y坐标
* @param width 矩形宽度
* @param height 矩形高度
* @param arc 圆角弧度
* @return 路径
*/
public static Path2D createLeftRoundRectangle(float x, float y, float width, float height, float arc) {
Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD, 7);
path.moveTo(x, y + arc);
path.lineTo(x, y + height - arc);
path.quadTo(x, y + height, x + arc, y + height);
path.lineTo(x + width, y + height);
path.lineTo(x + width, y);
path.lineTo(x + arc, y);
path.quadTo(x, y, x, arc + y);
path.closePath();
return path;
}
/**
* 创建一个右圆角矩形路径
*
* @param x x坐标
* @param y y坐标
* @param width 矩形宽度
* @param height 矩形高度
* @param arc 圆角弧度
* @return 路径
*/
public static Path2D createRightRoundRectangle(float x, float y, float width, float height, float arc) {
Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD, 7);
path.moveTo(x, y);
path.lineTo(x, y + height);
path.lineTo(x + width - arc, y + height);
path.quadTo(x + width, y + height, x + width, y + height - arc);
path.lineTo(x + width, y + arc);
path.quadTo(x + width, y, x + width - arc, y);
path.lineTo(x, y);
path.closePath();
return path;
}
/**
* 创建一个顶圆角矩形路径
*
* @param x x坐标
* @param y y坐标
* @param width 矩形宽度
* @param height 矩形高度
* @param arc 圆角弧度
* @return 路径
*/
public static Path2D createTopRoundRectangle(double x, double y, double width, double height, double arc) {
Path2D path = new Path2D.Double(Path2D.WIND_EVEN_ODD, 7);
path.moveTo(x, y + height);
path.lineTo(x, y + arc);
path.quadTo(x, y, x + arc, y);
path.lineTo(x + width - arc, y);
path.quadTo(x + width, y, x + width, y + arc);
path.lineTo(x + width, y + height);
path.lineTo(x, y + height);
path.closePath();
return path;
}
} }

655
designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java

@ -1,8 +1,7 @@
package com.fr.design.file; package com.fr.design.file;
import com.fr.base.GraphHelper; import com.fine.theme.icon.LazyIcon;
import com.fr.base.svg.IconUtils;
import com.fr.base.vcs.DesignerMode; import com.fr.base.vcs.DesignerMode;
import com.fr.design.actions.UpdateAction; import com.fr.design.actions.UpdateAction;
import com.fr.design.actions.file.LocateAction; import com.fr.design.actions.file.LocateAction;
@ -15,67 +14,45 @@ import com.fr.design.i18n.DesignSizeI18nManager;
import com.fr.design.i18n.Toolkit; import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.TemplateSavingChecker;
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager; import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.gui.GUIPaintUtils;
import com.fr.design.worker.WorkerManager; import com.fr.design.worker.WorkerManager;
import com.fr.design.worker.save.CallbackSaveWorker; import com.fr.design.worker.save.CallbackSaveWorker;
import com.fr.file.FILE; import com.fr.file.FILE;
import com.fr.file.FileNodeFILE; import com.fr.file.FileNodeFILE;
import com.fr.general.ComparatorUtils; import com.fr.general.ComparatorUtils;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory; import com.fr.log.FineLoggerFactory;
import com.fr.stable.Constants; import com.fr.stable.collections.combination.Pair;
import com.fr.third.javax.annotation.Nonnull; import com.fr.third.javax.annotation.Nonnull;
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import com.fr.workspace.server.lock.TplOperator; import com.fr.workspace.server.lock.TplOperator;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.ButtonModel;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator; import javax.swing.JSeparator;
import javax.swing.MenuElement; import javax.swing.MenuElement;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager; import javax.swing.ToolTipManager;
import javax.swing.plaf.basic.BasicMenuItemUI;
import java.awt.AWTEvent; import java.awt.AWTEvent;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.fine.theme.utils.FineUIScale.scale;
import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog; import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION; import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.OK_OPTION; import static javax.swing.JOptionPane.OK_OPTION;
import static javax.swing.JOptionPane.WARNING_MESSAGE; import static javax.swing.JOptionPane.WARNING_MESSAGE;
// todo: 自己绘制组件
/** /**
* 改个名字一个拼写 n 个错误 * 改个名字一个拼写 n 个错误
* *
@ -84,28 +61,14 @@ import static javax.swing.JOptionPane.WARNING_MESSAGE;
* <p> * <p>
* created by daisy on 2013/08/05 * created by daisy on 2013/08/05
**/ **/
public class MultiTemplateTabPane extends JComponent { public class MultiTemplateTabPane extends JPanel {
private static Icon LIST_DOWN = IconUtils.readIcon("/com/fr/design/standard/list/list");
private static Icon MOUSE_OVER_LIST_DOWN = IconUtils.readIcon("/com/fr/design/standard/list/list_pressed.svg");
private static Icon MOUSE_PRESS_LIST_DOWN = IconUtils.readIcon("/com/fr/design/standard/list/list_pressed.svg");
private static Icon CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close");
private static Icon MOUSE_OVER_CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close_mouseover.svg");
private static Icon MOUSE_PRESS_CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close_press.svg");
private static final Icon WHITE_SAVING_CLOSE_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/file/white_saving_close.gif"));
private static final Icon GREY_SAVING_CLOSE_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/file/grey_saving_close.gif"));
private static final String ELLIPSIS = "...";
private static final int GAP = 5;
private static final int SMALLGAP = 3;
private static final int LIST_BUTTON_WIDTH = 34;
private static final int HEIGHT = 26;
private static final int LIST_DOWN_HEIGHT = 25;
private static final double CORNOR_RADIUS = 0.0;
//选了30度和60度的特殊角度的x,y作为经过的两个点的坐标
private static final double SPECIAL_LOCATION_1 = 2.5;
private static final double SPECIAL_LOCATION_2 = 4.330127;
private static final int ICON_WIDTH = 22;
private static final String UI_CLASS_ID = "TemplateTabPaneUI";
private static final int GAP = 6;
private static final int SMALLGAP = 4;
private static final int TRAILING_WIDTH = 34;
private static final int LEADING_WIDTH = 38;
//每个标签页的最大的长度和最小长度。这些长度均为均分 //每个标签页的最大的长度和最小长度。这些长度均为均分
@ -122,8 +85,7 @@ public class MultiTemplateTabPane extends JComponent {
private int mouseOveredIndex = -1; private int mouseOveredIndex = -1;
//tab栏可以放下的每个tab的实际宽度 //tab栏可以放下的每个tab的实际宽度
private int realWidth = MAXWIDTH; private int tabWidth;
//当前标签页栏存放的所有标签页的index //当前标签页栏存放的所有标签页的index
private int minPaintIndex = 0; private int minPaintIndex = 0;
@ -132,13 +94,12 @@ public class MultiTemplateTabPane extends JComponent {
//每个关闭图标的起始位置 //每个关闭图标的起始位置
private int[] startX; private int[] startX;
private boolean[] isNeedToolTips;
//记录关闭按钮的状态 //记录关闭按钮的状态
private int closeIconIndex = -1; private int closeIconIndex = -1;
private boolean isCloseCurrent = false; private boolean isCloseCurrent = false;
private Icon clodeMode = CLOSE; private boolean hoverMoreAction = false;
private Icon listDownMode = LIST_DOWN; private Icon clodeIcon = new LazyIcon("clear");
private boolean isShowList = false; private boolean isShowList = false;
//自动新建的模板B若没有进行任何编辑,切换到其他 //自动新建的模板B若没有进行任何编辑,切换到其他
@ -146,10 +107,14 @@ public class MultiTemplateTabPane extends JComponent {
// 模板时,模板B会自动关闭 // 模板时,模板B会自动关闭
private JTemplate<?, ?> temTemplate = null; private JTemplate<?, ?> temTemplate = null;
// private final Color selectedColor = UIManager.getColor("TabbedPane.hoverColor"); @Override
// private Color hoverColor = UIManager.getColor("TabbedPane.inactiveUnderlineColor"); public String getUIClassID() {
return UI_CLASS_ID;
}
/**
* 单例
*/
public static MultiTemplateTabPane getInstance() { public static MultiTemplateTabPane getInstance() {
if (THIS == null) { if (THIS == null) {
THIS = new MultiTemplateTabPane(); THIS = new MultiTemplateTabPane();
@ -162,27 +127,19 @@ public class MultiTemplateTabPane extends JComponent {
* 多工作簿面板 * 多工作簿面板
*/ */
public MultiTemplateTabPane() { public MultiTemplateTabPane() {
this.setLayout(new BorderLayout(0, 0));
this.addMouseListener(new MultiTemplateTabMouseListener()); this.addMouseListener(new MultiTemplateTabMouseListener());
this.addMouseMotionListener(new MultiTemplateTabMouseMotionListener()); this.addMouseMotionListener(new MultiTemplateTabMouseMotionListener());
this.setBorder(null); this.setBorder(null);
// this.setForeground(new Color(58, 56, 58));
this.setFont(DesignUtils.getDefaultGUIFont().applySize(12));
openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList(); openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList();
selectedIndex = openedTemplate.size() - 1; selectedIndex = openedTemplate.size() - 1;
AWTEventListener awt = new AWTEventListener() { java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(event -> {
@Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent) { if (event instanceof MouseEvent) {
MouseEvent mv = (MouseEvent) event; MouseEvent mv = (MouseEvent) event;
if (mv.getClickCount() > 0 && !ComparatorUtils.equals(mv.getSource(), MultiTemplateTabPane.this)) { if (mv.getClickCount() > 0 && !ComparatorUtils.equals(mv.getSource(), MultiTemplateTabPane.this)) {
isShowList = false; isShowList = false;
} }
} }
} }, AWTEvent.MOUSE_EVENT_MASK);
};
java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK);
addMouseListener(new MouseAdapter() { addMouseListener(new MouseAdapter() {
@Override @Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
@ -229,6 +186,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 判断模板是否可以关闭两个条件1是否满足CloseOption里面的条件在左侧在右侧等2是否和当前正在编辑模板属于同一种模板tab操作类型 * 判断模板是否可以关闭两个条件1是否满足CloseOption里面的条件在左侧在右侧等2是否和当前正在编辑模板属于同一种模板tab操作类型
*
* @param closeJTemplate * @param closeJTemplate
* @param tplIndex * @param tplIndex
* @param i * @param i
@ -417,6 +375,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 关闭所有指定模板tab操作类型的模板 * 关闭所有指定模板tab操作类型的模板
*
* @param operatorType * @param operatorType
*/ */
public void closeOtherByOperatorType(String operatorType) { public void closeOtherByOperatorType(String operatorType) {
@ -438,6 +397,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 关闭指定的非当前编辑模板 * 关闭指定的非当前编辑模板
*
* @param templates * @param templates
* @param operatorType * @param operatorType
*/ */
@ -471,91 +431,19 @@ public class MultiTemplateTabPane extends JComponent {
} }
@Override
public Dimension getPreferredSize() {
Dimension dimension = super.getPreferredSize();
dimension.height = HEIGHT;
return dimension;
}
private UIMenuItem initCloseOther() {
UIMenuItem closeOther = new UIMenuItem(Toolkit.i18nText("Fine-Design_Basic_FS_Close_Other_Templates"));
// Yvan: 英文下文本显示不全,后续发现如果将模板名设置的比较短,其它语言也会出现显示不全的问题,所以设置一下文本水平居中
closeOther.setHorizontalAlignment(SwingConstants.CENTER);
setListDownItemPreferredSize(closeOther);
closeOther.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (openedTemplate.size() == 1) {
return;
}
if (!TemplateSavingChecker.check()) {
return;
}
SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false);
//点击关闭其他模板,并且点击确定保存
if (saveSomeTempaltePane.showSavePane()) {
JTemplate<?, ?>[] panes = new JTemplate<?, ?>[openedTemplate.size()];
for (int i = 0; i < openedTemplate.size(); i++) {
panes[i] = openedTemplate.get(i);
}
for (int i = 0; i < panes.length; i++) {
if (i != selectedIndex) {
JTemplate<?, ?> jTemplate = panes[i];
//判断关闭的模板是不是格式刷的被参照的模板
openedTemplate.remove(jTemplate);
closeFormat(jTemplate);
HistoryTemplateListCache.getInstance().closeSelectedReport(jTemplate);
closeAndFreeLock(jTemplate);
}
}
JTemplate<?, ?> currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
HistoryTemplateListCache.getInstance().removeAllHistory();
DesignerContext.getDesignerFrame().activateJTemplate(currentTemplate);
THIS.repaint();
}
//如果取消保存了,则不关闭其他模板
}
});
if (openedTemplate.size() == 1) {
closeOther.setEnabled(false);
}
return closeOther;
}
private UIMenuItem[] createListDownTemplate() { private String tempalteShowName(JTemplate<?, ?> template) {
UIMenuItem[] templates = new UIMenuItem[openedTemplate.size()]; return template.getTabShowName(template);
for (int i = 0; i < openedTemplate.size(); i++) {
final int index = i;
final JTemplate tem = openedTemplate.get(i);
templates[i] = new UIMenuItem(tempalteShowName(tem), tem.getIcon());
// templates[i].setUI(new UIListDownItemUI());
setListDownItemPreferredSize(templates[i]);
if (i == selectedIndex) {
//画选中的高亮
// templates[i].setBackground(UIConstants.SHADOW_CENTER);
}
templates[i].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
selectedIndex = index;
tem.activeNewJTemplate();
}
});
}
return templates;
} }
private void setListDownItemPreferredSize(UIMenuItem item) { public String getTemplateShowNameByIndex(int index) {
Dimension dimension = item.getPreferredSize(); JTemplate template = openedTemplate.get(index);
dimension.height = LIST_DOWN_HEIGHT; return template.getTabShowName(template);
item.setPreferredSize(dimension);
} }
public Icon getTemplateIconByIndex(int index) {
private String tempalteShowName(JTemplate<?, ?> template) { JTemplate template = openedTemplate.get(index);
return template.getTabShowName(template); return template.getIcon();
} }
/** /**
@ -585,145 +473,23 @@ public class MultiTemplateTabPane extends JComponent {
@Override @Override
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
super.paintComponent(g);
double maxWidth = getWidth() - LIST_BUTTON_WIDTH * 1.0D; //最大宽度
Graphics2D g2d = (Graphics2D) g;
paintBackgroundAndLine(g2d, maxWidth);
}
@Override double maxWidth = getWidth() - scale(TRAILING_WIDTH) - scale(LEADING_WIDTH); //最大宽度
public void paint(Graphics g) { int maxTemplateNum = (int) (maxWidth) / scale(MINWIDTH);
//不可见时,按钮.4f透明
AlphaComposite composite = DesignerMode.isVcsMode()
? AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)
: (AlphaComposite) ((Graphics2D) g).getComposite();
((Graphics2D) g).setComposite(composite);
super.paint(g);
}
private void paintBackgroundAndLine(Graphics2D g2d, double maxWidth) {
paintDefaultBackground(g2d);
//最多能画的个数
int maxTemplateNum = (int) (maxWidth) / MINWIDTH;
//计算开始画的最小模板index和最大模板index
calMinAndMaxIndex(maxTemplateNum); calMinAndMaxIndex(maxTemplateNum);
calculateRealAverageWidth(maxWidth, maxTemplateNum); calculateRealAverageWidth(maxWidth, maxTemplateNum);
int maxStringlength = calculateStringMaxLength(); calculateClosePosition();
if (selectedIndex >= openedTemplate.size()) { super.paintComponent(g);
selectedIndex = openedTemplate.size() - 1;
}
if (selectedIndex < 0) {
selectedIndex = 0;
}
double templateStartX = 0;
startX = new int[maxPaintIndex - minPaintIndex + 1];
isNeedToolTips = new boolean[maxPaintIndex - minPaintIndex + 1];
//从可以开始展示在tab面板上的tab开始画
for (int i = minPaintIndex; i <= maxPaintIndex; i++) {
JTemplate template = openedTemplate.get(i);
if (!showJTemplateTab(template)){
continue;
}
Icon icon = template.getIcon();
String name = tempalteShowName(template);
//如果tab名字的长度大于最大能显示的英文字符长度,则进行省略号处理
if (getStringWidth(name) > maxStringlength) {
name = getEllipsisName(name, maxStringlength);
isNeedToolTips[i - minPaintIndex] = true;
} else {
isNeedToolTips[i - minPaintIndex] = false;
}
Icon selectedIcon;
if (i == closeIconIndex) {
selectedIcon = clodeMode;
} else {
selectedIcon = CLOSE;
}
if (i == selectedIndex) {
if (template.isSaving()) {
selectedIcon = WHITE_SAVING_CLOSE_ICON;
}
startX[i - minPaintIndex] = paintSelectedTab(g2d, icon, templateStartX, name, selectedIcon);
} else {
if (template.isSaving()) {
selectedIcon = GREY_SAVING_CLOSE_ICON;
}
boolean isLeft = i < selectedIndex;
startX[i - minPaintIndex] = paintUnSelectedTab(g2d, icon, templateStartX, name, selectedIcon, isLeft, mouseOveredIndex, i);
}
templateStartX += realWidth;
}
if (!DesignerMode.isVcsMode()) {
paintListDown(g2d, maxWidth);
}
paintUnderLine(templateStartX, maxWidth, g2d);
}
private void paintUnderLine(double templateStartX, double maxWidth, Graphics2D g2d) {
//画下面的那条线
if (templateStartX < maxWidth) {
GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, 2);
generalPath.moveTo((float) templateStartX, (float) (getHeight() - 1.0D));
generalPath.lineTo((float) maxWidth, (float) (getHeight() - 1.0D));
g2d.fill(generalPath);
//TODO hzzz delete
// g2d.setPaint(UIConstants.LINE_COLOR);
// g2d.draw(new Line2D.Double((float) templateStartX, getHeight() - 1, (float) maxWidth + LIST_BUTTON_WIDTH, getHeight() - 1));
}
}
private void paintDefaultBackground(Graphics2D g2d) {
//画默认背景
g2d.setPaint(new GradientPaint(1, 1, getBackground(), 1, (float) (getHeight() - 1.0D), getBackground()));
g2d.fillRect(0, 0, getWidth(), getHeight());
}
private void paintListDown(Graphics2D g2d, double maxWidth) {
int x = (int) maxWidth + (LIST_BUTTON_WIDTH - listDownMode.getIconWidth()) / 2;
int y = (getHeight() - listDownMode.getIconHeight()) / 2;
listDownMode.paintIcon(this, g2d, x, y);
}
/**
* 判断tab文字的长度大于能装下的最大文字长度要用省略号
*
* @param name
* @param maxStringlength
* @return
*/
private String getEllipsisName(String name, int maxStringlength) {
//若是名字长度大于能显示的长度,那能显示的文字的最大长度还要减去省略号的最大长度
// int maxellipsislength = maxStringlength - ELLIPSIS.length();
int ellipsisWidth = getStringWidth(ELLIPSIS);
int leftkeyPoint = 0;
int rightKeyPoint = name.length() - 1;
int leftStrWidth = 0;
int rightStrWidth = 0;
while (leftStrWidth + rightStrWidth + ellipsisWidth < maxStringlength) {
if (leftStrWidth <= rightStrWidth) {
leftkeyPoint++;
} else {
rightKeyPoint--;
} }
leftStrWidth = getStringWidth(name.substring(0, leftkeyPoint));
rightStrWidth = getStringWidth(name.substring(rightKeyPoint));
if (leftStrWidth + rightStrWidth + ellipsisWidth > maxStringlength) { private void calculateClosePosition() {
if (leftStrWidth <= rightStrWidth) { startX = new int[maxPaintIndex - minPaintIndex + 1];
rightKeyPoint++; double templateStartX = scale(LEADING_WIDTH);
} for (int i = getViewRange().getFirst(); i <= getViewRange().getSecond(); i++) {
break; int closePosition = (int) templateStartX + getTabWidth() - clodeIcon.getIconWidth() - GAP;
} startX[i - minPaintIndex] = closePosition;
templateStartX += getTabWidth();
} }
return name.substring(0, leftkeyPoint) + ELLIPSIS + name.substring(rightKeyPoint);
} }
private void calMinAndMaxIndex(int maxTemplateNum) { private void calMinAndMaxIndex(int maxTemplateNum) {
@ -766,6 +532,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 先计算出需要补充的tab个数 * 先计算出需要补充的tab个数
*
* @return * @return
*/ */
private int calTabCountComplemented() { private int calTabCountComplemented() {
@ -821,170 +588,15 @@ public class MultiTemplateTabPane extends JComponent {
List<JTemplate<?, ?>> showTemplates = getOpenedJTemplatesByOperator(jTemplate.getTemplateTabOperatorType()); List<JTemplate<?, ?>> showTemplates = getOpenedJTemplatesByOperator(jTemplate.getTemplateTabOperatorType());
int num = Math.min(showTemplates.size(), templateNum); int num = Math.min(showTemplates.size(), templateNum);
realWidth = (int) (maxwidth / (num)); tabWidth = (int) (maxwidth / (num));
if (realWidth > MAXWIDTH) { if (tabWidth > scale(MAXWIDTH)) {
realWidth = MAXWIDTH; tabWidth = scale(MAXWIDTH);
} else if (realWidth < MINWIDTH) { } else if (tabWidth < scale(MINWIDTH)) {
//平均下来每个的宽度小于最小宽度 //平均下来每个的宽度小于最小宽度
realWidth = MINWIDTH; tabWidth = scale(MINWIDTH);
}
}
/**
* 计算过长度之后的每个tab的能接受的文字的英文字符数
*
* @return
*/
private int calculateStringMaxLength() {
return realWidth - 3 * GAP - ICON_WIDTH - SMALLGAP - CLOSE.getIconWidth();
}
private int getStringWidth(String str) {
return GraphHelper.getFontMetrics(this.getFont()).stringWidth(str);
}
/**
* 画选中的tab
*
* @param g2d
* @param sheeticon
* @param templateStartX
* @param sheetName
* @param closeIcon
* @return
*/
private int paintSelectedTab(Graphics2D g2d, Icon sheeticon, double templateStartX, String sheetName, Icon closeIcon) {
double[] x = {templateStartX, templateStartX, templateStartX + realWidth, templateStartX + realWidth, templateStartX};
double[] y = {1, getHeight() + 1, getHeight() + 1, 1, 1};
RoundRectangle2D.Double rect1 = new RoundRectangle2D.Double(templateStartX, 1, this.getWidth(), this.getHeight(), 7, 7);
g2d.setPaint(new GradientPaint(1, 1, getBackground(), (float) (getWidth() -1.0d), 1, getBackground()));
//选了30度和60度的特殊角度的x,y作为经过的两个点的坐标
double specialLocation1 = 2.5;
double specialLocation2 = 4.330127;
GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length);
generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]);
generalPath.curveTo(((float) x[0] + CORNOR_RADIUS - specialLocation1), (y[0] + CORNOR_RADIUS - specialLocation2), ((float) x[0] + CORNOR_RADIUS - specialLocation2), (y[0] + CORNOR_RADIUS - specialLocation1), x[0], y[0] + CORNOR_RADIUS);
for (int index = 1; index <= 2; index++) {
generalPath.lineTo((float) x[index], (float) y[index]);
}
generalPath.lineTo((float) x[3], (float) y[3] + CORNOR_RADIUS);
generalPath.curveTo(((float) x[3] - CORNOR_RADIUS + specialLocation1), ((float) y[3] + CORNOR_RADIUS - specialLocation2), ((float) x[3] - CORNOR_RADIUS + specialLocation2), ((float) y[3] + CORNOR_RADIUS - specialLocation1), (float) x[3] - CORNOR_RADIUS, (float) y[3]);
generalPath.lineTo((float) x[0] + CORNOR_RADIUS, (float) y[0]);
generalPath.closePath();
g2d.fill(generalPath);
// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// g2d.setPaint(Color.red);
// g2d.draw(new Arc2D.Double(x[0], y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0));
// g2d.draw(new Line2D.Double(x[0], y[0] + CORNOR_RADIUS, x[1], y[1]));
// g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2]));
// g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3] + CORNOR_RADIUS));
// g2d.draw(new Arc2D.Double(x[3] - CORNOR_RADIUS * 2, y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0));
// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
int sheetIconY = (getHeight() - sheeticon.getIconHeight()) / 2;
sheeticon.paintIcon(this, g2d, (int) templateStartX + GAP, sheetIconY);
// 画字符
g2d.setPaint(getForeground());
g2d.drawString(sheetName, (int) templateStartX + sheeticon.getIconWidth() + 2 * GAP, getHeight() - GAP * 2);
int closePosition = (int) templateStartX + realWidth - CLOSE.getIconWidth() - SMALLGAP;
int closeY = (getHeight() - closeIcon.getIconHeight()) / 2;
if (!DesignerMode.isVcsMode()) {
closeIcon.paintIcon(this, g2d, closePosition, closeY);
}
return closePosition;
}
/**
* 画没有选中的tab
*
* @param g2d
* @param sheeticon
* @param templateStartX
* @param sheetName
* @param closeIcon
* @param isLeft
* @return
*/
private int paintUnSelectedTab(Graphics2D g2d, Icon sheeticon, double templateStartX, String sheetName, Icon closeIcon, boolean isLeft, int mouseOveredIndex, int selfIndex) {
double[] x = {templateStartX, templateStartX, templateStartX + realWidth, templateStartX + realWidth, templateStartX};
double[] y = {-1, getHeight() - 1, getHeight() - 1, -1, -1};
if (selfIndex == mouseOveredIndex) {
g2d.setPaint(new GradientPaint(1, 1, getBackground(), 1, (float) (getHeight() - 1.0D), getBackground()));
} else {
g2d.setPaint(new GradientPaint(1, 1, getBackground(), 1, (float) (getHeight() - 1.0D), getBackground()));
}
GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length);
unSelectedClosedPath(generalPath, isLeft, x, y);
g2d.fill(generalPath);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(UIConstants.TEMPLATE_TAB_PANE_BACKGROUND);
//TODO hzzz delete
// if (isLeft) {
// g2d.draw(new Arc2D.Double(x[0], y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0));
// } else {
// g2d.draw(new Arc2D.Double(x[0] - CORNOR_RADIUS * 2, y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0));
// }
// g2d.draw(new Line2D.Double(x[0], y[0] + CORNOR_RADIUS, x[1], y[1] + 1));
// g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2]));
g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3] + CORNOR_RADIUS));
// if (isLeft) {
// g2d.draw(new Arc2D.Double(x[3], y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0));
// } else {
// g2d.draw(new Arc2D.Double(x[3] - CORNOR_RADIUS * 2, y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0));
// }
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
int sheetIconY = (getHeight() - sheeticon.getIconHeight()) / 2;
sheeticon.paintIcon(this, g2d, (int) templateStartX + GAP, sheetIconY);
// 画字符
g2d.setPaint(getForeground());
g2d.drawString(sheetName, (int) templateStartX + sheeticon.getIconWidth() + 2 * GAP, getHeight() - GAP * 2);
int closeY = (getHeight() - closeIcon.getIconHeight()) / 2;
int closePosition = (int) templateStartX + realWidth - CLOSE.getIconWidth() - SMALLGAP;
if (!DesignerMode.isVcsMode()) {
closeIcon.paintIcon(this, g2d, closePosition, closeY);
}
return closePosition;
}
private void unSelectedClosedPath(GeneralPath generalPath, boolean isLeft, double[] x, double[] y) {
if (isLeft) {
generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]);
generalPath.curveTo(((float) x[0] + CORNOR_RADIUS - SPECIAL_LOCATION_1), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[0] + CORNOR_RADIUS - SPECIAL_LOCATION_2), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_1), x[0], y[0] + CORNOR_RADIUS);
} else {
generalPath.moveTo((float) x[0] - CORNOR_RADIUS, (float) y[0]);
generalPath.curveTo(((float) x[0] - CORNOR_RADIUS + SPECIAL_LOCATION_1), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[0] - CORNOR_RADIUS + SPECIAL_LOCATION_2), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_1), x[0], y[0] + CORNOR_RADIUS);
} }
for (int index = 1; index <= 2; index++) {
generalPath.lineTo((float) x[index], (float) y[index]);
}
generalPath.lineTo((float) x[3], (float) y[3] + CORNOR_RADIUS);
if (isLeft) {
generalPath.curveTo(((float) x[3] + CORNOR_RADIUS - SPECIAL_LOCATION_1), ((float) y[3] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[3] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) y[3] - CORNOR_RADIUS + SPECIAL_LOCATION_1), (float) x[3] + CORNOR_RADIUS, (float) y[3]);
generalPath.lineTo((float) x[0] + CORNOR_RADIUS, (float) y[0]);
} else {
generalPath.curveTo(((float) x[3] - CORNOR_RADIUS + SPECIAL_LOCATION_1), ((float) y[3] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[3] - CORNOR_RADIUS + SPECIAL_LOCATION_2), ((float) y[3] + CORNOR_RADIUS - SPECIAL_LOCATION_1), (float) x[3] - CORNOR_RADIUS, (float) y[3]);
generalPath.lineTo((float) x[0] - CORNOR_RADIUS, (float) y[0]);
}
generalPath.closePath();
} }
public void setIsCloseCurrent(boolean isCloseCurrent) { public void setIsCloseCurrent(boolean isCloseCurrent) {
this.isCloseCurrent = isCloseCurrent; this.isCloseCurrent = isCloseCurrent;
@ -1107,6 +719,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 计算下一个可以展示的模板index * 计算下一个可以展示的模板index
*
* @param currentIndex * @param currentIndex
* @return * @return
*/ */
@ -1118,8 +731,9 @@ public class MultiTemplateTabPane extends JComponent {
private boolean isOverCloseIcon(int evtX) { private boolean isOverCloseIcon(int evtX) {
boolean isOverCloseIcon = false; boolean isOverCloseIcon = false;
// todo
for (int i = 0; i < startX.length; i++) { for (int i = 0; i < startX.length; i++) {
if (evtX >= startX[i] && evtX <= startX[i] + CLOSE.getIconWidth()) { if (evtX >= startX[i] && evtX <= startX[i] + clodeIcon.getIconWidth()) {
isOverCloseIcon = true; isOverCloseIcon = true;
break; break;
} }
@ -1129,15 +743,15 @@ public class MultiTemplateTabPane extends JComponent {
private boolean isOverListDown(int evtX) { private boolean isOverListDown(int evtX) {
int maxWidth = getWidth() - LIST_BUTTON_WIDTH; int maxWidth = getWidth() - scale(TRAILING_WIDTH) - scale(LEADING_WIDTH);
return evtX >= (maxWidth + SMALLGAP) && evtX <= (getWidth() - SMALLGAP); return evtX >= (maxWidth + SMALLGAP) && evtX <= (getWidth() - SMALLGAP);
} }
private int getTemplateIndex(int evtX) { private int getTemplateIndex(int evtX) {
int textX = 0; int textX = scale(LEADING_WIDTH);
for (int i = minPaintIndex; i <= maxPaintIndex; i++) { for (int i = minPaintIndex; i <= maxPaintIndex; i++) {
int textWidth = showJTemplateTab(openedTemplate.get(i)) ? realWidth : 0; int textWidth = showJTemplateTab(openedTemplate.get(i)) ? tabWidth : 0;
if (evtX >= textX && evtX < textX + textWidth) { if (evtX >= textX && evtX < textX + textWidth) {
return i; return i;
} }
@ -1169,35 +783,7 @@ public class MultiTemplateTabPane extends JComponent {
} }
} }
private class UIListDownItemUI extends BasicMenuItemUI { private class MultiTemplateTabMouseListener extends MouseAdapter {
@Override
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
if (menuItem.getIcon() == null) {
super.paintBackground(g, menuItem, bgColor);
return;
}
ButtonModel model = menuItem.getModel();
Color oldColor = g.getColor();
int menuWidth = menuItem.getWidth();
int menuHeight = menuItem.getHeight();
g.setColor(getBackground());
g.fillRect(0, 0, menuWidth, menuHeight);
boolean itemIsSelected = menuItem instanceof JMenu && model.isSelected();
if (menuItem.isOpaque()) {
if (model.isArmed() || itemIsSelected) {
GUIPaintUtils.fillPaint((Graphics2D) g, GAP, 0, menuWidth - GAP, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, UIConstants.ARC);
} else {
GUIPaintUtils.fillPaint((Graphics2D) g, GAP, 0, menuWidth - GAP, menuHeight, true, Constants.NULL, menuItem.getBackground(), UIConstants.ARC);
}
g.setColor(oldColor);
} else if (model.isArmed() || itemIsSelected) {
GUIPaintUtils.fillPaint((Graphics2D) g, GAP, 0, menuWidth - GAP, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, UIConstants.ARC);
g.setColor(oldColor);
}
}
}
private class MultiTemplateTabMouseListener implements MouseListener {
private boolean oldLightWeightPopupEnabled; private boolean oldLightWeightPopupEnabled;
@ -1222,32 +808,12 @@ public class MultiTemplateTabPane extends JComponent {
ToolTipManager.sharedInstance().setEnabled(false); ToolTipManager.sharedInstance().setEnabled(false);
ToolTipManager.sharedInstance().setEnabled(true); ToolTipManager.sharedInstance().setEnabled(true);
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(this.oldLightWeightPopupEnabled); ToolTipManager.sharedInstance().setLightWeightPopupEnabled(this.oldLightWeightPopupEnabled);
listDownMode = LIST_DOWN;
closeIconIndex = -1; closeIconIndex = -1;
mouseOveredIndex = -1; mouseOveredIndex = -1;
hoverMoreAction = false;
MultiTemplateTabPane.this.repaint(); MultiTemplateTabPane.this.repaint();
} }
/**
* 鼠标释放
*
* @param e 鼠标事件
*/
@Override
public void mouseReleased(MouseEvent e) {
// do nothing
}
/**
* 点击
*
* @param e 鼠标事件
*/
@Override
public void mouseClicked(MouseEvent e) {
// do nothing
}
/** /**
* 按下 * 按下
* *
@ -1264,8 +830,9 @@ public class MultiTemplateTabPane extends JComponent {
//是否点击关闭按钮 如果点击了关闭按钮,则将点击的模板关闭,不需要切换,如果没有点击关闭按钮,则切换到点击的模板处 //是否点击关闭按钮 如果点击了关闭按钮,则将点击的模板关闭,不需要切换,如果没有点击关闭按钮,则切换到点击的模板处
boolean isOverCloseIcon = isOverCloseIcon(evtX); boolean isOverCloseIcon = isOverCloseIcon(evtX);
if (isOverListDown(evtX)) { hoverMoreAction = isOverListDown(evtX);
listDownMode = isOverListDown(evtX) ? MOUSE_PRESS_LIST_DOWN : LIST_DOWN; if (hoverMoreAction) {
if (!isShowList) { if (!isShowList) {
showListDown(); showListDown();
} }
@ -1274,7 +841,6 @@ public class MultiTemplateTabPane extends JComponent {
} else if (isOverCloseIcon) { } else if (isOverCloseIcon) {
//关闭按钮的图标变化 //关闭按钮的图标变化
closeIconIndex = getTemplateIndex(evtX); closeIconIndex = getTemplateIndex(evtX);
clodeMode = MOUSE_PRESS_CLOSE;
//关闭close图标所在的模板{ //关闭close图标所在的模板{
JTemplate<?, ?> template = openedTemplate.get(closeIconIndex); JTemplate<?, ?> template = openedTemplate.get(closeIconIndex);
if (template.isOpening()) { if (template.isOpening()) {
@ -1298,7 +864,7 @@ public class MultiTemplateTabPane extends JComponent {
} else { } else {
//没有点击关闭和ListDown按钮,则切换到点击的模板处 //没有点击关闭和ListDown按钮,则切换到点击的模板处
closeIconIndex = -1; closeIconIndex = -1;
clodeMode = CLOSE; clodeIcon = new LazyIcon("clear");
switchJTemplate(getTemplateIndex(evtX)); switchJTemplate(getTemplateIndex(evtX));
isShowList = false; isShowList = false;
} }
@ -1308,6 +874,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 切换到指定模板 * 切换到指定模板
*
* @param jTemplate * @param jTemplate
*/ */
public void switchJTemplate(JTemplate jTemplate) { public void switchJTemplate(JTemplate jTemplate) {
@ -1319,6 +886,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 切换到指定index * 切换到指定index
*
* @param switchIndex * @param switchIndex
*/ */
private void switchJTemplate(int switchIndex) { private void switchJTemplate(int switchIndex) {
@ -1344,17 +912,7 @@ public class MultiTemplateTabPane extends JComponent {
return JTemplate.isValid(currentTemplate) && ComparatorUtils.equals(template.getPath(), currentTemplate.getPath()); return JTemplate.isValid(currentTemplate) && ComparatorUtils.equals(template.getPath(), currentTemplate.getPath());
} }
private class MultiTemplateTabMouseMotionListener implements MouseMotionListener { private class MultiTemplateTabMouseMotionListener extends MouseMotionAdapter {
/**
* 鼠标拖拽
*
* @param e 鼠标事件
*/
@Override
public void mouseDragged(MouseEvent e) {
// do nothing
}
/** /**
* 鼠标移动 * 鼠标移动
* *
@ -1364,25 +922,16 @@ public class MultiTemplateTabPane extends JComponent {
public void mouseMoved(MouseEvent e) { public void mouseMoved(MouseEvent e) {
int evtX = e.getX(); int evtX = e.getX();
mouseOveredIndex = getTemplateIndex(evtX); mouseOveredIndex = getTemplateIndex(evtX);
//看是否需要显示toolTip
if (mouseOveredIndex != -1 && isNeedToolTips[mouseOveredIndex - minPaintIndex]) {
setToolTipText(openedTemplate.get(mouseOveredIndex).getEditingFILE().getName()); setToolTipText(openedTemplate.get(mouseOveredIndex).getEditingFILE().getName());
} else { hoverMoreAction = isOverListDown(evtX);
setToolTipText(null); closeIconIndex = isOverCloseIcon(evtX) ? mouseOveredIndex : -1;
}
listDownMode = isOverListDown(evtX) ? MOUSE_OVER_LIST_DOWN : LIST_DOWN;
boolean isOverCloseIcon = isOverCloseIcon(evtX);
clodeMode = isOverCloseIcon ? MOUSE_OVER_CLOSE : CLOSE;
closeIconIndex = isOverCloseIcon ? mouseOveredIndex : -1;
MultiTemplateTabPane.this.repaint(); MultiTemplateTabPane.this.repaint();
} }
} }
/** /**
* 判断是否显示在tab栏上 * 判断是否显示在tab栏上
*
* @param jTemplate * @param jTemplate
* @return * @return
*/ */
@ -1393,6 +942,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 获取tab操作类型的模板 * 获取tab操作类型的模板
*
* @param operator * @param operator
* @return * @return
*/ */
@ -1403,6 +953,7 @@ public class MultiTemplateTabPane extends JComponent {
/** /**
* 根据tab操作类型进行分类 * 根据tab操作类型进行分类
*
* @return * @return
*/ */
public Map<String, List<JTemplate<?, ?>>> getOpenedJTemplatesByCategory() { public Map<String, List<JTemplate<?, ?>>> getOpenedJTemplatesByCategory() {
@ -1410,5 +961,67 @@ public class MultiTemplateTabPane extends JComponent {
.collect(Collectors.groupingBy(JTemplate::getTemplateTabOperatorType)); .collect(Collectors.groupingBy(JTemplate::getTemplateTabOperatorType));
} }
/**
* 返回当前tab数量
*
* @return tab数量
*/
public int getTabCount() {
return openedTemplate.size();
}
/**
* 获取选中的tab索引
*
* @return tab索引
*/
public int getSelectedIndex() {
return selectedIndex;
}
/**
* 获取每个tab宽度
*
* @return tab宽度
*/
public int getTabWidth() {
return tabWidth;
}
/**
* 是否悬浮在更多按钮上
*
* @return 是否悬浮
*/
public boolean isHoverMoreAction() {
return hoverMoreAction;
}
/**
* 是否悬浮在关闭按钮上0
*
* @param i 索引
* @return 是否悬浮在关闭按钮上
*/
public boolean isCloseCurrent(int i) {
return i == closeIconIndex;
}
/**
* 获取悬浮索引
*
* @return 悬浮在第几个tab
*/
public int getHoverIndex() {
return mouseOveredIndex;
}
/**
* 获取可视范围内的标签范围
*
* @return 标签范围
*/
public Pair<Integer, Integer> getViewRange() {
return new Pair<>(minPaintIndex, maxPaintIndex);
}
} }

132
designer-base/src/main/java/com/fr/design/gui/ibutton/UICombinationButton.java

@ -1,22 +1,39 @@
package com.fr.design.gui.ibutton; package com.fr.design.gui.ibutton;
import java.awt.BorderLayout; import com.fr.design.utils.gui.GUICoreUtils;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JPopupMenu; import javax.swing.JPopupMenu;
import java.awt.BorderLayout;
import com.fr.design.constants.UIConstants; import java.awt.event.MouseAdapter;
import com.fr.stable.Constants; import java.awt.event.MouseEvent;
import com.fr.design.utils.gui.GUICoreUtils; import java.util.function.Consumer;
import static com.fine.theme.utils.FineClientProperties.BUTTON_TYPE_LEFT_ROUND_RECT;
import static com.fine.theme.utils.FineClientProperties.BUTTON_TYPE_RIGHT_ROUND_RECT;
import static com.fine.theme.utils.FineClientProperties.STYLE_PRIMARY;
import static com.fine.theme.utils.FineClientProperties.setStyle;
import static com.formdev.flatlaf.FlatClientProperties.BUTTON_TYPE;
/**
* 双按钮组件
*
* @author vito
* @since 11.0
* <p>
* created by vito on 2023/12/28
**/
public class UICombinationButton extends JPanel { public class UICombinationButton extends JPanel {
private static final String UI_CLASS_ID = "CombinationButtonUI";
protected UIButton leftButton; protected UIButton leftButton;
protected UIButton rightButton; protected UIButton rightButton;
private Consumer<MouseEvent> leftClickLister;
private Consumer<MouseEvent> rightClickLister;
protected void leftButtonClickEvent() { protected void leftButtonClickEvent() {
// 左边按钮点击事件 // 左边按钮点击事件
} }
@ -29,55 +46,54 @@ public class UICombinationButton extends JPanel{
this(new UIButton(), new UIButton()); this(new UIButton(), new UIButton());
} }
public UICombinationButton(UIButton left, UIButton right) {
leftButton = left;
rightButton = right;
leftButton.setRoundBorder(true, Constants.RIGHT);
rightButton.setRoundBorder(true, Constants.LEFT);
leftButton.addMouseListener(new MouseAdapter() { /**
@Override * 添加左按钮监听器
public void mousePressed(MouseEvent e) { *
rightButton.getModel().setPressed(true); * @param lister 监听
rightButton.getModel().setSelected(true); */
rightButton.repaint(); public void addLeftClickLister(Consumer<MouseEvent> lister) {
this.leftClickLister = lister;
} }
@Override /**
public void mouseReleased(MouseEvent e) { * 添加右按钮监听器
rightButton.getModel().setPressed(false); *
rightButton.getModel().setSelected(false); * @param lister 监听
rightButton.repaint(); */
public void addRightClickLister(Consumer<MouseEvent> lister) {
this.rightClickLister = lister;
} }
public UICombinationButton(UIButton left, UIButton right) {
leftButton = left;
leftButton.putClientProperty(BUTTON_TYPE, BUTTON_TYPE_LEFT_ROUND_RECT);
rightButton = right;
rightButton.putClientProperty(BUTTON_TYPE, BUTTON_TYPE_RIGHT_ROUND_RECT);
leftButton.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (leftClickLister != null) {
leftClickLister.accept(e);
} else {
leftButtonClickEvent(); leftButtonClickEvent();
} }
}
}); });
rightButton.addMouseListener(new MouseAdapter() { rightButton.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
leftButton.getModel().setPressed(true);
leftButton.getModel().setSelected(true);
leftButton.repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
leftButton.getModel().setPressed(false);
leftButton.getModel().setSelected(false);
leftButton.repaint();
}
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
if (rightClickLister != null) {
rightClickLister.accept(e);
} else {
rightButtonClickEvent(); rightButtonClickEvent();
} }
}
}); });
this.setLayout(new BorderLayout()); this.setLayout(new BorderLayout());
this.add(leftButton, BorderLayout.CENTER); this.add(leftButton, BorderLayout.WEST);
this.add(rightButton, BorderLayout.EAST); this.add(rightButton, BorderLayout.EAST);
} }
@ -99,17 +115,27 @@ public class UICombinationButton extends JPanel{
rightButton.setIcon(right); rightButton.setIcon(right);
} }
@Override
public String getUIClassID() {
return UI_CLASS_ID;
}
public void setPrimary() {
setStyle(leftButton, STYLE_PRIMARY);
setStyle(rightButton, STYLE_PRIMARY);
}
public UIButton getLeftButton() { public UIButton getLeftButton() {
return leftButton; return leftButton;
} }
public void setExtraPainted(boolean isExtraPainted) { public void setExtraPainted(boolean isExtraPainted) {
if(!isExtraPainted) { // if (!isExtraPainted) {
leftButton.setBackground(null); // leftButton.setBackground(null);
rightButton.setBackground(null); // rightButton.setBackground(null);
leftButton.setOpaque(false); // leftButton.setOpaque(false);
rightButton.setOpaque(false); // rightButton.setOpaque(false);
} // }
} }
public UIButton getRightButton() { public UIButton getRightButton() {
@ -126,18 +152,4 @@ public class UICombinationButton extends JPanel{
protected void showPopWindow(JPopupMenu menu) { protected void showPopWindow(JPopupMenu menu) {
GUICoreUtils.showPopupMenu(menu, this, 0, getY() + getHeight() - 3); GUICoreUtils.showPopupMenu(menu, this, 0, getY() + getHeight() - 3);
} }
public static void main(String... args) {
JFrame jf = new JFrame("test");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = (JPanel)jf.getContentPane();
content.setLayout(null);
UICombinationButton bb = new UICombinationButton("123455", UIConstants.ARROW_DOWN_ICON);
bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height);
content.add(bb);
GUICoreUtils.centerWindow(jf);
jf.setSize(400, 400);
jf.setVisible(true);
}
} }

1
designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java

@ -61,6 +61,7 @@ public class UIHeadGroup extends Row {
* @see JComponent#getUIClassID * @see JComponent#getUIClassID
* @see UIDefaults#getUI * @see UIDefaults#getUI
*/ */
@Override
public String getUIClassID() { public String getUIClassID() {
return UI_CLASS_ID; return UI_CLASS_ID;
} }

1
designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java

@ -18,7 +18,6 @@ public class UIToolbar extends JToolBar {
setFloatable(false); setFloatable(false);
setRollover(true); setRollover(true);
setLayout(new FlowLayout(align, 4, 0)); setLayout(new FlowLayout(align, 4, 0));
// setUI(uiToolBarUI);
setBorderPainted(false); setBorderPainted(false);
} }

47
designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java

@ -1,13 +1,13 @@
package com.fr.design.mainframe; package com.fr.design.mainframe;
import com.formdev.flatlaf.util.ScaledEmptyBorder;
import com.fr.design.DesignState; import com.fr.design.DesignState;
import com.fr.design.base.mode.DesignModeContext; import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.constants.UIConstants;
import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MultiTemplateTabPane; import com.fr.design.file.MultiTemplateTabPane;
import com.fr.design.file.NewTemplatePane; import com.fr.design.file.NewTemplatePane;
import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.itoolbar.UILargeToolbar; import com.fr.design.gui.ibutton.UICombinationButton;
import com.fr.design.gui.itoolbar.UIToolbar; import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
@ -16,14 +16,11 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FlowLayout; import java.awt.FlowLayout;
import java.awt.Insets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -47,7 +44,7 @@ public class CenterRegionContainerPane extends JPanel {
private JComponent toolbarComponent;//cpt 字体 等工具栏 private JComponent toolbarComponent;//cpt 字体 等工具栏
private JPanel eastPane;//=largeToolbar+eastCenterPane private JPanel eastPane;//=largeToolbar+eastCenterPane
private UILargeToolbar largeToolbar;//预览 private UICombinationButton largeToolbar;//预览
private JPanel eastCenterPane;//=combineUp + templateTabPane private JPanel eastCenterPane;//=combineUp + templateTabPane
@ -70,37 +67,28 @@ public class CenterRegionContainerPane extends JPanel {
public CenterRegionContainerPane() { public CenterRegionContainerPane() {
toolbarPane = new JPanel() { toolbarPane = new JPanel();
toolbarPane.setBorder(new ScaledEmptyBorder(6, 0, 10, 0));
@Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
// dim.height = TOOLBAR_HEIGHT;
return dim;
}
};
toolbarPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
toolbarPane.setLayout(FRGUIPaneFactory.createBorderLayout()); toolbarPane.setLayout(FRGUIPaneFactory.createBorderLayout());
toolbarPane.setBackground(UIManager.getColor("Center.SpaceColor")); toolbarPane.setBackground(UIManager.getColor("Center.SpaceColor"));
eastPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); eastPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
eastPane.add(largeToolbar = getToolBarMenuDock().createLargeToolbar(), BorderLayout.WEST); largeToolbar = getToolBarMenuDock().createLargeToolbar();
eastCenterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); eastCenterPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
combineUpTooBar(); combineUpTooBar();
eastCenterPane.add(combineUp, BorderLayout.NORTH);
templateTabPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); templateTabPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
templateTabPane.add(newWorkBookPane = getToolBarMenuDock().getNewTemplatePane(), BorderLayout.WEST); newWorkBookPane = getToolBarMenuDock().getNewTemplatePane();
templateTabPane.add(MultiTemplateTabPane.getInstance(), BorderLayout.CENTER); eastCenterPane.add(templateTabPane, BorderLayout.NORTH);
eastCenterPane.add(templateTabPane, BorderLayout.CENTER); eastCenterPane.add(combineUp, BorderLayout.CENTER);
eastPane.add(eastCenterPane, BorderLayout.CENTER); eastPane.add(eastCenterPane, BorderLayout.CENTER);
toolbarPane.add(eastPane, BorderLayout.NORTH); toolbarPane.add(eastPane, BorderLayout.NORTH);
this.setLayout(new BorderLayout()); this.setLayout(new BorderLayout());
this.add(centerTemplateCardPane = new DesktopCardPane(), BorderLayout.CENTER); this.add(centerTemplateCardPane = new DesktopCardPane(), BorderLayout.CENTER);
centerTemplateCardPane.setBorder(new ScaledEmptyBorder(0, 10, 10, 10));
this.add(toolbarPane, BorderLayout.NORTH); this.add(toolbarPane, BorderLayout.NORTH);
this.setBackground(UIManager.getColor("Center.SpaceColor")); this.setBackground(UIManager.getColor("Center.SpaceColor"));
this.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); this.setBorder(new ScaledEmptyBorder(0, 0, 10, 0));
} }
public ToolBarMenuDock getToolBarMenuDock() { public ToolBarMenuDock getToolBarMenuDock() {
@ -112,10 +100,9 @@ public class CenterRegionContainerPane extends JPanel {
*/ */
private void combineUpTooBar() { private void combineUpTooBar() {
combineUp = new UIToolbar(FlowLayout.LEFT); combineUp = new UIToolbar(FlowLayout.LEFT);
combineUp.setBorder(new MatteBorder(new Insets(0, LEFT_ALIGN_GAP, 1, 0), UIConstants.LINE_COLOR)); combineUp.setBorder(new ScaledEmptyBorder(10, 10, 10, 10));
combineUp.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2)); combineUp.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2));
setUpUpToolBar(null); setUpUpToolBar(null);
} }
@ -135,6 +122,7 @@ public class CenterRegionContainerPane extends JPanel {
* @param toolbar4Form 目标组件 * @param toolbar4Form 目标组件
*/ */
private void setUpUpToolBar(@Nullable JComponent[] toolbar4Form) { private void setUpUpToolBar(@Nullable JComponent[] toolbar4Form) {
combineUp.add(largeToolbar);
UIButton[] fixButtons = getToolBarMenuDock().createUp(); UIButton[] fixButtons = getToolBarMenuDock().createUp();
for (UIButton fixButton : fixButtons) { for (UIButton fixButton : fixButtons) {
combineUp.add(fixButton); combineUp.add(fixButton);
@ -233,19 +221,20 @@ public class CenterRegionContainerPane extends JPanel {
// 颜色,字体那些按钮的工具栏 // 颜色,字体那些按钮的工具栏
toolbarPane.add(toolbarComponent = ad.resetToolBar(toolbarComponent, plus), BorderLayout.CENTER); toolbarPane.add(toolbarComponent = ad.resetToolBar(toolbarComponent, plus), BorderLayout.CENTER);
toolbarComponent.setBorder(new ScaledEmptyBorder(0, 10, 10, 10));
JPanel customNorthPane = strategy.customNorthPane(toolbarPane, plus); JPanel customNorthPane = strategy.customNorthPane(toolbarPane, plus);
if (!isExist(customNorthPane)) { if (!isExist(customNorthPane)) {
this.removeNorth(); this.removeNorth();
this.add(customNorthPane, BorderLayout.NORTH); this.add(customNorthPane, BorderLayout.NORTH);
} }
if (strategy.hasTemplateTabPane(plus)) { if (strategy.hasTemplateTabPane(plus)) {
eastCenterPane.add(templateTabPane, BorderLayout.CENTER); eastCenterPane.add(templateTabPane, BorderLayout.NORTH);
} else { } else {
eastCenterPane.remove(templateTabPane); eastCenterPane.remove(templateTabPane);
} }
if (strategy.hasCombineUp(plus)) { if (strategy.hasCombineUp(plus)) {
eastCenterPane.add(combineUp, BorderLayout.NORTH); eastCenterPane.add(combineUp, BorderLayout.CENTER);
} else { } else {
eastCenterPane.remove(combineUp); eastCenterPane.remove(combineUp);
} }
@ -274,11 +263,11 @@ public class CenterRegionContainerPane extends JPanel {
private void resetByDesignMode() { private void resetByDesignMode() {
if (DesignModeContext.isDuchampMode()) { if (DesignModeContext.isDuchampMode()) {
eastPane.remove(largeToolbar); // eastPane.remove(largeToolbar);
//移除新建模板按钮 //移除新建模板按钮
templateTabPane.remove(newWorkBookPane); templateTabPane.remove(newWorkBookPane);
} else { } else {
eastPane.add(largeToolbar, BorderLayout.WEST); // eastPane.add(largeToolbar, BorderLayout.WEST);
templateTabPane.add(newWorkBookPane, BorderLayout.WEST); templateTabPane.add(newWorkBookPane, BorderLayout.WEST);
} }

2
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -177,7 +177,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener; private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener;
public JTemplate() { public JTemplate() {
initAndStartPlugin(); // initAndStartPlugin();
startListenThemeConfig(); startListenThemeConfig();
} }

6
designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java

@ -1,6 +1,6 @@
package com.fr.design.mainframe; package com.fr.design.mainframe;
import com.fr.base.BaseUtils; import com.fine.theme.icon.LazyIcon;
import com.fr.design.DesignModelAdapter; import com.fr.design.DesignModelAdapter;
import com.fr.design.designer.TargetComponent; import com.fr.design.designer.TargetComponent;
import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.HistoryTemplateListPane;
@ -246,9 +246,9 @@ public class JVirtualTemplate extends JTemplate {
@Override @Override
public Icon getIcon() { public Icon getIcon() {
if (getPath().endsWith("cpt")) { if (getPath().endsWith("cpt")) {
return BaseUtils.readIcon("/com/fr/design/images/buttonicon/newcpts.png"); return new LazyIcon("cpt_icon");
} else { } else {
return BaseUtils.readIcon("/com/fr/web/images/form/new_form3.png"); return new LazyIcon("frm_icon");
} }
} }

11
designer-base/src/main/resources/com/fine/theme/icon/clear_hover.svg

@ -0,0 +1,11 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="14" height="14" rx="7" fill="#B8BFCB"/>
<g clip-path="url(#clip0_5140_94134)">
<path d="M6.46967 6.99995L3.81802 9.6516C3.67157 9.79804 3.67157 10.0355 3.81802 10.1819C3.96447 10.3284 4.2019 10.3284 4.34835 10.1819L7 7.53028L9.65165 10.1819C9.7981 10.3284 10.0355 10.3284 10.182 10.1819C10.3284 10.0355 10.3284 9.79804 10.182 9.6516L7.53033 6.99995L10.182 4.3483C10.3284 4.20185 10.3284 3.96441 10.182 3.81797C10.0355 3.67152 9.7981 3.67152 9.65165 3.81797L7 6.46962L4.34835 3.81797C4.2019 3.67152 3.96447 3.67152 3.81802 3.81797C3.67157 3.96441 3.67157 4.20185 3.81802 4.3483L6.46967 6.99995Z" fill="#0A1C38" fill-opacity="0.9"/>
</g>
<defs>
<clipPath id="clip0_5140_94134">
<rect x="1" y="1" width="12" height="12" rx="6" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 875 B

3
designer-base/src/main/resources/com/fine/theme/icon/toolbar/more.svg

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 16C28 22.6274 22.6274 28 16 28C9.37258 28 4 22.6274 4 16C4 9.37258 9.37258 4 16 4C22.6274 4 28 9.37258 28 16ZM30 16C30 23.732 23.732 30 16 30C8.26801 30 2 23.732 2 16C2 8.26801 8.26801 2 16 2C23.732 2 30 8.26801 30 16ZM10.5 17.5C11.3284 17.5 12 16.8284 12 16C12 15.1716 11.3284 14.5 10.5 14.5C9.67157 14.5 9 15.1716 9 16C9 16.8284 9.67157 17.5 10.5 17.5ZM16 17.5C16.8284 17.5 17.5 16.8284 17.5 16C17.5 15.1716 16.8284 14.5 16 14.5C15.1716 14.5 14.5 15.1716 14.5 16C14.5 16.8284 15.1716 17.5 16 17.5ZM23 16C23 16.8284 22.3284 17.5 21.5 17.5C20.6716 17.5 20 16.8284 20 16C20 15.1716 20.6716 14.5 21.5 14.5C22.3284 14.5 23 15.1716 23 16Z" fill="#0A1C38" fill-opacity="0.9"/>
</svg>

After

Width:  |  Height:  |  Size: 828 B

3
designer-base/src/main/resources/com/fine/theme/icon/toolbar/more_disable.svg

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 16C28 22.6274 22.6274 28 16 28C9.37258 28 4 22.6274 4 16C4 9.37258 9.37258 4 16 4C22.6274 4 28 9.37258 28 16ZM30 16C30 23.732 23.732 30 16 30C8.26801 30 2 23.732 2 16C2 8.26801 8.26801 2 16 2C23.732 2 30 8.26801 30 16ZM10.5 17.5C11.3284 17.5 12 16.8284 12 16C12 15.1716 11.3284 14.5 10.5 14.5C9.67157 14.5 9 15.1716 9 16C9 16.8284 9.67157 17.5 10.5 17.5ZM16 17.5C16.8284 17.5 17.5 16.8284 17.5 16C17.5 15.1716 16.8284 14.5 16 14.5C15.1716 14.5 14.5 15.1716 14.5 16C14.5 16.8284 15.1716 17.5 16 17.5ZM23 16C23 16.8284 22.3284 17.5 21.5 17.5C20.6716 17.5 20 16.8284 20 16C20 15.1716 20.6716 14.5 21.5 14.5C22.3284 14.5 23 15.1716 23 16Z" fill="#0A1C38" fill-opacity="0.29"/>
</svg>

After

Width:  |  Height:  |  Size: 829 B

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

@ -1,6 +1,6 @@
# \u516C\u5171\u5C5E\u6027\uFF0C\u5982UI\u7B49\uFF0C\u5176\u4ED6\u4E3B\u9898\u7EE7\u627F\u8BE5\u4E3B\u9898\uFF0C\u9632\u6B62\u51FA\u73B0UI\u4E0D\u5B58\u5728\u7B49\u95EE\u9898 # \u516C\u5171\u5C5E\u6027\uFF0C\u5982UI\u7B49\uFF0C\u5176\u4ED6\u4E3B\u9898\u7EE7\u627F\u8BE5\u4E3B\u9898\uFF0C\u9632\u6B62\u51FA\u73B0UI\u4E0D\u5B58\u5728\u7B49\u95EE\u9898
#---- UI delegates ---- #---- UI delegates ----
ButtonUI=com.formdev.flatlaf.ui.FlatButtonUI ButtonUI=com.fine.theme.light.ui.FineButtonUI
CheckBoxUI=com.fine.theme.light.ui.FineCheckBoxUI CheckBoxUI=com.fine.theme.light.ui.FineCheckBoxUI
CheckBoxMenuItemUI=com.formdev.flatlaf.ui.FlatCheckBoxMenuItemUI CheckBoxMenuItemUI=com.formdev.flatlaf.ui.FlatCheckBoxMenuItemUI
ColorChooserUI=com.formdev.flatlaf.ui.FlatColorChooserUI ColorChooserUI=com.formdev.flatlaf.ui.FlatColorChooserUI
@ -46,5 +46,7 @@ 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
CombinationButtonUI=com.fine.theme.light.ui.FineCombinationButtonUI
InputUI=com.fine.theme.light.ui.FineInputUI InputUI=com.fine.theme.light.ui.FineInputUI
GradientBarUI=com.fine.theme.light.ui.FineGradientBarUI GradientBarUI=com.fine.theme.light.ui.FineGradientBarUI
TemplateTabPaneUI=com.fine.theme.light.ui.FineTemplateTabPaneUI

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

@ -60,7 +60,7 @@ Component.defaultVGap=10
@disabledForeground = tint(@foreground,55%) @disabledForeground = tint(@foreground,55%)
# component background # component background
@buttonBackground = lighten(@background,5%) @buttonBackground = #FFF
@componentBackground = @background @componentBackground = @background
@menuBackground = @background @menuBackground = @background
@ -136,33 +136,50 @@ fill.disabled=#F2F4F8
border.divider=#DADEE7 border.divider=#DADEE7
tooltip.normal=#3F506A tooltip.normal=#3F506A
tooltip.disabled=#A3ADBD tooltip.disabled=#A3ADBD
hover.deep=#e2fbe6
#---- Button ---- #---- Button ----
Button.border = com.formdev.flatlaf.ui.FlatButtonBorder Button.border =com.fine.theme.light.ui.FineButtonBorder
Button.arc = 6 Button.arc = 6
Button.minimumWidth = 72 Button.minimumWidth = 0
Button.margin = 2,12,2,12 Button.margin = 2,12,2,12
Button.iconTextGap = 4 Button.iconTextGap = 4
Button.rollover = true Button.rollover = true
Button.defaultButtonFollowsFocus = false Button.defaultButtonFollowsFocus = false
Button.borderWidth = 1 Button.borderWidth = 2
Button.medium.margin = 2,12,2,12
Button.small.margin = 0,10,0,10
Button.background = @buttonBackground Button.background = @buttonBackground
Button.focusedBackground = changeLightness($Component.focusColor,95%) Button.focusedBackground = @buttonBackground
Button.hoverBackground = darken($Button.background,3%,derived) Button.hoverBackground = $fill.hover
Button.pressedBackground = darken($Button.background,10%,derived) Button.pressedBackground = $fill.click
Button.selectedBackground = darken($Button.background,20%,derived) Button.selectedBackground = darken($Button.background,20%,derived)
Button.selectedForeground = $Button.foreground Button.selectedForeground = $Button.foreground
Button.disabledSelectedBackground = darken($Button.background,13%,derived) Button.disabledSelectedBackground = darken($Button.background,13%,derived)
Button.disabledBackground = $fill.disabled
Button.borderColor = $Component.borderColor Button.borderColor = $Component.borderColor
Button.disabledBorderColor = $Component.disabledBorderColor Button.disabledBorderColor = $Component.disabledBorderColor
Button.focusedBorderColor = $Component.focusedBorderColor Button.focusedBorderColor = $border.divider
Button.hoverBorderColor = $Button.focusedBorderColor Button.hoverBorderColor = $border.divider
Button.innerFocusWidth = 0 Button.innerFocusWidth = 0
Button.text.background = $Button.background
Button.text.foreground = $Button.foreground
Button.text.focusedBackground = $Button.focusedBackground
Button.text.hoverBackground = darken($Button.default.background,3%,derived)
Button.text.pressedBackground = darken($Button.default.background,10%,derived)
Button.text.borderColor = @accentButtonDefaultBorderColor
Button.text.hoverBorderColor = $Button.hoverBorderColor
Button.text.focusedBorderColor = $Button.focusedBorderColor
Button.text.focusColor = $Component.focusColor
Button.text.borderWidth = 2
Button.default.background = $Button.background Button.default.background = $Button.background
Button.default.foreground = $Button.foreground Button.default.foreground = $Button.foreground
Button.default.focusedBackground = $Button.focusedBackground Button.default.focusedBackground = $Button.focusedBackground
@ -180,10 +197,29 @@ Button.toolbar.selectedBackground = $Button.selectedBackground
Button.toolbar.margin = 3,3,3,3 Button.toolbar.margin = 3,3,3,3
Button.toolbar.spacingInsets = 1,2,1,2 Button.toolbar.spacingInsets = 1,2,1,2
Button.group.background = #FFF
Button.group.selectedBackground = #2576EF
Button.group.pressedBackground = #2576EF
Button.group.selectedForeground = #FFF
Button.group.pressedForeground = #FFF
Button.group.minimumWidth = 32
Button.group.minimumHeight = 20
Button.group.arc = $Component.arc
Button.tab.hoverBackground = darken($Button.background,12%,derived)
#Button.tab.pressedBackground = #DEEAFD
Button.tab.selectedBackground = #DEEAFD
Button.tab.margin = 3,3,3,3
Button.tab.spacingInsets = 1,2,1,2
CombinationButton.background = $Button.background
CombinationButton.borderColor = $Component.borderColor
CombinationButton.arc = $Button.arc
#---- CheckBox ---- #---- CheckBox ----
CheckBox.border = com.formdev.flatlaf.ui.FlatMarginBorder CheckBox.border = com.formdev.flatlaf.ui.FlatMarginBorder
CheckBox.icon = com.formdev.flatlaf.icons.FlatCheckBoxIcon CheckBox.icon = com.fine.theme.icon.AnimatedSwitchIcon
CheckBox.arc = 4 CheckBox.arc = 4
CheckBox.margin = 2,2,2,2 CheckBox.margin = 2,2,2,2
CheckBox.iconTextGap = 4 CheckBox.iconTextGap = 4
@ -289,8 +325,8 @@ Component.minimumWidth = 64
Component.arrowType = chevron Component.arrowType = chevron
Component.hideMnemonics = true Component.hideMnemonics = true
Component.borderColor = shade(@background,20%) Component.borderColor = $defaultBorderColor
Component.disabledBorderColor = tint($Component.borderColor,20%) Component.disabledBorderColor = $defaultBorderColor
Component.focusedBorderColor = shade($Component.focusColor,10%) Component.focusedBorderColor = shade($Component.focusColor,10%)
Component.focusColor = @accentFocusColor Component.focusColor = @accentFocusColor
Component.linkColor = @accentLinkColor Component.linkColor = @accentLinkColor
@ -778,19 +814,19 @@ SplitPaneDivider.draggingColor = $Component.borderColor
#---- TabbedPane ---- #---- TabbedPane ----
TabbedPane.tabHeight = 32 TabbedPane.tabHeight = 30
TabbedPane.tabSelectionHeight = 3 TabbedPane.tabSelectionHeight = 0
TabbedPane.cardTabSelectionHeight = 3 TabbedPane.cardTabSelectionHeight = 0
TabbedPane.tabArc = 0 TabbedPane.tabArc = 0
TabbedPane.tabSelectionArc = 0 TabbedPane.tabSelectionArc = 0
TabbedPane.cardTabArc = 12 TabbedPane.cardTabArc = 12
TabbedPane.selectedInsets = 0,0,0,0 TabbedPane.selectedInsets = 10,0,0,0
TabbedPane.tabSelectionInsets = 0,0,0,0 TabbedPane.tabSelectionInsets = 0,0,0,0
TabbedPane.contentSeparatorHeight = 1 TabbedPane.contentSeparatorHeight = 1
TabbedPane.showTabSeparators = false TabbedPane.showTabSeparators = true
TabbedPane.tabSeparatorsFullHeight = false TabbedPane.tabSeparatorsFullHeight = false
TabbedPane.hasFullBorder = false TabbedPane.hasFullBorder = false
TabbedPane.tabInsets = 4,12,4,12 TabbedPane.tabInsets = 4,6,4,6
TabbedPane.tabAreaInsets = 0,0,0,0 TabbedPane.tabAreaInsets = 0,0,0,0
TabbedPane.selectedTabPadInsets = 0,0,0,0 TabbedPane.selectedTabPadInsets = 0,0,0,0
TabbedPane.tabRunOverlay = 0 TabbedPane.tabRunOverlay = 0
@ -798,6 +834,9 @@ TabbedPane.tabsOverlapBorder = false
TabbedPane.disabledForeground = @disabledForeground TabbedPane.disabledForeground = @disabledForeground
TabbedPane.shadow = @background TabbedPane.shadow = @background
TabbedPane.contentBorderInsets = null TabbedPane.contentBorderInsets = null
TabbedPane.background = $fill.disabled
TabbedPane.selectedBackground = #fff
TabbedPane.tabSeparatorColor = $border.divider
# allowed values: moreTabsButton or arrowButtons # allowed values: moreTabsButton or arrowButtons
TabbedPane.hiddenTabsNavigation = moreTabsButton TabbedPane.hiddenTabsNavigation = moreTabsButton
# allowed values: leading, trailing, center or fill # allowed values: leading, trailing, center or fill
@ -834,21 +873,36 @@ TabbedPane.closeCrossLineWidth = 1
TabbedPane.underlineColor = @accentUnderlineColor TabbedPane.underlineColor = @accentUnderlineColor
TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,50%) TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,50%)
TabbedPane.disabledUnderlineColor = darken(@background,28%) TabbedPane.disabledUnderlineColor = darken(@background,28%)
TabbedPane.hoverColor = #DADEE7 TabbedPane.hoverColor = $fill.hover
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%) TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%)
TabbedPane.contentAreaColor = $Component.borderColor TabbedPane.contentAreaColor = $fill.hover
TabbedPane.buttonHoverBackground = darken($TabbedPane.background,7%,derived) TabbedPane.buttonHoverBackground = darken($TabbedPane.background,7%,derived)
TabbedPane.buttonPressedBackground = darken($TabbedPane.background,10%,derived) TabbedPane.buttonPressedBackground = darken($TabbedPane.background,10%,derived)
TabbedPane.closeBackground = null TabbedPane.closeBackground = null
TabbedPane.closeForeground = @disabledForeground TabbedPane.closeForeground = @disabledForeground
TabbedPane.closeHoverBackground = darken($TabbedPane.background,20%,derived) TabbedPane.closeHoverBackground = $hover.deep
TabbedPane.closeHoverForeground = @foreground TabbedPane.closeHoverForeground = @foreground
TabbedPane.closePressedBackground = darken($TabbedPane.background,25%,derived) TabbedPane.closePressedBackground = darken($TabbedPane.background,25%,derived)
TabbedPane.closePressedForeground = $TabbedPane.closeHoverForeground TabbedPane.closePressedForeground = $TabbedPane.closeHoverForeground
#---- TemplateTabPane ----
TemplateTabPane.tabHeight = 30
TemplateTabPane.tabSelectionHeight = 0
TemplateTabPane.cardTabSelectionHeight = 0
TemplateTabPane.selectedInsets = 10,0,0,0
TemplateTabPane.hoverColor = $fill.hover
TemplateTabPane.contentAreaColor = $fill.hover
TemplateTabPane.background = $fill.disabled
TemplateTabPane.selectedBackground = #fff
TemplateTabPane.borderColor = $border.divider
TemplateTabPane.closeHoverBackground = $hover.deep
TemplateTabPane.tabInsets = 4,6,4,6
TemplateTabPane.borderWidth = 1
TemplateTabPane.tabArc = 5
TemplateTabPane.separatorHeight = 14
TemplateTabPane.icon.hoverBackground = #B8BFCB
#---- Table ---- #---- Table ----
Table.rowHeight = 20 Table.rowHeight = 20
@ -1038,6 +1092,7 @@ ToolBar.arrowKeysOnlyNavigation = true
ToolBar.hoverButtonGroupArc = 8 ToolBar.hoverButtonGroupArc = 8
ToolBar.floatable = false ToolBar.floatable = false
ToolBar.gripColor = @icon ToolBar.gripColor = @icon
ToolBar.background = #fff
ToolBar.dockingBackground = darken($ToolBar.background,5%) ToolBar.dockingBackground = darken($ToolBar.background,5%)
ToolBar.dockingForeground = $Component.borderColor ToolBar.dockingForeground = $Component.borderColor
ToolBar.floatingBackground = $ToolBar.background ToolBar.floatingBackground = $ToolBar.background
@ -1178,6 +1233,33 @@ CellOtherSetPane.height=$Component.defaultHeight
toolbar.pressedBackground: darken($TextField.background,8%); \ toolbar.pressedBackground: darken($TextField.background,8%); \
toolbar.selectedBackground: darken($TextField.background,12%) toolbar.selectedBackground: darken($TextField.background,12%)
[style]Button.primary = \
background : @BrandColor; \
foreground : #FFF; \
focusedBackground : #5493F2; \
hoverBackground : #5493F2; \
pressedBackground : #105DD1; \
disabledSelectedBackground : #F2F4F8; \
borderWidth : 0
[style]Button.small = margin : 0,10,0,10;
[style]Button.secondary = \
background : $Button.background; \
foreground : $Button.foreground; \
focusedBackground : $Button.focusedBackground; \
hoverBackground : darken($Button.default.background,3%,derived); \
pressedBackground : darken($Button.default.background,10%,derived); \
borderColor : @accentButtonDefaultBorderColor; \
hoverBorderColor : $Button.hoverBorderColor; \
focusedBorderColor : $Button.focusedBorderColor; \
focusColor : $Component.focusColor; \
borderWidth : 2
[style]CombinationButton.primary = \
background : @BrandColor; \
arc : 3
#---- clearButton ---- #---- clearButton ----
# for clear/cancel button in text fields # for clear/cancel button in text fields

126
designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonStoryBoard.java

@ -2,14 +2,21 @@ package com.fr.design.gui.storybook.components;
import com.fine.theme.icon.LazyIcon; import com.fine.theme.icon.LazyIcon;
import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UICombinationButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.storybook.Story; import com.fr.design.gui.storybook.Story;
import com.fr.design.gui.storybook.StoryBoard; import com.fr.design.gui.storybook.StoryBoard;
import javax.swing.JButton; import javax.swing.JButton;
import static com.fine.swing.ui.layout.Layouts.cell; import static com.fine.swing.ui.layout.Layouts.cell;
import static com.fine.swing.ui.layout.Layouts.column;
import static com.fine.swing.ui.layout.Layouts.flex; import static com.fine.swing.ui.layout.Layouts.flex;
import static com.fine.swing.ui.layout.Layouts.row; import static com.fine.swing.ui.layout.Layouts.row;
import static com.fine.theme.utils.FineClientProperties.STYLE_PRIMARY;
import static com.fine.theme.utils.FineClientProperties.STYLE_SIZE_SMALL;
import static com.fine.theme.utils.FineClientProperties.join;
import static com.fine.theme.utils.FineClientProperties.setStyle;
/** /**
* 按钮 * 按钮
@ -23,14 +30,127 @@ public class ButtonStoryBoard extends StoryBoard {
public ButtonStoryBoard() { public ButtonStoryBoard() {
super("按钮"); super("按钮");
setSpacing(16);
add( add(
row(10, row(30, true,
column(16,
cell(new UILabel(STYLE_PRIMARY)).with(this::h2),
cell(new UILabel("medium")).with(this::h3),
row(20,
cell(new UILabel("正常")),
cell(new UIButton("按钮"))
.with(it -> setStyle(it, STYLE_PRIMARY)),
cell(new UIButton("按钮", new LazyIcon("add")))
.with(it -> setStyle(it, STYLE_PRIMARY)),
cell(new UIButton(new LazyIcon("multi")))
.with(it -> setStyle(it, STYLE_PRIMARY))
),
row(20,
cell(new UILabel("禁用")),
cell(new UIButton("按钮")).with(it -> {
setStyle(it, STYLE_PRIMARY);
it.setEnabled(false);
}),
cell(new UIButton("保存", new LazyIcon("save"))).with(it -> {
setStyle(it, STYLE_PRIMARY);
it.setEnabled(false);
}),
cell(new UIButton(new LazyIcon("add"))).with(it -> {
setStyle(it, STYLE_PRIMARY);
it.setEnabled(false);
})
),
cell(new UILabel("small")).with(this::h3),
row(20,
cell(new UILabel("正常")),
cell(new UIButton("按钮"))
.with(it -> setStyle(it, join(STYLE_PRIMARY, STYLE_SIZE_SMALL))),
cell(new UIButton("按钮", new LazyIcon("add")))
.with(it -> setStyle(it, join(STYLE_PRIMARY, STYLE_SIZE_SMALL))),
cell(new UIButton(new LazyIcon("multi")))
.with(it -> setStyle(it, join(STYLE_PRIMARY, STYLE_SIZE_SMALL)))
),
row(20,
cell(new UILabel("禁用")),
cell(new UIButton("按钮")).with(it -> {
setStyle(it, join(STYLE_PRIMARY, STYLE_SIZE_SMALL));
it.setEnabled(false);
}),
cell(new UIButton("保存", new LazyIcon("save"))).with(it -> {
setStyle(it, join(STYLE_PRIMARY, STYLE_SIZE_SMALL));
it.setEnabled(false);
}),
cell(new UIButton(new LazyIcon("add"))).with(it -> {
setStyle(it, join(STYLE_PRIMARY, STYLE_SIZE_SMALL));
it.setEnabled(false);
})
)
),
column(16,
cell(new UILabel("Secondary")).with(this::h2),
cell(new UILabel("medium")).with(this::h3),
row(20,
cell(new UILabel("正常")).with(it -> setStyle(it, "secondary")),
cell(new UIButton("按钮")), cell(new UIButton("按钮")),
cell(new UIButton("保存", new LazyIcon("save"))), cell(new UIButton("按钮", new LazyIcon("add"))),
cell(new UIButton(new LazyIcon("multi"))) cell(new UIButton(new LazyIcon("multi")))
), ),
row(10, row(20,
cell(new UILabel("禁用")),
cell(new UIButton("按钮")).with(it -> it.setEnabled(false)),
cell(new UIButton("保存", new LazyIcon("save"))).with(it -> it.setEnabled(false)),
cell(new UIButton(new LazyIcon("add"))).with(it -> it.setEnabled(false))
),
cell(new UILabel("small")).with(this::h3),
row(20,
cell(new UILabel("正常")),
cell(new UIButton("按钮"))
.with(it -> setStyle(it, STYLE_SIZE_SMALL)),
cell(new UIButton("按钮", new LazyIcon("add")))
.with(it -> setStyle(it, STYLE_SIZE_SMALL)),
cell(new UIButton(new LazyIcon("multi")))
.with(it -> setStyle(it, STYLE_SIZE_SMALL))
),
row(20,
cell(new UILabel("禁用")),
cell(new UIButton("按钮")).with(it -> {
setStyle(it, STYLE_SIZE_SMALL);
it.setEnabled(false);
}),
cell(new UIButton("保存", new LazyIcon("save"))).with(it -> {
setStyle(it, STYLE_SIZE_SMALL);
it.setEnabled(false);
}),
cell(new UIButton(new LazyIcon("add"))).with(it -> {
setStyle(it, STYLE_SIZE_SMALL);
it.setEnabled(false);
})
)
)
),
cell(new UILabel("JButton")).with(this::h2),
row(20,
cell(new UILabel("medium")),
cell(new JButton("按钮")), cell(new JButton("按钮")),
cell(new JButton("按钮", new LazyIcon("add"))),
cell(new JButton(new LazyIcon("multi")))
),
row(20,
cell(new UILabel("medium")),
cell(new JButton("按钮")).with(it -> it.setEnabled(false)),
cell(new JButton("保存", new LazyIcon("save"))).with(it -> it.setEnabled(false)),
cell(new JButton(new LazyIcon("add"))).with(it -> it.setEnabled(false))
),
row(20,
cell(new UICombinationButton("按钮", new LazyIcon("triangle_down")))
.with(it -> {
setStyle(it, STYLE_PRIMARY);
it.setExtraPainted(false);
}),
cell(new UICombinationButton("按钮", new LazyIcon("triangle_down")))
.with(it -> setStyle(it, STYLE_PRIMARY)),
cell(new UICombinationButton("按钮2", new LazyIcon("triangle_down"))),
cell(new JButton("按钮", new LazyIcon("add"))),
cell(new JButton(new LazyIcon("multi"))) cell(new JButton(new LazyIcon("multi")))
), ),
flex() flex()

42
designer-base/src/test/java/com/fr/design/gui/storybook/components/JTestTemplate.java

@ -0,0 +1,42 @@
package com.fr.design.gui.storybook.components;
import com.fine.theme.icon.LazyIcon;
import com.fr.design.mainframe.JNullTemplate;
import com.fr.file.FILE;
import com.fr.file.MemFILE;
import javax.swing.Icon;
/**
* @author vito
* @since 11.0
* Created on 2023/12/18
*/
public class JTestTemplate extends JNullTemplate {
private String name;
private FILE file;
public JTestTemplate(String name) {
this.name = name;
this.file = new MemFILE(name);
}
public String getTemplateName() {
return name;
}
@Override
public Icon getIcon() {
return new LazyIcon("save");
}
public String getTemplateTabOperatorType(){
return "DefaultTabOperator";
}
@Override
public FILE getEditingFILE() {
return file;
}
}

36
designer-base/src/test/java/com/fr/design/gui/storybook/components/TemplateTabStoryBoard.java

@ -0,0 +1,36 @@
package com.fr.design.gui.storybook.components;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MultiTemplateTabPane;
import com.fr.design.gui.storybook.Story;
import com.fr.design.gui.storybook.StoryBoard;
import com.fr.value.NullableLazyValue;
/**
* 新建模版Tab
*
* @author vito
* @since 11.0
* Created on 2023/11/27
*/
@Story
public class TemplateTabStoryBoard extends StoryBoard {
final static NullableLazyValue<Void> init = NullableLazyValue.createValue(() -> {
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(new JTestTemplate("ghjffdhsakjfjdks.cpt"));
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(new JTestTemplate("模版1.cpt"));
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(new JTestTemplate("模版.cpt"));
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(new JTestTemplate("模版1.cpt"));
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(new JTestTemplate("模版模版模版模版.cpt"));
return null;
});
public TemplateTabStoryBoard() {
super("新建模版Tab");
init.getValue();
add(MultiTemplateTabPane.getInstance());
}
}

3
designer-form/src/main/java/com/fr/design/mainframe/JForm.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe; package com.fr.design.mainframe;
import com.fine.theme.icon.LazyIcon;
import com.fr.base.PaperSize; import com.fr.base.PaperSize;
import com.fr.base.Parameter; import com.fr.base.Parameter;
import com.fr.base.Releasable; import com.fr.base.Releasable;
@ -1067,7 +1068,7 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
* @return 图表 * @return 图表
*/ */
public Icon getIcon() { public Icon getIcon() {
return IconUtils.readIcon("/com/fr/web/images/form/new_form3.png"); return new LazyIcon("frm_icon");
} }
@Override @Override

3
designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe; package com.fr.design.mainframe;
import com.fine.theme.icon.LazyIcon;
import com.fr.base.DynamicUnitList; import com.fr.base.DynamicUnitList;
import com.fr.base.Parameter; import com.fr.base.Parameter;
import com.fr.base.ScreenResolution; import com.fr.base.ScreenResolution;
@ -1152,7 +1153,7 @@ public class JWorkBook extends JTemplate<WorkBook, WorkBookUndoState> {
@Override @Override
public Icon getIcon() { public Icon getIcon() {
return IconUtils.readIcon("/com/fr/design/images/buttonicon/newcpts.png"); return new LazyIcon("cpt_icon");
} }
/** /**

84
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -14,7 +14,6 @@ import com.fr.design.actions.server.TemplateThemeManagerAction;
import com.fr.design.actions.server.WidgetManagerAction; import com.fr.design.actions.server.WidgetManagerAction;
import com.fr.design.base.mode.DesignModeContext; import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.carton.SwitchForSwingChecker; import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.constants.UIConstants;
import com.fr.design.deeplink.DeepLinkManager; import com.fr.design.deeplink.DeepLinkManager;
import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.HistoryTemplateListPane;
@ -22,11 +21,10 @@ import com.fr.design.file.MultiTemplateTabPane;
import com.fr.design.fun.MenuHandler; import com.fr.design.fun.MenuHandler;
import com.fr.design.fun.OemProcessor; import com.fr.design.fun.OemProcessor;
import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIPreviewButton; import com.fr.design.gui.ibutton.UICombinationButton;
import com.fr.design.gui.ibutton.UISaveForbiddenButton; import com.fr.design.gui.ibutton.UISaveForbiddenButton;
import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.gui.itoolbar.UILargeToolbar;
import com.fr.design.mainframe.ActiveKeyGenerator; import com.fr.design.mainframe.ActiveKeyGenerator;
import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.InformationCollector; import com.fr.design.mainframe.InformationCollector;
@ -79,13 +77,9 @@ import com.fr.workspace.WorkContext;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.border.MatteBorder;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FlowLayout; import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -106,7 +100,7 @@ public class MainDesigner extends BaseDesigner {
private UIButton undo; private UIButton undo;
private UIButton redo; private UIButton redo;
private UIButton[] upToolBar; private UIButton[] upToolBar;
private UIPreviewButton run; private UICombinationButton run;
public MainDesigner(String[] args) { public MainDesigner(String[] args) {
super(args); super(args);
@ -268,15 +262,8 @@ public class MainDesigner extends BaseDesigner {
* @return 返回大图标对应的工具栏 * @return 返回大图标对应的工具栏
*/ */
@Override @Override
public UILargeToolbar createLargeToolbar() { public UICombinationButton createLargeToolbar() {
UILargeToolbar largeToolbar = super.createLargeToolbar(); UICombinationButton largeToolbar = createRunButton();
largeToolbar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 4));
largeToolbar.add(generateEmptyGap(1));
createRunButton(largeToolbar);
largeToolbar.add(run);
largeToolbar.add(generateEmptyGap(GAP));
largeToolbar.addSeparator(new Dimension(2, 42));
largeToolbar.setBorder(new MatteBorder(new Insets(0, 0, 1, 0), UIConstants.LINE_COLOR));
return largeToolbar; return largeToolbar;
} }
@ -315,15 +302,12 @@ public class MainDesigner extends BaseDesigner {
saveButton = new UIButton(new LazyIcon("save")); saveButton = new UIButton(new LazyIcon("save"));
saveButton.setToolTipText(KeySetUtils.SAVE_TEMPLATE.getMenuKeySetName()); saveButton.setToolTipText(KeySetUtils.SAVE_TEMPLATE.getMenuKeySetName());
saveButton.set4ToolbarButton(); saveButton.set4ToolbarButton();
saveButton.addActionListener(new ActionListener() { saveButton.addActionListener(e -> {
@Override
public void actionPerformed(ActionEvent e) {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
jt.stopEditing(); jt.stopEditing();
jt.saveDirectly(); jt.saveDirectly();
jt.requestFocus(); jt.requestFocus();
SharableManager.saveTemplate(jt); SharableManager.saveTemplate(jt);
}
}); });
} }
@ -332,14 +316,11 @@ public class MainDesigner extends BaseDesigner {
undo = new UIButton(new LazyIcon("undo")); undo = new UIButton(new LazyIcon("undo"));
undo.setToolTipText(KeySetUtils.UNDO.getMenuKeySetName()); undo.setToolTipText(KeySetUtils.UNDO.getMenuKeySetName());
undo.set4ToolbarButton(); undo.set4ToolbarButton();
undo.addActionListener(new ActionListener() { undo.addActionListener(e -> {
@Override
public void actionPerformed(ActionEvent e) {
JTemplate<?, ?> jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
if (jt != null) { if (jt != null) {
jt.undo(); jt.undo();
} }
}
}); });
} }
@ -347,41 +328,25 @@ public class MainDesigner extends BaseDesigner {
redo = new UIButton(new LazyIcon("redo")); redo = new UIButton(new LazyIcon("redo"));
redo.setToolTipText(KeySetUtils.REDO.getMenuKeySetName()); redo.setToolTipText(KeySetUtils.REDO.getMenuKeySetName());
redo.set4ToolbarButton(); redo.set4ToolbarButton();
redo.addActionListener(new ActionListener() { redo.addActionListener(e -> {
@Override
public void actionPerformed(ActionEvent e) {
JTemplate<?, ?> jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
if (jt != null) { if (jt != null) {
jt.redo(); jt.redo();
} }
}
}); });
} }
private void createRunButton(UILargeToolbar largeToolbar) { private UICombinationButton createRunButton() {
run = new UIPreviewButton(new UISaveForbiddenButton(UIConstants.PAGE_BIG_ICON) { run = new UICombinationButton(new UISaveForbiddenButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"), new LazyIcon("add")),
@Override new UISaveForbiddenButton(new LazyIcon("triangle_down")));
public Dimension getPreferredSize() { run.addLeftClickLister(mouseEvent -> {
return new Dimension(34, 34);
}
}, new UISaveForbiddenButton(UIConstants.PREVIEW_DOWN) {
@Override
public Dimension getPreferredSize() {
return new Dimension(34, 10);
}
}
) {
@Override
protected void upButtonClickEvent() {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (jt == null || jt.isSaving()) { if (jt == null || jt.isSaving()) {
return; return;
} }
WebPreviewUtils.preview(jt); WebPreviewUtils.preview(jt);
} });
run.addRightClickLister(mouseEvent -> {
@Override
protected void downButtonClickEvent() {
final JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); final JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (jt == null) { if (jt == null) {
return; return;
@ -390,22 +355,17 @@ public class MainDesigner extends BaseDesigner {
UIPopupMenu menu = new UIPopupMenu(); UIPopupMenu menu = new UIPopupMenu();
UIMenuItem[] items = jt.createMenuItem4Preview(); UIMenuItem[] items = jt.createMenuItem4Preview();
for (int i = 0; i < items.length; i++) { for (UIMenuItem item : items) {
menu.add(items[i]); menu.add(item);
}
GUICoreUtils.showPopupMenu(menu, MultiTemplateTabPane.getInstance(), MultiTemplateTabPane.getInstance().getX() - PREVIEW_DOWN_X_GAP, MultiTemplateTabPane.getInstance().getY() - 1 + MultiTemplateTabPane.getInstance().getHeight());
} }
GUICoreUtils.showPopupMenu(menu, run, run.getX(), run.getY() - 1 + run.getHeight());
@Override });
public Dimension getPreferredSize() { run.setPrimary();
// TODO Auto-generated method stub
return new Dimension(34, 46);
}
};
run.setExtraPainted(false); run.setExtraPainted(false);
run.set4Toolbar(); run.set4Toolbar();
run.getUpButton().setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview")); run.getLeftButton().setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"));
run.getDownButton().setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Dropdown_More_Preview")); run.getRightButton().setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Dropdown_More_Preview"));
return run;
} }
@Override @Override
@ -425,7 +385,7 @@ public class MainDesigner extends BaseDesigner {
redo.setEnabled(false); redo.setEnabled(false);
} }
run.getUpButton().setIcon(jt.getPreviewLargeIcon()); // run.getLeftButton().setIcon(jt.getPreviewLargeIcon());
} }

Loading…
Cancel
Save