diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineButtonBorder.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineButtonBorder.java new file mode 100644 index 0000000000..16405a1552 --- /dev/null +++ b/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); + } + } + + +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineButtonUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineButtonUI.java new file mode 100644 index 0000000000..d5b3c17f74 --- /dev/null +++ b/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; + } + +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineCombinationButtonUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineCombinationButtonUI.java new file mode 100644 index 0000000000..6e61a1f79b --- /dev/null +++ b/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; + } + } +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java index ccb9d9ef07..bd0c0157fd 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java +++ b/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("popup", "com/fine/theme/icon/popup/popup.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), @@ -172,6 +173,7 @@ public class FineLightIconSet extends AbstractIconSet { 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_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), diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineTemplateTabPaneUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineTemplateTabPaneUI.java new file mode 100644 index 0000000000..61fb25466d --- /dev/null +++ b/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 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 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); + } +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java index 7ab6d6c722..10d6456488 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java +++ b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java @@ -22,7 +22,7 @@ public abstract class FineLaf extends FlatLaf { public String getName() { return NAME; } - + @Override public String getDescription() { return "Fine New Look and Feel"; diff --git a/designer-base/src/main/java/com/fine/theme/utils/FineClientProperties.java b/designer-base/src/main/java/com/fine/theme/utils/FineClientProperties.java index ab6384aef6..72effbc10b 100644 --- a/designer-base/src/main/java/com/fine/theme/utils/FineClientProperties.java +++ b/designer-base/src/main/java/com/fine/theme/utils/FineClientProperties.java @@ -1,7 +1,10 @@ package com.fine.theme.utils; +import com.finebi.cbb.utils.StringUtils; import com.formdev.flatlaf.FlatClientProperties; +import javax.swing.JComponent; + /** * FR-UI中使用的各类属性 * @@ -13,4 +16,78 @@ public interface FineClientProperties extends FlatClientProperties { 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,该方法会接在原样式后方 + * + * FineClientProperties.appendStyle("primary small") + * + * + * @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,该方法会替换原样式 + * + * FineClientProperties.setStyle("primary small") + * + * + * @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; + } + + } diff --git a/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java b/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java index e3065c16fc..0448fa82f0 100644 --- a/designer-base/src/main/java/com/fine/theme/utils/FineUIUtils.java +++ b/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 java.awt.Color; +import java.awt.Component; import java.awt.Composite; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Insets; +import java.awt.geom.Path2D; import java.awt.geom.RoundRectangle2D; import java.lang.reflect.Field; +import static com.fine.theme.light.ui.FineButtonUI.isLeftRoundButton; +import static com.formdev.flatlaf.util.UIScale.scale; + /** * UI绘制的一些常用方法 * @@ -133,7 +138,7 @@ public class FineUIUtils { /** * 通过key获取UI的边距,如果没有则使用后备边距 * - * @param key 边距key + * @param key 边距key * @param defaultInsets 后备边距 * @return 边距 */ @@ -178,4 +183,127 @@ public class FineUIUtils { 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; + } + } diff --git a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java index 670e3ca15f..b89019cd43 100644 --- a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java @@ -1,8 +1,7 @@ package com.fr.design.file; -import com.fr.base.GraphHelper; -import com.fr.base.svg.IconUtils; +import com.fine.theme.icon.LazyIcon; import com.fr.base.vcs.DesignerMode; import com.fr.design.actions.UpdateAction; 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.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; -import com.fr.design.mainframe.TemplateSavingChecker; 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.GUIPaintUtils; import com.fr.design.worker.WorkerManager; import com.fr.design.worker.save.CallbackSaveWorker; import com.fr.file.FILE; import com.fr.file.FileNodeFILE; import com.fr.general.ComparatorUtils; -import com.fr.general.IOUtils; 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.workspace.WorkContext; import com.fr.workspace.server.lock.TplOperator; import javax.swing.BorderFactory; -import javax.swing.ButtonModel; 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.JPanel; import javax.swing.JSeparator; import javax.swing.MenuElement; -import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; -import javax.swing.plaf.basic.BasicMenuItemUI; import java.awt.AWTEvent; -import java.awt.AlphaComposite; -import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; -import java.awt.GradientPaint; 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.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -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.awt.event.MouseMotionAdapter; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import static com.fine.theme.utils.FineUIScale.scale; import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog; import static javax.swing.JOptionPane.OK_CANCEL_OPTION; import static javax.swing.JOptionPane.OK_OPTION; import static javax.swing.JOptionPane.WARNING_MESSAGE; -// todo: 自己绘制组件 /** * 改个名字,一个拼写 n 个错误 * @@ -84,28 +61,14 @@ import static javax.swing.JOptionPane.WARNING_MESSAGE; *

* created by daisy on 2013/08/05 **/ -public class MultiTemplateTabPane extends JComponent { - - 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; +public class MultiTemplateTabPane extends JPanel { + 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; //tab栏可以放下的每个tab的实际宽度 - private int realWidth = MAXWIDTH; - + private int tabWidth; //当前标签页栏存放的所有标签页的index private int minPaintIndex = 0; @@ -132,13 +94,12 @@ public class MultiTemplateTabPane extends JComponent { //每个关闭图标的起始位置 private int[] startX; - private boolean[] isNeedToolTips; //记录关闭按钮的状态 private int closeIconIndex = -1; private boolean isCloseCurrent = false; - private Icon clodeMode = CLOSE; - private Icon listDownMode = LIST_DOWN; + private boolean hoverMoreAction = false; + private Icon clodeIcon = new LazyIcon("clear"); private boolean isShowList = false; //自动新建的模板B若没有进行任何编辑,切换到其他 @@ -146,10 +107,14 @@ public class MultiTemplateTabPane extends JComponent { // 模板时,模板B会自动关闭 private JTemplate temTemplate = null; -// private final Color selectedColor = UIManager.getColor("TabbedPane.hoverColor"); -// private Color hoverColor = UIManager.getColor("TabbedPane.inactiveUnderlineColor"); - + @Override + public String getUIClassID() { + return UI_CLASS_ID; + } + /** + * 单例 + */ public static MultiTemplateTabPane getInstance() { if (THIS == null) { THIS = new MultiTemplateTabPane(); @@ -162,27 +127,19 @@ public class MultiTemplateTabPane extends JComponent { * 多工作簿面板 */ public MultiTemplateTabPane() { - this.setLayout(new BorderLayout(0, 0)); this.addMouseListener(new MultiTemplateTabMouseListener()); this.addMouseMotionListener(new MultiTemplateTabMouseMotionListener()); this.setBorder(null); -// this.setForeground(new Color(58, 56, 58)); - this.setFont(DesignUtils.getDefaultGUIFont().applySize(12)); openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList(); selectedIndex = openedTemplate.size() - 1; - AWTEventListener awt = new AWTEventListener() { - @Override - public void eventDispatched(AWTEvent event) { - if (event instanceof MouseEvent) { - MouseEvent mv = (MouseEvent) event; - if (mv.getClickCount() > 0 && !ComparatorUtils.equals(mv.getSource(), MultiTemplateTabPane.this)) { - isShowList = false; - } + java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(event -> { + if (event instanceof MouseEvent) { + MouseEvent mv = (MouseEvent) event; + if (mv.getClickCount() > 0 && !ComparatorUtils.equals(mv.getSource(), MultiTemplateTabPane.this)) { + isShowList = false; } } - - }; - java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + }, AWTEvent.MOUSE_EVENT_MASK); addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { @@ -229,6 +186,7 @@ public class MultiTemplateTabPane extends JComponent { /** * 判断模板是否可以关闭,两个条件:1、是否满足CloseOption里面的条件(在左侧、在右侧等)2、是否和当前正在编辑模板属于同一种模板tab操作类型 + * * @param closeJTemplate * @param tplIndex * @param i @@ -369,7 +327,7 @@ public class MultiTemplateTabPane extends JComponent { if (openedTemplate.size() == 0) { DesignerContext.getDesignerFrame().addAndActivateJTemplate(); - } else if (option == CloseOption.All){ + } else if (option == CloseOption.All) { //openedTemplate(0)是JVirtualTemplate时需重新打开 openedTemplate.get(0).activeOldJTemplate(); } else { @@ -417,9 +375,10 @@ public class MultiTemplateTabPane extends JComponent { /** * 关闭所有指定模板tab操作类型的模板 + * * @param operatorType */ - public void closeOtherByOperatorType(String operatorType){ + public void closeOtherByOperatorType(String operatorType) { JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false); if (saveSomeTempaltePane.showSavePane(null, false, true)) { @@ -438,6 +397,7 @@ public class MultiTemplateTabPane extends JComponent { /** * 关闭指定的非当前编辑模板 + * * @param templates * @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() { - UIMenuItem[] templates = new UIMenuItem[openedTemplate.size()]; - 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 String tempalteShowName(JTemplate template) { + return template.getTabShowName(template); } - private void setListDownItemPreferredSize(UIMenuItem item) { - Dimension dimension = item.getPreferredSize(); - dimension.height = LIST_DOWN_HEIGHT; - item.setPreferredSize(dimension); + public String getTemplateShowNameByIndex(int index) { + JTemplate template = openedTemplate.get(index); + return template.getTabShowName(template); } - - private String tempalteShowName(JTemplate template) { - return template.getTabShowName(template); + public Icon getTemplateIconByIndex(int index) { + JTemplate template = openedTemplate.get(index); + return template.getIcon(); } /** @@ -585,145 +473,23 @@ public class MultiTemplateTabPane extends JComponent { @Override public void paintComponent(Graphics g) { - super.paintComponent(g); - double maxWidth = getWidth() - LIST_BUTTON_WIDTH * 1.0D; //最大宽度 - Graphics2D g2d = (Graphics2D) g; - paintBackgroundAndLine(g2d, maxWidth); - } - - @Override - public void paint(Graphics g) { - //不可见时,按钮.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 + double maxWidth = getWidth() - scale(TRAILING_WIDTH) - scale(LEADING_WIDTH); //最大宽度 + int maxTemplateNum = (int) (maxWidth) / scale(MINWIDTH); calMinAndMaxIndex(maxTemplateNum); calculateRealAverageWidth(maxWidth, maxTemplateNum); - int maxStringlength = calculateStringMaxLength(); - if (selectedIndex >= openedTemplate.size()) { - 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); + calculateClosePosition(); + super.paintComponent(g); } - /** - * 判断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) { - if (leftStrWidth <= rightStrWidth) { - rightKeyPoint++; - } - break; - } + private void calculateClosePosition() { + startX = new int[maxPaintIndex - minPaintIndex + 1]; + double templateStartX = scale(LEADING_WIDTH); + for (int i = getViewRange().getFirst(); i <= getViewRange().getSecond(); i++) { + 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) { @@ -766,9 +532,10 @@ public class MultiTemplateTabPane extends JComponent { /** * 先计算出需要补充的tab个数 + * * @return */ - private int calTabCountComplemented(){ + private int calTabCountComplemented() { int a = 0; for (int i = minPaintIndex; i <= maxPaintIndex; i++) { JTemplate template = openedTemplate.get(i); @@ -783,9 +550,9 @@ public class MultiTemplateTabPane extends JComponent { /** * 由于可能存在宽度为0的tab,所以这边需要重新check下,先往后补,再往前补 */ - private void checkActualPaintIndex(){ + private void checkActualPaintIndex() { int tabCount = calTabCountComplemented(); - if (tabCount == 0){ + if (tabCount == 0) { return; } if (maxPaintIndex < openedTemplate.size() - 1) { @@ -795,19 +562,19 @@ public class MultiTemplateTabPane extends JComponent { tabCount--; } maxPaintIndex++; - if (tabCount == 0){ + if (tabCount == 0) { return; } } } - if (minPaintIndex > 0){ + if (minPaintIndex > 0) { for (int i = minPaintIndex - 1; i >= 0; i--) { JTemplate template = openedTemplate.get(i); if (showJTemplateTab(template)) { tabCount--; } minPaintIndex--; - if (tabCount == 0){ + if (tabCount == 0) { return; } } @@ -821,170 +588,15 @@ public class MultiTemplateTabPane extends JComponent { List> showTemplates = getOpenedJTemplatesByOperator(jTemplate.getTemplateTabOperatorType()); int num = Math.min(showTemplates.size(), templateNum); - realWidth = (int) (maxwidth / (num)); - if (realWidth > MAXWIDTH) { - realWidth = MAXWIDTH; - } else if (realWidth < MINWIDTH) { + tabWidth = (int) (maxwidth / (num)); + if (tabWidth > scale(MAXWIDTH)) { + tabWidth = scale(MAXWIDTH); + } else if (tabWidth < scale(MINWIDTH)) { //平均下来每个的宽度小于最小宽度 - realWidth = 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); + tabWidth = scale(MINWIDTH); } - 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) { this.isCloseCurrent = isCloseCurrent; @@ -1107,19 +719,21 @@ public class MultiTemplateTabPane extends JComponent { /** * 计算下一个可以展示的模板index + * * @param currentIndex * @return */ public int calNextShowJTemplateIndex(int currentIndex) { - JTemplate jTemplate= HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); return MultiTemplateTabUtils.calShowTemplateIndex(currentIndex, openedTemplate, jTemplate.getTemplateTabOperatorType()); } private boolean isOverCloseIcon(int evtX) { boolean isOverCloseIcon = false; + // todo 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; break; } @@ -1129,15 +743,15 @@ public class MultiTemplateTabPane extends JComponent { 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); } private int getTemplateIndex(int evtX) { - int textX = 0; + int textX = scale(LEADING_WIDTH); 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) { return i; } @@ -1169,35 +783,7 @@ public class MultiTemplateTabPane extends JComponent { } } - private class UIListDownItemUI extends BasicMenuItemUI { - @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 class MultiTemplateTabMouseListener extends MouseAdapter { private boolean oldLightWeightPopupEnabled; @@ -1222,32 +808,12 @@ public class MultiTemplateTabPane extends JComponent { ToolTipManager.sharedInstance().setEnabled(false); ToolTipManager.sharedInstance().setEnabled(true); ToolTipManager.sharedInstance().setLightWeightPopupEnabled(this.oldLightWeightPopupEnabled); - listDownMode = LIST_DOWN; closeIconIndex = -1; mouseOveredIndex = -1; + hoverMoreAction = false; 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); - if (isOverListDown(evtX)) { - listDownMode = isOverListDown(evtX) ? MOUSE_PRESS_LIST_DOWN : LIST_DOWN; + hoverMoreAction = isOverListDown(evtX); + if (hoverMoreAction) { + if (!isShowList) { showListDown(); } @@ -1274,7 +841,6 @@ public class MultiTemplateTabPane extends JComponent { } else if (isOverCloseIcon) { //关闭按钮的图标变化 closeIconIndex = getTemplateIndex(evtX); - clodeMode = MOUSE_PRESS_CLOSE; //关闭close图标所在的模板{ JTemplate template = openedTemplate.get(closeIconIndex); if (template.isOpening()) { @@ -1298,7 +864,7 @@ public class MultiTemplateTabPane extends JComponent { } else { //没有点击关闭和ListDown按钮,则切换到点击的模板处 closeIconIndex = -1; - clodeMode = CLOSE; + clodeIcon = new LazyIcon("clear"); switchJTemplate(getTemplateIndex(evtX)); isShowList = false; } @@ -1308,6 +874,7 @@ public class MultiTemplateTabPane extends JComponent { /** * 切换到指定模板 + * * @param jTemplate */ public void switchJTemplate(JTemplate jTemplate) { @@ -1319,9 +886,10 @@ public class MultiTemplateTabPane extends JComponent { /** * 切换到指定index + * * @param switchIndex */ - private void switchJTemplate(int switchIndex){ + private void switchJTemplate(int switchIndex) { int tempSelectedIndex = selectedIndex; if (selectedIndex != switchIndex && switchIndex != -1) { openedTemplate.get(selectedIndex).stopEditing(); @@ -1344,17 +912,7 @@ public class MultiTemplateTabPane extends JComponent { return JTemplate.isValid(currentTemplate) && ComparatorUtils.equals(template.getPath(), currentTemplate.getPath()); } - private class MultiTemplateTabMouseMotionListener implements MouseMotionListener { - /** - * 鼠标拖拽 - * - * @param e 鼠标事件 - */ - @Override - public void mouseDragged(MouseEvent e) { - // do nothing - } - + private class MultiTemplateTabMouseMotionListener extends MouseMotionAdapter { /** * 鼠标移动 * @@ -1364,51 +922,106 @@ public class MultiTemplateTabPane extends JComponent { public void mouseMoved(MouseEvent e) { int evtX = e.getX(); mouseOveredIndex = getTemplateIndex(evtX); - - //看是否需要显示toolTip - if (mouseOveredIndex != -1 && isNeedToolTips[mouseOveredIndex - minPaintIndex]) { - setToolTipText(openedTemplate.get(mouseOveredIndex).getEditingFILE().getName()); - } else { - setToolTipText(null); - } - - listDownMode = isOverListDown(evtX) ? MOUSE_OVER_LIST_DOWN : LIST_DOWN; - - boolean isOverCloseIcon = isOverCloseIcon(evtX); - clodeMode = isOverCloseIcon ? MOUSE_OVER_CLOSE : CLOSE; - closeIconIndex = isOverCloseIcon ? mouseOveredIndex : -1; + setToolTipText(openedTemplate.get(mouseOveredIndex).getEditingFILE().getName()); + hoverMoreAction = isOverListDown(evtX); + closeIconIndex = isOverCloseIcon(evtX) ? mouseOveredIndex : -1; MultiTemplateTabPane.this.repaint(); } } /** * 判断是否显示在tab栏上 + * * @param jTemplate * @return */ - private boolean showJTemplateTab(JTemplate jTemplate){ + private boolean showJTemplateTab(JTemplate jTemplate) { JTemplate current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); return ComparatorUtils.equals(current.getTemplateTabOperatorType(), jTemplate.getTemplateTabOperatorType()); } /** * 获取tab操作类型的模板 + * * @param operator * @return */ - public List> getOpenedJTemplatesByOperator(String operator) { + public List> getOpenedJTemplatesByOperator(String operator) { return openedTemplate.stream().filter((jTemplate) -> ComparatorUtils.equals(jTemplate.getTemplateTabOperatorType(), operator)) .collect(Collectors.toList()); } /** * 根据tab操作类型进行分类 + * * @return */ public Map>> getOpenedJTemplatesByCategory() { - return openedTemplate.stream() - .collect(Collectors.groupingBy(JTemplate::getTemplateTabOperatorType)); + return openedTemplate.stream() + .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 getViewRange() { + return new Pair<>(minPaintIndex, maxPaintIndex); + } } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UICombinationButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UICombinationButton.java index 4a24c8de25..ff3398077d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UICombinationButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UICombinationButton.java @@ -1,143 +1,155 @@ package com.fr.design.gui.ibutton; -import java.awt.BorderLayout; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.Icon; -import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import java.awt.BorderLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.function.Consumer; -import com.fr.design.constants.UIConstants; -import com.fr.stable.Constants; -import com.fr.design.utils.gui.GUICoreUtils; +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 + *

+ * created by vito on 2023/12/28 + **/ +public class UICombinationButton extends JPanel { + private static final String UI_CLASS_ID = "CombinationButtonUI"; + + protected UIButton leftButton; + protected UIButton rightButton; + + + private Consumer leftClickLister; + private Consumer rightClickLister; + + protected void leftButtonClickEvent() { + // 左边按钮点击事件 + } + + protected void rightButtonClickEvent() { + // 右边按钮点击事件 + } + + public UICombinationButton() { + this(new UIButton(), new UIButton()); + } + + + /** + * 添加左按钮监听器 + * + * @param lister 监听 + */ + public void addLeftClickLister(Consumer lister) { + this.leftClickLister = lister; + } + + /** + * 添加右按钮监听器 + * + * @param lister 监听 + */ + public void addRightClickLister(Consumer 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 + public void mouseClicked(MouseEvent e) { + if (leftClickLister != null) { + leftClickLister.accept(e); + } else { + leftButtonClickEvent(); + } + } + }); + rightButton.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (rightClickLister != null) { + rightClickLister.accept(e); + } else { + rightButtonClickEvent(); + } + } + }); + + this.setLayout(new BorderLayout()); + this.add(leftButton, BorderLayout.WEST); + this.add(rightButton, BorderLayout.EAST); + } + + public UICombinationButton(String left, Icon right) { + this(); + leftButton.setText(left); + rightButton.setIcon(right); + } + + public UICombinationButton(String left, String right) { + this(); + leftButton.setText(left); + rightButton.setText(right); + } + + public UICombinationButton(Icon left, Icon right) { + this(); + leftButton.setIcon(left); + 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() { + return leftButton; + } + + public void setExtraPainted(boolean isExtraPainted) { +// if (!isExtraPainted) { +// leftButton.setBackground(null); +// rightButton.setBackground(null); +// leftButton.setOpaque(false); +// rightButton.setOpaque(false); +// } + } + + public UIButton getRightButton() { + return rightButton; + } + + public void set4Toolbar() { + leftButton.setNormalPainted(false); + rightButton.setNormalPainted(false); + leftButton.setBorderPaintedOnlyWhenPressed(true); + rightButton.setBorderPaintedOnlyWhenPressed(true); + } -public class UICombinationButton extends JPanel{ - protected UIButton leftButton; - protected UIButton rightButton; - - protected void leftButtonClickEvent() { - // 左边按钮点击事件 - } - - protected void rightButtonClickEvent() { - // 右边按钮点击事件 - } - - public UICombinationButton() { - 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); - rightButton.getModel().setSelected(true); - rightButton.repaint(); - } - - @Override - public void mouseReleased(MouseEvent e) { - rightButton.getModel().setPressed(false); - rightButton.getModel().setSelected(false); - rightButton.repaint(); - } - @Override - public void mouseClicked(MouseEvent e) { - leftButtonClickEvent(); - } - }); - 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 - public void mouseClicked(MouseEvent e) { - rightButtonClickEvent(); - } - }); - - this.setLayout(new BorderLayout()); - this.add(leftButton, BorderLayout.CENTER); - this.add(rightButton, BorderLayout.EAST); - } - - public UICombinationButton(String left, Icon right) { - this(); - leftButton.setText(left); - rightButton.setIcon(right); - } - - public UICombinationButton(String left, String right) { - this(); - leftButton.setText(left); - rightButton.setText(right); - } - - public UICombinationButton(Icon left, Icon right) { - this(); - leftButton.setIcon(left); - rightButton.setIcon(right); - } - - public UIButton getLeftButton() { - return leftButton; - } - - public void setExtraPainted(boolean isExtraPainted) { - if(!isExtraPainted) { - leftButton.setBackground(null); - rightButton.setBackground(null); - leftButton.setOpaque(false); - rightButton.setOpaque(false); - } - } - - public UIButton getRightButton() { - return rightButton; - } - - public void set4Toolbar() { - leftButton.setNormalPainted(false); - rightButton.setNormalPainted(false); - leftButton.setBorderPaintedOnlyWhenPressed(true); - rightButton.setBorderPaintedOnlyWhenPressed(true); - } - - protected void showPopWindow(JPopupMenu menu) { - 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); - } + protected void showPopWindow(JPopupMenu menu) { + GUICoreUtils.showPopupMenu(menu, this, 0, getY() + getHeight() - 3); + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java index 4fa5cc4eba..4f6ee08cc8 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIHeadGroup.java @@ -61,6 +61,7 @@ public class UIHeadGroup extends Row { * @see JComponent#getUIClassID * @see UIDefaults#getUI */ + @Override public String getUIClassID() { return UI_CLASS_ID; } diff --git a/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java b/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java index 7b30e45d96..618f4c5510 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java +++ b/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java @@ -18,7 +18,6 @@ public class UIToolbar extends JToolBar { setFloatable(false); setRollover(true); setLayout(new FlowLayout(align, 4, 0)); -// setUI(uiToolBarUI); setBorderPainted(false); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java index 96265efcf1..9f36dfddd2 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java @@ -1,13 +1,13 @@ package com.fr.design.mainframe; +import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.fr.design.DesignState; import com.fr.design.base.mode.DesignModeContext; -import com.fr.design.constants.UIConstants; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.MultiTemplateTabPane; import com.fr.design.file.NewTemplatePane; 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.layout.FRGUIPaneFactory; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; @@ -16,14 +16,11 @@ import org.jetbrains.annotations.Nullable; import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.BorderFactory; import javax.swing.UIManager; -import javax.swing.border.MatteBorder; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; -import java.awt.Insets; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -47,7 +44,7 @@ public class CenterRegionContainerPane extends JPanel { private JComponent toolbarComponent;//cpt 字体 等工具栏 private JPanel eastPane;//=largeToolbar+eastCenterPane - private UILargeToolbar largeToolbar;//预览 + private UICombinationButton largeToolbar;//预览 private JPanel eastCenterPane;//=combineUp + templateTabPane @@ -70,37 +67,28 @@ public class CenterRegionContainerPane extends JPanel { public CenterRegionContainerPane() { - toolbarPane = new JPanel() { - - @Override - public Dimension getPreferredSize() { - - Dimension dim = super.getPreferredSize(); - // dim.height = TOOLBAR_HEIGHT; - return dim; - } - }; - toolbarPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); + toolbarPane = new JPanel(); + toolbarPane.setBorder(new ScaledEmptyBorder(6, 0, 10, 0)); toolbarPane.setLayout(FRGUIPaneFactory.createBorderLayout()); toolbarPane.setBackground(UIManager.getColor("Center.SpaceColor")); eastPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - eastPane.add(largeToolbar = getToolBarMenuDock().createLargeToolbar(), BorderLayout.WEST); + largeToolbar = getToolBarMenuDock().createLargeToolbar(); eastCenterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); combineUpTooBar(); - eastCenterPane.add(combineUp, BorderLayout.NORTH); templateTabPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - templateTabPane.add(newWorkBookPane = getToolBarMenuDock().getNewTemplatePane(), BorderLayout.WEST); - templateTabPane.add(MultiTemplateTabPane.getInstance(), BorderLayout.CENTER); - eastCenterPane.add(templateTabPane, BorderLayout.CENTER); + newWorkBookPane = getToolBarMenuDock().getNewTemplatePane(); + eastCenterPane.add(templateTabPane, BorderLayout.NORTH); + eastCenterPane.add(combineUp, BorderLayout.CENTER); eastPane.add(eastCenterPane, BorderLayout.CENTER); toolbarPane.add(eastPane, BorderLayout.NORTH); this.setLayout(new BorderLayout()); this.add(centerTemplateCardPane = new DesktopCardPane(), BorderLayout.CENTER); + centerTemplateCardPane.setBorder(new ScaledEmptyBorder(0, 10, 10, 10)); this.add(toolbarPane, BorderLayout.NORTH); 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() { @@ -112,10 +100,9 @@ public class CenterRegionContainerPane extends JPanel { */ private void combineUpTooBar() { 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)); setUpUpToolBar(null); - } @@ -135,6 +122,7 @@ public class CenterRegionContainerPane extends JPanel { * @param toolbar4Form 目标组件 */ private void setUpUpToolBar(@Nullable JComponent[] toolbar4Form) { + combineUp.add(largeToolbar); UIButton[] fixButtons = getToolBarMenuDock().createUp(); for (UIButton fixButton : fixButtons) { combineUp.add(fixButton); @@ -233,19 +221,20 @@ public class CenterRegionContainerPane extends JPanel { // 颜色,字体那些按钮的工具栏 toolbarPane.add(toolbarComponent = ad.resetToolBar(toolbarComponent, plus), BorderLayout.CENTER); + toolbarComponent.setBorder(new ScaledEmptyBorder(0, 10, 10, 10)); JPanel customNorthPane = strategy.customNorthPane(toolbarPane, plus); if (!isExist(customNorthPane)) { this.removeNorth(); this.add(customNorthPane, BorderLayout.NORTH); } if (strategy.hasTemplateTabPane(plus)) { - eastCenterPane.add(templateTabPane, BorderLayout.CENTER); + eastCenterPane.add(templateTabPane, BorderLayout.NORTH); } else { eastCenterPane.remove(templateTabPane); } if (strategy.hasCombineUp(plus)) { - eastCenterPane.add(combineUp, BorderLayout.NORTH); + eastCenterPane.add(combineUp, BorderLayout.CENTER); } else { eastCenterPane.remove(combineUp); } @@ -274,11 +263,11 @@ public class CenterRegionContainerPane extends JPanel { private void resetByDesignMode() { if (DesignModeContext.isDuchampMode()) { - eastPane.remove(largeToolbar); +// eastPane.remove(largeToolbar); //移除新建模板按钮 templateTabPane.remove(newWorkBookPane); } else { - eastPane.add(largeToolbar, BorderLayout.WEST); +// eastPane.add(largeToolbar, BorderLayout.WEST); templateTabPane.add(newWorkBookPane, BorderLayout.WEST); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index e3742f8a31..685a31843a 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -177,7 +177,7 @@ public abstract class JTemplate> private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener; public JTemplate() { - initAndStartPlugin(); +// initAndStartPlugin(); startListenThemeConfig(); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java index 911c0dc17a..04975208de 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java @@ -1,6 +1,6 @@ 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.designer.TargetComponent; import com.fr.design.file.HistoryTemplateListPane; @@ -246,9 +246,9 @@ public class JVirtualTemplate extends JTemplate { @Override public Icon getIcon() { if (getPath().endsWith("cpt")) { - return BaseUtils.readIcon("/com/fr/design/images/buttonicon/newcpts.png"); + return new LazyIcon("cpt_icon"); } else { - return BaseUtils.readIcon("/com/fr/web/images/form/new_form3.png"); + return new LazyIcon("frm_icon"); } } diff --git a/designer-base/src/main/resources/com/fine/theme/icon/clear_hover.svg b/designer-base/src/main/resources/com/fine/theme/icon/clear_hover.svg new file mode 100644 index 0000000000..6981454e9e --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/clear_hover.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/designer-base/src/main/resources/com/fine/theme/icon/toolbar/more.svg b/designer-base/src/main/resources/com/fine/theme/icon/toolbar/more.svg new file mode 100644 index 0000000000..42f49767c8 --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/toolbar/more.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fine/theme/icon/toolbar/more_disable.svg b/designer-base/src/main/resources/com/fine/theme/icon/toolbar/more_disable.svg new file mode 100644 index 0000000000..6570607cd1 --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/toolbar/more_disable.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties index adb218b4a6..41d855e279 100644 --- a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLaf.properties +++ b/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 #---- UI delegates ---- -ButtonUI=com.formdev.flatlaf.ui.FlatButtonUI +ButtonUI=com.fine.theme.light.ui.FineButtonUI CheckBoxUI=com.fine.theme.light.ui.FineCheckBoxUI CheckBoxMenuItemUI=com.formdev.flatlaf.ui.FlatCheckBoxMenuItemUI ColorChooserUI=com.formdev.flatlaf.ui.FlatColorChooserUI @@ -44,7 +44,9 @@ ToolTipUI=com.fine.theme.light.ui.FineTooltipUI TreeUI=com.fine.theme.light.ui.UIFlatTreeUI ViewportUI=com.formdev.flatlaf.ui.FlatViewportUI HeadGroupUI=com.fine.theme.light.ui.FineHeadGroupUI -ButtonGroupUI= com.fine.theme.light.ui.FineButtonGroupUI -SelectBoxUI= com.fine.theme.light.ui.FineSelectBoxUI +ButtonGroupUI=com.fine.theme.light.ui.FineButtonGroupUI +SelectBoxUI=com.fine.theme.light.ui.FineSelectBoxUI +CombinationButtonUI=com.fine.theme.light.ui.FineCombinationButtonUI InputUI=com.fine.theme.light.ui.FineInputUI -GradientBarUI=com.fine.theme.light.ui.FineGradientBarUI \ No newline at end of file +GradientBarUI=com.fine.theme.light.ui.FineGradientBarUI +TemplateTabPaneUI=com.fine.theme.light.ui.FineTemplateTabPaneUI \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties index 51b2c52785..88e185f0ab 100644 --- a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties +++ b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties @@ -60,7 +60,7 @@ Component.defaultVGap=10 @disabledForeground = tint(@foreground,55%) # component background -@buttonBackground = lighten(@background,5%) +@buttonBackground = #FFF @componentBackground = @background @menuBackground = @background @@ -136,33 +136,50 @@ fill.disabled=#F2F4F8 border.divider=#DADEE7 tooltip.normal=#3F506A tooltip.disabled=#A3ADBD +hover.deep=#e2fbe6 #---- Button ---- -Button.border = com.formdev.flatlaf.ui.FlatButtonBorder +Button.border =com.fine.theme.light.ui.FineButtonBorder Button.arc = 6 -Button.minimumWidth = 72 +Button.minimumWidth = 0 Button.margin = 2,12,2,12 Button.iconTextGap = 4 Button.rollover = true 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.focusedBackground = changeLightness($Component.focusColor,95%) -Button.hoverBackground = darken($Button.background,3%,derived) -Button.pressedBackground = darken($Button.background,10%,derived) +Button.focusedBackground = @buttonBackground +Button.hoverBackground = $fill.hover +Button.pressedBackground = $fill.click Button.selectedBackground = darken($Button.background,20%,derived) Button.selectedForeground = $Button.foreground Button.disabledSelectedBackground = darken($Button.background,13%,derived) +Button.disabledBackground = $fill.disabled Button.borderColor = $Component.borderColor Button.disabledBorderColor = $Component.disabledBorderColor -Button.focusedBorderColor = $Component.focusedBorderColor -Button.hoverBorderColor = $Button.focusedBorderColor +Button.focusedBorderColor = $border.divider +Button.hoverBorderColor = $border.divider 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.foreground = $Button.foreground Button.default.focusedBackground = $Button.focusedBackground @@ -180,10 +197,29 @@ Button.toolbar.selectedBackground = $Button.selectedBackground Button.toolbar.margin = 3,3,3,3 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.border = com.formdev.flatlaf.ui.FlatMarginBorder -CheckBox.icon = com.formdev.flatlaf.icons.FlatCheckBoxIcon +CheckBox.icon = com.fine.theme.icon.AnimatedSwitchIcon CheckBox.arc = 4 CheckBox.margin = 2,2,2,2 CheckBox.iconTextGap = 4 @@ -289,8 +325,8 @@ Component.minimumWidth = 64 Component.arrowType = chevron Component.hideMnemonics = true -Component.borderColor = shade(@background,20%) -Component.disabledBorderColor = tint($Component.borderColor,20%) +Component.borderColor = $defaultBorderColor +Component.disabledBorderColor = $defaultBorderColor Component.focusedBorderColor = shade($Component.focusColor,10%) Component.focusColor = @accentFocusColor Component.linkColor = @accentLinkColor @@ -778,19 +814,19 @@ SplitPaneDivider.draggingColor = $Component.borderColor #---- TabbedPane ---- -TabbedPane.tabHeight = 32 -TabbedPane.tabSelectionHeight = 3 -TabbedPane.cardTabSelectionHeight = 3 +TabbedPane.tabHeight = 30 +TabbedPane.tabSelectionHeight = 0 +TabbedPane.cardTabSelectionHeight = 0 TabbedPane.tabArc = 0 TabbedPane.tabSelectionArc = 0 TabbedPane.cardTabArc = 12 -TabbedPane.selectedInsets = 0,0,0,0 +TabbedPane.selectedInsets = 10,0,0,0 TabbedPane.tabSelectionInsets = 0,0,0,0 TabbedPane.contentSeparatorHeight = 1 -TabbedPane.showTabSeparators = false +TabbedPane.showTabSeparators = true TabbedPane.tabSeparatorsFullHeight = false TabbedPane.hasFullBorder = false -TabbedPane.tabInsets = 4,12,4,12 +TabbedPane.tabInsets = 4,6,4,6 TabbedPane.tabAreaInsets = 0,0,0,0 TabbedPane.selectedTabPadInsets = 0,0,0,0 TabbedPane.tabRunOverlay = 0 @@ -798,6 +834,9 @@ TabbedPane.tabsOverlapBorder = false TabbedPane.disabledForeground = @disabledForeground TabbedPane.shadow = @background TabbedPane.contentBorderInsets = null +TabbedPane.background = $fill.disabled +TabbedPane.selectedBackground = #fff +TabbedPane.tabSeparatorColor = $border.divider # allowed values: moreTabsButton or arrowButtons TabbedPane.hiddenTabsNavigation = moreTabsButton # allowed values: leading, trailing, center or fill @@ -834,21 +873,36 @@ TabbedPane.closeCrossLineWidth = 1 TabbedPane.underlineColor = @accentUnderlineColor TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,50%) TabbedPane.disabledUnderlineColor = darken(@background,28%) -TabbedPane.hoverColor = #DADEE7 +TabbedPane.hoverColor = $fill.hover TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%) -TabbedPane.contentAreaColor = $Component.borderColor +TabbedPane.contentAreaColor = $fill.hover TabbedPane.buttonHoverBackground = darken($TabbedPane.background,7%,derived) TabbedPane.buttonPressedBackground = darken($TabbedPane.background,10%,derived) TabbedPane.closeBackground = null TabbedPane.closeForeground = @disabledForeground -TabbedPane.closeHoverBackground = darken($TabbedPane.background,20%,derived) +TabbedPane.closeHoverBackground = $hover.deep TabbedPane.closeHoverForeground = @foreground TabbedPane.closePressedBackground = darken($TabbedPane.background,25%,derived) 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.rowHeight = 20 @@ -1038,6 +1092,7 @@ ToolBar.arrowKeysOnlyNavigation = true ToolBar.hoverButtonGroupArc = 8 ToolBar.floatable = false ToolBar.gripColor = @icon +ToolBar.background = #fff ToolBar.dockingBackground = darken($ToolBar.background,5%) ToolBar.dockingForeground = $Component.borderColor ToolBar.floatingBackground = $ToolBar.background @@ -1178,6 +1233,33 @@ CellOtherSetPane.height=$Component.defaultHeight toolbar.pressedBackground: darken($TextField.background,8%); \ 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 ---- # for clear/cancel button in text fields diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonStoryBoard.java index bc157a2f57..e0d0dad170 100644 --- a/designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonStoryBoard.java +++ b/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.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.StoryBoard; import javax.swing.JButton; 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.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() { super("按钮"); + setSpacing(16); add( - row(10, - cell(new UIButton("按钮")), - cell(new UIButton("保存", new LazyIcon("save"))), - cell(new UIButton(new LazyIcon("multi"))) + 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("按钮", new LazyIcon("add"))), + cell(new UIButton(new LazyIcon("multi"))) + ), + 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); + }) + ) + ) ), - row(10, + cell(new UILabel("JButton")).with(this::h2), + row(20, + cell(new UILabel("medium")), 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"))) ), flex() diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/components/JTestTemplate.java b/designer-base/src/test/java/com/fr/design/gui/storybook/components/JTestTemplate.java new file mode 100644 index 0000000000..72a97c5d3f --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/components/TemplateTabStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/components/TemplateTabStoryBoard.java new file mode 100644 index 0000000000..31e2406682 --- /dev/null +++ b/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 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()); + } + + +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java index 97488e7d83..34603c59e0 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java @@ -1,5 +1,6 @@ package com.fr.design.mainframe; +import com.fine.theme.icon.LazyIcon; import com.fr.base.PaperSize; import com.fr.base.Parameter; import com.fr.base.Releasable; @@ -1067,7 +1068,7 @@ public class JForm extends JTemplate implements BaseJForm { @Override public Icon getIcon() { - return IconUtils.readIcon("/com/fr/design/images/buttonicon/newcpts.png"); + return new LazyIcon("cpt_icon"); } /** diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java index 21b6c7eed4..8ab1ea9eb2 100644 --- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java +++ b/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.base.mode.DesignModeContext; import com.fr.design.carton.SwitchForSwingChecker; -import com.fr.design.constants.UIConstants; import com.fr.design.deeplink.DeepLinkManager; import com.fr.design.file.HistoryTemplateListCache; 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.OemProcessor; 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.imenu.UIMenuItem; 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.DesignerContext; import com.fr.design.mainframe.InformationCollector; @@ -79,13 +77,9 @@ import com.fr.workspace.WorkContext; import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.border.MatteBorder; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; import java.util.concurrent.LinkedBlockingQueue; @@ -106,7 +100,7 @@ public class MainDesigner extends BaseDesigner { private UIButton undo; private UIButton redo; private UIButton[] upToolBar; - private UIPreviewButton run; + private UICombinationButton run; public MainDesigner(String[] args) { super(args); @@ -268,15 +262,8 @@ public class MainDesigner extends BaseDesigner { * @return 返回大图标对应的工具栏 */ @Override - public UILargeToolbar createLargeToolbar() { - UILargeToolbar largeToolbar = super.createLargeToolbar(); - 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)); + public UICombinationButton createLargeToolbar() { + UICombinationButton largeToolbar = createRunButton(); return largeToolbar; } @@ -315,15 +302,12 @@ public class MainDesigner extends BaseDesigner { saveButton = new UIButton(new LazyIcon("save")); saveButton.setToolTipText(KeySetUtils.SAVE_TEMPLATE.getMenuKeySetName()); saveButton.set4ToolbarButton(); - saveButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - jt.stopEditing(); - jt.saveDirectly(); - jt.requestFocus(); - SharableManager.saveTemplate(jt); - } + saveButton.addActionListener(e -> { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + jt.stopEditing(); + jt.saveDirectly(); + jt.requestFocus(); + SharableManager.saveTemplate(jt); }); } @@ -332,13 +316,10 @@ public class MainDesigner extends BaseDesigner { undo = new UIButton(new LazyIcon("undo")); undo.setToolTipText(KeySetUtils.UNDO.getMenuKeySetName()); undo.set4ToolbarButton(); - undo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); - if (jt != null) { - jt.undo(); - } + undo.addActionListener(e -> { + JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if (jt != null) { + jt.undo(); } }); } @@ -347,65 +328,44 @@ public class MainDesigner extends BaseDesigner { redo = new UIButton(new LazyIcon("redo")); redo.setToolTipText(KeySetUtils.REDO.getMenuKeySetName()); redo.set4ToolbarButton(); - redo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); - if (jt != null) { - jt.redo(); - } + redo.addActionListener(e -> { + JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if (jt != null) { + jt.redo(); } }); } - private void createRunButton(UILargeToolbar largeToolbar) { - run = new UIPreviewButton(new UISaveForbiddenButton(UIConstants.PAGE_BIG_ICON) { - @Override - public Dimension getPreferredSize() { - return new Dimension(34, 34); + private UICombinationButton createRunButton() { + run = new UICombinationButton(new UISaveForbiddenButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"), new LazyIcon("add")), + new UISaveForbiddenButton(new LazyIcon("triangle_down"))); + run.addLeftClickLister(mouseEvent -> { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (jt == null || jt.isSaving()) { + return; } - }, new UISaveForbiddenButton(UIConstants.PREVIEW_DOWN) { - @Override - public Dimension getPreferredSize() { - return new Dimension(34, 10); - } - } - ) { - @Override - protected void upButtonClickEvent() { - JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (jt == null || jt.isSaving()) { - return; - } - WebPreviewUtils.preview(jt); + WebPreviewUtils.preview(jt); + }); + run.addRightClickLister(mouseEvent -> { + final JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (jt == null) { + return; } - @Override - protected void downButtonClickEvent() { - final JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (jt == null) { - return; - } - - UIPopupMenu menu = new UIPopupMenu(); + UIPopupMenu menu = new UIPopupMenu(); - UIMenuItem[] items = jt.createMenuItem4Preview(); - for (int i = 0; i < items.length; i++) { - menu.add(items[i]); - } - GUICoreUtils.showPopupMenu(menu, MultiTemplateTabPane.getInstance(), MultiTemplateTabPane.getInstance().getX() - PREVIEW_DOWN_X_GAP, MultiTemplateTabPane.getInstance().getY() - 1 + MultiTemplateTabPane.getInstance().getHeight()); + UIMenuItem[] items = jt.createMenuItem4Preview(); + for (UIMenuItem item : items) { + menu.add(item); } - - @Override - public Dimension getPreferredSize() { - // TODO Auto-generated method stub - return new Dimension(34, 46); - } - }; + GUICoreUtils.showPopupMenu(menu, run, run.getX(), run.getY() - 1 + run.getHeight()); + }); + run.setPrimary(); run.setExtraPainted(false); run.set4Toolbar(); - run.getUpButton().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.getLeftButton().setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview")); + run.getRightButton().setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Dropdown_More_Preview")); + return run; } @Override @@ -425,7 +385,7 @@ public class MainDesigner extends BaseDesigner { redo.setEnabled(false); } - run.getUpButton().setIcon(jt.getPreviewLargeIcon()); +// run.getLeftButton().setIcon(jt.getPreviewLargeIcon()); }