From 97cb1b2f9ca756027dcba0703684953e5a37604d Mon Sep 17 00:00:00 2001 From: richie Date: Mon, 28 Oct 2019 16:43:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E7=9A=84=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fanruan/api/design/macro/UIConstants.java | 21 + .../design/ui/component/UIButtonGroup.java | 13 +- .../api/design/ui/layout/TableLayoutKit.java | 53 +++ .../ui/layout/macro/LayoutConstants.java | 35 ++ .../fanruan/api/design/util/GUICoreKit.java | 29 ++ .../api/design/work/RichTextToolBar.java | 6 +- .../work/component/container/FontPane.java | 366 ++++++++++++++++++ .../component/container/NumberDragPane.java | 141 +++++++ .../fanruan/api/report/form/WidgetKit.java | 43 ++ .../form/category/BaseBorderStyleWidget.java | 234 ++++++++++- .../java/com/fanruan/api/util/GraphKit.java | 21 + .../java/com/fanruan/api/util/MathKit.java | 19 + 12 files changed, 976 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/fanruan/api/design/ui/layout/macro/LayoutConstants.java create mode 100644 src/main/java/com/fanruan/api/design/work/component/container/FontPane.java create mode 100644 src/main/java/com/fanruan/api/design/work/component/container/NumberDragPane.java create mode 100644 src/main/java/com/fanruan/api/report/form/WidgetKit.java create mode 100644 src/main/java/com/fanruan/api/util/MathKit.java diff --git a/src/main/java/com/fanruan/api/design/macro/UIConstants.java b/src/main/java/com/fanruan/api/design/macro/UIConstants.java index 925b64d..8e92bcf 100644 --- a/src/main/java/com/fanruan/api/design/macro/UIConstants.java +++ b/src/main/java/com/fanruan/api/design/macro/UIConstants.java @@ -1,5 +1,6 @@ package com.fanruan.api.design.macro; +import com.fanruan.api.macro.LineConstants; import com.fanruan.api.util.IOKit; import javax.swing.*; @@ -34,4 +35,24 @@ public interface UIConstants { * 用于表示字体的图标 */ Icon FONT_ICON = IOKit.readIcon("/com/fr/design/images/gui/color/foreground.png"); + + /** + * 边框线数组 + */ + int[] BORDER_LINE_STYLE_ARRAY = new int[]{ + LineConstants.LINE_THIN, + LineConstants.LINE_MEDIUM, + LineConstants.LINE_DASH, + LineConstants.LINE_HAIR, + LineConstants.LINE_HAIR2, + LineConstants.LINE_THICK, + LineConstants.LINE_DOUBLE, + LineConstants.LINE_DOT, + LineConstants.LINE_MEDIUM_DASH, + LineConstants.LINE_DASH_DOT, + LineConstants.LINE_MEDIUM_DASH_DOT, + LineConstants.LINE_DASH_DOT_DOT, + LineConstants.LINE_MEDIUM_DASH_DOT_DOT, + LineConstants.LINE_SLANTED_DASH_DOT, + }; } diff --git a/src/main/java/com/fanruan/api/design/ui/component/UIButtonGroup.java b/src/main/java/com/fanruan/api/design/ui/component/UIButtonGroup.java index 4af87f9..2a99129 100644 --- a/src/main/java/com/fanruan/api/design/ui/component/UIButtonGroup.java +++ b/src/main/java/com/fanruan/api/design/ui/component/UIButtonGroup.java @@ -1,18 +1,29 @@ package com.fanruan.api.design.ui.component; -import javax.swing.Icon; +import javax.swing.*; /** * @author Bjorn * @version 10.0 * Created by Bjorn on 2019-09-19 + * 按钮组 */ public class UIButtonGroup extends com.fr.design.gui.ibutton.UIButtonGroup { + /** + * 创建一个有不同文本的按钮组 + * + * @param textArray 用于表示的选项的字符串数组 + */ public UIButtonGroup(String[] textArray) { super(textArray); } + /** + * 创建一个有不同图标的按钮组 + * + * @param iconArray 用于表示的选项的图标数组 + */ public UIButtonGroup(Icon[] iconArray) { super(iconArray); } diff --git a/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java b/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java index fa2b661..d011afb 100644 --- a/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java +++ b/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java @@ -37,6 +37,26 @@ public class TableLayoutKit { */ public static final double FILL = TableLayout.FILL; + /** + * 不填充 + */ + public static final int FILL_NONE = 0; + + /** + * 最后一列自动充满 + */ + public static final int FILL_LAST_COLUMN = 1; + + /** + * 填充最后一行 + */ + public static final int FILL_LAST_ROW = 2; + + /** + * 同时填充最后一行和最后一列 + */ + public static final int FILL_LAST_COL_AND_ROW = 3; + /** * 创建一个简单的表格布局并把组件添加到布局容器中 * @@ -63,6 +83,23 @@ public class TableLayoutKit { return TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, gap); } + /** + * 创建一个简单的表格布局并把组件添加到布局容器中 + * + * @param components 组件 + * @param fillType 填充策略 + * @param horizontalGap 水平间隙 + * @param verticalGap 垂直间隙 + * @return 按要求的布局添加好组件的容器 + * @see TableLayoutKit#FILL_NONE + * @see TableLayoutKit#FILL_LAST_COLUMN + * @see TableLayoutKit#FILL_LAST_ROW + * @see TableLayoutKit#FILL_LAST_COL_AND_ROW + */ + public static JPanel createGapTableLayoutPane(Component[][] components, int fillType, double horizontalGap, double verticalGap) { + return TableLayoutHelper.createGapTableLayoutPane(components, fillType, horizontalGap, verticalGap); + } + /** * 创建一个简单的表格布局并把组件添加到布局容器中 * @@ -77,4 +114,20 @@ public class TableLayoutKit { return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, horizontalGap, verticalGap); } + + /** + * 创建一个简单的表格布局并把组件添加到布局容器中 + * + * @param components 组件 + * @param rowSize 行尺寸信息,可以是固定的数值,也可以是PREFERRED或者FILL常量 + * @param columnSize 列尺寸信息,可以是固定的数值,也可以是PREFERRED或者FILL常量 + * @param rowCount 行数量 + * @param horizontalGap 水平间隙 + * @param verticalGap 垂直间隙 + * @return 按要求的布局添加好组件的容器 + */ + public static JPanel createGapTableLayoutPane(Component[][] components, + double[] rowSize, double[] columnSize, int[][] rowCount, double horizontalGap, double verticalGap) { + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, horizontalGap, verticalGap); + } } diff --git a/src/main/java/com/fanruan/api/design/ui/layout/macro/LayoutConstants.java b/src/main/java/com/fanruan/api/design/ui/layout/macro/LayoutConstants.java new file mode 100644 index 0000000..4d62bd1 --- /dev/null +++ b/src/main/java/com/fanruan/api/design/ui/layout/macro/LayoutConstants.java @@ -0,0 +1,35 @@ +package com.fanruan.api.design.ui.layout.macro; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019/10/28 + * 布局常数 + */ +public class LayoutConstants { + + /** + * 水平间隙 + */ + public static final int HGAP_SMALL = 1; + /** + * 水平间隙 + */ + public static final int HGAP_LARGE = 4; + /** + * 垂直间隙 + */ + public static final int VGAP_SMALL = 4; + /** + * 垂直间隙 + */ + public static final int VGAP_MEDIUM = 6; + /** + * 垂直间隙 + */ + public static final int VGAP_LARGE = 10; + /** + * 垂直间隙 + */ + public static final int VGAP_HUGER = 20; +} diff --git a/src/main/java/com/fanruan/api/design/util/GUICoreKit.java b/src/main/java/com/fanruan/api/design/util/GUICoreKit.java index af8661c..e9ea44a 100644 --- a/src/main/java/com/fanruan/api/design/util/GUICoreKit.java +++ b/src/main/java/com/fanruan/api/design/util/GUICoreKit.java @@ -1,9 +1,11 @@ package com.fanruan.api.design.util; +import com.fr.design.border.UITitledBorder; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.*; +import javax.swing.border.TitledBorder; import java.awt.*; public class GUICoreKit { @@ -118,6 +120,7 @@ public class GUICoreKit { public static JPanel createBorderLayoutPane() { return FRGUIPaneFactory.createBorderLayout_S_Pane(); } + /** * 设置一个窗口居中 */ @@ -134,4 +137,30 @@ public class GUICoreKit { } win.setLocation((screenSize.width - winSize.width) / 2, (screenSize.height - winSize.height) / 2 - 20); } + + /** + * 设置黑色的边框 + * + * @param title 标题 + * @return 同上 + */ + public static TitledBorder createTitledBorder(String title) { + return createTitledBorder(title, Color.black); + } + + /** + * 设置带指定颜色的边框 + * + * @param title 标题 + * @param color 颜色 + * @return 带颜色的边框 + */ + public static TitledBorder createTitledBorder(String title, Color color) { + UITitledBorder tb = UITitledBorder.createBorderWithTitle(title); + if (color == null) { + color = Color.black; + } + tb.setTitleColor(color); + return tb; + } } diff --git a/src/main/java/com/fanruan/api/design/work/RichTextToolBar.java b/src/main/java/com/fanruan/api/design/work/RichTextToolBar.java index 4fa9425..995bc25 100644 --- a/src/main/java/com/fanruan/api/design/work/RichTextToolBar.java +++ b/src/main/java/com/fanruan/api/design/work/RichTextToolBar.java @@ -14,8 +14,6 @@ import com.fr.design.formula.FormulaFactory; import com.fr.design.formula.UIFormula; import com.fr.design.gui.style.FRFontPane; import com.fr.design.mainframe.DesignerContext; -import com.fr.design.report.RichTextEditingPane; -import com.fr.design.report.RichTextPane; import com.fr.design.style.color.UIToolbarColorButton; import com.fr.general.FRFont; import com.fr.report.cell.cellattr.core.RichTextConverter; @@ -55,6 +53,8 @@ public class RichTextToolBar extends BasicPane { private static final Dimension BUTTON_SIZE = new Dimension(24, 20); + private static final FRFont DEFAULT_FONT = FRFont.getInstance().applySize(13); + private static final int NOT_INITIALIZED = -1; private static final int UPDATING = -2; @@ -152,7 +152,7 @@ public class RichTextToolBar extends BasicPane { } private void bindListener() { - FRFont defaultFont = (this.textPane != null) ? FRFont.getInstance(this.textPane.getFont()) : RichTextPane.DEFAUL_FONT; + FRFont defaultFont = (this.textPane != null) ? FRFont.getInstance(this.textPane.getFont()) : DEFAULT_FONT; fontNameComboBox.addItemListener(fontNameItemListener); fontNameComboBox.setSelectedItem(defaultFont.getFontName()); fontSizeComboBox.addItemListener(fontSizeItemListener); diff --git a/src/main/java/com/fanruan/api/design/work/component/container/FontPane.java b/src/main/java/com/fanruan/api/design/work/component/container/FontPane.java new file mode 100644 index 0000000..7153eec --- /dev/null +++ b/src/main/java/com/fanruan/api/design/work/component/container/FontPane.java @@ -0,0 +1,366 @@ +package com.fanruan.api.design.work.component.container; + + +import com.fanruan.api.design.DesignKit; +import com.fanruan.api.design.macro.UIConstants; +import com.fanruan.api.design.ui.component.UIColorButton; +import com.fanruan.api.design.ui.component.UIComboBox; +import com.fanruan.api.design.ui.component.UIToggleButton; +import com.fanruan.api.design.ui.layout.TableLayoutKit; +import com.fanruan.api.design.ui.layout.macro.LayoutConstants; +import com.fanruan.api.design.util.GUICoreKit; +import com.fanruan.api.design.work.component.LineComboBox; +import com.fanruan.api.macro.LineConstants; +import com.fanruan.api.util.AssistKit; +import com.fanruan.api.util.GeneralKit; +import com.fanruan.api.util.IOKit; +import com.fanruan.api.util.MathKit; +import com.fr.base.FRContext; +import com.fr.base.Style; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.gui.style.AbstractBasicStylePane; +import com.fr.general.DefaultValues; +import com.fr.general.FRFont; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.util.Vector; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019/10/28 + * 用于编辑字体的面板容器 + */ +public class FontPane extends AbstractBasicStylePane implements GlobalNameObserver { + + public static final Integer[] FONT_SIZES = { + 6, 8, 9, 10, 11, 12, 13, 14, 16, + 18, 20, 22, 24, 26, 28, 30, 32, 34, + 36, 38, 40, 48, 64, 72, 128 + }; + private static final int MAX_FONT_SIZE = 100; + private static final Dimension BUTTON_SIZE = new Dimension(20, 18); + private static final Dimension UNDER_LINE_SIZE = new Dimension(87, 20); + private static final Dimension HIDE_SIZE = new Dimension(0, 0); + private final String[] fontSizeStyles = {DesignKit.i18nText("Fine-Design_Basic_FR_Font_Plain"), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Bold"), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Italic"), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Bolditalic")}; + private JPanel buttonPane; + private JPanel isSuperOrSubPane; + private UIComboBox fontNameComboBox; + private UIComboBox fontSizeStyleComboBox; + private UIComboBox fontSizeComboBox; + private UIToggleButton bold; + private UIToggleButton italic; + private UIToggleButton underline; + private GlobalNameListener globalNameListener = null; + + private LineComboBox underlineCombo; + private UIColorButton colorSelectPane; + + private UIToggleButton isStrikethroughCheckBox; + private UIToggleButton isShadowCheckBox; + private UIToggleButton superPane; + private UIToggleButton subPane; + private JPanel linePane; + + public FontPane() { + this.initComponents(); + } + + public static void main(String[] args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + content.add(new com.fr.design.gui.style.FRFontPane(), BorderLayout.CENTER); + GUICoreKit.centerWindow(jf); + jf.setSize(290, 400); + jf.setVisible(true); + } + + + @Override + protected String title4PopupWindow() { + return DesignKit.i18nText("Fine-Design_Report_Sytle_FRFont"); + } + + /** + * Use font to populate pane. + */ + public void populateBean(FRFont frFont) { + fontNameComboBox.setSelectedItem(frFont.getFamily()); + fontSizeStyleComboBox.setSelectedIndex(frFont.getStyle()); + fontSizeComboBox.setSelectedItem(MathKit.round5(frFont.getSize2D())); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + + this.colorSelectPane.setColor(frFont.getForeground()); + this.colorSelectPane.repaint(); + + CardLayout cly = (CardLayout) linePane.getLayout(); + int line = frFont.getUnderline(); + if (line == LineConstants.LINE_NONE) { + underline.setSelected(false); + cly.show(linePane, "none"); + linePane.setPreferredSize(HIDE_SIZE); + } else { + underline.setSelected(true); + cly.show(linePane, "combobox"); + linePane.setPreferredSize(UNDER_LINE_SIZE); + this.underlineCombo.setSelectedLineStyle(line); + } + // effects + this.isStrikethroughCheckBox.setSelected(frFont.isStrikethrough()); + this.isShadowCheckBox.setSelected(frFont.isShadow()); + if (frFont.isSuperscript()) { + this.superPane.setSelected(true); + this.subPane.setSelected(false); + } else if (frFont.isSubscript()) { + this.superPane.setSelected(false); + this.subPane.setSelected(true); + } else { + this.superPane.setSelected(false); + this.subPane.setSelected(false); + } + } + + /** + * Update pane to get new font. + */ + public FRFont update(FRFont frFont) { + + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_Name"))) { + frFont = frFont.applyName((String) fontNameComboBox.getSelectedItem()); + } + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Style"))) { + frFont = frFont.applyStyle(fontSizeStyleComboBox.getSelectedIndex()); + } + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Form_FRFont_Size"))) { + frFont = frFont.applySize(Float.parseFloat(fontSizeComboBox.getSelectedItem().toString())); + } + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Foreground"))) { + frFont = frFont.applyForeground(this.colorSelectPane.getColor()); + } + + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Underline"))) { + + int line = underline.isSelected() ? this.underlineCombo.getSelectedLineStyle() : LineConstants.LINE_NONE; + frFont = frFont.applyUnderline(line); + + } + + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Form_FRFont_Line_Style"))) { + frFont = frFont.applyUnderline(this.underlineCombo.getSelectedLineStyle()); + } + + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Strikethrough"))) { + frFont = frFont.applyStrikethrough(isStrikethroughCheckBox.isSelected()); + } + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Shadow"))) { + frFont = frFont.applyShadow(isShadowCheckBox.isSelected()); + } + + frFont = updateOthers(frFont); + + return frFont; + } + + + private FRFont updateOthers(FRFont frFont) { + frFont = updateSubSuperscript(frFont); + return frFont; + } + + private FRFont updateSubSuperscript(FRFont frFont) { + boolean isSuper = frFont.isSuperscript(); + boolean isSub = frFont.isSubscript(); + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Superscript"))) { + //如果上标没有选中,点击则选中上标,并且下标一定是不选中状态 + //如果上标选中,点击则取消选中上标,字体回复正常 + if (superPane.isSelected() && !isSuper) { + frFont = frFont.applySuperscript(true); + frFont = frFont.applySubscript(false); + this.subPane.setSelected(false); + } else if (!superPane.isSelected() && isSuper) { + frFont = frFont.applySuperscript(false); + } + } + if (AssistKit.equals(globalNameListener.getGlobalName(), DesignKit.i18nText("Fine-Design_Basic_FR_Font_Subscript"))) { + if (subPane.isSelected() && !isSub) { + frFont = frFont.applySubscript(true); + frFont = frFont.applySuperscript(false); + this.superPane.setSelected(false); + } else if (!subPane.isSelected() && isSub) { + frFont = frFont.applySubscript(false); + } + } + return frFont; + } + + @Override + public void populateBean(Style style) { + this.populateBean(style.getFRFont()); + } + + @Override + public Style update(Style style) { + FRFont frFont = style.getFRFont(); + frFont = this.update(frFont); + return style.deriveFRFont(frFont); + } + + public static Vector getFontSizes() { + Vector FONT_SIZES = new Vector(); + for (int i = 1; i < MAX_FONT_SIZE; i++) { + FONT_SIZES.add(i); + } + return FONT_SIZES; + } + + protected void initComponents() { + fontSizeStyleComboBox = new UIComboBox<>(fontSizeStyles); + fontNameComboBox = new UIComboBox<>(GeneralKit.getAvailableFontFamilyNames()); + fontNameComboBox.setPreferredSize(new Dimension(144, 20)); + fontSizeComboBox = new UIComboBox<>(getFontSizes()); + fontSizeComboBox.setEditable(true); + this.underlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY); + colorSelectPane = new UIColorButton(); + bold = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); + italic = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); + underline = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); + bold.setPreferredSize(BUTTON_SIZE); + italic.setPreferredSize(BUTTON_SIZE); + underline.setPreferredSize(BUTTON_SIZE); + isStrikethroughCheckBox = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/strikethrough.png")); + isStrikethroughCheckBox.setPreferredSize(BUTTON_SIZE); + isShadowCheckBox = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/shadow.png")); + isShadowCheckBox.setPreferredSize(BUTTON_SIZE); + superPane = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/sup.png")); + superPane.setPreferredSize(BUTTON_SIZE); + subPane = new UIToggleButton(IOKit.readIcon("/com/fr/design/images/m_format/cellstyle/sub.png")); + subPane.setPreferredSize(BUTTON_SIZE); + Component[] SuperOrSubComponents = new Component[]{ + superPane, subPane + }; + isSuperOrSubPane = new JPanel(new BorderLayout()); + isSuperOrSubPane.add(GUICoreKit.createFlowPane(SuperOrSubComponents, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL)); + Component[] components_font = new Component[]{ + colorSelectPane, underline, isStrikethroughCheckBox, isShadowCheckBox + }; + buttonPane = new JPanel(new BorderLayout()); + buttonPane.add(GUICoreKit.createFlowPane(components_font, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL)); + linePane = new JPanel(new CardLayout()); + initAllNames(); + setToolTips(); + this.setLayout(new BorderLayout()); + this.add(createPane(), BorderLayout.CENTER); + DefaultValues defaultValues = FRContext.getDefaultValues(); + populateBean(defaultValues.getFRFont()); + } + + private void initAllNames() { + fontSizeStyleComboBox.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Style")); + fontNameComboBox.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_Name")); + fontSizeComboBox.setGlobalName(DesignKit.i18nText("Fine-Design_Form_FRFont_Size")); + colorSelectPane.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Foreground")); + italic.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Italic")); + bold.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Bold")); + underline.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Underline")); + underlineCombo.setGlobalName(DesignKit.i18nText("Fine-Design_Form_FRFont_Line_Style")); + isStrikethroughCheckBox.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Strikethrough")); + isShadowCheckBox.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Shadow")); + superPane.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Superscript")); + subPane.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Subscript")); + } + + private void setToolTips() { + colorSelectPane.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Foreground")); + italic.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Italic")); + bold.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Bold")); + underline.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Underline")); + isStrikethroughCheckBox.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Strikethrough")); + isShadowCheckBox.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Shadow")); + superPane.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Superscript")); + subPane.setToolTipText(DesignKit.i18nText("Fine-Design_Basic_FR_Font_Subscript")); + } + + + private JPanel createLinePane() { + linePane.add(new JPanel(), "none"); + JPanel gap = new JPanel(new GridLayout(0, 1)); + gap.add(underlineCombo); + linePane.add(gap, "combobox"); + underline.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + CardLayout cly = (CardLayout) linePane.getLayout(); + cly.show(linePane, underline.isSelected() ? "combobox" : "none"); + if (underline.isSelected()) { + linePane.setPreferredSize(UNDER_LINE_SIZE); + } else { + linePane.setPreferredSize(HIDE_SIZE); + } + } + }); + + return linePane; + } + + private JPanel createLeftPane() { + double p = TableLayoutKit.PREFERRED; + double f = TableLayoutKit.FILL; + double[] columnSize = {p}; + double[] rowSize = {p, p, p}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}}; + Component[][] components = new Component[][]{ + new Component[]{fontSizeStyleComboBox}, + new Component[]{buttonPane}, + new Component[]{createLinePane()} + }; + return TableLayoutKit.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_MEDIUM, LayoutConstants.VGAP_MEDIUM); + } + + protected JPanel createRightPane() { + double p = TableLayoutKit.PREFERRED; + double f = TableLayoutKit.FILL; + double[] columnSize = {f}; + double[] rowSize = {p, p}; + int[][] rowCount = {{1, 1}, {1, 1}}; + Component[][] components = new Component[][]{ + new Component[]{fontSizeComboBox}, + new Component[]{isSuperOrSubPane} + }; + return TableLayoutKit.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_MEDIUM, LayoutConstants.VGAP_MEDIUM); + } + + private JPanel createPane() { + JPanel createPane = new JPanel(new BorderLayout()); + createPane.add(fontNameComboBox, BorderLayout.NORTH); + JPanel jPanel = TableLayoutKit.createGapTableLayoutPane( + new Component[][]{new Component[]{createLeftPane(), createRightPane()}}, + TableLayoutKit.FILL_LAST_COLUMN, + LayoutConstants.VGAP_LARGE, + LayoutConstants.VGAP_LARGE); + jPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + createPane.add(jPanel, BorderLayout.CENTER); + return createPane; + } + + /** + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + public boolean shouldResponseNameListener() { + return false; + } + + public void setGlobalName(String name) { + } +} diff --git a/src/main/java/com/fanruan/api/design/work/component/container/NumberDragPane.java b/src/main/java/com/fanruan/api/design/work/component/container/NumberDragPane.java new file mode 100644 index 0000000..0654659 --- /dev/null +++ b/src/main/java/com/fanruan/api/design/work/component/container/NumberDragPane.java @@ -0,0 +1,141 @@ +package com.fanruan.api.design.work.component.container; + +import com.fanruan.api.design.DesignKit; +import com.fanruan.api.design.ui.component.UISpinner; +import com.fanruan.api.util.StringKit; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.gui.style.NumberDragBar; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019/10/28 + * 可以通过拖动滑动条的方式设置数字的控件 + */ +public class NumberDragPane extends BasicBeanPane implements GlobalNameObserver { + private static final long serialVersionUID = -8681716725163358247L; + private NumberDragBar dragBar; + private UISpinner spinner; + private boolean isEditing = false; + private String numberDragPaneName = StringKit.EMPTY; + private GlobalNameListener globalNameListener = null; + + public NumberDragPane(double minValue, double maxValue) { + this(minValue, maxValue, 1); + } + + public NumberDragPane(double minValue, double maxValue, double delta) { + dragBar = new NumberDragBar((int) minValue, (int) maxValue); + spinner = new UISpinner(minValue, maxValue, delta, minValue); + spinner.setGlobalName(DesignKit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation")); + this.setLayout(new BorderLayout(4, 0)); + this.add(spinner, BorderLayout.EAST); + this.add(dragBar, BorderLayout.CENTER); + dragBar.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(numberDragPaneName); + } + spinner.setValue(dragBar.getValue()); + if (isEditing) { + userEvent(updateBean()); + } + } + }); + spinner.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(numberDragPaneName); + } + dragBar.setValue((int) spinner.getValue()); + if (isEditing) { + userEvent(updateBean()); + } + } + }); + } + + public void userEvent(double value) { + + } + + /** + * 添加事件 + * + * @param l 事件 + */ + public void addChangeListener(ChangeListener l) { + spinner.addChangeListener(l); + + } + + /** + * 移除事件 + * + * @param l 事件 + */ + public void removeChangeListener(ChangeListener l) { + spinner.removeChangeListener(l); + } + + public void setGlobalName(String name) { + numberDragPaneName = name; + } + + @Override + public void populateBean(Double ob) { + isEditing = false; + dragBar.setValue(ob.intValue()); + spinner.setValue(ob); + isEditing = true; + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = super.getPreferredSize().width; + dim.height = super.getPreferredSize().height + 2; + return dim; + } + + public void setEnabled(boolean enabled) { + dragBar.setEnabled(enabled); + spinner.setEnabled(enabled); + } + + @Override + public Double updateBean() { + return spinner.getValue(); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + /** + * 注册 + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 是否应该响应 + * + * @return 是否应该响应 + */ + public boolean shouldResponseNameListener() { + return true; + } +} diff --git a/src/main/java/com/fanruan/api/report/form/WidgetKit.java b/src/main/java/com/fanruan/api/report/form/WidgetKit.java new file mode 100644 index 0000000..2ddd81e --- /dev/null +++ b/src/main/java/com/fanruan/api/report/form/WidgetKit.java @@ -0,0 +1,43 @@ +package com.fanruan.api.report.form; + +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.WidgetTitle; +import com.fr.general.act.BorderPacker; +import com.fr.general.act.TitlePacker; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019/10/28 + * 控件相关工具类 + */ +public class WidgetKit { + + /** + * 创建一个空的控件标题对象 + * + * @return 控件标题 + */ + public static TitlePacker newWidgetTitle() { + return new WidgetTitle(); + } + + /** + * 根据指定的名字创建一个控件标题对象 + * + * @param title 标题内容 + * @return 控件标题 + */ + public static TitlePacker newWidgetTitle(String title) { + return new WidgetTitle(title); + } + + /** + * 创建一个空的边框样式对象 + * + * @return 边框样式 + */ + public static BorderPacker newLayoutBorderStyle() { + return new LayoutBorderStyle(); + } +} diff --git a/src/main/java/com/fanruan/api/report/form/category/BaseBorderStyleWidget.java b/src/main/java/com/fanruan/api/report/form/category/BaseBorderStyleWidget.java index b363455..2ebcd52 100644 --- a/src/main/java/com/fanruan/api/report/form/category/BaseBorderStyleWidget.java +++ b/src/main/java/com/fanruan/api/report/form/category/BaseBorderStyleWidget.java @@ -1,11 +1,28 @@ package com.fanruan.api.report.form.category; import com.fanruan.api.report.form.BaseWidget; +import com.fanruan.api.report.form.WidgetKit; +import com.fr.base.BaseXMLUtils; +import com.fr.base.iofile.IOFileAttrMarkReader; import com.fr.form.ui.LayoutBorderStyle; import com.fr.form.ui.PaddingMargin; import com.fr.form.ui.RichStyleWidgetProvider; import com.fr.general.Background; import com.fr.general.act.BorderPacker; +import com.fr.general.xml.GeneralXMLTools; +import com.fr.json.JSONException; +import com.fr.json.JSONObject; +import com.fr.plugin.solution.sandbox.collection.PluginSandboxCollections; +import com.fr.stable.fun.IOFileAttrMark; +import com.fr.stable.script.CalculatorProvider; +import com.fr.stable.web.Repository; +import com.fr.stable.xml.XMLConstants; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLableReader; +import com.fr.web.BaseHTMLWriterUtils; + +import java.util.Map; /** * @author richie @@ -15,7 +32,222 @@ import com.fr.general.act.BorderPacker; */ public abstract class BaseBorderStyleWidget extends BaseWidget implements RichStyleWidgetProvider { - private BorderPacker borderStyle = new LayoutBorderStyle(); + private BorderPacker borderStyle = WidgetKit.newLayoutBorderStyle(); private Background background; private PaddingMargin margin = new PaddingMargin(); + + // widget对象添加额外的属性: 是否共享之类的 + private Map widgetAttrMarkMap; + + public BaseBorderStyleWidget() { + + } + + /** + * 获取背景 + */ + public Background getBackground() { + return background; + } + + /** + * 设置主体背景 + */ + public void setBackground(Background background) { + this.background = background; + } + + /** + * 获取边框样式 + */ + public BorderPacker getBorderStyle() { + return borderStyle; + } + + /** + * 设置边框样式 + */ + public void setBorderStyle(BorderPacker borderStyle) { + this.borderStyle = borderStyle; + // 主体的背景也都是放在borderStyle + setBackground(borderStyle.getBackground()); + } + + /** + * 获取边距 + */ + public PaddingMargin getMargin() { + return margin; + } + + /** + * 设置边距 + */ + public void setMargin(PaddingMargin margin) { + if (!canCurrentMarginAvailable(margin)) { + throw new UnsupportedOperationException(); + } else { + this.margin = margin; + } + } + + /** + * 清除边距, 默认的是(1,1,1,1). + */ + public void clearMargin() { + this.margin = new PaddingMargin(0, 0, 0, 0); + } + + /** + * 给widget对象添加额外的属性 + * + * @param attrMark 额外的属性对象 + */ + public void addWidgetAttrMark(IOFileAttrMark attrMark) { + if (attrMark == null) { + return; + } + + if (widgetAttrMarkMap == null) { + widgetAttrMarkMap = PluginSandboxCollections.newSandboxMap(); + } + widgetAttrMarkMap.put(attrMark.xmlTag(), attrMark); + } + + /** + * 根据标签获取widget的属性对象 + * + * @param tagName 标签名 + * @param 对象类型 + * @return 属性对象 + */ + public T getWidgetAttrMark(String tagName) { + if (widgetAttrMarkMap == null) { + return null; + } + IOFileAttrMark mark = widgetAttrMarkMap.get(tagName); + return (T) mark; + } + + /** + * 当前设置的边距值是否可用,若设置后有控件达到最小尺寸则返回false + * + * @param margin 边距 + * @return 可用则返回true + */ + public abstract boolean canCurrentMarginAvailable(PaddingMargin margin); + + /** + * 设置边框样式 + */ + public void setBorderStyleNoBackground(LayoutBorderStyle borderStyle) { + this.borderStyle = borderStyle; + } + + + @Override + public void mixinJSON(Repository repo, CalculatorProvider c, JSONObject jo) { + if (PaddingMargin.need(margin)) { + margin.createJSONConfig(jo); + } + + if (this.background != null) { + createBackgroundJson(repo, jo); + } + + if (this.borderStyle != null) { + borderStyle.mixinJSON(repo, c, jo); + } + + if (widgetAttrMarkMap != null) { + for (Map.Entry entry : widgetAttrMarkMap.entrySet()) { + jo.put(entry.getKey(), entry.getValue().createJSONConfig()); + } + } + } + + private void createBackgroundJson(Repository repo, JSONObject jo) throws JSONException { + if (repo.getDevice().isMobile()) { + jo.put("widgetBackground", background.toJSONObject(repo)); + } else { + jo.put("widgetBackground", BaseHTMLWriterUtils.jsonBackground(background, repo)); + } + } + + @Override + public void readXML(XMLableReader reader) { + super.readXML(reader); + if (reader.isChildNode()) { + String tagName = reader.getTagName(); + if (PaddingMargin.XML_TAG.equals(tagName)) { + PaddingMargin newMargin = new PaddingMargin(); + reader.readXMLObject(newMargin); + this.margin = newMargin; + } else if (XMLConstants.Border_TAG.equals(tagName)) { + final LayoutBorderStyle border = new LayoutBorderStyle(); + reader.readXMLObject(new XMLReadable() { + public void readXML(XMLableReader reader) { + reader.readXMLObject(border); + } + }); + this.setBorderStyle(border); + } else if (XMLConstants.Background_TAG.equals(tagName)) { + this.background = BaseXMLUtils.readBackground(reader); + } else { + readExtra(reader); + } + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + super.writeXML(writer); + + if (this.margin != null) { + this.margin.writeXML(writer); + } + + if (this.borderStyle != null) { + this.borderStyle.writeXML(writer); + } + + if (this.background != null) { + BaseXMLUtils.writeBackground(writer, this.background); + } + + writeExtra(writer); + } + + private void writeExtra(XMLPrintWriter writer) { + if (widgetAttrMarkMap != null) { + for (Map.Entry entry : widgetAttrMarkMap.entrySet()) { + GeneralXMLTools.writeXMLable(writer, entry.getValue(), entry.getKey()); + } + } + } + + protected void readExtra(XMLableReader reader) { + addWidgetAttrMark(IOFileAttrMarkReader.read(reader)); + } + + + @Override + public Object clone() throws CloneNotSupportedException { + BaseBorderStyleWidget cloned = (BaseBorderStyleWidget) super.clone(); + if (this.margin != null) { + cloned.margin = (PaddingMargin) this.margin.clone(); + } + if (widgetAttrMarkMap != null) { + Map clonedMap = PluginSandboxCollections.newSandboxMap(); + for (Map.Entry entry : widgetAttrMarkMap.entrySet()) { + clonedMap.put(entry.getKey(), entry.getValue().clone()); + } + cloned.widgetAttrMarkMap = clonedMap; + } + if (this.background != null) { + cloned.background = (Background) this.background.clone(); + } + cloned.borderStyle = (LayoutBorderStyle) this.borderStyle.clone(); + return cloned; + } } diff --git a/src/main/java/com/fanruan/api/util/GraphKit.java b/src/main/java/com/fanruan/api/util/GraphKit.java index a906e2e..74c7bd5 100644 --- a/src/main/java/com/fanruan/api/util/GraphKit.java +++ b/src/main/java/com/fanruan/api/util/GraphKit.java @@ -33,6 +33,27 @@ public class GraphKit { return GraphDrawHelper.getFontMetrics(font, g2d); } + /** + * 绘制指定的形状 + * + * @param g 图形绘制上下文 + * @param shape 形状 + */ + public static void draw(Graphics g, Shape shape) { + GraphDrawHelper.draw(g, shape); + } + + /** + * 使用特定的线型绘制指定的形状 + * + * @param g 图形绘制上下文 + * @param shape 形状 + * @param lineStyle 线型 + */ + public static void draw(Graphics g, Shape shape, int lineStyle) { + GraphDrawHelper.draw(g, shape, lineStyle); + } + /** * 绘制文本 * diff --git a/src/main/java/com/fanruan/api/util/MathKit.java b/src/main/java/com/fanruan/api/util/MathKit.java new file mode 100644 index 0000000..95abeca --- /dev/null +++ b/src/main/java/com/fanruan/api/util/MathKit.java @@ -0,0 +1,19 @@ +package com.fanruan.api.util; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019/10/28 + * 数学计算相关的工具类 + */ +public class MathKit { + + /** + * 四舍五入取靠近如11、11.5、12的值 + * + * @param number 值 + */ + public static float round5(float number) { + return (float) (Math.round(number * 2)) / 2; + } +}