diff --git a/build.gradle b/build.gradle index a3892da96..8e2e8b627 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,7 @@ plugins { // 模块参数 ext { frVersion = "" + cbbVersion = "" outputPath = "build" ignoreTestFailureSetting = true languageLevelSetting = 1.8 @@ -44,6 +45,9 @@ allprojects { repositories { mavenLocal() + maven { + url 'https://maven.ej-technologies.com/repository' + } } idea { @@ -57,6 +61,9 @@ allprojects { } dependencies { + implementation 'com.fr.essential:fine-essential:' + cbbVersion + implementation 'com.fr.cbb:fine-universal-skeleton:' + cbbVersion + implementation 'com.install4j:install4j-runtime:8.0.4' implementation 'com.fr.third:jxbrowser:6.23' implementation 'com.fr.third:jxbrowser-mac:6.23' implementation 'com.fr.third:jxbrowser-win64:6.23' diff --git a/designer-base/src/main/java/com/fr/base/svg/IconUtils.java b/designer-base/src/main/java/com/fr/base/svg/IconUtils.java index 79d3cef76..fd99f0e99 100644 --- a/designer-base/src/main/java/com/fr/base/svg/IconUtils.java +++ b/designer-base/src/main/java/com/fr/base/svg/IconUtils.java @@ -6,8 +6,7 @@ import com.fr.stable.bridge.StableFactory; import com.fr.stable.fun.ResourcePathTransformer; import com.fr.stable.plugin.ExtraClassManagerProvider; -import javax.swing.Icon; -import javax.swing.ImageIcon; +import javax.swing.*; import java.util.Arrays; import java.util.HashSet; import java.util.Set; diff --git a/designer-base/src/main/java/com/fr/base/svg/SVGIcon.java b/designer-base/src/main/java/com/fr/base/svg/SVGIcon.java index 9667895ee..172b10dac 100644 --- a/designer-base/src/main/java/com/fr/base/svg/SVGIcon.java +++ b/designer-base/src/main/java/com/fr/base/svg/SVGIcon.java @@ -2,10 +2,8 @@ package com.fr.base.svg; import com.fr.general.IOUtils; -import javax.swing.Icon; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; +import javax.swing.*; +import java.awt.*; import java.awt.image.BufferedImage; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/designer-base/src/main/java/com/fr/base/svg/SVGLoader.java b/designer-base/src/main/java/com/fr/base/svg/SVGLoader.java deleted file mode 100644 index 3c0b7a036..000000000 --- a/designer-base/src/main/java/com/fr/base/svg/SVGLoader.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fr.base.svg; - -import com.fr.general.IOUtils; -import org.apache.batik.transcoder.TranscoderException; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.xmlgraphics.java2d.Dimension2DDouble; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.Image; -import java.io.IOException; -import java.net.URL; - -/** - * SVG图标加载器 - * @author Yvan - * @version 10.0 - * Created by Yvan on 2020/12/17 - */ -public class SVGLoader { - public static final int ICON_DEFAULT_SIZE = 16; - - public SVGLoader() { - } - - @Nullable - public static Image load(@NotNull String url) { - try { - URL resource = IOUtils.getResource(url, SVGLoader.class); - if (resource == null) { - return null; - } - return load(resource, SVGIcon.SYSTEM_SCALE); - } catch (IOException ignore) { - return null; - } - } - - @Nullable - public static Image load(@NotNull URL url) throws IOException { - return load(url, SVGIcon.SYSTEM_SCALE); - } - - @Nullable - public static Image load(@NotNull URL url, double scale) throws IOException { - try { - String svgUri = url.toString(); - TranscoderInput input = new TranscoderInput(svgUri); - return SVGTranscoder.createImage(scale, input).getImage(); - } catch (TranscoderException ignore) { - return null; - } - } - - @Nullable - public static Image load(@NotNull URL url, double scale, Dimension2DDouble dimension) throws IOException { - try { - String svgUri = url.toString(); - TranscoderInput input = new TranscoderInput(svgUri); - return SVGTranscoder.createImage(scale, input, - (float) (dimension.getWidth() * scale), (float) (dimension.getHeight() * scale)).getImage(); - } catch (TranscoderException ignore) { - return null; - } - } - - - @Nullable - public static Image load(@NotNull URL url, double scale, double overriddenWidth, double overriddenHeight) throws IOException { - try { - String svgUri = url.toString(); - TranscoderInput input = new TranscoderInput(svgUri); - return SVGTranscoder.createImage(scale, input, (float) (overriddenWidth * scale), (float) (overriddenHeight * scale)).getImage(); - } catch (TranscoderException ignore) { - return null; - } - } - - @Nullable - public static Image load(@NotNull String url, float width, float height) { - try { - URL resource = IOUtils.getResource(url, SVGLoader.class); - if (resource == null) { - return null; - } - TranscoderInput input = new TranscoderInput(resource.toString()); - return SVGTranscoder.createImage(SVGIcon.SYSTEM_SCALE, input, -1, -1, width, height).getImage(); - } catch (TranscoderException ignore) { - return null; - } - } -} diff --git a/designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java b/designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java deleted file mode 100644 index dd47bc575..000000000 --- a/designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.fr.base.svg; - -import com.fr.stable.AssistUtils; -import com.fr.value.AtomicNotNullLazyValue; -import org.apache.batik.anim.dom.SAXSVGDocumentFactory; -import org.apache.batik.anim.dom.SVGOMDocument; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.UserAgent; -import org.apache.batik.transcoder.SVGAbstractTranscoder; -import org.apache.batik.transcoder.TranscoderException; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.ImageTranscoder; -import org.apache.batik.util.XMLResourceDescriptor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; - -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.StringReader; - -/** - * 可以根据某个缩放倍数scale,将SVG图片转化为Image对象 - * @author Yvan - * @version 10.0 - * Created by Yvan on 2020/12/17 - */ -public class SVGTranscoder extends ImageTranscoder { - - private static final float DEFAULT_VALUE = -1.0F; - public static final float ICON_DEFAULT_SIZE = 16F; - private float origDocWidth; - private float origDocHeight; - @Nullable - private BufferedImage image; - private final double scale; - - @NotNull - private static AtomicNotNullLazyValue iconMaxSize = new AtomicNotNullLazyValue() { - @NotNull - @Override - protected Double compute() { - double maxSize = Double.MAX_VALUE; - if (!GraphicsEnvironment.isHeadless()) { - GraphicsDevice defaultScreenDevice = GraphicsEnvironment - .getLocalGraphicsEnvironment() - .getDefaultScreenDevice(); - Rectangle bounds = defaultScreenDevice.getDefaultConfiguration().getBounds(); - AffineTransform tx = defaultScreenDevice - .getDefaultConfiguration() - .getDefaultTransform(); - maxSize = Math.max(bounds.width * tx.getScaleX(), bounds.height * tx.getScaleY()); - } - return maxSize; - } - }; - - public SVGTranscoder(double scale) { - this.scale = scale; - this.width = ICON_DEFAULT_SIZE; - this.height = ICON_DEFAULT_SIZE; - } - - public SVGTranscoder(double scale, float width, float height) { - this.scale = scale; - this.width = width; - this.height = height; - } - - public final float getOrigDocWidth() { - return this.origDocWidth; - } - - public final void setOrigDocWidth(float origDocWidth) { - this.origDocWidth = origDocWidth; - } - - public final float getOrigDocHeight() { - return this.origDocHeight; - } - - public final void setOrigDocHeight(float origDocHeight) { - this.origDocHeight = origDocHeight; - } - - public static double getIconMaxSize() { - return iconMaxSize.getValue(); - } - - @Nullable - public final BufferedImage getImage() { - return this.image; - } - - @NotNull - public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input) throws TranscoderException { - return createImage(scale, input, -1, -1); - } - - @NotNull - public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight) throws TranscoderException { - return createImage(scale, input, overriddenWidth, overriddenHeight, ICON_DEFAULT_SIZE, ICON_DEFAULT_SIZE); - } - - @NotNull - public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight, float width, float height) throws TranscoderException { - SVGTranscoder transcoder = new SVGTranscoder(scale, width, height); - if (!AssistUtils.equals(overriddenWidth, DEFAULT_VALUE)) { - transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, overriddenWidth); - } - - if (!AssistUtils.equals(overriddenHeight, DEFAULT_VALUE)) { - transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, overriddenHeight); - } - - double iconMaxSize = SVGTranscoder.iconMaxSize.getValue(); - transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_WIDTH, (float) iconMaxSize); - transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_HEIGHT, (float) iconMaxSize); - transcoder.transcode(input, null); - return transcoder; - } - - private static SVGDocument createFallbackPlaceholder() { - try { - String fallbackIcon = "\n" + - " \n" + - " \n" + - " \n" + - "\n"; - - SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()); - return (SVGDocument) factory.createDocument(null, new StringReader(fallbackIcon)); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - @Override - protected void setImageSize(float docWidth, float docHeight) { - super.setImageSize((float) (docWidth * this.scale), (float) (docHeight * this.scale)); - this.origDocWidth = docWidth; - this.origDocHeight = docHeight; - } - - @Override - @NotNull - public BufferedImage createImage(int width, int height) { - return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - } - - @Override - public void writeImage(@NotNull BufferedImage image, @Nullable TranscoderOutput output) { - this.image = image; - } - - @Override - @NotNull - protected UserAgent createUserAgent() { - return new SVGAbstractTranscoderUserAgent() { - @Override - @NotNull - public SVGDocument getBrokenLinkDocument(@NotNull Element e, @NotNull String url, @NotNull String message) { - return createFallbackPlaceholder(); - } - }; - } - - /** - * 开放访问权限 - */ - @Override - public BridgeContext createBridgeContext(SVGOMDocument doc) { - return super.createBridgeContext(doc); - } -} diff --git a/designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java b/designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java deleted file mode 100644 index 4b7974806..000000000 --- a/designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.fr.base.svg; - -import com.bulenkov.iconloader.util.UIUtil; -import com.fr.log.FineLoggerFactory; -import com.fr.stable.StableUtils; -import com.fr.stable.os.OperatingSystem; -import org.jetbrains.annotations.NotNull; - -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.lang.reflect.Method; -import java.util.concurrent.atomic.AtomicReference; - -/** - * 获取系统Scale相关的工具类 - * @author Yvan - * @version 10.0 - * Created by Yvan on 2020/12/17 - */ -public class SystemScaleUtils { - - private static final AtomicReference JRE_HIDPI = new AtomicReference<>(); - - private static final String HI_DPI = "hidpi"; - - /** - * 判断是否支持高清 - * @return - */ - public static boolean isJreHiDPIEnabled() { - if (JRE_HIDPI.get() != null) { - return JRE_HIDPI.get(); - } - if (OperatingSystem.isMacos()) { - // 如果是mac os系统,直接返回true - return true; - } - if (OperatingSystem.isWindows() && StableUtils.getMajorJavaVersion() <= 8) { - // 如果是jdk8 + Windows系统,直接返回false - return false; - } - synchronized (JRE_HIDPI) { - if (JRE_HIDPI.get() != null) { - return JRE_HIDPI.get(); - } - boolean result = false; - if (getBooleanProperty(HI_DPI, true)) { - try { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Class sunGraphicsEnvironmentClass = Class.forName("sun.java2d.SunGraphicsEnvironment"); - if (sunGraphicsEnvironmentClass.isInstance(ge)) { - try { - Method method = sunGraphicsEnvironmentClass.getDeclaredMethod("isUIScaleEnabled"); - method.setAccessible(true); - result = (Boolean)method.invoke(ge); - } - catch (NoSuchMethodException e) { - FineLoggerFactory.getLogger().error(e.getMessage()); - } - } - } - catch (Throwable ignore) { - } - } - JRE_HIDPI.set(result); - return result; - } - } - - public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) { - final String value = System.getProperty(key); - return value == null ? defaultValue : Boolean.parseBoolean(value); - } - - /** - * 获取系统Scale - * @return - */ - public static float sysScale() { - // 如果检测到是retina,直接返回2 - if (UIUtil.isRetina()) { - return 2.0f; - } - float scale = 1.0f; - // 先判断是否支持高清,不支持代表此时是Windows + jdk8 的设计器,返回的scale值为1.0 - if (isJreHiDPIEnabled()) { - // 获取屏幕图形设备对象 - GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); - if (graphicsDevice != null) { - // 获取图形配置对象 - GraphicsConfiguration configuration = graphicsDevice.getDefaultConfiguration(); - if (configuration != null && configuration.getDevice().getType() != GraphicsDevice.TYPE_PRINTER) { - // 获取屏幕缩放率,Windows+jdk11环境下会得到用户设置的dpi值 - scale = (float) configuration.getDefaultTransform().getScaleX(); - } - } - } - return scale; - } -} diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 5a777b895..2fa06a564 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java @@ -108,7 +108,7 @@ public class PreferencePane extends BasicPane { private static final int CACHING_DEFAULT = 5; private static final int CACHING_GAP = 5; private static final int MEMORY_TIP_LABEL_MAX_WIDTH = 230; - private static final int OFFSET_HEIGHT = 50; + private static final int OFFSET_HEIGHT = 60; private static final String TYPE = "pressed"; private static final String DISPLAY_TYPE = "+"; diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java index 204123095..7784aa571 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java @@ -15,9 +15,9 @@ import com.fr.stable.StringUtils; import javax.swing.JPanel; import javax.swing.SwingConstants; +import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; @@ -34,13 +34,12 @@ public class AdvancePane extends BasicPane { public AdvancePane() { - + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); DBCP_VALIDATION_QUERY.addFocusListener(new JTextFieldHintListener(DBCP_VALIDATION_QUERY)); - ; double p = TableLayout.PREFERRED; - DBCP_VALIDATION_QUERY.setColumns(15); + DBCP_VALIDATION_QUERY.setColumns(20); double[] rowSizeDbcp = {p, p, p, p}; - double[] columnDbcp = {p, p}; + double[] columnDbcp = {190, p}; Component[][] comps = { {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE}, {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY}, @@ -49,9 +48,8 @@ public class AdvancePane extends BasicPane { }; JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSizeDbcp, columnDbcp, 11, 11); - this.add(contextPane); - this.setPreferredSize(new Dimension(630, 120)); - this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + jPanel.add(contextPane, BorderLayout.CENTER); + this.add(jPanel); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java index 91e8006d1..4d5556ef9 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java @@ -7,6 +7,7 @@ import com.fr.data.impl.Connection; import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.impl.JNDIDatabaseConnection; import com.fr.data.operator.DataOperatorProvider; +import com.fr.data.security.ssl.impl.NormalSsl; import com.fr.data.solution.ExceptionSolutionSelector; import com.fr.data.solution.entity.DriverPage; import com.fr.data.solution.processor.ClassNotFoundExceptionSolutionProcessor; @@ -61,7 +62,7 @@ import java.util.concurrent.ExecutionException; * Database Connection pane. */ public abstract class DatabaseConnectionPane extends BasicBeanPane { - private static int MAX_MAIN_PANEL_HEIGHT = 430; + private static int MAX_MAIN_PANEL_HEIGHT = 410; private static int MAX_MAIN_PANEL_WIDTH = 675; private UILabel message; @@ -312,6 +313,15 @@ public abstract class DatabaseConnectionPane jdbcMap = new HashMap(); + private JPanel linkPanel; static { jdbcMap.put(OTHER_DB, new DriverURLName[]{new DriverURLName("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:"), @@ -193,7 +197,9 @@ public class JDBCDefPane extends JPanel { userNameTextField = new UITextField(15); userNameTextField.setName(USER_NAME); passwordTextField = new UIPasswordFieldWithFixedLength(15); - dbtypeButton = new UIButton("."); + dbtypeButton = new UIButton(); + dbtypeButton.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT)); + dbtypeButton.setPreferredSize(new Dimension(20, 20)); dbtypeButton.setToolTipText(Toolkit.i18nText("Fine-Design_Basic_Click_Get_Default_URL")); dbtypeButton.addActionListener(dbtypeButtonActionListener); @@ -477,11 +483,16 @@ public class JDBCDefPane extends JPanel { } ActionListener driverListener = new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + linkPanel.setVisible(DriverClasses.MYSQL.toString().equalsIgnoreCase((String) dbtypeComboBox.getSelectedItem()) + && driverComboBox.getSelectedItem() != null + && ComparatorUtils.equals(DriverClasses.MYSQL.getDriverClass(), driverComboBox.getSelectedItem().toString().trim())); + odbcTipsLink.setVisible(driverComboBox.getSelectedItem() != null + && ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem().toString().trim())); // 选择的如果是ODBC就显示提示 if (driverComboBox.getSelectedItem() == null || ComparatorUtils.equals(driverComboBox.getSelectedItem(), StringUtils.EMPTY)) { return; } - odbcTipsLink.setVisible(ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem())); // 选择的如果是ODBC就显示提示 Iterator> jdbc = jdbcMap.entrySet().iterator(); while (jdbc.hasNext()) { Entry entry = jdbc.next(); @@ -494,7 +505,6 @@ public class JDBCDefPane extends JPanel { } } } - }; ActionListener dbtypeButtonActionListener = new ActionListener() { @@ -738,4 +748,7 @@ public class JDBCDefPane extends JPanel { } + public void addLinkPane(JPanel panel) { + linkPanel = panel; + } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java new file mode 100644 index 000000000..9a870d07d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java @@ -0,0 +1,301 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.data.impl.JDBCDatabaseConnection; +import com.fr.data.security.ssh.BaseSsh; +import com.fr.data.security.ssh.Ssh; +import com.fr.data.security.ssh.SshException; +import com.fr.data.security.ssh.SshType; +import com.fr.data.security.ssh.impl.KeyVerifySsh; +import com.fr.data.security.ssh.impl.NormalSsh; +import com.fr.design.border.UITitledBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.editor.NotNegativeIntegerEditor; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ipasswordfield.UIPasswordFieldWithFixedLength; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.third.guava.collect.HashBiMap; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author xiqiu + * @date 2021/12/23 + * @description + */ +public class SshPane extends BasicPane { + private static HashBiMap typeMap; + + static { + typeMap = HashBiMap.create(); + typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Password"), SshType.NORMAL); + typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Ssh_Public_Key"), SshType.KEY); + } + + private UICheckBox usingSsh = new UICheckBox(i18nText("Fine-Design_Basic_Ssh_Using")); + private NotNegativeIntegerEditor port = new NotNegativeIntegerEditor(20); + private UITextField ip = new UITextField(20); + private UIComboBox type = new UIComboBox(); + private UITextField user = new UITextField(20); + private JPasswordField password = new UIPasswordFieldWithFixedLength(20); + private JPasswordField secret = new UIPasswordFieldWithFixedLength(20); + private KeyFileUITextField keyPath = new KeyFileUITextField(18); + private JPanel contextPane; + private Component[][] passwordComps; + private Component[][] keyComps; + private double p = TableLayout.PREFERRED; + private double f = TableLayout.FILL; + private JPanel jPanel; + private UIButton fileChooserButton = new UIButton(); + private double[] columnSize = new double[]{195, p}; + + public SshPane() { + fileChooserButton.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT)); + this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings"))); + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + typeMap.keySet().forEach(key -> type.addItem(key)); + type.setSelectedItem(typeMap.inverse().get(SshType.KEY)); + jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + fileChooserButton.setPreferredSize(new Dimension(20, 20)); + type.setEditable(false); + type.setSelectedItem(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key")); + JPanel filePanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPath, fileChooserButton}}, new double[]{p}, new double[]{f, 20}, 0); + Component[] compIp = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Host") + ":", SwingConstants.RIGHT), ip}; + Component[] compPort = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Port") + ":", SwingConstants.RIGHT), port}; + Component[] compUserName = {new UILabel(Toolkit.i18nText("Fine-Design_Report_UserName") + ":", SwingConstants.RIGHT), user}; + Component[] compMethod = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Verify_Method") + ":", SwingConstants.RIGHT), type}; + Component[] compPassword = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Password") + ":", SwingConstants.RIGHT), password}; + Component[] compKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key") + ":", SwingConstants.RIGHT), filePanel}; + Component[] comSecret = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Secret") + ":", SwingConstants.RIGHT), secret}; + + passwordComps = new Component[][]{ + compIp, + compPort, + compUserName, + compMethod, + compPassword + }; + keyComps = new Component[][]{ + compIp, + compPort, + compUserName, + compMethod, + compKey, + comSecret + }; + usingSsh.setSelected(true); + contextPane = TableLayoutHelper.createGapTableLayoutPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, 11, 11); + jPanel.add(usingSsh, BorderLayout.NORTH); + jPanel.add(contextPane, BorderLayout.CENTER); + this.add(jPanel); + + usingSsh.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + changePane(); + } + }); + + type.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + changePaneForType(); + } + }); + fileChooserButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true)); + int type = fileChooser.showOpenDialog(SshPane.this, StringUtils.EMPTY); + if (type == FILEChooserPane.OK_OPTION) { + final FILE file = fileChooser.getSelectedFILE(); + if (file == null) { + keyPath.setText(StringUtils.EMPTY); + } else { + keyPath.setText(file.getPath()); + } + } + fileChooser.removeAllFilter(); + } + }); + } + + + private void changePane() { + contextPane.setVisible(usingSsh.isSelected()); + } + + private void changePaneForType() { + contextPane.removeAll(); + switch (typeMap.get(type.getSelectedItem())) { + case NORMAL: + TableLayoutHelper.addComponent2ResultPane(passwordComps, new double[]{p, p, p, p, p}, columnSize, contextPane); + break; + case KEY: + TableLayoutHelper.addComponent2ResultPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, contextPane); + break; + default: + throw new SshException("un support ssh type"); + } + jPanel.revalidate(); + jPanel.repaint(); + } + + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings"); + } + + + public void populate(JDBCDatabaseConnection jdbcDatabase) { + if (jdbcDatabase.getSsh() == null) { + jdbcDatabase.setSsh(new NormalSsh()); + } + Ssh ssh = jdbcDatabase.getSsh(); + switch (ssh.getSshType()) { + case KEY: + type.setSelectedItem(typeMap.inverse().get(ssh.getSshType())); + KeyVerifySsh keyVerifySsh = (KeyVerifySsh) ssh; + keyPath.setText(keyVerifySsh.getPrivateKeyPath()); + secret.setText(keyVerifySsh.getSecret()); + password.setText(StringUtils.EMPTY); + setCommonConfig(keyVerifySsh); + break; + case NORMAL: + type.setSelectedItem(typeMap.inverse().get(ssh.getSshType())); + NormalSsh normalSsh = (NormalSsh) ssh; + password.setText(normalSsh.getSecret()); + keyPath.setText(StringUtils.EMPTY); + secret.setText(StringUtils.EMPTY); + setCommonConfig(normalSsh); + break; + default: + throw new SshException("un support ssh type"); + } + usingSsh.setSelected(ssh.isUsingSsh()); + changePane(); + } + + private void setCommonConfig(BaseSsh baseSsh) { + ip.setText(baseSsh.getIp()); + port.setValue(baseSsh.getPort()); + user.setText(baseSsh.getUser()); + } + + public void update(JDBCDatabaseConnection jdbcDatabase) { + Ssh ssh; + switch (typeMap.get(type.getSelectedItem())) { + case NORMAL: + NormalSsh normalSsh = new NormalSsh(); + normalSsh.setSecret(new String(password.getPassword()).trim()); + getCommonConfig(normalSsh); + ssh = normalSsh; + break; + case KEY: + KeyVerifySsh keyVerifySsh = new KeyVerifySsh(); + keyVerifySsh.setPrivateKeyPath(keyPath.getText().trim()); + keyVerifySsh.setSecret(new String(secret.getPassword()).trim()); + getCommonConfig(keyVerifySsh); + ssh = keyVerifySsh; + break; + default: + throw new SshException("un support ssh type"); + } + jdbcDatabase.setSsh(ssh); + } + + private void getCommonConfig(BaseSsh baseSsh) { + baseSsh.setUsingSsh(usingSsh.isSelected()); + baseSsh.setIp(ip.getText().trim()); + baseSsh.setPort(port.getValue()); + baseSsh.setUser(user.getText().trim()); + } + + public static class KeyFileUITextField extends UITextField { + private static final Pattern ERROR_START = Pattern.compile("^([/\\\\.]+).*"); + private static final Pattern MUTI_DOT = Pattern.compile("\\.+"); + private static final String PREFIX = ProjectConstants.RESOURCES_NAME + "/"; + private static final String UPPER = ".."; + + public KeyFileUITextField(int columns) { + this(); + this.setColumns(columns); + } + + + public KeyFileUITextField() { + super(); + this.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + String text = KeyFileUITextField.this.getTextOrigin(); + if (!StringUtils.isEmpty(text)) { + if (text.contains(UPPER)) { + text = MUTI_DOT.matcher(text).replaceAll("."); + KeyFileUITextField.this.setTextOrigin(text); + } + Matcher matcher = ERROR_START.matcher(text); + if (matcher.matches()) { + text = text.substring(matcher.group(1).length()); + KeyFileUITextField.this.setTextOrigin(text); + } + } + } + }); + } + + public String getTextOrigin() { + return super.getText(); + } + + public void setTextOrigin(String text) { + super.setText(text); + } + + @Override + public String getText() { + // 获取的时候,不为空,给他加上前缀就好了,否则还是空 + if (!StringUtils.isEmpty(super.getText())) { + return PREFIX + super.getText(); + } + return StringUtils.EMPTY; + } + + @Override + public void setText(String text) { + // 设置的时候,不为空,说明文件指定了(文件需要是resource下),替换掉前缀 + if (!StringUtils.isEmpty(text) && text.startsWith(PREFIX)) { + super.setText(text.replaceFirst(PREFIX, "")); + } else { + super.setText(text); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java new file mode 100644 index 000000000..2d9c26e23 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java @@ -0,0 +1,164 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.data.impl.JDBCDatabaseConnection; +import com.fr.data.security.ssl.Ssl; +import com.fr.data.security.ssl.SslException; +import com.fr.data.security.ssl.SslType; +import com.fr.data.security.ssl.impl.NormalSsl; +import com.fr.design.border.UITitledBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.data.datapane.connect.SshPane.KeyFileUITextField; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author xiqiu + * @date 2022/1/4 + * @description + */ +public class SslPane extends BasicPane { + UICheckBox usingSsl = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Using")); + private KeyFileUITextField keyPathCa = new KeyFileUITextField(18); + private UIButton fileChooserButtonCa = new UIButton(); + private KeyFileUITextField keyPathClientCert = new KeyFileUITextField(18); + private UIButton fileChooserButtonClientCert = new UIButton(); + private KeyFileUITextField keyPathClientKey = new KeyFileUITextField(18); + private UIButton fileChooserButtonClientKey = new UIButton(); + private UICheckBox verifyCa = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Verify_Ca")); +// private UITextField cipher = new UITextField(20); + private JPanel jPanel; + private Component[][] usingComps; + private double p = TableLayout.PREFERRED; + private double f = TableLayout.FILL; + private JPanel contextPane; + private double[] columnSize = new double[]{195, p}; + + public SslPane() { + fileChooserButtonCa.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT)); + fileChooserButtonClientCert.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT)); + fileChooserButtonClientKey.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT)); + this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings"))); + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + Dimension dimension = new Dimension(20, 20); + fileChooserButtonCa.setPreferredSize(dimension); + fileChooserButtonClientCert.setPreferredSize(dimension); + fileChooserButtonClientKey.setPreferredSize(dimension); + JPanel filePanelCa = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathCa, fileChooserButtonCa}}, new double[]{p}, new double[]{f, 20}, 0); + Component[] compCa = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Ca") + ":", SwingConstants.RIGHT), filePanelCa}; + Component[] compVerifyCa = {null, verifyCa}; + JPanel filePanelClientCert = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathClientCert, fileChooserButtonClientCert}}, new double[]{p}, new double[]{f, 20}, 0); + Component[] compClientCert = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Cert") + ":", SwingConstants.RIGHT), filePanelClientCert}; + JPanel filePanelClientKey = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathClientKey, fileChooserButtonClientKey}}, new double[]{p}, new double[]{f, 20}, 0); + Component[] compClientKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Key") + ":", SwingConstants.RIGHT), filePanelClientKey}; +// Component[] comCipher = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Cipher") + ":", SwingConstants.RIGHT), cipher}; + usingComps = new Component[][]{ + compCa, + compVerifyCa, + compClientCert, + compClientKey, +// comCipher + }; + usingSsl.setSelected(true); + contextPane = TableLayoutHelper.createGapTableLayoutPane(usingComps, new double[]{p, p, p, p}, columnSize, 11, 11); + jPanel.add(usingSsl, BorderLayout.NORTH); + jPanel.add(contextPane, BorderLayout.CENTER); + this.add(jPanel); + usingSsl.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + changePane(); + } + }); + fileChooserButtonCa.addActionListener(new TextFieldActionListener(keyPathCa)); + fileChooserButtonClientCert.addActionListener(new TextFieldActionListener(keyPathClientCert)); + fileChooserButtonClientKey.addActionListener(new TextFieldActionListener(keyPathClientKey)); + } + + private void changePane() { + contextPane.setVisible(usingSsl.isSelected()); + } + + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings"); + } + + public void populate(JDBCDatabaseConnection jdbcDatabase) { + Ssl ssl = jdbcDatabase.getSsl(); + if (ssl == null) { + ssl = new NormalSsl(); + jdbcDatabase.setSsl(ssl); + } + if (ssl.getSslType() == SslType.NORMAL) { + NormalSsl normalSsl = (NormalSsl) ssl; + keyPathCa.setText(normalSsl.getCaCertificate()); + keyPathClientCert.setText(normalSsl.getClientCertificate()); + keyPathClientKey.setText(normalSsl.getClientPrivateKey()); + verifyCa.setSelected(normalSsl.isVerifyCa()); +// cipher.setText(normalSsl.getCipher()); + } else { + throw new SslException("un support ssl type"); + } + usingSsl.setSelected(ssl.isUsingSsl()); + changePane(); + } + + public void update(JDBCDatabaseConnection jdbcDatabase) { + NormalSsl normalSsl = new NormalSsl(); +// normalSsl.setCipher(cipher.getText().trim()); + normalSsl.setVerifyCa(verifyCa.isSelected()); + normalSsl.setCaCertificate(keyPathCa.getText().trim()); + normalSsl.setClientCertificate(keyPathClientCert.getText().trim()); + normalSsl.setClientPrivateKey(keyPathClientKey.getText().trim()); + normalSsl.setUsingSsl(usingSsl.isSelected()); + jdbcDatabase.setSsl(normalSsl); + } + + private class TextFieldActionListener implements ActionListener { + private UITextField textField; + + public TextFieldActionListener(UITextField textField) { + this.textField = textField; + } + + @Override + public void actionPerformed(ActionEvent e) { + FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true)); + int type = fileChooser.showOpenDialog(SslPane.this, StringUtils.EMPTY); + if (type == FILEChooserPane.OK_OPTION) { + final FILE file = fileChooser.getSelectedFILE(); + if (file == null) { + textField.setText(StringUtils.EMPTY); + } else { + textField.setText(file.getPath()); + } + } + fileChooser.removeAllFilter(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/deeplink/DeepLink.java b/designer-base/src/main/java/com/fr/design/deeplink/DeepLink.java new file mode 100644 index 000000000..5b40c8845 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/deeplink/DeepLink.java @@ -0,0 +1,15 @@ +package com.fr.design.deeplink; + +import java.util.Map; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/6 + */ +public abstract class DeepLink { + + public abstract boolean accept(String url, String host, String path, Map params); + + public abstract void run(String url, String host, String path, Map params); +} diff --git a/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java b/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java new file mode 100644 index 000000000..55a45709b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java @@ -0,0 +1,184 @@ +package com.fr.design.deeplink; + +import com.fr.design.constants.DesignerLaunchStatus; +import com.fr.design.startup.FineStartupNotificationFactory; +import com.fr.design.startup.FineStartupNotificationProvider; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.event.Null; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.stable.os.OperatingSystem; +import com.fr.third.org.apache.http.NameValuePair; +import com.fr.web.URLUtils; + +import javax.swing.SwingUtilities; +import java.awt.Color; +import java.awt.Frame; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/6 + */ +public class DeepLinkCore { + + protected DeepLinkCore(){} + private static final DeepLinkCore instance = new DeepLinkCore(); + public static DeepLinkCore getInstance(){ + return instance; + } + + private String pendingURL; + + private final List deepLinkList = new ArrayList<>(); + + private boolean isDesignerStartupCompleted = false; + + public void register(DeepLink deepLink) { + if (deepLink != null) { + deepLinkList.add(deepLink); + } + } + + public void start(String[] args) { + if (OperatingSystem.isWindows()) { + if (args.length > 0) { + receiveDeeplink(args[0]); + } + } + + if (OperatingSystem.isWindows() && args.length > 0) { + receiveDeeplink(args[0]); + } + + FineStartupNotificationFactory.getNotification() + .registerStartupListener(new FineStartupNotificationProvider.Listener() { + @Override + public void startupPerformed(String parameters) { + receiveDeeplink(parameters); + } + }); + + EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { + @Override + public void on(Event event, Null param) { + EventDispatcher.stopListen(this); + isDesignerStartupCompleted = true; + if (canConsumePendingURL()) { + consumePendingURL(); + } + } + }); + } + + public void receiveDeeplink(String url) { + if (canAcceptNewURL()) { + acceptNewURL(url); + if (canConsumePendingURL()) { + consumePendingURL(); + } + } + } + + public void receiveDeeplink2(String url) { + if (canAcceptNewURL()) { + acceptNewURL(url); + if (canConsumePendingURL()) { + consumePendingURL(); + } else { + Frame frame = new Frame("can not ConsumePendingURL"); + frame.setSize(400, 400); + frame.setBackground(Color.BLACK); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent windowEvent){ + frame.dispose(); + } + }); + frame.setVisible(true); + } + } else { + Frame frame = new Frame("can not AcceptNewURL"); + frame.setSize(400, 400); + frame.setBackground(Color.BLACK); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent windowEvent){ + frame.dispose(); + } + }); + frame.setVisible(true); + } + } + + private boolean canAcceptNewURL() { + return StringUtils.isEmpty(this.pendingURL); + } + + private void acceptNewURL(String url) { + this.pendingURL = url; + } + + private boolean canConsumePendingURL() { + return StringUtils.isNotEmpty(this.pendingURL) && isDesignerStartupCompleted; + } + + private void consumePendingURL() { + String host = null; + String path = null; + Map params = new HashMap<>(); + + URL url = null; + try { + url = new URL(null, this.pendingURL, new URLStreamHandler() { + @Override + protected URLConnection openConnection(URL u) throws IOException { + return null; + } + }); + } catch (MalformedURLException ignored) {} + + if (url != null) { + host = url.getHost(); + path = url.getPath(); + + List pairs = URLUtils.parse(url.getQuery()); + for (NameValuePair pair: pairs) { + params.put(pair.getName(), pair.getValue()); + } + } + + FineLoggerFactory.getLogger().info("consume deep link: " + this.pendingURL); + performDeepLinks(this.pendingURL, host, path, params); + + markPendingURLConsumed(); + } + + private void performDeepLinks(String url, String host, String path, Map params) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + for (DeepLink deepLink: deepLinkList) { + if (deepLink.accept(url, host, path, params)) { + deepLink.run(url, host, path, params); + } + } + } + }); + } + + private void markPendingURLConsumed() { + this.pendingURL = null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/editor/editor/NotNegativeIntegerEditor.java b/designer-base/src/main/java/com/fr/design/editor/editor/NotNegativeIntegerEditor.java new file mode 100644 index 000000000..98c59c173 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/editor/editor/NotNegativeIntegerEditor.java @@ -0,0 +1,33 @@ +package com.fr.design.editor.editor; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * @author xiqiu + * @date 2022/1/10 + * @description 一个简单的非负整数框 + */ +public class NotNegativeIntegerEditor extends IntegerEditor { + private static final String NEG = "-"; + + public NotNegativeIntegerEditor(int columns) { + this(); + this.setColumns(columns); + } + + public NotNegativeIntegerEditor() { + super(); + this.numberField.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent evt) { + char keyChar = evt.getKeyChar(); + if (NEG.equals(keyChar + "")) { + numberField.setText(numberField.getTextValue().replace(NEG, "")); + } + } + }); + } +} + diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java index 795ff721f..a6346c4dd 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java @@ -16,6 +16,7 @@ import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.autocomplete.AutoCompleteExtraRefreshComponent; import com.fr.design.gui.autocomplete.CompletionCellRenderer; import com.fr.design.gui.autocomplete.CompletionProvider; import com.fr.design.gui.autocomplete.DefaultCompletionProvider; @@ -416,7 +417,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { autoCompletion = new FormulaPaneAutoCompletion(provider); autoCompletion.setListCellRenderer(new CompletionCellRenderer()); autoCompletion.install(formulaTextArea); - autoCompletion.installVariableTree(variableTreeAndDescriptionArea); + autoCompletion.installExtraRefreshComponent(variableTreeAndDescriptionArea); } @@ -1044,7 +1045,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { } } - public class VariableTreeAndDescriptionArea extends JPanel { + public class VariableTreeAndDescriptionArea extends JPanel implements AutoCompleteExtraRefreshComponent { private JTree variablesTree; private UITextArea descriptionTextArea; @@ -1285,6 +1286,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { functionTypeList.setSelectedIndex(0); } + @Override + public void refresh(String replacementText) { + refreshText(replacementText); + } + /* * 查看函数的详细信息 */ diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java index dd830ed57..fb4eea22b 100644 --- a/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java @@ -90,6 +90,8 @@ public class MismatchedTokenFunction implements Function"; + } else if (tokenType == 33 || tokenType == 26 || tokenType == 31) { + return Toolkit.i18nText("Fine-Design_Basic_Formula_Right_Closing_Symbol"); } else { String[] tokenNames = (String[]) getFieldValue(exception, "tokenNames"); return tokenType >= 0 && tokenType < tokenNames.length ? TranslateTokenUtils.translateToken(tokenNames[tokenType]) : "<" + tokenType + ">"; diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteExtraRefreshComponent.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteExtraRefreshComponent.java new file mode 100644 index 000000000..ff6b7faef --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteExtraRefreshComponent.java @@ -0,0 +1,5 @@ +package com.fr.design.gui.autocomplete; + +public interface AutoCompleteExtraRefreshComponent { + void refresh(String replacementText); +} diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteWithExtraRefreshPopupWindow.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteWithExtraRefreshPopupWindow.java new file mode 100644 index 000000000..3f4f19177 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteWithExtraRefreshPopupWindow.java @@ -0,0 +1,982 @@ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator; +import com.fr.log.FineLoggerFactory; +import java.awt.BorderLayout; +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JWindow; +import javax.swing.KeyStroke; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.plaf.ListUI; +import javax.swing.text.Caret; +import javax.swing.text.JTextComponent; + +public abstract class AutoCompleteWithExtraRefreshPopupWindow extends JWindow implements CaretListener, + ListSelectionListener, MouseListener { + private final static int DIS = 5; + /** + * The parent AutoCompletion instance. + */ + private AutoCompletion ac; + + /** + * The list of completion choices. + */ + private JList list; + + /** + * The contents of {@link #list()}. + */ + private CompletionListModel model; + + /** + * A hack to work around the fact that we clear our completion model (and + * our selection) when hiding the completion window. This allows us to + * still know what the user selected after the popup is hidden. + */ + private Completion lastSelection; + + /** + * Optional popup window containing a description of the currently + * selected completion. + */ + private AutoCompleteDescWindow descWindow; + + /** + * The preferred size of the optional description window. This field + * only exists because the user may (and usually will) set the size of + * the description window before it exists (it must be parented to a + * Window). + */ + private Dimension preferredDescWindowSize; + + + + /** + * Whether the completion window and the optional description window + * should be displayed above the current caret position (as opposed to + * underneath it, which is preferred unless there is not enough space). + */ + private boolean aboveCaret; + + private int lastLine; + + private KeyActionPair escapeKap; + private KeyActionPair upKap; + private KeyActionPair downKap; + private KeyActionPair leftKap; + private KeyActionPair rightKap; + private KeyActionPair enterKap; + private KeyActionPair tabKap; + private KeyActionPair homeKap; + private KeyActionPair endKap; + private KeyActionPair pageUpKap; + private KeyActionPair pageDownKap; + private KeyActionPair ctrlCKap; + + private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight, + oldEnter, oldTab, oldHome, oldEnd, oldPageUp, oldPageDown, + oldCtrlC; + + /** + * The space between the caret and the completion popup. + */ + private static final int VERTICAL_SPACE = 1; + + /** + * The class name of the Substance List UI. + */ + private static final String SUBSTANCE_LIST_UI = + "org.pushingpixels.substance.internal.ui.SubstanceListUI"; + + + protected AutoCompleteExtraRefreshComponent component; + + + /** + * Constructor. + * + * @param parent The parent window (hosting the text component). + * @param ac The auto-completion instance. + */ + public AutoCompleteWithExtraRefreshPopupWindow(Window parent, final AutoCompletion ac) { + + super(parent); + ComponentOrientation o = ac.getTextComponentOrientation(); + + this.ac = ac; + model = new CompletionListModel(); + list = new PopupList(model); + + list.setCellRenderer(new DelegatingCellRenderer()); + list.addListSelectionListener(this); + list.addMouseListener(this); + + JPanel contentPane = new JPanel(new BorderLayout()); + JScrollPane sp = new JScrollPane(list, + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + + // In 1.4, JScrollPane.setCorner() has a bug where it won't accept + // JScrollPane.LOWER_TRAILING_CORNER, even though that constant is + // defined. So we have to put the logic added in 1.5 to handle it + // here. + JPanel corner = new SizeGrip(); + //sp.setCorner(JScrollPane.LOWER_TRAILING_CORNER, corner); + boolean isLeftToRight = o.isLeftToRight(); + String str = isLeftToRight ? JScrollPane.LOWER_RIGHT_CORNER : + JScrollPane.LOWER_LEFT_CORNER; + sp.setCorner(str, corner); + + contentPane.add(sp); + setContentPane(contentPane); + applyComponentOrientation(o); + + // Give apps a chance to decorate us with drop shadows, etc. + if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) { + PopupWindowDecorator decorator = PopupWindowDecorator.get(); + if (decorator != null) { + decorator.decorate(this); + } + } + + pack(); + + setFocusableWindowState(false); + + lastLine = -1; + + } + + + public void caretUpdate(CaretEvent e) { + if (isVisible()) { // Should always be true + int line = ac.getLineOfCaret(); + if (line != lastLine) { + lastLine = -1; + setVisible(false); + } else { + doAutocomplete(); + } + } else if (AutoCompletion.isDebug()) { + Thread.dumpStack(); + } + } + + + /** + * Creates the description window. + * + * @return The description window. + */ + private AutoCompleteDescWindow createDescriptionWindow() { + AutoCompleteDescWindow dw = new AutoCompleteDescWindow(this, ac); + dw.applyComponentOrientation(ac.getTextComponentOrientation()); + Dimension size = preferredDescWindowSize; + if (size == null) { + size = getSize(); + } + dw.setSize(size); + return dw; + } + + + /** + * Creates the mappings from keys to Actions we'll be putting into the + * text component's ActionMap and InputMap. + */ + private void createKeyActionPairs() { + + // Actions we'll install. + EnterAction enterAction = new EnterAction(); + escapeKap = new KeyActionPair("Escape", new EscapeAction()); + upKap = new KeyActionPair("Up", new UpAction()); + downKap = new KeyActionPair("Down", new DownAction()); + leftKap = new KeyActionPair("Left", new LeftAction()); + rightKap = new KeyActionPair("Right", new RightAction()); + enterKap = new KeyActionPair("Enter", enterAction); + tabKap = new KeyActionPair("Tab", enterAction); + homeKap = new KeyActionPair("Home", new HomeAction()); + endKap = new KeyActionPair("End", new EndAction()); + pageUpKap = new KeyActionPair("PageUp", new PageUpAction()); + pageDownKap = new KeyActionPair("PageDown", new PageDownAction()); + ctrlCKap = new KeyActionPair("CtrlC", new CopyAction()); + + // Buffers for the actions we replace. + oldEscape = new KeyActionPair(); + oldUp = new KeyActionPair(); + oldDown = new KeyActionPair(); + oldLeft = new KeyActionPair(); + oldRight = new KeyActionPair(); + oldEnter = new KeyActionPair(); + oldTab = new KeyActionPair(); + oldHome = new KeyActionPair(); + oldEnd = new KeyActionPair(); + oldPageUp = new KeyActionPair(); + oldPageDown = new KeyActionPair(); + oldCtrlC = new KeyActionPair(); + + } + + + protected void doAutocomplete() { + lastLine = ac.refreshPopupWindow(); + } + + + /** + * Returns the copy keystroke to use for this platform. + * + * @return The copy keystroke. + */ + private static final KeyStroke getCopyKeyStroke() { + int key = KeyEvent.VK_C; + int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + return KeyStroke.getKeyStroke(key, mask); + } + + + /** + * Returns the default list cell renderer used when a completion provider + * does not supply its own. + * + * @return The default list cell renderer. + * @see #setListCellRenderer(ListCellRenderer) + */ + public ListCellRenderer getListCellRenderer() { + DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. + getCellRenderer(); + return dcr.getFallbackCellRenderer(); + } + + + /** + * Returns the selected value, or null if nothing is selected. + * + * @return The selected value. + */ + public Completion getSelection() { + return isShowing() ? (Completion) list.getSelectedValue() : lastSelection; + } + + + /** + * Inserts the currently selected completion. + * + * @see #getSelection() + */ + private void insertSelectedCompletion() { + Completion comp = getSelection(); + ac.insertCompletion(comp); + } + + public void installComp(AutoCompleteExtraRefreshComponent component){ + this.component = component; + } + + public void refreshInstallComp() { + component.refresh(getSelection().getReplacementText()); + } + + /** + * Registers keyboard actions to listen for in the text component and + * intercept. + * + * @see #uninstallKeyBindings() + */ + private void installKeyBindings() { + + if (AutoCompletion.isDebug()) { + FineLoggerFactory.getLogger().debug("PopupWindow: Installing keybindings"); + } + + if (escapeKap == null) { // Lazily create actions. + createKeyActionPairs(); + } + + JTextComponent comp = ac.getTextComponent(); + InputMap im = comp.getInputMap(); + ActionMap am = comp.getActionMap(); + + replaceAction(im, am, KeyEvent.VK_ESCAPE, escapeKap, oldEscape); + if (AutoCompletion.isDebug() && oldEscape.action == escapeKap.action) { + Thread.dumpStack(); + } + replaceAction(im, am, KeyEvent.VK_UP, upKap, oldUp); + replaceAction(im, am, KeyEvent.VK_LEFT, leftKap, oldLeft); + replaceAction(im, am, KeyEvent.VK_DOWN, downKap, oldDown); + replaceAction(im, am, KeyEvent.VK_RIGHT, rightKap, oldRight); + replaceAction(im, am, KeyEvent.VK_ENTER, enterKap, oldEnter); + replaceAction(im, am, KeyEvent.VK_TAB, tabKap, oldTab); + replaceAction(im, am, KeyEvent.VK_HOME, homeKap, oldHome); + replaceAction(im, am, KeyEvent.VK_END, endKap, oldEnd); + replaceAction(im, am, KeyEvent.VK_PAGE_UP, pageUpKap, oldPageUp); + replaceAction(im, am, KeyEvent.VK_PAGE_DOWN, pageDownKap, oldPageDown); + + // Make Ctrl+C copy from description window. This isn't done + // automagically because the desc. window is not focusable, and copying + // from text components can only be done from focused components. + KeyStroke ks = getCopyKeyStroke(); + oldCtrlC.key = im.get(ks); + im.put(ks, ctrlCKap.key); + oldCtrlC.action = am.get(ctrlCKap.key); + am.put(ctrlCKap.key, ctrlCKap.action); + + comp.addCaretListener(this); + + } + + + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2 && e.getButton() == 1) { + insertSelectedCompletion(); + } + } + + + public void mouseEntered(MouseEvent e) { + } + + + public void mouseExited(MouseEvent e) { + } + + + public void mousePressed(MouseEvent e) { + refreshInstallComp(); + } + + + public void mouseReleased(MouseEvent e) { + } + + + /** + * Positions the description window relative to the completion choices + * window. We assume there is room on one side of the other for this + * entire window to fit. + */ + private void positionDescWindow() { + + boolean showDescWindow = descWindow != null && ac.isShowDescWindow(); + if (!showDescWindow) { + return; + } + + // Don't use getLocationOnScreen() as this throws an exception if + // window isn't visible yet, but getLocation() doesn't, and is in + // screen coordinates! + Point p = getLocation(); + Rectangle screenBounds = Util.getScreenBoundsForPoint(p.x, p.y); + //Dimension screenSize = getToolkit().getScreenSize(); + //int totalH = Math.max(getHeight(), descWindow.getHeight()); + + // Try to position to the right first (LTR) + int x; + if (ac.getTextComponentOrientation().isLeftToRight()) { + x = getX() + getWidth() + DIS; + if (x + descWindow.getWidth() > screenBounds.x + screenBounds.width) { // doesn't fit + x = getX() - DIS - descWindow.getWidth(); + } + } else { // RTL + x = getX() - DIS - descWindow.getWidth(); + if (x < screenBounds.x) { // Doesn't fit + x = getX() + getWidth() + DIS; + } + } + + int y = getY(); + if (aboveCaret) { + y = y + getHeight() - descWindow.getHeight(); + } + + if (x != descWindow.getX() || y != descWindow.getY()) { + descWindow.setLocation(x, y); + } + + } + + + /** + * "Puts back" the original key/Action pair for a keystroke. This is used + * when this popup is hidden. + * + * @param im The input map. + * @param am The action map. + * @param key The keystroke whose key/Action pair to change. + * @param kap The (original) key/Action pair. + * @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair) + */ + private void putBackAction(InputMap im, ActionMap am, int key, + KeyActionPair kap) { + KeyStroke ks = KeyStroke.getKeyStroke(key, 0); + am.put(im.get(ks), kap.action); // Original action for the "new" key + im.put(ks, kap.key); // Original key for the keystroke. + } + + + /** + * Replaces a key/Action pair in an InputMap and ActionMap with a new + * pair. + * + * @param im The input map. + * @param am The action map. + * @param key The keystroke whose information to replace. + * @param kap The new key/Action pair for key. + * @param old A buffer in which to place the old key/Action pair. + * @see #putBackAction(InputMap, ActionMap, int, KeyActionPair) + */ + private void replaceAction(InputMap im, ActionMap am, int key, + KeyActionPair kap, KeyActionPair old) { + KeyStroke ks = KeyStroke.getKeyStroke(key, 0); + old.key = im.get(ks); + im.put(ks, kap.key); + old.action = am.get(kap.key); + am.put(kap.key, kap.action); + } + + + /** + * Selects the first item in the completion list. + * + * @see #selectLastItem() + */ + private void selectFirstItem() { + if (model.getSize() > 0) { + list.setSelectedIndex(0); + list.ensureIndexIsVisible(0); + } + } + + + /** + * Selects the last item in the completion list. + * + * @see #selectFirstItem() + */ + private void selectLastItem() { + int index = model.getSize() - 1; + if (index > -1) { + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + } + + + /** + * Selects the next item in the completion list. + * + * @see #selectPreviousItem() + */ + private void selectNextItem() { + int index = list.getSelectedIndex(); + if (index > -1) { + index = (index + 1) % model.getSize(); + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + } + + + /** + * Selects the completion item one "page down" from the currently selected + * one. + * + * @see #selectPageUpItem() + */ + private void selectPageDownItem() { + int visibleRowCount = list.getVisibleRowCount(); + int i = Math.min(list.getModel().getSize() - 1, + list.getSelectedIndex() + visibleRowCount); + list.setSelectedIndex(i); + list.ensureIndexIsVisible(i); + } + + + /** + * Selects the completion item one "page up" from the currently selected + * one. + * + * @see #selectPageDownItem() + */ + private void selectPageUpItem() { + int visibleRowCount = list.getVisibleRowCount(); + int i = Math.max(0, list.getSelectedIndex() - visibleRowCount); + list.setSelectedIndex(i); + list.ensureIndexIsVisible(i); + } + + + /** + * Selects the previous item in the completion list. + * + * @see #selectNextItem() + */ + private void selectPreviousItem() { + int index = list.getSelectedIndex(); + switch (index) { + case 0: + index = list.getModel().getSize() - 1; + break; + case -1: // Check for an empty list (would be an error) + index = list.getModel().getSize() - 1; + if (index == -1) { + return; + } + break; + default: + index = index - 1; + break; + } + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + + + /** + * Sets the completions to display in the choices list. The first + * completion is selected. + * + * @param completions The completions to display. + */ + public void setCompletions(List completions) { + model.setContents(completions); + selectFirstItem(); + } + + + /** + * Sets the size of the description window. + * + * @param size The new size. This cannot be null. + */ + public void setDescriptionWindowSize(Dimension size) { + if (descWindow != null) { + descWindow.setSize(size); + } else { + preferredDescWindowSize = size; + } + } + + + /** + * Sets the default list cell renderer to use when a completion provider + * does not supply its own. + * + * @param renderer The renderer to use. If this is null, + * a default renderer is used. + * @see #getListCellRenderer() + */ + public void setListCellRenderer(ListCellRenderer renderer) { + DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. + getCellRenderer(); + dcr.setFallbackCellRenderer(renderer); + } + + + /** + * Sets the location of this window to be "good" relative to the specified + * rectangle. That rectangle should be the location of the text + * component's caret, in screen coordinates. + * + * @param r The text component's caret position, in screen coordinates. + */ + public void setLocationRelativeTo(Rectangle r) { + + // Multi-monitor support - make sure the completion window (and + // description window, if applicable) both fit in the same window in + // a multi-monitor environment. To do this, we decide which monitor + // the rectangle "r" is in, and use that one (just pick top-left corner + // as the defining point). + Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y); + //Dimension screenSize = getToolkit().getScreenSize(); + + boolean showDescWindow = descWindow != null && ac.isShowDescWindow(); + int totalH = getHeight(); + if (showDescWindow) { + totalH = Math.max(totalH, descWindow.getHeight()); + } + + // Try putting our stuff "below" the caret first. We assume that the + // entire height of our stuff fits on the screen one way or the other. + aboveCaret = false; + int y = r.y + r.height + VERTICAL_SPACE; + if (y + totalH > screenBounds.height) { + y = r.y - VERTICAL_SPACE - getHeight(); + aboveCaret = true; + } + + // Get x-coordinate of completions. Try to align left edge with the + // caret first. + int x = r.x; + if (!ac.getTextComponentOrientation().isLeftToRight()) { + x -= getWidth(); // RTL => align right edge + } + if (x < screenBounds.x) { + x = screenBounds.x; + } else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit + x = screenBounds.x + screenBounds.width - getWidth(); + } + + setLocation(x, y); + + // Position the description window, if necessary. + if (showDescWindow) { + positionDescWindow(); + } + + } + + + /** + * Toggles the visibility of this popup window. + * + * @param visible Whether this window should be visible. + */ + @Override + public void setVisible(boolean visible) { + + if (visible != isVisible()) { + + if (visible) { + installKeyBindings(); + lastLine = ac.getLineOfCaret(); + selectFirstItem(); + if (descWindow == null && ac.isShowDescWindow()) { + descWindow = createDescriptionWindow(); + positionDescWindow(); + } + // descWindow needs a kick-start the first time it's displayed. + // Also, the newly-selected item in the choices list is + // probably different from the previous one anyway. + if (descWindow != null) { + Completion c = (Completion) list.getSelectedValue(); + if (c != null) { + descWindow.setDescriptionFor(c); + } + } + } else { + uninstallKeyBindings(); + } + + super.setVisible(visible); + + // Some languages, such as Java, can use quite a lot of memory + // when displaying hundreds of completion choices. We pro-actively + // clear our list model here to make them available for GC. + // Otherwise, they stick around, and consider the following: a + // user starts code-completion for Java 5 SDK classes, then hides + // the dialog, then changes the "class path" to use a Java 6 SDK + // instead. On pressing Ctrl+space, a new array of Completions is + // created. If this window holds on to the previous Completions, + // you're getting roughly 2x the necessary Completions in memory + // until the Completions are actually passed to this window. + if (!visible) { // Do after super.setVisible(false) + lastSelection = (Completion) list.getSelectedValue(); + model.clear(); + } + + // Must set descWindow's visibility one way or the other each time, + // because of the way child JWindows' visibility is handled - in + // some ways it's dependent on the parent, in other ways it's not. + if (descWindow != null) { + descWindow.setVisible(visible && ac.isShowDescWindow()); + } + + } + + } + + + /** + * Stops intercepting certain keystrokes from the text component. + * + * @see #installKeyBindings() + */ + private void uninstallKeyBindings() { + + if (AutoCompletion.isDebug()) { + FineLoggerFactory.getLogger().debug("PopupWindow: Removing keybindings"); + } + + JTextComponent comp = ac.getTextComponent(); + InputMap im = comp.getInputMap(); + ActionMap am = comp.getActionMap(); + + putBackAction(im, am, KeyEvent.VK_ESCAPE, oldEscape); + putBackAction(im, am, KeyEvent.VK_UP, oldUp); + putBackAction(im, am, KeyEvent.VK_DOWN, oldDown); + putBackAction(im, am, KeyEvent.VK_LEFT, oldLeft); + putBackAction(im, am, KeyEvent.VK_RIGHT, oldRight); + putBackAction(im, am, KeyEvent.VK_ENTER, oldEnter); + putBackAction(im, am, KeyEvent.VK_TAB, oldTab); + putBackAction(im, am, KeyEvent.VK_HOME, oldHome); + putBackAction(im, am, KeyEvent.VK_END, oldEnd); + putBackAction(im, am, KeyEvent.VK_PAGE_UP, oldPageUp); + putBackAction(im, am, KeyEvent.VK_PAGE_DOWN, oldPageDown); + + // Ctrl+C + KeyStroke ks = getCopyKeyStroke(); + am.put(im.get(ks), oldCtrlC.action); // Original action + im.put(ks, oldCtrlC.key); // Original key + + comp.removeCaretListener(this); + + } + + + /** + * Updates the LookAndFeel of this window and the description + * window. + */ + public void updateUI() { + SwingUtilities.updateComponentTreeUI(this); + if (descWindow != null) { + descWindow.updateUI(); + } + } + + + /** + * Called when a new item is selected in the popup list. + * + * @param e The event. + */ + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + Object value = list.getSelectedValue(); + if (value != null && descWindow != null) { + descWindow.setDescriptionFor((Completion) value); + positionDescWindow(); + } + } + } + + + class CopyAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + boolean doNormalCopy = false; + if (descWindow != null && descWindow.isVisible()) { + doNormalCopy = !descWindow.copy(); + } + if (doNormalCopy) { + ac.getTextComponent().copy(); + } + } + + } + + + class DownAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectNextItem(); + refreshInstallComp(); + } + } + + } + + + class EndAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectLastItem(); + } + } + + } + + + class EnterAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + insertSelectedCompletion(); + refreshInstallComp(); + } + } + + } + + + class EscapeAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + setVisible(false); + } + } + + } + + + class HomeAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectFirstItem(); + } + } + + } + + + /** + * A mapping from a key (an Object) to an Action. + */ + private static class KeyActionPair { + + public Object key; + public Action action; + + public KeyActionPair() { + } + + public KeyActionPair(Object key, Action a) { + this.key = key; + this.action = a; + } + + } + + + class LeftAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + JTextComponent comp = ac.getTextComponent(); + Caret c = comp.getCaret(); + int dot = c.getDot(); + if (dot > 0) { + c.setDot(--dot); + // Ensure moving left hasn't moved us up a line, thus + // hiding the popup window. + if (comp.isVisible()) { + if (lastLine != -1) { + doAutocomplete(); + } + } + } + } + } + + } + + + class PageDownAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectPageDownItem(); + } + } + + } + + + class PageUpAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectPageUpItem(); + } + } + + } + + + /** + * The actual list of completion choices in this popup window. + */ + private class PopupList extends JList { + + public PopupList(CompletionListModel model) { + super(model); + } + + @Override + public void setUI(ListUI ui) { + if (Util.getUseSubstanceRenderers() && + SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) { + // Substance requires its special ListUI be installed for + // its renderers to actually render (!), but long completion + // lists (e.g. PHPCompletionProvider in RSTALanguageSupport) + // will simply populate too slowly on initial display (when + // calculating preferred size of all items), so in this case + // we give a prototype cell value. + CompletionProvider p = ac.getCompletionProvider(); + BasicCompletion bc = new BasicCompletion(p, "Hello world"); + setPrototypeCellValue(bc); + } else { + // Our custom UI that is faster for long HTML completion lists. + ui = new FastListUI(); + setPrototypeCellValue(null); + } + super.setUI(ui); + } + + } + + + class RightAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + JTextComponent comp = ac.getTextComponent(); + Caret c = comp.getCaret(); + int dot = c.getDot(); + if (dot < comp.getDocument().getLength()) { + c.setDot(++dot); + // Ensure moving right hasn't moved us up a line, thus + // hiding the popup window. + if (comp.isVisible()) { + if (lastLine != -1) { + doAutocomplete(); + } + } + } + } + } + + } + + + class UpAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectPreviousItem(); + refreshInstallComp(); + } + } + + } + +} diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompletionWithExtraRefresh.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompletionWithExtraRefresh.java new file mode 100644 index 000000000..4def5370d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompletionWithExtraRefresh.java @@ -0,0 +1,1260 @@ +package com.fr.design.gui.autocomplete; + +import com.fr.design.formula.FormulaPane; +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.JTextComponent; + + +import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; + +public abstract class AutoCompletionWithExtraRefresh extends AutoCompletion{ + private AutoCompleteExtraRefreshComponent area; + + /** + * The text component we're providing completion for. + */ + private JTextComponent textComponent; + + /** + * The parent window of {@link #textComponent}. + */ + private Window parentWindow; + + /** + * The popup window containing completion choices. + */ + private AutoCompleteWithExtraRefreshPopupWindow popupWindow; + + /** + * The preferred size of the completion choices window. This field exists + * because the user will likely set the preferred size of the window + * before it is actually created. + */ + private Dimension preferredChoicesWindowSize; + + /** + * The preferred size of the optional description window. This field + * only exists because the user may (and usually will) set the size of + * the description window before it exists (it must be parented to a + * Window). + */ + private Dimension preferredDescWindowSize; + + /** + * Manages any parameterized completions that are inserted. + */ + private ParameterizedCompletionContext pcc; + + /** + * Provides the completion options relevant to the current caret position. + */ + private CompletionProvider provider; + + /** + * The renderer to use for the completion choices. If this is + * null, then a default renderer is used. + */ + private ListCellRenderer renderer; + + /** + * The handler to use when an external URL is clicked in the help + * documentation. + */ + private ExternalURLHandler externalURLHandler; + + /** + * An optional redirector that converts URL's to some other location before + * being handed over to externalURLHandler. + */ + private static LinkRedirector linkRedirector; + + /** + * Whether the description window should be displayed along with the + * completion choice window. + */ + private boolean showDescWindow; + + /** + * Whether auto-complete is enabled. + */ + private boolean autoCompleteEnabled; + + /** + * Whether the auto-activation of auto-complete (after a delay, after the + * user types an appropriate character) is enabled. + */ + private boolean autoActivationEnabled; + + /** + * Whether or not, when there is only a single auto-complete option + * that matches the text at the current text position, that text should + * be auto-inserted, instead of the completion window displaying. + */ + private boolean autoCompleteSingleChoices; + + /** + * Whether parameter assistance is enabled. + */ + private boolean parameterAssistanceEnabled; + + /** + * A renderer used for {@link Completion}s in the optional parameter + * choices popup window (displayed when a {@link ParameterizedCompletion} + * is code-completed). If this isn't set, a default renderer is used. + */ + private ListCellRenderer paramChoicesRenderer; + + /** + * The keystroke that triggers the completion window. + */ + private KeyStroke trigger; + + /** + * The previous key in the text component's InputMap for the + * trigger key. + */ + private Object oldTriggerKey; + + /** + * The action previously assigned to {@link #trigger}, so we can reset it + * if the user disables auto-completion. + */ + private Action oldTriggerAction; + + /** + * The previous key in the text component's InputMap for the + * parameter completion trigger key. + */ + private Object oldParenKey; + + /** + * The action previously assigned to the parameter completion key, so we + * can reset it when we uninstall. + */ + private Action oldParenAction; + + /** + * Listens for events in the parent window that affect the visibility of + * the popup windows. + */ + private ParentWindowListener parentWindowListener; + + /** + * Listens for events from the text component that affect the visibility + * of the popup windows. + */ + private TextComponentListener textComponentListener; + + /** + * Listens for events in the text component that cause the popup windows + * to automatically activate. + */ + private AutoActivationListener autoActivationListener; + + /** + * Listens for LAF changes so the auto-complete windows automatically + * update themselves accordingly. + */ + private LookAndFeelChangeListener lafListener; + + /** + * The key used in the input map for the AutoComplete action. + */ + private static final String PARAM_TRIGGER_KEY = "AutoComplete"; + + /** + * Key used in the input map for the parameter completion action. + */ + private static final String PARAM_COMPLETE_KEY = "AutoCompletion.FunctionStart"; + + /** + * Stores how to render auto-completion-specific highlights in text + * components. + */ + private static final AutoCompletionStyleContext STYLE_CONTEXT = + new AutoCompletionStyleContext(); + + /** + * Whether debug messages should be printed to stdout as AutoCompletion + * runs. + */ + private static final boolean DEBUG = initDebug(); + + Window getParentWindow(){ + return parentWindow; + } + + ListCellRenderer getCellRender(){ + return renderer; + } + + Dimension getPreferredChoicesWindowSize(){ + return preferredChoicesWindowSize; + } + + Dimension getPreferredDescWindowSize(){ + return preferredDescWindowSize; + } + /** + * Constructor. + * + * @param provider The completion provider. This cannot be + * null. + */ + public AutoCompletionWithExtraRefresh(CompletionProvider provider) { + super(provider); + setChoicesWindowSize(350, 200); + setDescriptionWindowSize(350, 250); + + setCompletionProvider(provider); + setTriggerKey(getDefaultTriggerKey()); + setAutoCompleteEnabled(true); + setAutoCompleteSingleChoices(true); + setAutoActivationEnabled(false); + setShowDescWindow(false); + parentWindowListener = new ParentWindowListener(); + textComponentListener = new TextComponentListener(); + autoActivationListener = new AutoActivationListener(); + lafListener = new LookAndFeelChangeListener(); + } + + + /** + * Displays the popup window. Hosting applications can call this method + * to programmatically begin an auto-completion operation. + */ + public void doCompletion() { + refreshPopupWindow(); + } + + + /** + * Returns the delay between when the user types a character and when the + * code completion popup should automatically appear (if applicable). + * + * @return The delay, in milliseconds. + * @see #setAutoActivationDelay(int) + */ + public int getAutoActivationDelay() { + return autoActivationListener.timer.getDelay(); + } + + + /** + * Returns whether, if a single auto-complete choice is available, it + * should be automatically inserted, without displaying the popup menu. + * + * @return Whether to auto-complete single choices. + * @see #setAutoCompleteSingleChoices(boolean) + */ + public boolean isAutoCompleteSingleChoices() { + return autoCompleteSingleChoices; + } + + + /** + * Returns the completion provider. + * + * @return The completion provider. + */ + public CompletionProvider getCompletionProvider() { + return provider; + } + + + /** + * Returns whether debug is enabled for AutoCompletion. + * + * @return Whether debug is enabled. + */ + static boolean isDebug() { + return DEBUG; + } + + + /** + * Returns the default auto-complete "trigger key" for this OS. For + * Windows, for example, it is Ctrl+Space. + * + * @return The default auto-complete trigger key. + */ + public static KeyStroke getDefaultTriggerKey() { + // Default to CTRL, even on Mac, since Ctrl+Space activates Spotlight + return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, DEFAULT_MODIFIER); + } + + + /** + * Returns the handler to use when an external URL is clicked in the + * description window. + * + * @return The handler. + * @see #setExternalURLHandler(ExternalURLHandler) + * @see #getLinkRedirector() + */ + public ExternalURLHandler getExternalURLHandler() { + return externalURLHandler; + } + + + int getLineOfCaret() { + Document doc = textComponent.getDocument(); + Element root = doc.getDefaultRootElement(); + return root.getElementIndex(textComponent.getCaretPosition()); + } + + + /** + * Returns the link redirector, if any. + * + * @return The link redirector, or null if none. + * @see #setLinkRedirector(LinkRedirector) + */ + public static LinkRedirector getLinkRedirector() { + return linkRedirector; + } + + + /** + * Returns the default list cell renderer used when a completion provider + * does not supply its own. + * + * @return The default list cell renderer. + * @see #setListCellRenderer(ListCellRenderer) + */ + public ListCellRenderer getListCellRenderer() { + return renderer; + } + + + /** + * Returns the renderer to use for {@link Completion}s in the optional + * parameter choices popup window (displayed when a + * {@link ParameterizedCompletion} is code-completed). If this returns + * null, a default renderer is used. + * + * @return The renderer to use. + * @see #setParamChoicesRenderer(ListCellRenderer) + * @see #isParameterAssistanceEnabled() + */ + public ListCellRenderer getParamChoicesRenderer() { + return paramChoicesRenderer; + } + + + /** + * Returns the text to replace with in the document. This is a + * "last-chance" hook for subclasses to make special modifications to the + * completion text inserted. The default implementation simply returns + * c.getReplacementText(). You usually will not need to modify + * this method. + * + * @param c The completion being inserted. + * @param doc The document being modified. + * @param start The start of the text being replaced. + * @param len The length of the text being replaced. + * @return The text to replace with. + */ + protected String getReplacementText(Completion c, Document doc, int start, + int len) { + return c.getReplacementText(); + } + + + /** + * Returns whether the "description window" should be shown alongside + * the completion window. + * + * @return Whether the description window should be shown. + * @see #setShowDescWindow(boolean) + */ + public boolean isShowDescWindow() { + return showDescWindow; + } + + + /** + * Returns the style context describing how auto-completion related + * highlights in the editor are rendered. + * + * @return The style context. + */ + public static AutoCompletionStyleContext getStyleContext() { + return STYLE_CONTEXT; + } + + + /** + * Returns the text component for which auto-completion is enabled. + * + * @return The text component, or null if this + * {@link AutoCompletion} is not installed on any text component. + * @see #install(JTextComponent) + */ + public JTextComponent getTextComponent() { + return textComponent; + } + + + /** + * Returns the orientation of the text component we're installed to. + * + * @return The orientation of the text component, or null if + * we are not installed on one. + */ + ComponentOrientation getTextComponentOrientation() { + return textComponent == null ? null : + textComponent.getComponentOrientation(); + } + + + /** + * Returns the "trigger key" used for auto-complete. + * + * @return The trigger key. + * @see #setTriggerKey(KeyStroke) + */ + public KeyStroke getTriggerKey() { + return trigger; + } + + + /** + * Hides any child windows being displayed by the auto-completion system. + * + * @return Whether any windows were visible. + */ + public boolean hideChildWindows() { + //return hidePopupWindow() || hideToolTipWindow(); + boolean res = hidePopupWindow(); + res |= hideParameterCompletionPopups(); + return res; + } + + + /** + * Hides and disposes of any parameter completion-related popups. + * + * @return Whether any such windows were visible (and thus hidden). + */ + private boolean hideParameterCompletionPopups() { + if (pcc != null) { + pcc.deactivate(); + pcc = null; + return true; + } + return false; + } + + + /** + * Hides the popup window, if it is visible. + * + * @return Whether the popup window was visible. + */ + protected boolean hidePopupWindow() { + if (popupWindow != null) { + if (popupWindow.isVisible()) { + popupWindow.setVisible(false); + return true; + } + } + return false; + } + + + /** + * Determines whether debug should be enabled for the AutoCompletion + * library. This method checks a system property, but takes care of + * {@link SecurityException}s in case we're in an applet or WebStart. + * + * @return Whether debug should be enabled. + */ + private static boolean initDebug() { + boolean debug = false; + try { + debug = Boolean.getBoolean("AutoCompletion.debug"); + } catch (SecurityException se) { // We're in an applet or WebStart. + debug = false; + } + return debug; + } + + + /** + * Installs this auto-completion on a text component. If this + * {@link AutoCompletion} is already installed on another text component, + * it is uninstalled first. + * + * @param c The text component. + * @see #uninstall() + */ + public void install(JTextComponent c) { + + if (textComponent != null) { + uninstall(); + } + + this.textComponent = c; + installTriggerKey(getTriggerKey()); + + // Install the function completion key, if there is one. + // NOTE: We cannot do this if the start char is ' ' (e.g. just a space + // between the function name and parameters) because it overrides + // RSTA's special space action. It seems KeyStorke.getKeyStroke(' ') + // hoses ctrl+space, shift+space, etc., even though I think it + // shouldn't... + char start = provider.getParameterListStart(); + if (start != 0 && start != ' ') { + InputMap im = c.getInputMap(); + ActionMap am = c.getActionMap(); + KeyStroke ks = KeyStroke.getKeyStroke(start); + oldParenKey = im.get(ks); + im.put(ks, PARAM_COMPLETE_KEY); + oldParenAction = am.get(PARAM_COMPLETE_KEY); + am.put(PARAM_COMPLETE_KEY, + new ParameterizedCompletionStartAction(start)); + } + + textComponentListener.addTo(this.textComponent); + // In case textComponent is already in a window... + textComponentListener.hierarchyChanged(null); + + if (isAutoActivationEnabled()) { + autoActivationListener.addTo(this.textComponent); + } + + UIManager.addPropertyChangeListener(lafListener); + updateUI(); // In case there have been changes since we uninstalled + + } + + + /** + * Installs a "trigger key" action onto the current text component. + * + * @param ks The keystroke that should trigger the action. + */ + private void installTriggerKey(KeyStroke ks) { + InputMap im = textComponent.getInputMap(); + oldTriggerKey = im.get(ks); + im.put(ks, PARAM_TRIGGER_KEY); + ActionMap am = textComponent.getActionMap(); + oldTriggerAction = am.get(PARAM_TRIGGER_KEY); + am.put(PARAM_TRIGGER_KEY, new AutoCompleteAction()); + } + + + /** + * Returns whether auto-activation is enabled (that is, whether the + * completion popup will automatically appear after a delay when the user + * types an appropriate character). Note that this parameter will be + * ignored if auto-completion is disabled. + * + * @return Whether auto-activation is enabled. + * @see #setAutoActivationEnabled(boolean) + * @see #getAutoActivationDelay() + * @see #isAutoCompleteEnabled() + */ + public boolean isAutoActivationEnabled() { + return autoActivationEnabled; + } + + + /** + * Returns whether auto-completion is enabled. + * + * @return Whether auto-completion is enabled. + * @see #setAutoCompleteEnabled(boolean) + */ + public boolean isAutoCompleteEnabled() { + return autoCompleteEnabled; + } + + + /** + * Returns whether parameter assistance is enabled. + * + * @return Whether parameter assistance is enabled. + * @see #setParameterAssistanceEnabled(boolean) + */ + public boolean isParameterAssistanceEnabled() { + return parameterAssistanceEnabled; + } + + + /** + * Returns whether the completion popup window is visible. + * + * @return Whether the completion popup window is visible. + */ + public boolean isPopupVisible() { + return popupWindow != null && popupWindow.isVisible(); + } + + private boolean needSetPopupWindow(int count, int textLen) { + return (count == 1 && (isPopupVisible() || textLen == 0)) + || (count == 1 && !isAutoCompleteSingleChoices()) + || count > 1; + } + + protected abstract AutoCompleteWithExtraRefreshPopupWindow createAutoCompletePopupWindow(); + + /** + * Sets the delay between when the user types a character and when the + * code completion popup should automatically appear (if applicable). + * + * @param ms The delay, in milliseconds. This should be greater than zero. + * @see #getAutoActivationDelay() + */ + public void setAutoActivationDelay(int ms) { + ms = Math.max(0, ms); + autoActivationListener.timer.stop(); + autoActivationListener.timer.setInitialDelay(ms); + } + + + /** + * Toggles whether auto-activation is enabled. Note that auto-activation + * also depends on auto-completion itself being enabled. + * + * @param enabled Whether auto-activation is enabled. + * @see #isAutoActivationEnabled() + * @see #setAutoActivationDelay(int) + */ + public void setAutoActivationEnabled(boolean enabled) { + if (enabled != autoActivationEnabled) { + autoActivationEnabled = enabled; + if (textComponent != null) { + if (autoActivationEnabled) { + autoActivationListener.addTo(textComponent); + } else { + autoActivationListener.removeFrom(textComponent); + } + } + } + } + + + /** + * Sets whether auto-completion is enabled. + * + * @param enabled Whether auto-completion is enabled. + * @see #isAutoCompleteEnabled() + */ + public void setAutoCompleteEnabled(boolean enabled) { + if (enabled != autoCompleteEnabled) { + autoCompleteEnabled = enabled; + hidePopupWindow(); + } + } + + + /** + * Sets whether, if a single auto-complete choice is available, it should + * be automatically inserted, without displaying the popup menu. + * + * @param autoComplete Whether to auto-complete single choices. + * @see #isAutoCompleteSingleChoices() + */ + public void setAutoCompleteSingleChoices(boolean autoComplete) { + autoCompleteSingleChoices = autoComplete; + } + + + /** + * Sets the completion provider being used. + * + * @param provider The new completion provider. This cannot be + * null. + * @throws IllegalArgumentException If provider is + * null. + */ + public void setCompletionProvider(CompletionProvider provider) { + if (provider == null) { + throw new IllegalArgumentException("provider cannot be null"); + } + this.provider = provider; + hidePopupWindow(); // In case new choices should be displayed. + } + + + /** + * Sets the size of the completion choices window. + * + * @param w The new width. + * @param h The new height. + * @see #setDescriptionWindowSize(int, int) + */ + public void setChoicesWindowSize(int w, int h) { + preferredChoicesWindowSize = new Dimension(w, h); + if (popupWindow != null) { + popupWindow.setSize(preferredChoicesWindowSize); + } + } + + + /** + * Sets the size of the description window. + * + * @param w The new width. + * @param h The new height. + * @see #setChoicesWindowSize(int, int) + */ + public void setDescriptionWindowSize(int w, int h) { + preferredDescWindowSize = new Dimension(w, h); + if (popupWindow != null) { + popupWindow.setDescriptionWindowSize(preferredDescWindowSize); + } + } + + + /** + * Sets the handler to use when an external URL is clicked in the + * description window. This handler can perform some action, such as + * open the URL in a web browser. The default implementation will open + * the URL in a browser, but only if running in Java 6. If you want + * browser support for Java 5 and below, or otherwise want to respond to + * hyperlink clicks, you will have to install your own handler to do so. + * + * @param handler The new handler. + * @see #getExternalURLHandler() + */ + public void setExternalURLHandler(ExternalURLHandler handler) { + this.externalURLHandler = handler; + } + + + /** + * Sets the redirector for external URL's found in code completion + * documentation. When a non-local link in completion popups is clicked, + * this redirector is given the chance to modify the URL fetched and + * displayed. + * + * @param redirector The link redirector, or null for + * none. + * @see #getLinkRedirector() + */ + public static void setLinkRedirector(LinkRedirector redirector) { + linkRedirector = redirector; + } + + + /** + * Sets the default list cell renderer to use when a completion provider + * does not supply its own. + * + * @param renderer The renderer to use. If this is null, + * a default renderer is used. + * @see #getListCellRenderer() + */ + public void setListCellRenderer(ListCellRenderer renderer) { + this.renderer = renderer; + if (popupWindow != null) { + popupWindow.setListCellRenderer(renderer); + hidePopupWindow(); + } + } + + + /** + * Sets the renderer to use for {@link Completion}s in the optional + * parameter choices popup window (displayed when a + * {@link ParameterizedCompletion} is code-completed). If this isn't set, + * a default renderer is used. + * + * @param r The renderer to use. + * @see #getParamChoicesRenderer() + * @see #setParameterAssistanceEnabled(boolean) + */ + public void setParamChoicesRenderer(ListCellRenderer r) { + paramChoicesRenderer = r; + } + + + /** + * Sets whether parameter assistance is enabled. If parameter assistance + * is enabled, and a "parameterized" completion (such as a function or + * method) is inserted, the user will get "assistance" in inserting the + * parameters in the form of a popup window with documentation and easy + * tabbing through the arguments (as seen in Eclipse and NetBeans). + * + * @param enabled Whether parameter assistance should be enabled. + * @see #isParameterAssistanceEnabled() + */ + public void setParameterAssistanceEnabled(boolean enabled) { + parameterAssistanceEnabled = enabled; + } + + + /** + * Sets whether the "description window" should be shown beside the + * completion window. + * + * @param show Whether to show the description window. + * @see #isShowDescWindow() + */ + public void setShowDescWindow(boolean show) { + hidePopupWindow(); // Needed to force it to take effect + showDescWindow = show; + } + + + /** + * Sets the keystroke that should be used to trigger the auto-complete + * popup window. + * + * @param ks The keystroke. + * @throws IllegalArgumentException If ks is null. + * @see #getTriggerKey() + */ + public void setTriggerKey(KeyStroke ks) { + if (ks == null) { + throw new IllegalArgumentException("trigger key cannot be null"); + } + if (!ks.equals(trigger)) { + if (textComponent != null) { + // Put old trigger action back. + uninstallTriggerKey(); + // Grab current action for new trigger and replace it. + installTriggerKey(ks); + } + trigger = ks; + } + } + + + /** + * Uninstalls this auto-completion from its text component. If it is not + * installed on any text component, nothing happens. + * + * @see #install(JTextComponent) + */ + public void uninstall() { + + if (textComponent != null) { + + hidePopupWindow(); // Unregisters listeners, actions, etc. + + uninstallTriggerKey(); + + // Uninstall the function completion key. + char start = provider.getParameterListStart(); + if (start != 0) { + KeyStroke ks = KeyStroke.getKeyStroke(start); + InputMap im = textComponent.getInputMap(); + im.put(ks, oldParenKey); + ActionMap am = textComponent.getActionMap(); + am.put(PARAM_COMPLETE_KEY, oldParenAction); + } + + textComponentListener.removeFrom(textComponent); + if (parentWindow != null) { + parentWindowListener.removeFrom(parentWindow); + } + + if (isAutoActivationEnabled()) { + autoActivationListener.removeFrom(textComponent); + } + + UIManager.removePropertyChangeListener(lafListener); + + textComponent = null; + popupWindow = null; + + } + + } + + + /** + * Replaces the "trigger key" action with the one that was there + * before auto-completion was installed. + */ + private void uninstallTriggerKey() { + InputMap im = textComponent.getInputMap(); + im.put(trigger, oldTriggerKey); + ActionMap am = textComponent.getActionMap(); + am.put(PARAM_TRIGGER_KEY, oldTriggerAction); + } + + + /** + * Updates the LookAndFeel of the popup window. Applications can call + * this method as appropriate if they support changing the LookAndFeel + * at runtime. + */ + private void updateUI() { + if (popupWindow != null) { + popupWindow.updateUI(); + } + if (pcc != null) { + pcc.updateUI(); + } + // Will practically always be a JComponent (a JLabel) + if (paramChoicesRenderer instanceof JComponent) { + ((JComponent) paramChoicesRenderer).updateUI(); + } + } + + + /** + * Listens for events in the text component to auto-activate the code + * completion popup. + */ + private class AutoActivationListener extends FocusAdapter + implements DocumentListener, CaretListener, ActionListener { + + private Timer timer; + private boolean justInserted; + + public AutoActivationListener() { + timer = new Timer(200, this); + timer.setRepeats(false); + } + + public void actionPerformed(ActionEvent e) { + doCompletion(); + } + + public void addTo(JTextComponent tc) { + tc.addFocusListener(this); + tc.getDocument().addDocumentListener(this); + tc.addCaretListener(this); + } + + public void caretUpdate(CaretEvent e) { + if (justInserted) { + justInserted = false; + } else { + timer.stop(); + } + } + + public void changedUpdate(DocumentEvent e) { + // Ignore + } + + @Override + public void focusLost(FocusEvent e) { + timer.stop(); + //hideChildWindows(); Other listener will do this + } + + public void insertUpdate(DocumentEvent e) { + justInserted = false; + if (isAutoCompleteEnabled() && isAutoActivationEnabled() && + e.getLength() == 1) { + if (provider.isAutoActivateOkay(textComponent)) { + timer.restart(); + justInserted = true; + } else { + timer.stop(); + } + } else { + timer.stop(); + } + } + + public void removeFrom(JTextComponent tc) { + tc.removeFocusListener(this); + tc.getDocument().removeDocumentListener(this); + tc.removeCaretListener(this); + timer.stop(); + justInserted = false; + } + + public void removeUpdate(DocumentEvent e) { + timer.stop(); + } + + } + + + /** + * The Action that displays the popup window if + * auto-completion is enabled. + */ + private class AutoCompleteAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isAutoCompleteEnabled()) { + refreshPopupWindow(); + } else if (oldTriggerAction != null) { + oldTriggerAction.actionPerformed(e); + } + } + + } + + + /** + * Listens for LookAndFeel changes and updates the various popup windows + * involved in auto-completion accordingly. + */ + private class LookAndFeelChangeListener implements PropertyChangeListener { + + public void propertyChange(PropertyChangeEvent e) { + String name = e.getPropertyName(); + if ("lookAndFeel".equals(name)) { + updateUI(); + } + } + + } + + + /** + * Action that starts a parameterized completion, e.g. after '(' is + * typed. + */ + private class ParameterizedCompletionStartAction extends AbstractAction { + + private String start; + + public ParameterizedCompletionStartAction(char ch) { + this.start = Character.toString(ch); + } + + public void actionPerformed(ActionEvent e) { + + // Prevents keystrokes from messing up + boolean wasVisible = hidePopupWindow(); + + // Only proceed if they were selecting a completion + if (!wasVisible || !isParameterAssistanceEnabled()) { + textComponent.replaceSelection(start); + return; + } + + Completion c = popupWindow.getSelection(); + if (c instanceof ParameterizedCompletion) { // Should always be true + // Fixes capitalization of the entered text. + insertCompletion(c, true); + } + + } + + } + + + /** + * Listens for events in the parent window of the text component with + * auto-completion enabled. + */ + private class ParentWindowListener extends ComponentAdapter + implements WindowFocusListener { + + public void addTo(Window w) { + w.addComponentListener(this); + w.addWindowFocusListener(this); + } + + @Override + public void componentHidden(ComponentEvent e) { + hideChildWindows(); + } + + @Override + public void componentMoved(ComponentEvent e) { + hideChildWindows(); + } + + @Override + public void componentResized(ComponentEvent e) { + hideChildWindows(); + } + + public void removeFrom(Window w) { + w.removeComponentListener(this); + w.removeWindowFocusListener(this); + } + + public void windowGainedFocus(WindowEvent e) { + } + + public void windowLostFocus(WindowEvent e) { + hideChildWindows(); + } + + } + + + /** + * Listens for events from the text component we're installed on. + */ + private class TextComponentListener extends FocusAdapter + implements HierarchyListener { + + void addTo(JTextComponent tc) { + tc.addFocusListener(this); + tc.addHierarchyListener(this); + } + + /** + * Hide the auto-completion windows when the text component loses + * focus. + */ + @Override + public void focusLost(FocusEvent e) { + hideChildWindows(); + } + + /** + * Called when the component hierarchy for our text component changes. + * When the text component is added to a new {@link Window}, this + * method registers listeners on that Window. + * + * @param e The event. + */ + public void hierarchyChanged(HierarchyEvent e) { + + // NOTE: e many be null as we call this method at other times. + //System.out.println("Hierarchy changed! " + e); + + Window oldParentWindow = parentWindow; + parentWindow = SwingUtilities.getWindowAncestor(textComponent); + if (parentWindow != oldParentWindow) { + if (oldParentWindow != null) { + parentWindowListener.removeFrom(oldParentWindow); + } + if (parentWindow != null) { + parentWindowListener.addTo(parentWindow); + } + } + + } + + public void removeFrom(JTextComponent tc) { + tc.removeFocusListener(this); + tc.removeHierarchyListener(this); + } + + } + + public void installExtraRefreshComponent(AutoCompleteExtraRefreshComponent jComp) { + area = jComp; + } + + + /** + * Displays a "tool tip" detailing the inputs to the function just entered. + * + * @param pc The completion. + * @param typedParamListStartChar Whether the parameterized completion list + * starting character was typed. + */ + protected void startParameterizedCompletionAssistance( + ParameterizedCompletion pc, boolean typedParamListStartChar) { + + // Get rid of the previous tool tip window, if there is one. + hideParameterCompletionPopups(); + + // Don't bother with a tool tip if there are no parameters, but if + // they typed e.g. the opening '(', make them overtype the ')'. + if (pc.getParamCount() == 0 && !(pc instanceof TemplateCompletion)) { + CompletionProvider p = pc.getProvider(); + char end = p.getParameterListEnd(); // Might be '\0' + String text = end == '\0' ? "" : Character.toString(end); + if (typedParamListStartChar) { + String template = "${}" + text + "${cursor}"; + textComponent.replaceSelection(Character.toString(p.getParameterListStart())); + TemplateCompletion tc = new TemplateCompletion(p, null, null, template); + pc = tc; + } else { + text = p.getParameterListStart() + text; + textComponent.replaceSelection(text); + return; + } + } + + pcc = new ParameterizedCompletionContext(parentWindow, this, pc); + pcc.activate(); + + } + + protected int refreshPopupWindow() { + // A return value of null => don't suggest completions + String text = provider.getAlreadyEnteredText(textComponent); + if (text == null && !isPopupVisible()) { + return getLineOfCaret(); + } + // If the popup is currently visible, and they type a space (or any + // character that resets the completion list to "all completions"), + // the popup window should be hidden instead of being reset to show + // everything. + int textLen = text == null ? 0 : text.length(); + if (textLen == 0 && isPopupVisible()) { + hidePopupWindow(); + return getLineOfCaret(); + } + final List completions = provider.getCompletions(textComponent); + int count = completions.size(); + if (needSetPopupWindow(count, textLen)) { + if (popupWindow == null) { + popupWindow = createAutoCompletePopupWindow(); + } + popupWindow.installComp(area); + popupWindow.setCompletions(completions); + if (!popupWindow.isVisible()) { + Rectangle r = null; + try { + r = textComponent.modelToView(textComponent.getCaretPosition()); + } catch (BadLocationException ble) { + return -1; + } + Point p = new Point(r.x, r.y); + SwingUtilities.convertPointToScreen(p, textComponent); + r.x = p.x; + r.y = p.y; + popupWindow.setLocationRelativeTo(r); + popupWindow.setVisible(true); + } + } else if (count == 1) { // !isPopupVisible && autoCompleteSingleChoices + SwingUtilities.invokeLater(new Runnable() { + public void run() { + insertCompletion(completions.get(0)); + } + }); + } else { + hidePopupWindow(); + } + return getLineOfCaret(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java index 0e1c7c6ac..daed7cd4c 100644 --- a/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java @@ -9,41 +9,7 @@ */ package com.fr.design.gui.autocomplete; -import com.fr.design.formula.FormulaPane; -import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator; -import com.fr.log.FineLoggerFactory; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ActionMap; -import javax.swing.InputMap; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JWindow; -import javax.swing.KeyStroke; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.plaf.ListUI; -import javax.swing.text.Caret; -import javax.swing.text.JTextComponent; -import java.awt.BorderLayout; -import java.awt.ComponentOrientation; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.List; - /** * The actual popup window of choices. When visible, this window intercepts @@ -55,949 +21,11 @@ import java.util.List; * @author Robert Futrell * @version 1.0 */ -class FormulaAutoCompletePopupWindow extends JWindow implements CaretListener, - ListSelectionListener, MouseListener { - - private final static int DIS = 5; - /** - * The parent AutoCompletion instance. - */ - private FormulaPaneAutoCompletion ac; - - /** - * The list of completion choices. - */ - private JList list; - - /** - * The contents of {@link #list()}. - */ - private CompletionListModel model; - - /** - * A hack to work around the fact that we clear our completion model (and - * our selection) when hiding the completion window. This allows us to - * still know what the user selected after the popup is hidden. - */ - private Completion lastSelection; - - /** - * Optional popup window containing a description of the currently - * selected completion. - */ - private AutoCompleteDescWindow descWindow; - - /** - * The preferred size of the optional description window. This field - * only exists because the user may (and usually will) set the size of - * the description window before it exists (it must be parented to a - * Window). - */ - private Dimension preferredDescWindowSize; - - private FormulaPane.VariableTreeAndDescriptionArea component; - - /** - * Whether the completion window and the optional description window - * should be displayed above the current caret position (as opposed to - * underneath it, which is preferred unless there is not enough space). - */ - private boolean aboveCaret; - - private int lastLine; - - private KeyActionPair escapeKap; - private KeyActionPair upKap; - private KeyActionPair downKap; - private KeyActionPair leftKap; - private KeyActionPair rightKap; - private KeyActionPair enterKap; - private KeyActionPair tabKap; - private KeyActionPair homeKap; - private KeyActionPair endKap; - private KeyActionPair pageUpKap; - private KeyActionPair pageDownKap; - private KeyActionPair ctrlCKap; - - private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight, - oldEnter, oldTab, oldHome, oldEnd, oldPageUp, oldPageDown, - oldCtrlC; - - /** - * The space between the caret and the completion popup. - */ - private static final int VERTICAL_SPACE = 1; - - /** - * The class name of the Substance List UI. - */ - private static final String SUBSTANCE_LIST_UI = - "org.pushingpixels.substance.internal.ui.SubstanceListUI"; +class FormulaAutoCompletePopupWindow extends AutoCompleteWithExtraRefreshPopupWindow { - /** - * Constructor. - * - * @param parent The parent window (hosting the text component). - * @param ac The auto-completion instance. - */ public FormulaAutoCompletePopupWindow(Window parent, final FormulaPaneAutoCompletion ac) { - - super(parent); - ComponentOrientation o = ac.getTextComponentOrientation(); - - this.ac = ac; - model = new CompletionListModel(); - list = new PopupList(model); - - list.setCellRenderer(new DelegatingCellRenderer()); - list.addListSelectionListener(this); - list.addMouseListener(this); - - JPanel contentPane = new JPanel(new BorderLayout()); - JScrollPane sp = new JScrollPane(list, - JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, - JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - - // In 1.4, JScrollPane.setCorner() has a bug where it won't accept - // JScrollPane.LOWER_TRAILING_CORNER, even though that constant is - // defined. So we have to put the logic added in 1.5 to handle it - // here. - JPanel corner = new SizeGrip(); - //sp.setCorner(JScrollPane.LOWER_TRAILING_CORNER, corner); - boolean isLeftToRight = o.isLeftToRight(); - String str = isLeftToRight ? JScrollPane.LOWER_RIGHT_CORNER : - JScrollPane.LOWER_LEFT_CORNER; - sp.setCorner(str, corner); - - contentPane.add(sp); - setContentPane(contentPane); - applyComponentOrientation(o); - - // Give apps a chance to decorate us with drop shadows, etc. - if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) { - PopupWindowDecorator decorator = PopupWindowDecorator.get(); - if (decorator != null) { - decorator.decorate(this); - } - } - - pack(); - - setFocusableWindowState(false); - - lastLine = -1; - - } - - - public void caretUpdate(CaretEvent e) { - if (isVisible()) { // Should always be true - int line = ac.getLineOfCaret(); - if (line != lastLine) { - lastLine = -1; - setVisible(false); - } else { - doAutocomplete(); - } - } else if (AutoCompletion.isDebug()) { - Thread.dumpStack(); - } - } - - - /** - * Creates the description window. - * - * @return The description window. - */ - private AutoCompleteDescWindow createDescriptionWindow() { - AutoCompleteDescWindow dw = new AutoCompleteDescWindow(this, ac); - dw.applyComponentOrientation(ac.getTextComponentOrientation()); - Dimension size = preferredDescWindowSize; - if (size == null) { - size = getSize(); - } - dw.setSize(size); - return dw; - } - - - /** - * Creates the mappings from keys to Actions we'll be putting into the - * text component's ActionMap and InputMap. - */ - private void createKeyActionPairs() { - - // Actions we'll install. - EnterAction enterAction = new EnterAction(); - escapeKap = new KeyActionPair("Escape", new EscapeAction()); - upKap = new KeyActionPair("Up", new UpAction()); - downKap = new KeyActionPair("Down", new DownAction()); - leftKap = new KeyActionPair("Left", new LeftAction()); - rightKap = new KeyActionPair("Right", new RightAction()); - enterKap = new KeyActionPair("Enter", enterAction); - tabKap = new KeyActionPair("Tab", enterAction); - homeKap = new KeyActionPair("Home", new HomeAction()); - endKap = new KeyActionPair("End", new EndAction()); - pageUpKap = new KeyActionPair("PageUp", new PageUpAction()); - pageDownKap = new KeyActionPair("PageDown", new PageDownAction()); - ctrlCKap = new KeyActionPair("CtrlC", new CopyAction()); - - // Buffers for the actions we replace. - oldEscape = new KeyActionPair(); - oldUp = new KeyActionPair(); - oldDown = new KeyActionPair(); - oldLeft = new KeyActionPair(); - oldRight = new KeyActionPair(); - oldEnter = new KeyActionPair(); - oldTab = new KeyActionPair(); - oldHome = new KeyActionPair(); - oldEnd = new KeyActionPair(); - oldPageUp = new KeyActionPair(); - oldPageDown = new KeyActionPair(); - oldCtrlC = new KeyActionPair(); - - } - - - protected void doAutocomplete() { - lastLine = ac.refreshPopupWindow(); - } - - - /** - * Returns the copy keystroke to use for this platform. - * - * @return The copy keystroke. - */ - private static final KeyStroke getCopyKeyStroke() { - int key = KeyEvent.VK_C; - int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - return KeyStroke.getKeyStroke(key, mask); - } - - - /** - * Returns the default list cell renderer used when a completion provider - * does not supply its own. - * - * @return The default list cell renderer. - * @see #setListCellRenderer(ListCellRenderer) - */ - public ListCellRenderer getListCellRenderer() { - DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. - getCellRenderer(); - return dcr.getFallbackCellRenderer(); - } - - - /** - * Returns the selected value, or null if nothing is selected. - * - * @return The selected value. - */ - public Completion getSelection() { - return isShowing() ? (Completion) list.getSelectedValue() : lastSelection; - } - - - /** - * Inserts the currently selected completion. - * - * @see #getSelection() - */ - private void insertSelectedCompletion() { - Completion comp = getSelection(); - ac.insertCompletion(comp); - } - - public void installComp(FormulaPane.VariableTreeAndDescriptionArea component) { - this.component = component; - } - - private void refreshInstallComp() { - component.refreshText(getSelection().getReplacementText()); - } - - - /** - * Registers keyboard actions to listen for in the text component and - * intercept. - * - * @see #uninstallKeyBindings() - */ - private void installKeyBindings() { - - if (AutoCompletion.isDebug()) { - FineLoggerFactory.getLogger().debug("PopupWindow: Installing keybindings"); - } - - if (escapeKap == null) { // Lazily create actions. - createKeyActionPairs(); - } - - JTextComponent comp = ac.getTextComponent(); - InputMap im = comp.getInputMap(); - ActionMap am = comp.getActionMap(); - - replaceAction(im, am, KeyEvent.VK_ESCAPE, escapeKap, oldEscape); - if (AutoCompletion.isDebug() && oldEscape.action == escapeKap.action) { - Thread.dumpStack(); - } - replaceAction(im, am, KeyEvent.VK_UP, upKap, oldUp); - replaceAction(im, am, KeyEvent.VK_LEFT, leftKap, oldLeft); - replaceAction(im, am, KeyEvent.VK_DOWN, downKap, oldDown); - replaceAction(im, am, KeyEvent.VK_RIGHT, rightKap, oldRight); - replaceAction(im, am, KeyEvent.VK_ENTER, enterKap, oldEnter); - replaceAction(im, am, KeyEvent.VK_TAB, tabKap, oldTab); - replaceAction(im, am, KeyEvent.VK_HOME, homeKap, oldHome); - replaceAction(im, am, KeyEvent.VK_END, endKap, oldEnd); - replaceAction(im, am, KeyEvent.VK_PAGE_UP, pageUpKap, oldPageUp); - replaceAction(im, am, KeyEvent.VK_PAGE_DOWN, pageDownKap, oldPageDown); - - // Make Ctrl+C copy from description window. This isn't done - // automagically because the desc. window is not focusable, and copying - // from text components can only be done from focused components. - KeyStroke ks = getCopyKeyStroke(); - oldCtrlC.key = im.get(ks); - im.put(ks, ctrlCKap.key); - oldCtrlC.action = am.get(ctrlCKap.key); - am.put(ctrlCKap.key, ctrlCKap.action); - - comp.addCaretListener(this); - - } - - - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2 && e.getButton() == 1) { - insertSelectedCompletion(); - } - } - - - public void mouseEntered(MouseEvent e) { - } - - - public void mouseExited(MouseEvent e) { - } - - - public void mousePressed(MouseEvent e) { - refreshInstallComp(); - } - - - public void mouseReleased(MouseEvent e) { - } - - - /** - * Positions the description window relative to the completion choices - * window. We assume there is room on one side of the other for this - * entire window to fit. - */ - private void positionDescWindow() { - - boolean showDescWindow = descWindow != null && ac.isShowDescWindow(); - if (!showDescWindow) { - return; - } - - // Don't use getLocationOnScreen() as this throws an exception if - // window isn't visible yet, but getLocation() doesn't, and is in - // screen coordinates! - Point p = getLocation(); - Rectangle screenBounds = Util.getScreenBoundsForPoint(p.x, p.y); - //Dimension screenSize = getToolkit().getScreenSize(); - //int totalH = Math.max(getHeight(), descWindow.getHeight()); - - // Try to position to the right first (LTR) - int x; - if (ac.getTextComponentOrientation().isLeftToRight()) { - x = getX() + getWidth() + DIS; - if (x + descWindow.getWidth() > screenBounds.x + screenBounds.width) { // doesn't fit - x = getX() - DIS - descWindow.getWidth(); - } - } else { // RTL - x = getX() - DIS - descWindow.getWidth(); - if (x < screenBounds.x) { // Doesn't fit - x = getX() + getWidth() + DIS; - } - } - - int y = getY(); - if (aboveCaret) { - y = y + getHeight() - descWindow.getHeight(); - } - - if (x != descWindow.getX() || y != descWindow.getY()) { - descWindow.setLocation(x, y); - } - - } - - - /** - * "Puts back" the original key/Action pair for a keystroke. This is used - * when this popup is hidden. - * - * @param im The input map. - * @param am The action map. - * @param key The keystroke whose key/Action pair to change. - * @param kap The (original) key/Action pair. - * @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair) - */ - private void putBackAction(InputMap im, ActionMap am, int key, - KeyActionPair kap) { - KeyStroke ks = KeyStroke.getKeyStroke(key, 0); - am.put(im.get(ks), kap.action); // Original action for the "new" key - im.put(ks, kap.key); // Original key for the keystroke. - } - - - /** - * Replaces a key/Action pair in an InputMap and ActionMap with a new - * pair. - * - * @param im The input map. - * @param am The action map. - * @param key The keystroke whose information to replace. - * @param kap The new key/Action pair for key. - * @param old A buffer in which to place the old key/Action pair. - * @see #putBackAction(InputMap, ActionMap, int, KeyActionPair) - */ - private void replaceAction(InputMap im, ActionMap am, int key, - KeyActionPair kap, KeyActionPair old) { - KeyStroke ks = KeyStroke.getKeyStroke(key, 0); - old.key = im.get(ks); - im.put(ks, kap.key); - old.action = am.get(kap.key); - am.put(kap.key, kap.action); - } - - - /** - * Selects the first item in the completion list. - * - * @see #selectLastItem() - */ - private void selectFirstItem() { - if (model.getSize() > 0) { - list.setSelectedIndex(0); - list.ensureIndexIsVisible(0); - } - } - - - /** - * Selects the last item in the completion list. - * - * @see #selectFirstItem() - */ - private void selectLastItem() { - int index = model.getSize() - 1; - if (index > -1) { - list.setSelectedIndex(index); - list.ensureIndexIsVisible(index); - } - } - - - /** - * Selects the next item in the completion list. - * - * @see #selectPreviousItem() - */ - private void selectNextItem() { - int index = list.getSelectedIndex(); - if (index > -1) { - index = (index + 1) % model.getSize(); - list.setSelectedIndex(index); - list.ensureIndexIsVisible(index); - } - } - - - /** - * Selects the completion item one "page down" from the currently selected - * one. - * - * @see #selectPageUpItem() - */ - private void selectPageDownItem() { - int visibleRowCount = list.getVisibleRowCount(); - int i = Math.min(list.getModel().getSize() - 1, - list.getSelectedIndex() + visibleRowCount); - list.setSelectedIndex(i); - list.ensureIndexIsVisible(i); - } - - - /** - * Selects the completion item one "page up" from the currently selected - * one. - * - * @see #selectPageDownItem() - */ - private void selectPageUpItem() { - int visibleRowCount = list.getVisibleRowCount(); - int i = Math.max(0, list.getSelectedIndex() - visibleRowCount); - list.setSelectedIndex(i); - list.ensureIndexIsVisible(i); - } - - - /** - * Selects the previous item in the completion list. - * - * @see #selectNextItem() - */ - private void selectPreviousItem() { - int index = list.getSelectedIndex(); - switch (index) { - case 0: - index = list.getModel().getSize() - 1; - break; - case -1: // Check for an empty list (would be an error) - index = list.getModel().getSize() - 1; - if (index == -1) { - return; - } - break; - default: - index = index - 1; - break; - } - list.setSelectedIndex(index); - list.ensureIndexIsVisible(index); - } - - - /** - * Sets the completions to display in the choices list. The first - * completion is selected. - * - * @param completions The completions to display. - */ - public void setCompletions(List completions) { - model.setContents(completions); - selectFirstItem(); - } - - - /** - * Sets the size of the description window. - * - * @param size The new size. This cannot be null. - */ - public void setDescriptionWindowSize(Dimension size) { - if (descWindow != null) { - descWindow.setSize(size); - } else { - preferredDescWindowSize = size; - } - } - - - /** - * Sets the default list cell renderer to use when a completion provider - * does not supply its own. - * - * @param renderer The renderer to use. If this is null, - * a default renderer is used. - * @see #getListCellRenderer() - */ - public void setListCellRenderer(ListCellRenderer renderer) { - DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. - getCellRenderer(); - dcr.setFallbackCellRenderer(renderer); - } - - - /** - * Sets the location of this window to be "good" relative to the specified - * rectangle. That rectangle should be the location of the text - * component's caret, in screen coordinates. - * - * @param r The text component's caret position, in screen coordinates. - */ - public void setLocationRelativeTo(Rectangle r) { - - // Multi-monitor support - make sure the completion window (and - // description window, if applicable) both fit in the same window in - // a multi-monitor environment. To do this, we decide which monitor - // the rectangle "r" is in, and use that one (just pick top-left corner - // as the defining point). - Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y); - //Dimension screenSize = getToolkit().getScreenSize(); - - boolean showDescWindow = descWindow != null && ac.isShowDescWindow(); - int totalH = getHeight(); - if (showDescWindow) { - totalH = Math.max(totalH, descWindow.getHeight()); - } - - // Try putting our stuff "below" the caret first. We assume that the - // entire height of our stuff fits on the screen one way or the other. - aboveCaret = false; - int y = r.y + r.height + VERTICAL_SPACE; - if (y + totalH > screenBounds.height) { - y = r.y - VERTICAL_SPACE - getHeight(); - aboveCaret = true; - } - - // Get x-coordinate of completions. Try to align left edge with the - // caret first. - int x = r.x; - if (!ac.getTextComponentOrientation().isLeftToRight()) { - x -= getWidth(); // RTL => align right edge - } - if (x < screenBounds.x) { - x = screenBounds.x; - } else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit - x = screenBounds.x + screenBounds.width - getWidth(); - } - - setLocation(x, y); - - // Position the description window, if necessary. - if (showDescWindow) { - positionDescWindow(); - } - - } - - - /** - * Toggles the visibility of this popup window. - * - * @param visible Whether this window should be visible. - */ - @Override - public void setVisible(boolean visible) { - - if (visible != isVisible()) { - - if (visible) { - installKeyBindings(); - lastLine = ac.getLineOfCaret(); - selectFirstItem(); - if (descWindow == null && ac.isShowDescWindow()) { - descWindow = createDescriptionWindow(); - positionDescWindow(); - } - // descWindow needs a kick-start the first time it's displayed. - // Also, the newly-selected item in the choices list is - // probably different from the previous one anyway. - if (descWindow != null) { - Completion c = (Completion) list.getSelectedValue(); - if (c != null) { - descWindow.setDescriptionFor(c); - } - } - } else { - uninstallKeyBindings(); - } - - super.setVisible(visible); - - // Some languages, such as Java, can use quite a lot of memory - // when displaying hundreds of completion choices. We pro-actively - // clear our list model here to make them available for GC. - // Otherwise, they stick around, and consider the following: a - // user starts code-completion for Java 5 SDK classes, then hides - // the dialog, then changes the "class path" to use a Java 6 SDK - // instead. On pressing Ctrl+space, a new array of Completions is - // created. If this window holds on to the previous Completions, - // you're getting roughly 2x the necessary Completions in memory - // until the Completions are actually passed to this window. - if (!visible) { // Do after super.setVisible(false) - lastSelection = (Completion) list.getSelectedValue(); - model.clear(); - } - - // Must set descWindow's visibility one way or the other each time, - // because of the way child JWindows' visibility is handled - in - // some ways it's dependent on the parent, in other ways it's not. - if (descWindow != null) { - descWindow.setVisible(visible && ac.isShowDescWindow()); - } - - } - - } - - - /** - * Stops intercepting certain keystrokes from the text component. - * - * @see #installKeyBindings() - */ - private void uninstallKeyBindings() { - - if (AutoCompletion.isDebug()) { - FineLoggerFactory.getLogger().debug("PopupWindow: Removing keybindings"); - } - - JTextComponent comp = ac.getTextComponent(); - InputMap im = comp.getInputMap(); - ActionMap am = comp.getActionMap(); - - putBackAction(im, am, KeyEvent.VK_ESCAPE, oldEscape); - putBackAction(im, am, KeyEvent.VK_UP, oldUp); - putBackAction(im, am, KeyEvent.VK_DOWN, oldDown); - putBackAction(im, am, KeyEvent.VK_LEFT, oldLeft); - putBackAction(im, am, KeyEvent.VK_RIGHT, oldRight); - putBackAction(im, am, KeyEvent.VK_ENTER, oldEnter); - putBackAction(im, am, KeyEvent.VK_TAB, oldTab); - putBackAction(im, am, KeyEvent.VK_HOME, oldHome); - putBackAction(im, am, KeyEvent.VK_END, oldEnd); - putBackAction(im, am, KeyEvent.VK_PAGE_UP, oldPageUp); - putBackAction(im, am, KeyEvent.VK_PAGE_DOWN, oldPageDown); - - // Ctrl+C - KeyStroke ks = getCopyKeyStroke(); - am.put(im.get(ks), oldCtrlC.action); // Original action - im.put(ks, oldCtrlC.key); // Original key - - comp.removeCaretListener(this); - - } - - - /** - * Updates the LookAndFeel of this window and the description - * window. - */ - public void updateUI() { - SwingUtilities.updateComponentTreeUI(this); - if (descWindow != null) { - descWindow.updateUI(); - } - } - - - /** - * Called when a new item is selected in the popup list. - * - * @param e The event. - */ - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting()) { - Object value = list.getSelectedValue(); - if (value != null && descWindow != null) { - descWindow.setDescriptionFor((Completion) value); - positionDescWindow(); - } - } - } - - - class CopyAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - boolean doNormalCopy = false; - if (descWindow != null && descWindow.isVisible()) { - doNormalCopy = !descWindow.copy(); - } - if (doNormalCopy) { - ac.getTextComponent().copy(); - } - } - - } - - - class DownAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - selectNextItem(); - refreshInstallComp(); - } - } - - } - - - class EndAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - selectLastItem(); - } - } - - } - - - class EnterAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - insertSelectedCompletion(); - refreshInstallComp(); - } - } - + super(parent,ac); } - - class EscapeAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - setVisible(false); - } - } - - } - - - class HomeAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - selectFirstItem(); - } - } - - } - - - /** - * A mapping from a key (an Object) to an Action. - */ - private static class KeyActionPair { - - public Object key; - public Action action; - - public KeyActionPair() { - } - - public KeyActionPair(Object key, Action a) { - this.key = key; - this.action = a; - } - - } - - - class LeftAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - JTextComponent comp = ac.getTextComponent(); - Caret c = comp.getCaret(); - int dot = c.getDot(); - if (dot > 0) { - c.setDot(--dot); - // Ensure moving left hasn't moved us up a line, thus - // hiding the popup window. - if (comp.isVisible()) { - if (lastLine != -1) { - doAutocomplete(); - } - } - } - } - } - - } - - - class PageDownAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - selectPageDownItem(); - } - } - - } - - - class PageUpAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - selectPageUpItem(); - } - } - - } - - - /** - * The actual list of completion choices in this popup window. - */ - private class PopupList extends JList { - - public PopupList(CompletionListModel model) { - super(model); - } - - @Override - public void setUI(ListUI ui) { - if (Util.getUseSubstanceRenderers() && - SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) { - // Substance requires its special ListUI be installed for - // its renderers to actually render (!), but long completion - // lists (e.g. PHPCompletionProvider in RSTALanguageSupport) - // will simply populate too slowly on initial display (when - // calculating preferred size of all items), so in this case - // we give a prototype cell value. - CompletionProvider p = ac.getCompletionProvider(); - BasicCompletion bc = new BasicCompletion(p, "Hello world"); - setPrototypeCellValue(bc); - } else { - // Our custom UI that is faster for long HTML completion lists. - ui = new FastListUI(); - setPrototypeCellValue(null); - } - super.setUI(ui); - } - - } - - - class RightAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - JTextComponent comp = ac.getTextComponent(); - Caret c = comp.getCaret(); - int dot = c.getDot(); - if (dot < comp.getDocument().getLength()) { - c.setDot(++dot); - // Ensure moving right hasn't moved us up a line, thus - // hiding the popup window. - if (comp.isVisible()) { - if (lastLine != -1) { - doAutocomplete(); - } - } - } - } - } - - } - - - class UpAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isVisible()) { - selectPreviousItem(); - refreshInstallComp(); - } - } - - } - - } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java index 8168c767d..cd37fd9bc 100644 --- a/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java @@ -2,226 +2,18 @@ package com.fr.design.gui.autocomplete; import com.fr.design.formula.FormulaPane; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ActionMap; -import javax.swing.InputMap; -import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.UIManager; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.BadLocationException; import javax.swing.text.Caret; -import javax.swing.text.Document; -import javax.swing.text.Element; import javax.swing.text.JTextComponent; -import java.awt.ComponentOrientation; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowEvent; -import java.awt.event.WindowFocusListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.List; - -import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; /** * @author Hoky * @date 2021/11/2 * @description 重写一个支持刷新公式树组件的AutoCompletion */ -public class FormulaPaneAutoCompletion extends AutoCompletion { - private FormulaPane.VariableTreeAndDescriptionArea area; - - /** - * The text component we're providing completion for. - */ - private JTextComponent textComponent; - - /** - * The parent window of {@link #textComponent}. - */ - private Window parentWindow; - - /** - * The popup window containing completion choices. - */ - private FormulaAutoCompletePopupWindow popupWindow; - - /** - * The preferred size of the completion choices window. This field exists - * because the user will likely set the preferred size of the window - * before it is actually created. - */ - private Dimension preferredChoicesWindowSize; - - /** - * The preferred size of the optional description window. This field - * only exists because the user may (and usually will) set the size of - * the description window before it exists (it must be parented to a - * Window). - */ - private Dimension preferredDescWindowSize; - - /** - * Manages any parameterized completions that are inserted. - */ - private ParameterizedCompletionContext pcc; - - /** - * Provides the completion options relevant to the current caret position. - */ - private CompletionProvider provider; - - /** - * The renderer to use for the completion choices. If this is - * null, then a default renderer is used. - */ - private ListCellRenderer renderer; - - /** - * The handler to use when an external URL is clicked in the help - * documentation. - */ - private ExternalURLHandler externalURLHandler; - - /** - * An optional redirector that converts URL's to some other location before - * being handed over to externalURLHandler. - */ - private static LinkRedirector linkRedirector; - - /** - * Whether the description window should be displayed along with the - * completion choice window. - */ - private boolean showDescWindow; - - /** - * Whether auto-complete is enabled. - */ - private boolean autoCompleteEnabled; - - /** - * Whether the auto-activation of auto-complete (after a delay, after the - * user types an appropriate character) is enabled. - */ - private boolean autoActivationEnabled; - - /** - * Whether or not, when there is only a single auto-complete option - * that matches the text at the current text position, that text should - * be auto-inserted, instead of the completion window displaying. - */ - private boolean autoCompleteSingleChoices; - - /** - * Whether parameter assistance is enabled. - */ - private boolean parameterAssistanceEnabled; - - /** - * A renderer used for {@link Completion}s in the optional parameter - * choices popup window (displayed when a {@link ParameterizedCompletion} - * is code-completed). If this isn't set, a default renderer is used. - */ - private ListCellRenderer paramChoicesRenderer; - - /** - * The keystroke that triggers the completion window. - */ - private KeyStroke trigger; - - /** - * The previous key in the text component's InputMap for the - * trigger key. - */ - private Object oldTriggerKey; - - /** - * The action previously assigned to {@link #trigger}, so we can reset it - * if the user disables auto-completion. - */ - private Action oldTriggerAction; - - /** - * The previous key in the text component's InputMap for the - * parameter completion trigger key. - */ - private Object oldParenKey; - - /** - * The action previously assigned to the parameter completion key, so we - * can reset it when we uninstall. - */ - private Action oldParenAction; - - /** - * Listens for events in the parent window that affect the visibility of - * the popup windows. - */ - private ParentWindowListener parentWindowListener; - - /** - * Listens for events from the text component that affect the visibility - * of the popup windows. - */ - private TextComponentListener textComponentListener; - - /** - * Listens for events in the text component that cause the popup windows - * to automatically activate. - */ - private AutoActivationListener autoActivationListener; - - /** - * Listens for LAF changes so the auto-complete windows automatically - * update themselves accordingly. - */ - private LookAndFeelChangeListener lafListener; - - /** - * The key used in the input map for the AutoComplete action. - */ - private static final String PARAM_TRIGGER_KEY = "AutoComplete"; - - /** - * Key used in the input map for the parameter completion action. - */ - private static final String PARAM_COMPLETE_KEY = "AutoCompletion.FunctionStart"; - - /** - * Stores how to render auto-completion-specific highlights in text - * components. - */ - private static final AutoCompletionStyleContext STYLE_CONTEXT = - new AutoCompletionStyleContext(); - - /** - * Whether debug messages should be printed to stdout as AutoCompletion - * runs. - */ - private static final boolean DEBUG = initDebug(); - - +public class FormulaPaneAutoCompletion extends AutoCompletionWithExtraRefresh { /** * Constructor. * @@ -230,957 +22,29 @@ public class FormulaPaneAutoCompletion extends AutoCompletion { */ public FormulaPaneAutoCompletion(CompletionProvider provider) { super(provider); - setChoicesWindowSize(350, 200); - setDescriptionWindowSize(350, 250); - - setCompletionProvider(provider); - setTriggerKey(getDefaultTriggerKey()); - setAutoCompleteEnabled(true); - setAutoCompleteSingleChoices(true); - setAutoActivationEnabled(false); - setShowDescWindow(false); - parentWindowListener = new ParentWindowListener(); - textComponentListener = new TextComponentListener(); - autoActivationListener = new AutoActivationListener(); - lafListener = new LookAndFeelChangeListener(); - } - - - /** - * Displays the popup window. Hosting applications can call this method - * to programmatically begin an auto-completion operation. - */ - public void doCompletion() { - refreshPopupWindow(); - } - - - /** - * Returns the delay between when the user types a character and when the - * code completion popup should automatically appear (if applicable). - * - * @return The delay, in milliseconds. - * @see #setAutoActivationDelay(int) - */ - public int getAutoActivationDelay() { - return autoActivationListener.timer.getDelay(); } - - /** - * Returns whether, if a single auto-complete choice is available, it - * should be automatically inserted, without displaying the popup menu. - * - * @return Whether to auto-complete single choices. - * @see #setAutoCompleteSingleChoices(boolean) - */ - public boolean isAutoCompleteSingleChoices() { - return autoCompleteSingleChoices; - } - - - /** - * Returns the completion provider. - * - * @return The completion provider. - */ - public CompletionProvider getCompletionProvider() { - return provider; - } - - - /** - * Returns whether debug is enabled for AutoCompletion. - * - * @return Whether debug is enabled. - */ - static boolean isDebug() { - return DEBUG; - } - - - /** - * Returns the default auto-complete "trigger key" for this OS. For - * Windows, for example, it is Ctrl+Space. - * - * @return The default auto-complete trigger key. - */ - public static KeyStroke getDefaultTriggerKey() { - // Default to CTRL, even on Mac, since Ctrl+Space activates Spotlight - return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, DEFAULT_MODIFIER); - } - - - /** - * Returns the handler to use when an external URL is clicked in the - * description window. - * - * @return The handler. - * @see #setExternalURLHandler(ExternalURLHandler) - * @see #getLinkRedirector() - */ - public ExternalURLHandler getExternalURLHandler() { - return externalURLHandler; - } - - - int getLineOfCaret() { - Document doc = textComponent.getDocument(); - Element root = doc.getDefaultRootElement(); - return root.getElementIndex(textComponent.getCaretPosition()); - } - - - /** - * Returns the link redirector, if any. - * - * @return The link redirector, or null if none. - * @see #setLinkRedirector(LinkRedirector) - */ - public static LinkRedirector getLinkRedirector() { - return linkRedirector; - } - - - /** - * Returns the default list cell renderer used when a completion provider - * does not supply its own. - * - * @return The default list cell renderer. - * @see #setListCellRenderer(ListCellRenderer) - */ - public ListCellRenderer getListCellRenderer() { - return renderer; - } - - - /** - * Returns the renderer to use for {@link Completion}s in the optional - * parameter choices popup window (displayed when a - * {@link ParameterizedCompletion} is code-completed). If this returns - * null, a default renderer is used. - * - * @return The renderer to use. - * @see #setParamChoicesRenderer(ListCellRenderer) - * @see #isParameterAssistanceEnabled() - */ - public ListCellRenderer getParamChoicesRenderer() { - return paramChoicesRenderer; - } - - - /** - * Returns the text to replace with in the document. This is a - * "last-chance" hook for subclasses to make special modifications to the - * completion text inserted. The default implementation simply returns - * c.getReplacementText(). You usually will not need to modify - * this method. - * - * @param c The completion being inserted. - * @param doc The document being modified. - * @param start The start of the text being replaced. - * @param len The length of the text being replaced. - * @return The text to replace with. - */ - protected String getReplacementText(Completion c, Document doc, int start, - int len) { - return c.getReplacementText(); - } - - - /** - * Returns whether the "description window" should be shown alongside - * the completion window. - * - * @return Whether the description window should be shown. - * @see #setShowDescWindow(boolean) - */ - public boolean isShowDescWindow() { - return showDescWindow; - } - - - /** - * Returns the style context describing how auto-completion related - * highlights in the editor are rendered. - * - * @return The style context. - */ - public static AutoCompletionStyleContext getStyleContext() { - return STYLE_CONTEXT; - } - - - /** - * Returns the text component for which auto-completion is enabled. - * - * @return The text component, or null if this - * {@link AutoCompletion} is not installed on any text component. - * @see #install(JTextComponent) - */ - public JTextComponent getTextComponent() { - return textComponent; - } - - - /** - * Returns the orientation of the text component we're installed to. - * - * @return The orientation of the text component, or null if - * we are not installed on one. - */ - ComponentOrientation getTextComponentOrientation() { - return textComponent == null ? null : - textComponent.getComponentOrientation(); - } - - - /** - * Returns the "trigger key" used for auto-complete. - * - * @return The trigger key. - * @see #setTriggerKey(KeyStroke) - */ - public KeyStroke getTriggerKey() { - return trigger; - } - - - /** - * Hides any child windows being displayed by the auto-completion system. - * - * @return Whether any windows were visible. - */ - public boolean hideChildWindows() { - //return hidePopupWindow() || hideToolTipWindow(); - boolean res = hidePopupWindow(); - res |= hideParameterCompletionPopups(); - return res; - } - - - /** - * Hides and disposes of any parameter completion-related popups. - * - * @return Whether any such windows were visible (and thus hidden). - */ - private boolean hideParameterCompletionPopups() { - if (pcc != null) { - pcc.deactivate(); - pcc = null; - return true; - } - return false; - } - - - /** - * Hides the popup window, if it is visible. - * - * @return Whether the popup window was visible. - */ - private boolean hidePopupWindow() { - if (popupWindow != null) { - if (popupWindow.isVisible()) { - popupWindow.setVisible(false); - return true; - } - } - return false; - } - - - /** - * Determines whether debug should be enabled for the AutoCompletion - * library. This method checks a system property, but takes care of - * {@link SecurityException}s in case we're in an applet or WebStart. - * - * @return Whether debug should be enabled. - */ - private static boolean initDebug() { - boolean debug = false; - try { - debug = Boolean.getBoolean("AutoCompletion.debug"); - } catch (SecurityException se) { // We're in an applet or WebStart. - debug = false; - } - return debug; - } - - - /** - * Installs this auto-completion on a text component. If this - * {@link AutoCompletion} is already installed on another text component, - * it is uninstalled first. - * - * @param c The text component. - * @see #uninstall() - */ - public void install(JTextComponent c) { - - if (textComponent != null) { - uninstall(); - } - - this.textComponent = c; - installTriggerKey(getTriggerKey()); - - // Install the function completion key, if there is one. - // NOTE: We cannot do this if the start char is ' ' (e.g. just a space - // between the function name and parameters) because it overrides - // RSTA's special space action. It seems KeyStorke.getKeyStroke(' ') - // hoses ctrl+space, shift+space, etc., even though I think it - // shouldn't... - char start = provider.getParameterListStart(); - if (start != 0 && start != ' ') { - InputMap im = c.getInputMap(); - ActionMap am = c.getActionMap(); - KeyStroke ks = KeyStroke.getKeyStroke(start); - oldParenKey = im.get(ks); - im.put(ks, PARAM_COMPLETE_KEY); - oldParenAction = am.get(PARAM_COMPLETE_KEY); - am.put(PARAM_COMPLETE_KEY, - new ParameterizedCompletionStartAction(start)); - } - - textComponentListener.addTo(this.textComponent); - // In case textComponent is already in a window... - textComponentListener.hierarchyChanged(null); - - if (isAutoActivationEnabled()) { - autoActivationListener.addTo(this.textComponent); - } - - UIManager.addPropertyChangeListener(lafListener); - updateUI(); // In case there have been changes since we uninstalled - - } - - - /** - * Installs a "trigger key" action onto the current text component. - * - * @param ks The keystroke that should trigger the action. - */ - private void installTriggerKey(KeyStroke ks) { - InputMap im = textComponent.getInputMap(); - oldTriggerKey = im.get(ks); - im.put(ks, PARAM_TRIGGER_KEY); - ActionMap am = textComponent.getActionMap(); - oldTriggerAction = am.get(PARAM_TRIGGER_KEY); - am.put(PARAM_TRIGGER_KEY, new AutoCompleteAction()); - } - - - /** - * Returns whether auto-activation is enabled (that is, whether the - * completion popup will automatically appear after a delay when the user - * types an appropriate character). Note that this parameter will be - * ignored if auto-completion is disabled. - * - * @return Whether auto-activation is enabled. - * @see #setAutoActivationEnabled(boolean) - * @see #getAutoActivationDelay() - * @see #isAutoCompleteEnabled() - */ - public boolean isAutoActivationEnabled() { - return autoActivationEnabled; - } - - - /** - * Returns whether auto-completion is enabled. - * - * @return Whether auto-completion is enabled. - * @see #setAutoCompleteEnabled(boolean) - */ - public boolean isAutoCompleteEnabled() { - return autoCompleteEnabled; - } - - - /** - * Returns whether parameter assistance is enabled. - * - * @return Whether parameter assistance is enabled. - * @see #setParameterAssistanceEnabled(boolean) - */ - public boolean isParameterAssistanceEnabled() { - return parameterAssistanceEnabled; - } - - - /** - * Returns whether the completion popup window is visible. - * - * @return Whether the completion popup window is visible. - */ - public boolean isPopupVisible() { - return popupWindow != null && popupWindow.isVisible(); - } - - private boolean needSetPopupWindow(int count, int textLen) { - return (count == 1 && (isPopupVisible() || textLen == 0)) - || (count == 1 && !isAutoCompleteSingleChoices()) - || count > 1; - } - - private FormulaAutoCompletePopupWindow createAutoCompletePopupWindow() { - FormulaAutoCompletePopupWindow popupWindow = new FormulaAutoCompletePopupWindow(parentWindow, this); + @Override + protected AutoCompleteWithExtraRefreshPopupWindow createAutoCompletePopupWindow() { + FormulaAutoCompletePopupWindow popupWindow = new FormulaAutoCompletePopupWindow(getParentWindow(), this); // Completion is usually done for code, which is always done // LTR, so make completion stuff RTL only if text component is // also RTL. popupWindow.applyComponentOrientation( getTextComponentOrientation()); - if (renderer != null) { - popupWindow.setListCellRenderer(renderer); + if (getCellRender() != null) { + popupWindow.setListCellRenderer(getCellRender()); } - if (preferredChoicesWindowSize != null) { - popupWindow.setSize(preferredChoicesWindowSize); + if (getPreferredChoicesWindowSize() != null) { + popupWindow.setSize(getPreferredChoicesWindowSize()); } - if (preferredDescWindowSize != null) { + if (getPreferredDescWindowSize() != null) { popupWindow.setDescriptionWindowSize( - preferredDescWindowSize); + getPreferredDescWindowSize()); } return popupWindow; } - /** - * Sets the delay between when the user types a character and when the - * code completion popup should automatically appear (if applicable). - * - * @param ms The delay, in milliseconds. This should be greater than zero. - * @see #getAutoActivationDelay() - */ - public void setAutoActivationDelay(int ms) { - ms = Math.max(0, ms); - autoActivationListener.timer.stop(); - autoActivationListener.timer.setInitialDelay(ms); - } - - - /** - * Toggles whether auto-activation is enabled. Note that auto-activation - * also depends on auto-completion itself being enabled. - * - * @param enabled Whether auto-activation is enabled. - * @see #isAutoActivationEnabled() - * @see #setAutoActivationDelay(int) - */ - public void setAutoActivationEnabled(boolean enabled) { - if (enabled != autoActivationEnabled) { - autoActivationEnabled = enabled; - if (textComponent != null) { - if (autoActivationEnabled) { - autoActivationListener.addTo(textComponent); - } else { - autoActivationListener.removeFrom(textComponent); - } - } - } - } - - - /** - * Sets whether auto-completion is enabled. - * - * @param enabled Whether auto-completion is enabled. - * @see #isAutoCompleteEnabled() - */ - public void setAutoCompleteEnabled(boolean enabled) { - if (enabled != autoCompleteEnabled) { - autoCompleteEnabled = enabled; - hidePopupWindow(); - } - } - - - /** - * Sets whether, if a single auto-complete choice is available, it should - * be automatically inserted, without displaying the popup menu. - * - * @param autoComplete Whether to auto-complete single choices. - * @see #isAutoCompleteSingleChoices() - */ - public void setAutoCompleteSingleChoices(boolean autoComplete) { - autoCompleteSingleChoices = autoComplete; - } - - - /** - * Sets the completion provider being used. - * - * @param provider The new completion provider. This cannot be - * null. - * @throws IllegalArgumentException If provider is - * null. - */ - public void setCompletionProvider(CompletionProvider provider) { - if (provider == null) { - throw new IllegalArgumentException("provider cannot be null"); - } - this.provider = provider; - hidePopupWindow(); // In case new choices should be displayed. - } - - - /** - * Sets the size of the completion choices window. - * - * @param w The new width. - * @param h The new height. - * @see #setDescriptionWindowSize(int, int) - */ - public void setChoicesWindowSize(int w, int h) { - preferredChoicesWindowSize = new Dimension(w, h); - if (popupWindow != null) { - popupWindow.setSize(preferredChoicesWindowSize); - } - } - - - /** - * Sets the size of the description window. - * - * @param w The new width. - * @param h The new height. - * @see #setChoicesWindowSize(int, int) - */ - public void setDescriptionWindowSize(int w, int h) { - preferredDescWindowSize = new Dimension(w, h); - if (popupWindow != null) { - popupWindow.setDescriptionWindowSize(preferredDescWindowSize); - } - } - - - /** - * Sets the handler to use when an external URL is clicked in the - * description window. This handler can perform some action, such as - * open the URL in a web browser. The default implementation will open - * the URL in a browser, but only if running in Java 6. If you want - * browser support for Java 5 and below, or otherwise want to respond to - * hyperlink clicks, you will have to install your own handler to do so. - * - * @param handler The new handler. - * @see #getExternalURLHandler() - */ - public void setExternalURLHandler(ExternalURLHandler handler) { - this.externalURLHandler = handler; - } - - - /** - * Sets the redirector for external URL's found in code completion - * documentation. When a non-local link in completion popups is clicked, - * this redirector is given the chance to modify the URL fetched and - * displayed. - * - * @param redirector The link redirector, or null for - * none. - * @see #getLinkRedirector() - */ - public static void setLinkRedirector(LinkRedirector redirector) { - linkRedirector = redirector; - } - - - /** - * Sets the default list cell renderer to use when a completion provider - * does not supply its own. - * - * @param renderer The renderer to use. If this is null, - * a default renderer is used. - * @see #getListCellRenderer() - */ - public void setListCellRenderer(ListCellRenderer renderer) { - this.renderer = renderer; - if (popupWindow != null) { - popupWindow.setListCellRenderer(renderer); - hidePopupWindow(); - } - } - - - /** - * Sets the renderer to use for {@link Completion}s in the optional - * parameter choices popup window (displayed when a - * {@link ParameterizedCompletion} is code-completed). If this isn't set, - * a default renderer is used. - * - * @param r The renderer to use. - * @see #getParamChoicesRenderer() - * @see #setParameterAssistanceEnabled(boolean) - */ - public void setParamChoicesRenderer(ListCellRenderer r) { - paramChoicesRenderer = r; - } - - - /** - * Sets whether parameter assistance is enabled. If parameter assistance - * is enabled, and a "parameterized" completion (such as a function or - * method) is inserted, the user will get "assistance" in inserting the - * parameters in the form of a popup window with documentation and easy - * tabbing through the arguments (as seen in Eclipse and NetBeans). - * - * @param enabled Whether parameter assistance should be enabled. - * @see #isParameterAssistanceEnabled() - */ - public void setParameterAssistanceEnabled(boolean enabled) { - parameterAssistanceEnabled = enabled; - } - - - /** - * Sets whether the "description window" should be shown beside the - * completion window. - * - * @param show Whether to show the description window. - * @see #isShowDescWindow() - */ - public void setShowDescWindow(boolean show) { - hidePopupWindow(); // Needed to force it to take effect - showDescWindow = show; - } - - - /** - * Sets the keystroke that should be used to trigger the auto-complete - * popup window. - * - * @param ks The keystroke. - * @throws IllegalArgumentException If ks is null. - * @see #getTriggerKey() - */ - public void setTriggerKey(KeyStroke ks) { - if (ks == null) { - throw new IllegalArgumentException("trigger key cannot be null"); - } - if (!ks.equals(trigger)) { - if (textComponent != null) { - // Put old trigger action back. - uninstallTriggerKey(); - // Grab current action for new trigger and replace it. - installTriggerKey(ks); - } - trigger = ks; - } - } - - - /** - * Uninstalls this auto-completion from its text component. If it is not - * installed on any text component, nothing happens. - * - * @see #install(JTextComponent) - */ - public void uninstall() { - - if (textComponent != null) { - - hidePopupWindow(); // Unregisters listeners, actions, etc. - - uninstallTriggerKey(); - - // Uninstall the function completion key. - char start = provider.getParameterListStart(); - if (start != 0) { - KeyStroke ks = KeyStroke.getKeyStroke(start); - InputMap im = textComponent.getInputMap(); - im.put(ks, oldParenKey); - ActionMap am = textComponent.getActionMap(); - am.put(PARAM_COMPLETE_KEY, oldParenAction); - } - - textComponentListener.removeFrom(textComponent); - if (parentWindow != null) { - parentWindowListener.removeFrom(parentWindow); - } - - if (isAutoActivationEnabled()) { - autoActivationListener.removeFrom(textComponent); - } - - UIManager.removePropertyChangeListener(lafListener); - - textComponent = null; - popupWindow = null; - - } - - } - - - /** - * Replaces the "trigger key" action with the one that was there - * before auto-completion was installed. - */ - private void uninstallTriggerKey() { - InputMap im = textComponent.getInputMap(); - im.put(trigger, oldTriggerKey); - ActionMap am = textComponent.getActionMap(); - am.put(PARAM_TRIGGER_KEY, oldTriggerAction); - } - - - /** - * Updates the LookAndFeel of the popup window. Applications can call - * this method as appropriate if they support changing the LookAndFeel - * at runtime. - */ - private void updateUI() { - if (popupWindow != null) { - popupWindow.updateUI(); - } - if (pcc != null) { - pcc.updateUI(); - } - // Will practically always be a JComponent (a JLabel) - if (paramChoicesRenderer instanceof JComponent) { - ((JComponent) paramChoicesRenderer).updateUI(); - } - } - - - /** - * Listens for events in the text component to auto-activate the code - * completion popup. - */ - private class AutoActivationListener extends FocusAdapter - implements DocumentListener, CaretListener, ActionListener { - - private Timer timer; - private boolean justInserted; - - public AutoActivationListener() { - timer = new Timer(200, this); - timer.setRepeats(false); - } - - public void actionPerformed(ActionEvent e) { - doCompletion(); - } - - public void addTo(JTextComponent tc) { - tc.addFocusListener(this); - tc.getDocument().addDocumentListener(this); - tc.addCaretListener(this); - } - - public void caretUpdate(CaretEvent e) { - if (justInserted) { - justInserted = false; - } else { - timer.stop(); - } - } - - public void changedUpdate(DocumentEvent e) { - // Ignore - } - - @Override - public void focusLost(FocusEvent e) { - timer.stop(); - //hideChildWindows(); Other listener will do this - } - - public void insertUpdate(DocumentEvent e) { - justInserted = false; - if (isAutoCompleteEnabled() && isAutoActivationEnabled() && - e.getLength() == 1) { - if (provider.isAutoActivateOkay(textComponent)) { - timer.restart(); - justInserted = true; - } else { - timer.stop(); - } - } else { - timer.stop(); - } - } - - public void removeFrom(JTextComponent tc) { - tc.removeFocusListener(this); - tc.getDocument().removeDocumentListener(this); - tc.removeCaretListener(this); - timer.stop(); - justInserted = false; - } - - public void removeUpdate(DocumentEvent e) { - timer.stop(); - } - - } - - - /** - * The Action that displays the popup window if - * auto-completion is enabled. - */ - private class AutoCompleteAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - if (isAutoCompleteEnabled()) { - refreshPopupWindow(); - } else if (oldTriggerAction != null) { - oldTriggerAction.actionPerformed(e); - } - } - - } - - - /** - * Listens for LookAndFeel changes and updates the various popup windows - * involved in auto-completion accordingly. - */ - private class LookAndFeelChangeListener implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - String name = e.getPropertyName(); - if ("lookAndFeel".equals(name)) { - updateUI(); - } - } - - } - - - /** - * Action that starts a parameterized completion, e.g. after '(' is - * typed. - */ - private class ParameterizedCompletionStartAction extends AbstractAction { - - private String start; - - public ParameterizedCompletionStartAction(char ch) { - this.start = Character.toString(ch); - } - - public void actionPerformed(ActionEvent e) { - - // Prevents keystrokes from messing up - boolean wasVisible = hidePopupWindow(); - - // Only proceed if they were selecting a completion - if (!wasVisible || !isParameterAssistanceEnabled()) { - textComponent.replaceSelection(start); - return; - } - - Completion c = popupWindow.getSelection(); - if (c instanceof ParameterizedCompletion) { // Should always be true - // Fixes capitalization of the entered text. - insertCompletion(c, true); - } - - } - - } - - - /** - * Listens for events in the parent window of the text component with - * auto-completion enabled. - */ - private class ParentWindowListener extends ComponentAdapter - implements WindowFocusListener { - - public void addTo(Window w) { - w.addComponentListener(this); - w.addWindowFocusListener(this); - } - - @Override - public void componentHidden(ComponentEvent e) { - hideChildWindows(); - } - - @Override - public void componentMoved(ComponentEvent e) { - hideChildWindows(); - } - - @Override - public void componentResized(ComponentEvent e) { - hideChildWindows(); - } - - public void removeFrom(Window w) { - w.removeComponentListener(this); - w.removeWindowFocusListener(this); - } - - public void windowGainedFocus(WindowEvent e) { - } - - public void windowLostFocus(WindowEvent e) { - hideChildWindows(); - } - - } - - - /** - * Listens for events from the text component we're installed on. - */ - private class TextComponentListener extends FocusAdapter - implements HierarchyListener { - - void addTo(JTextComponent tc) { - tc.addFocusListener(this); - tc.addHierarchyListener(this); - } - - /** - * Hide the auto-completion windows when the text component loses - * focus. - */ - @Override - public void focusLost(FocusEvent e) { - hideChildWindows(); - } - - /** - * Called when the component hierarchy for our text component changes. - * When the text component is added to a new {@link Window}, this - * method registers listeners on that Window. - * - * @param e The event. - */ - public void hierarchyChanged(HierarchyEvent e) { - - // NOTE: e many be null as we call this method at other times. - //System.out.println("Hierarchy changed! " + e); - - Window oldParentWindow = parentWindow; - parentWindow = SwingUtilities.getWindowAncestor(textComponent); - if (parentWindow != oldParentWindow) { - if (oldParentWindow != null) { - parentWindowListener.removeFrom(oldParentWindow); - } - if (parentWindow != null) { - parentWindowListener.addTo(parentWindow); - } - } - - } - - public void removeFrom(JTextComponent tc) { - tc.removeFocusListener(this); - tc.removeHierarchyListener(this); - } - - } - - public void installVariableTree(FormulaPane.VariableTreeAndDescriptionArea jComp) { - area = jComp; - } - /** * Inserts a completion. Any time a code completion event occurs, the * actual text insertion happens through this method. @@ -1223,89 +87,4 @@ public class FormulaPaneAutoCompletion extends AutoCompletion { } } - - /** - * Displays a "tool tip" detailing the inputs to the function just entered. - * - * @param pc The completion. - * @param typedParamListStartChar Whether the parameterized completion list - * starting character was typed. - */ - private void startParameterizedCompletionAssistance( - ParameterizedCompletion pc, boolean typedParamListStartChar) { - - // Get rid of the previous tool tip window, if there is one. - hideParameterCompletionPopups(); - - // Don't bother with a tool tip if there are no parameters, but if - // they typed e.g. the opening '(', make them overtype the ')'. - if (pc.getParamCount() == 0 && !(pc instanceof TemplateCompletion)) { - CompletionProvider p = pc.getProvider(); - char end = p.getParameterListEnd(); // Might be '\0' - String text = end == '\0' ? "" : Character.toString(end); - if (typedParamListStartChar) { - String template = "${}" + text + "${cursor}"; - textComponent.replaceSelection(Character.toString(p.getParameterListStart())); - TemplateCompletion tc = new TemplateCompletion(p, null, null, template); - pc = tc; - } else { - text = p.getParameterListStart() + text; - textComponent.replaceSelection(text); - return; - } - } - - pcc = new ParameterizedCompletionContext(parentWindow, this, pc); - pcc.activate(); - - } - - protected int refreshPopupWindow() { - // A return value of null => don't suggest completions - String text = provider.getAlreadyEnteredText(textComponent); - if (text == null && !isPopupVisible()) { - return getLineOfCaret(); - } - // If the popup is currently visible, and they type a space (or any - // character that resets the completion list to "all completions"), - // the popup window should be hidden instead of being reset to show - // everything. - int textLen = text == null ? 0 : text.length(); - if (textLen == 0 && isPopupVisible()) { - hidePopupWindow(); - return getLineOfCaret(); - } - final List completions = provider.getCompletions(textComponent); - int count = completions.size(); - if (needSetPopupWindow(count, textLen)) { - if (popupWindow == null) { - popupWindow = createAutoCompletePopupWindow(); - } - popupWindow.installComp(area); - popupWindow.setCompletions(completions); - if (!popupWindow.isVisible()) { - Rectangle r = null; - try { - r = textComponent.modelToView(textComponent.getCaretPosition()); - } catch (BadLocationException ble) { - return -1; - } - Point p = new Point(r.x, r.y); - SwingUtilities.convertPointToScreen(p, textComponent); - r.x = p.x; - r.y = p.y; - popupWindow.setLocationRelativeTo(r); - popupWindow.setVisible(true); - } - } else if (count == 1) { // !isPopupVisible && autoCompleteSingleChoices - SwingUtilities.invokeLater(new Runnable() { - public void run() { - insertCompletion(completions.get(0)); - } - }); - } else { - hidePopupWindow(); - } - return getLineOfCaret(); - } } diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/JSAutoCompletePopupWindow.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/JSAutoCompletePopupWindow.java new file mode 100644 index 000000000..80a26bf96 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/JSAutoCompletePopupWindow.java @@ -0,0 +1,16 @@ +package com.fr.design.gui.autocomplete; + +import java.awt.Window; + +public class JSAutoCompletePopupWindow extends AutoCompleteWithExtraRefreshPopupWindow { + + /** + * Constructor. + * + * @param parent The parent window (hosting the text component). + * @param ac The auto-completion instance. + */ + public JSAutoCompletePopupWindow(Window parent, AutoCompletion ac) { + super(parent, ac); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/JSImplPaneAutoCompletion.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/JSImplPaneAutoCompletion.java new file mode 100644 index 000000000..0c534bf72 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/JSImplPaneAutoCompletion.java @@ -0,0 +1,31 @@ +package com.fr.design.gui.autocomplete; + +public class JSImplPaneAutoCompletion extends AutoCompletionWithExtraRefresh{ + /** + * Constructor. + * + * @param provider The completion provider. This cannot be + * null. + */ + public JSImplPaneAutoCompletion(CompletionProvider provider) { + super(provider); + } + + @Override + protected AutoCompleteWithExtraRefreshPopupWindow createAutoCompletePopupWindow() { + JSAutoCompletePopupWindow popupWindow = new JSAutoCompletePopupWindow(getParentWindow(),this); + popupWindow.applyComponentOrientation( + getTextComponentOrientation()); + if (getCellRender() != null) { + popupWindow.setListCellRenderer(getCellRender()); + } + if (getPreferredChoicesWindowSize() != null) { + popupWindow.setSize(getPreferredChoicesWindowSize()); + } + if (getPreferredDescWindowSize() != null) { + popupWindow.setDescriptionWindowSize( + getPreferredDescWindowSize()); + } + return popupWindow; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ilable/UIAutoChangeLineLabel.java b/designer-base/src/main/java/com/fr/design/gui/ilable/UIAutoChangeLineLabel.java new file mode 100644 index 000000000..d2bb0450b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ilable/UIAutoChangeLineLabel.java @@ -0,0 +1,78 @@ +package com.fr.design.gui.ilable; + +import javax.swing.JLabel; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.util.ArrayList; +import java.util.List; + +public class UIAutoChangeLineLabel extends JLabel { + private final String text; + private final int width; + + + public UIAutoChangeLineLabel(String text, int width) { + super(text); + this.text = text; + this.width = width; + } + + + @Override + public void doLayout() { + super.doLayout(); + this.setText(wrapperHtmlText()); + } + + private String wrapperHtmlText() { + List stringList = autoChangeLine(this.getWidth()); + StringBuilder builder = new StringBuilder(""); + for (String s : stringList) { + //用THML标签进行拼接,以实现自动换行 + builder.append(s).append("
"); + } + builder.append(""); + return builder.toString(); + } + + private List autoChangeLine(int width) { + List result = new ArrayList<>(); + if (width <= 0) { + result.add(this.text); + } else { + + char[] chars = this.text.toCharArray(); + //获取字体计算大小 + FontMetrics fontMetrics = this.getFontMetrics(this.getFont()); + int start = 0; + int len = 0; + while (start + len < this.text.length()) { + while (true) { + len++; + if (start + len > this.text.length()) + break; + if (fontMetrics.charsWidth(chars, start, len) + > width) { + break; + } + } + result.add(String.copyValueOf(chars, start, len - 1)); + start = start + len - 1; + len = 0; + } + if (this.text.length() - start > 0) { + result.add(String.copyValueOf(chars, start, this.text.length() - start)); + } + } + return result; + } + + + @Override + public Dimension getPreferredSize() { + Dimension preferredSize = super.getPreferredSize(); + List stringList = autoChangeLine(width); + FontMetrics fontMetrics = this.getFontMetrics(this.getFont()); + return new Dimension(preferredSize.width, fontMetrics.getHeight() * stringList.size()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java b/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java index 10e11c8fb..65bec03a8 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java @@ -1,10 +1,13 @@ package com.fr.design.javascript; +import com.fr.base.svg.IconUtils; import com.fr.design.DesignerEnvManager; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.KeyWords; import com.fr.design.constants.UIConstants; +import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.gui.autocomplete.AutoCompletion; import com.fr.design.gui.autocomplete.BasicCompletion; import com.fr.design.gui.autocomplete.CompletionProvider; @@ -14,32 +17,147 @@ import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.i18n.Toolkit; import com.fr.design.javascript.beautify.JavaScriptFormatHelper; +import com.fr.design.javascript.jsapi.JSImplPopulateAction; +import com.fr.design.javascript.jsapi.JSImplUpdateAction; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; import com.fr.general.IOUtils; +import com.fr.js.JavaScriptImpl; -import javax.swing.*; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FontMetrics; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.SwingConstants; +import javax.swing.SwingWorker; public class JSContentPane extends BasicPane { - private RSyntaxTextArea contentTextArea; - private UILabel funNameLabel; + protected RSyntaxTextArea contentTextArea; + private UILabel funNameLabel = new UILabel(); private AutoCompletion ac; private static final Dimension FUNCTION_NAME_LABEL_SIZE = new Dimension(300, 80); - + private String[] defaultArgs; private int titleWidth = 180; + private JPanel labelPane = new JPanel(new BorderLayout(6, 4));; + private NewJavaScriptImplPane newJavaScriptImplPane = null; + private JavaScriptImpl javaScript; + private JSImplUpdateAction jsImplUpdateAction; + private JSImplPopulateAction jsImplPopulateAction; + private boolean modal; + BasicDialog advancedEditorDialog ; + public JSContentPane(){} public JSContentPane(String[] args) { + defaultArgs = args; this.setLayout(FRGUIPaneFactory.createBorderLayout()); - funNameLabel = new UILabel(); - this.setFunctionTitle(args); + initFunctionTitle(args); + + JPanel jsParaPane = createJSParaPane(); + addNewPaneLabel(); + this.add(jsParaPane, BorderLayout.NORTH); + + UIScrollPane sp = createContentTextAreaPanel(); + initContentTextAreaListener(); + this.add(sp, BorderLayout.CENTER); + + UILabel funNameLabel2 = new UILabel(); + funNameLabel2.setText("}"); + this.add(funNameLabel2, BorderLayout.SOUTH); + } + public JSContentPane(String[] args,boolean modal) { + this(args); + this.modal = modal; + } + + + public void setJsImplUpdateAction(JSImplUpdateAction jsImplUpdateAction){ + this.jsImplUpdateAction = jsImplUpdateAction; + } + + public void setJsImplPopulateAction(JSImplPopulateAction jsImplPopulateAction){ + this.jsImplPopulateAction = jsImplPopulateAction; + } + + public void updateJSImpl(JavaScriptImpl javaScript){ + this.javaScript = javaScript; + } + + + private void addNewPaneLabel(){ + UILabel advancedEditorLabel = new UILabel(Toolkit.i18nText("Fine-Design_Advanced_Editor"), IconUtils.readIcon("com/fr/design/images/edit/advancedEditor.svg"), SwingConstants.LEFT); + advancedEditorLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + advancedEditorLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if(newJavaScriptImplPane == null){ + newJavaScriptImplPane = new NewJavaScriptImplPane(defaultArgs); + } + jsImplUpdateAction.update(javaScript); + newJavaScriptImplPane.populate(javaScript); + if(advancedEditorDialog == null || !advancedEditorDialog.isVisible()) { + advancedEditorDialog = newJavaScriptImplPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + if (javaScript != null) { + newJavaScriptImplPane.updateBean(javaScript); + jsImplPopulateAction.populate(javaScript); + } + } + + @Override + public void doCancel() { + super.doCancel(); + } + },new Dimension(900,800)); + advancedEditorDialog.setModal(modal); + advancedEditorDialog.setResizable(true); + advancedEditorDialog.pack(); + advancedEditorDialog.setVisible(true); + } + advancedEditorDialog.requestFocus(); + } + }); + labelPane.add(advancedEditorLabel,BorderLayout.EAST); + } + + protected UIScrollPane createContentTextAreaPanel(){ + contentTextArea = new RSyntaxTextArea(); + contentTextArea.setCloseCurlyBraces(true); + contentTextArea.setLineWrap(true); + contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); + contentTextArea.setCodeFoldingEnabled(true); + contentTextArea.setAntiAliasingEnabled(true); + return new UIScrollPane(contentTextArea); + } + + private void initContentTextAreaListener(){ + contentTextArea.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + // 获得焦点时 安装 + installAutoCompletion(); + } + + @Override + public void focusLost(FocusEvent e) { + // 失去焦点时 卸载 + uninstallAutoCompletion(); + } + }); + } + + protected JPanel createJSParaPane(){ UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Format_JavaScript"), IOUtils.readIcon("com/fr/design/images/edit/format.png"), SwingConstants.LEFT); label.setCursor(new Cursor(Cursor.HAND_CURSOR)); label.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Format_JavaScript")); @@ -65,43 +183,20 @@ public class JSContentPane extends BasicPane { } }); - //REPORT-10533 用户参数多达25个,导致JS没地方写,增加滚动条显示 + labelPane.add(label,BorderLayout.CENTER); JPanel jsParaPane = new JPanel(new BorderLayout(4, 4)); jsParaPane.setPreferredSize(new Dimension(300, 80)); UIScrollPane scrollPane = new UIScrollPane(funNameLabel); scrollPane.setPreferredSize(FUNCTION_NAME_LABEL_SIZE); scrollPane.setBorder(new UIRoundedBorder(UIConstants.TITLED_BORDER_COLOR, 1, UIConstants.ARC)); jsParaPane.add(scrollPane, BorderLayout.WEST); - jsParaPane.add(label, BorderLayout.EAST); - this.add(jsParaPane, BorderLayout.NORTH); - - contentTextArea = new RSyntaxTextArea(); - contentTextArea.setCloseCurlyBraces(true); - contentTextArea.setLineWrap(true); - contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); - contentTextArea.setCodeFoldingEnabled(true); - contentTextArea.setAntiAliasingEnabled(true); - - UIScrollPane sp = new UIScrollPane(contentTextArea); - this.add(sp, BorderLayout.CENTER); - - contentTextArea.addFocusListener(new FocusListener() { - @Override - public void focusGained(FocusEvent e) { - // 获得焦点时 安装 - installAutoCompletion(); - } - - @Override - public void focusLost(FocusEvent e) { - // 失去焦点时 卸载 - uninstallAutoCompletion(); - } - }); + jsParaPane.add(labelPane, BorderLayout.EAST); + return jsParaPane; + } - UILabel funNameLabel2 = new UILabel(); - funNameLabel2.setText("}"); - this.add(funNameLabel2, BorderLayout.SOUTH); + protected void initFunctionTitle(String[] args){ + funNameLabel = new UILabel(); + this.setFunctionTitle(args); } private KeyStroke convert2KeyStroke(String ks) { diff --git a/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java b/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java new file mode 100644 index 000000000..8e8ef45b9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java @@ -0,0 +1,924 @@ +package com.fr.design.javascript; + +import com.fr.base.svg.IconUtils; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.autocomplete.AutoCompleteExtraRefreshComponent; +import com.fr.design.gui.autocomplete.BasicCompletion; +import com.fr.design.gui.autocomplete.CompletionCellRenderer; +import com.fr.design.gui.autocomplete.CompletionProvider; +import com.fr.design.gui.autocomplete.DefaultCompletionProvider; +import com.fr.design.gui.autocomplete.JSImplPaneAutoCompletion; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.gui.itextfield.PlaceholderTextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.javascript.jsapi.JSAPITreeHelper; +import com.fr.design.javascript.jsapi.JSAPIUserObject; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.CloudCenter; +import com.fr.general.ComparatorUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.json.JSONArray; +import com.fr.json.JSONException; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +public class JSContentWithDescriptionPane extends JSContentPane implements KeyListener { + + //搜索关键词输入框 + private PlaceholderTextField keyWordTextField = new PlaceholderTextField(16); + //搜索出的提示列表 + private JList tipsList; + private DefaultListModel tipsListModel = new DefaultListModel(); + + private JList interfaceNameList; + private DefaultListModel interfaceNameModel; + + private JTree moduleTree; + + private DefaultCompletionProvider completionProvider; + private JSImplPaneAutoCompletion autoCompletion; + + //函数说明文本框 + private UITextArea descriptionTextArea; + + private JPopupMenu popupMenu; + + private InterfaceAndDescriptionPanel interfaceAndDescriptionPanel; + private JList helpDOCList; + + private int ifHasBeenWriten = 0; + private int currentPosition = 0; + private int beginPosition = 0; + private int insertPosition = 0; + private static final String SEPARATOR = "_"; + + private static final int KEY_10 = 10; + //上下左右 + private static final int KEY_37 = 37; + private static final int KEY_38 = 38; + private static final int KEY_39 = 39; + private static final int KEY_40 = 40; + + private static final String URL_FOR_TEST_NETWORK = "https://www.baidu.com"; + + private static final String DOCUMENT_SEARCH_URL = "https://help.fanruan.com/finereport/api-helpdoc-title-"; + + private String currentValue; + + private static CardLayout card; + + private static final String RELOAD_CARD = "reloadCard"; + private static final String DOC_LIST_CARD = "docListCard"; + + public JSContentWithDescriptionPane(String[] args) { + this.setLayout(new BorderLayout()); + //=============================== + this.initFunctionTitle(args); + JPanel jsParaAndSearchPane = new JPanel(new BorderLayout()); + + //js函数声明面板 + JPanel jsParaPane = createJSParaPane(); + + jsParaPane.setPreferredSize(new Dimension(650, 80)); + //右上角的搜索提示面板 + JPanel tipsPane = createTipsPane(); + + jsParaAndSearchPane.add(jsParaPane, BorderLayout.CENTER); + jsParaAndSearchPane.add(tipsPane, BorderLayout.EAST); + + initPopTips(); + + //js文本编辑面板 + UIScrollPane contentTextAreaPanel = createContentTextAreaPanel(); + initContextAreaListener(); + + contentTextAreaPanel.setPreferredSize(new Dimension(850, 250)); + //js函数结束标签 + UILabel endBracketsLabel = new UILabel(); + endBracketsLabel.setText("}"); + + //结尾括号和复用函数按钮面板 + JPanel endBracketsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + endBracketsPanel.add(endBracketsLabel, BorderLayout.WEST); + + JPanel northPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + northPanel.add(jsParaAndSearchPane, BorderLayout.NORTH); + + northPanel.add(contentTextAreaPanel, BorderLayout.CENTER); + northPanel.add(endBracketsPanel, BorderLayout.SOUTH); + + //主编辑框,也就是面板的正中间部分 + this.add(northPanel, BorderLayout.CENTER); + + //函数分类和函数说明面板================================== + JPanel functionNameAndDescriptionPanel = createInterfaceAndDescriptionPanel(); + functionNameAndDescriptionPanel.setPreferredSize(new Dimension(880, 220)); + + this.add(functionNameAndDescriptionPanel, BorderLayout.SOUTH); + } + + public void populate(String js) { + contentTextArea.setText(js); + ifHasBeenWriten = 1; + currentPosition = contentTextArea.getCaretPosition(); + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + } + + private void initContextAreaListener() { + contentTextArea.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + if ((e.getKeyChar() >= 'A' && e.getKeyChar() <= 'z') || e.getKeyChar() == '_') { + if (autoCompletion != null) { + autoCompletion.doCompletion(); + } + } + } + + @Override + public void keyReleased(KeyEvent e) { + contentTextArea.setForeground(Color.black); + } + }); + contentTextArea.addKeyListener(this); + contentTextArea.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (autoCompletion == null) { + installAutoCompletion(); + } + } + + @Override + public void focusLost(FocusEvent e) { + uninstallAutoCompletion(); + } + }); + contentTextArea.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + insertPosition = contentTextArea.getCaretPosition(); + if (ifHasBeenWriten == 0) { + contentTextArea.setText(StringUtils.EMPTY); + ifHasBeenWriten = 1; + contentTextArea.setForeground(Color.black); + insertPosition = 0; + } + } + + @Override + public void mouseReleased(MouseEvent e) { + currentPosition = contentTextArea.getCaretPosition(); + if (currentPosition == insertPosition) { + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + } + } + }); + } + + @Override + public void keyTyped(KeyEvent e) { + + } + + @Override + public void keyPressed(KeyEvent e) { + if (ifHasBeenWriten == 0) { + this.contentTextArea.setText(StringUtils.EMPTY); + } + } + + @Override + public void keyReleased(KeyEvent e) { + int key = e.getKeyCode(); + if (key == KEY_38 || key == KEY_40 || key == KEY_37 || key == KEY_39 || key == KEY_10) //如果是删除符号 ,为了可读性 没有和其他按键的程序相融合 + { + currentPosition = contentTextArea.getCaretPosition(); + insertPosition = currentPosition; + beginPosition = getBeginPosition(); + } else { + if (contentTextArea.getText().trim().length() == 0) { + insertPosition = 0; + } else { + contentTextArea.setForeground(Color.black); + currentPosition = contentTextArea.getCaretPosition(); + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + ifHasBeenWriten = 1; + } + } + } + + private int getBeginPosition() { + int i = currentPosition; + String textArea = contentTextArea.getText(); + for (; i > 0; i--) { + String tested = textArea.substring(i - 1, i).toUpperCase(); + char[] testedChar = tested.toCharArray(); + if (isChar(testedChar[0]) || isNum(testedChar[0])) { + continue; + } else { + break; + } + } + return i; + } + + private static boolean isNum(char tested) { + return tested >= '0' && tested <= '9'; + } + + private boolean isChar(char tested) { + return tested >= 'A' && tested <= 'Z' || tested >= 'a' && tested < 'z'; + } + + public class InterfaceAndDescriptionPanel extends JPanel implements AutoCompleteExtraRefreshComponent { + @Override + public void refresh(String replacementText) { + fixInterfaceNameList(replacementText); + } + } + + private void fixInterfaceNameList(String interfaceName) { + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) moduleTree.getModel(); + TreeNode root = (TreeNode) defaultTreeModel.getRoot(); + String directCategory = JSAPITreeHelper.getDirectCategory(interfaceName); + if (directCategory == null) { + return; + } + setModuleTreeSelection(root, directCategory, defaultTreeModel); + interfaceNameModel = (DefaultListModel) interfaceNameList.getModel(); + interfaceNameModel.clear(); + List interfaceNames = JSAPITreeHelper.getNames(directCategory); + int index = 0; + for (int i = 0; i < interfaceNames.size(); i++) { + interfaceNameModel.addElement(interfaceNames.get(i)); + if (StringUtils.equals(interfaceNames.get(i), interfaceName)) { + index = i; + } + } + interfaceNameList.setSelectedIndex(index); + interfaceNameList.ensureIndexIsVisible(index); + } + + private boolean setModuleTreeSelection(TreeNode node, String directCategory, DefaultTreeModel treeModel) { + + DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) node; + Object userObject = defaultMutableTreeNode.getUserObject(); + if (userObject instanceof JSAPIUserObject) { + String value = ((JSAPIUserObject) userObject).getValue(); + if (StringUtils.equals(value, directCategory)) { + moduleTree.setSelectionPath(new TreePath(treeModel.getPathToRoot(node))); + moduleTree.scrollPathToVisible(moduleTree.getSelectionPath()); + return true; + } + } + for (int i = 0; i < node.getChildCount(); i++) { + if (setModuleTreeSelection(node.getChildAt(i), directCategory, treeModel)) { + return true; + } + } + return false; + } + + private JPanel createInterfaceAndDescriptionPanel() { + interfaceAndDescriptionPanel = new InterfaceAndDescriptionPanel(); + interfaceAndDescriptionPanel.setLayout(new BorderLayout(4, 4)); + JPanel interfacePanel = new JPanel(new BorderLayout(4, 4)); + interfaceAndDescriptionPanel.add(interfacePanel, BorderLayout.WEST); + JPanel descriptionAndDocumentPanel = new JPanel(new BorderLayout(4, 4)); + //函数说明和帮助文档框 + initDescriptionArea(descriptionAndDocumentPanel); + + //模块和接口面板 + initInterfaceModuleTree(interfacePanel); + initInterfaceNameList(interfacePanel); + + initHelpDocumentPane(descriptionAndDocumentPanel); + + interfaceAndDescriptionPanel.add(descriptionAndDocumentPanel, BorderLayout.CENTER); + return interfaceAndDescriptionPanel; + } + + private void doHelpDocumentSearch() { + Object value = interfaceNameList.getSelectedValue(); + if (value != null) { + String url = CloudCenter.getInstance().acquireUrlByKind("af.doc_search", DOCUMENT_SEARCH_URL) + value.toString(); + try { + String result = HttpToolbox.get(url); + JSONObject jsonObject = new JSONObject(result); + JSONArray jsonArray = jsonObject.optJSONArray("list"); + if (jsonArray != null) { + DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel(); + helpDOCModel.clear(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject resultJSONObject = jsonArray.optJSONObject(i); + String docURL = resultJSONObject.optString("url"); + String name = resultJSONObject.optString("title").trim(); + HelpDocument helpDocument = new HelpDocument(docURL, name); + helpDOCModel.addElement(helpDocument); + } + } + } catch (JSONException e) { + FineLoggerFactory.getLogger().debug(e.getMessage(), e); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + private void initHelpDocumentPane(JPanel descriptionAndDocumentPanel) { + card = new CardLayout(); + JPanel mainPane = new JPanel(card); + initHelpDocumentList(); + UIScrollPane helpDOCScrollPane = new UIScrollPane(helpDOCList); + helpDOCScrollPane.setPreferredSize(new Dimension(200, 200)); + helpDOCScrollPane.setBorder(null); + mainPane.add(helpDOCScrollPane, DOC_LIST_CARD); + + UILabel imageLabel = new UILabel(); + imageLabel.setIcon(IconUtils.readIcon("com/fr/design/javascript/jsapi/images/connectFailed.svg")); + imageLabel.setPreferredSize(new Dimension(180, 65)); + JPanel imagePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + imagePane.setBorder(BorderFactory.createEmptyBorder(0, 42, 0, 0)); + imagePane.add(imageLabel); + imagePane.setBackground(Color.WHITE); + + UILabel failedLabel = new UILabel(Toolkit.i18nText("Fine-Design_Net_Connect_Failed"), 0); + failedLabel.setPreferredSize(new Dimension(180, 20)); + UILabel reloadLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Reload"), 0); + reloadLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + reloadLabel.setPreferredSize(new Dimension(180, 20)); + reloadLabel.setForeground(Color.blue); + JPanel labelPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, 0, 0, 0); + + labelPane.setBorder(BorderFactory.createEmptyBorder(35, 45, 0, 0)); + labelPane.setBackground(Color.WHITE); + labelPane.add(imagePane); + labelPane.add(failedLabel); + labelPane.add(reloadLabel); + JPanel containerPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + containerPanel.add(labelPane, BorderLayout.CENTER); + reloadLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (isNetworkOk()) { + doHelpDocumentSearch(); + card.show(mainPane, DOC_LIST_CARD); + } + } + }); + mainPane.add(containerPanel, RELOAD_CARD); + if (isNetworkOk()) { + doHelpDocumentSearch(); + card.show(mainPane, DOC_LIST_CARD); + } else { + card.show(mainPane, RELOAD_CARD); + } + descriptionAndDocumentPanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Relevant_Cases"), mainPane), BorderLayout.EAST); + } + + private void initHelpDocumentList() { + helpDOCList = new JList(new DefaultListModel()); + initHelpDOCListRender(); + initHelpDOCListListener(); + } + + private void initHelpDOCListListener() { + helpDOCList.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + Object value = helpDOCList.getSelectedValue(); + if (value instanceof HelpDocument) { + String url = ((HelpDocument) value).getDocumentUrl(); + browse(url); + } + } + } + }); + } + + private void browse(String url){ + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + } + + private void initHelpDOCListRender() { + helpDOCList.setCellRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof HelpDocument) { + this.setText(((HelpDocument) value).getName()); + this.setForeground(Color.BLUE); + } + return this; + } + }); + } + + private static boolean isNetworkOk() { + try { + HttpToolbox.get(URL_FOR_TEST_NETWORK); + return true; + } catch (Exception ignore) { + // 网络异常 + return false; + } + } + + private static class HelpDocument { + private String documentUrl; + + + private String name; + + public HelpDocument(String documentUrl, String name) { + this.documentUrl = documentUrl; + this.name = name; + } + + public String getDocumentUrl() { + return documentUrl; + } + + public String getName() { + return name; + } + } + + private void initDescriptionArea(JPanel descriptionPanel) { + descriptionTextArea = new UITextArea(); + UIScrollPane descriptionScrollPane = new UIScrollPane(descriptionTextArea); + descriptionScrollPane.setPreferredSize(new Dimension(300, 200)); + descriptionPanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Interface_Description"), descriptionScrollPane), BorderLayout.CENTER); + descriptionTextArea.setBackground(Color.white); + descriptionTextArea.setLineWrap(true); + descriptionTextArea.setWrapStyleWord(true); + descriptionTextArea.setEditable(false); + } + + private void installAutoCompletion() { + CompletionProvider provider = createCompletionProvider(); + autoCompletion = new JSImplPaneAutoCompletion(provider); + autoCompletion.setListCellRenderer(new CompletionCellRenderer()); + autoCompletion.install(contentTextArea); + autoCompletion.installExtraRefreshComponent(interfaceAndDescriptionPanel); + } + + private void uninstallAutoCompletion() { + if (autoCompletion != null) { + autoCompletion.uninstall(); + autoCompletion = null; + } + } + + private CompletionProvider createCompletionProvider() { + if (completionProvider == null) { + completionProvider = new DefaultCompletionProvider(); + for (String name : JSAPITreeHelper.getAllNames()) { + completionProvider.addCompletion(new BasicCompletion(completionProvider, name)); + } + } + return completionProvider; + } + + private void initInterfaceModuleTree(JPanel interfacePanel) { + moduleTree = new JTree(); + UIScrollPane moduleTreePane = new UIScrollPane(moduleTree); + moduleTreePane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + interfacePanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Module"), moduleTreePane), BorderLayout.WEST); + moduleTreePane.setPreferredSize(new Dimension(180, 200)); + + moduleTree.setRootVisible(false); + moduleTree.setShowsRootHandles(true); + moduleTree.setCellRenderer(moduleTreeCellRender); + DefaultTreeModel moduleTreeModel = (DefaultTreeModel) moduleTree.getModel(); + DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) moduleTreeModel.getRoot(); + rootNode.removeAllChildren(); + + JSAPITreeHelper.createJSAPITree(rootNode); + moduleTreeModel.reload(); + + initModuleTreeSelectionListener(); + } + + private void initModuleTreeSelectionListener() { + moduleTree.addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) moduleTree.getLastSelectedPathComponent(); + Object selectedValue = selectedTreeNode.getUserObject(); + if (null == selectedValue) { + return; + } + if (selectedValue instanceof JSAPIUserObject) { + interfaceNameModel = (DefaultListModel) interfaceNameList.getModel(); + interfaceNameModel.clear(); + String text = ((JSAPIUserObject) selectedValue).getValue(); + List allInterfaceNames = JSAPITreeHelper.getNames(text); + for (String interfaceName : allInterfaceNames) { + interfaceNameModel.addElement(interfaceName); + } + if (interfaceNameModel.size() > 0) { + interfaceNameList.setSelectedIndex(0); + setDescription(interfaceNameList.getSelectedValue().toString()); + interfaceNameList.ensureIndexIsVisible(0); + } + } + } + }); + } + + + private DefaultTreeCellRenderer moduleTreeCellRender = new DefaultTreeCellRenderer() { + public Component getTreeCellRendererComponent(JTree tree, + Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, + expanded, leaf, row, hasFocus); + + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; + Object userObj = treeNode.getUserObject(); + if (userObj instanceof JSAPIUserObject) { + this.setText(((JSAPIUserObject) userObj).getDisplayText()); + this.setIcon(null); + } + return this; + } + + }; + + + private void initInterfaceNameList(JPanel interfacePanel) { + interfaceNameList = new JList(new DefaultListModel()); + UIScrollPane interfaceNamePanelScrollPane = new UIScrollPane(interfaceNameList); + interfaceNamePanelScrollPane.setPreferredSize(new Dimension(180, 200)); + interfacePanel.add( + this.createNamePane(Toolkit.i18nText("Fine-Design_Interface") + ":", interfaceNamePanelScrollPane), + BorderLayout.CENTER); + + interfaceNamePanelScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + initInterfaceNameModule(); + initInterfaceNameListSelectionListener(); + initInterfaceNameListMouseListener(); + } + + private void initInterfaceNameModule() { + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) moduleTree.getModel(); + TreeNode root = (TreeNode) defaultTreeModel.getRoot(); + while (root.getChildCount() > 0){ + root = root.getChildAt(0); + } + moduleTree.setSelectionPath(new TreePath(defaultTreeModel.getPathToRoot(root))); + } + + private void setDescription(String interfaceName) { + StringBuilder il8Key = new StringBuilder(); + moduleTree.getSelectionPath().getPath(); + Object obj = moduleTree.getSelectionPath().getPath()[moduleTree.getSelectionPath().getPath().length - 1]; + Object userObject = ((DefaultMutableTreeNode) obj).getUserObject(); + if (userObject instanceof JSAPIUserObject) { + il8Key.append(JSAPITreeHelper.getDirectCategory(interfaceName)); + } + interfaceName = interfaceName.toUpperCase(); + if (!interfaceName.startsWith(SEPARATOR)) { + interfaceName = SEPARATOR + interfaceName; + } + il8Key.append(interfaceName); + descriptionTextArea.setText(Toolkit.i18nText(il8Key.toString())); + descriptionTextArea.moveCaretPosition(0); + } + + private void initInterfaceNameListSelectionListener() { + interfaceNameList.addListSelectionListener(new ListSelectionListener() { + + public void valueChanged(ListSelectionEvent evt) { + Object selectedValue = interfaceNameList.getSelectedValue(); + if (selectedValue == null) { + return; + } + String interfaceName = selectedValue.toString(); + if (!StringUtils.equals(interfaceName, currentValue)) { + setDescription(interfaceName); + doHelpDocumentSearch(); + currentValue = interfaceName; + } + + } + }); + } + + + private void initInterfaceNameListMouseListener() { + interfaceNameList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + if (evt.getClickCount() >= 2) { + Object selectedValue = interfaceNameList.getSelectedValue(); + String interfaceName = selectedValue.toString(); + applyText(interfaceName); + } + } + }); + } + + private void applyText(String text) { + if (text == null || text.length() <= 0) { + return; + } + if (ifHasBeenWriten == 0) { + contentTextArea.setForeground(Color.black); + contentTextArea.setText(StringUtils.EMPTY); + ifHasBeenWriten = 1; + insertPosition = 0; + } + String textAll = contentTextArea.getText(); + currentPosition = contentTextArea.getCaretPosition(); + int insert = 0; + int current = 0; + if (insertPosition <= currentPosition) { + insert = insertPosition; + current = currentPosition; + } else { + insert = currentPosition; + current = insertPosition; + } + String beforeIndexOfInsertString = textAll.substring(0, insert); + String afterIndexofInsertString = textAll.substring(current); + contentTextArea.setText(beforeIndexOfInsertString + text + afterIndexofInsertString); + contentTextArea.getText(); + contentTextArea.requestFocus(); + insertPosition = contentTextArea.getCaretPosition(); + } + + private JPanel createNamePane(String name, JComponent comp) { + JPanel namePane = new JPanel(new BorderLayout(4, 4)); + namePane.add(new UILabel(name), BorderLayout.NORTH); + namePane.add(comp, BorderLayout.CENTER); + return namePane; + } + + private JPanel createTipsPane() { + JPanel tipsPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + tipsPane.setLayout(new BorderLayout(4, 4)); + tipsPane.setBorder(BorderFactory.createEmptyBorder(30, 2, 0, 0)); + JPanel searchPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + searchPane.setLayout(new BorderLayout(4, 4)); + keyWordTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Search_Interface")); + searchPane.add(keyWordTextField, BorderLayout.CENTER); + + //搜索按钮 + UIButton searchButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Search")); + searchButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String toFind = keyWordTextField.getText(); + search(toFind); + popTips(); + tipsList.requestFocusInWindow(); + } + }); + + keyWordTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + e.consume(); + String toFind = keyWordTextField.getText(); + search(toFind); + popTips(); + tipsList.requestFocusInWindow(); + } + } + }); + + searchPane.add(searchButton, BorderLayout.EAST); + tipsPane.add(searchPane, BorderLayout.NORTH); + + tipsList = new JList(tipsListModel); + tipsList.addMouseListener(tipsListMouseListener); + tipsList.addListSelectionListener(tipsListSelectionListener); + tipsList.addKeyListener(tipListKeyListener); + + return tipsPane; + } + + private void search(String key) { + tipsListModel.removeAllElements(); + tipsListModel.clear(); + key = key.replaceAll(StringUtils.BLANK, StringUtils.EMPTY); + ArrayList list = new ArrayList<>(); + if (!StringUtils.isEmpty(key)) { + List allNames = JSAPITreeHelper.getAllNames(); + for (String name : allNames) { + if (searchResult(key, name)) { + list.add(name); + } + } + String finalKey = key; + Collections.sort(list, new Comparator() { + @Override + public int compare(String o1, String o2) { + int result; + boolean o1StartWidth = o1.toLowerCase().startsWith(finalKey.toLowerCase()); + boolean o2StartWidth = o2.toLowerCase().startsWith(finalKey.toLowerCase()); + if (o1StartWidth) { + result = o2StartWidth ? o1.compareTo(o2) : -1; + } else { + result = o2StartWidth ? 1 : o1.compareTo(o2); + } + return result; + } + }); + for (String name : list) { + tipsListModel.addElement(name); + } + if (!tipsListModel.isEmpty()) { + tipsList.setSelectedIndex(0); + } + } + } + + private boolean searchResult(String key, String interfaceName) { + if (StringUtils.isBlank(key) || StringUtils.isBlank(interfaceName)) { + return false; + } + int length = key.length(); + String temp = interfaceName.toUpperCase(); + for (int i = 0; i < length; i++) { + String check = key.substring(i, i + 1); + int index = temp.indexOf(check.toUpperCase()); + if (index == -1) { + return false; + } else { + temp = temp.substring(index + 1); + } + } + return true; + } + + private void initPopTips() { + popupMenu = new JPopupMenu(); + JScrollPane tipsScrollPane = new JScrollPane(tipsList); + popupMenu.add(tipsScrollPane); + tipsScrollPane.setPreferredSize(new Dimension(220, 146)); + tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + } + + private void popTips() { + popupMenu.show(keyWordTextField, 0, 23); + } + + private ListSelectionListener tipsListSelectionListener = new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + Object selectValue = tipsList.getSelectedValue(); + if (selectValue == null) { + return; + } + String interfaceName = selectValue.toString(); + fixInterfaceNameList(interfaceName); + } + }; + + private KeyListener tipListKeyListener = new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + Object selectValue = tipsList.getSelectedValue(); + if (selectValue == null) { + return; + } + tipListValueSelectAction(selectValue.toString()); + if (popupMenu != null) { + popupMenu.setVisible(false); + } + contentTextArea.requestFocusInWindow(); + } + } + }; + + private void tipListValueSelectAction(String value) { + if (ifHasBeenWriten == 0) { + contentTextArea.setForeground(Color.black); + contentTextArea.setText(StringUtils.EMPTY); + } + contentTextArea.setForeground(Color.black); + currentPosition = contentTextArea.getCaretPosition(); + String output = value; + String textAll = contentTextArea.getText(); + String textReplaced; + int position = 0; + if (insertPosition <= currentPosition) { + textReplaced = textAll.substring(0, insertPosition) + output + textAll.substring(currentPosition); + position = insertPosition + output.length(); + } else { + textReplaced = textAll.substring(0, currentPosition) + output + textAll.substring(insertPosition); + position = currentPosition + output.length(); + } + contentTextArea.setText(textReplaced); + contentTextArea.setCaretPosition(position); + insertPosition = position; + ifHasBeenWriten = 1; + tipsListModel.removeAllElements(); + } + + private MouseListener tipsListMouseListener = new MouseAdapter() { + String singlePressContent; + + String doublePressContent; + + @Override + public void mousePressed(MouseEvent e) { + int index = tipsList.getSelectedIndex(); + if (index != -1) { + if (e.getClickCount() == 1) { + singlePressContent = (String) tipsListModel.getElementAt(index); + } else if (e.getClickCount() == 2) { + doublePressContent = (String) tipsListModel.getElementAt(index); + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + int index = tipsList.getSelectedIndex(); + if (index != -1) { + if (e.getClickCount() == 1) { + if (ComparatorUtils.equals((String) tipsListModel.getElementAt(index), singlePressContent)) { + singleClickActuator(singlePressContent); + } + } else if (e.getClickCount() == 2) { + if (ComparatorUtils.equals((String) tipsListModel.getElementAt(index), doublePressContent)) { + doubleClickActuator(doublePressContent); + } + if (popupMenu != null) { + popupMenu.setVisible(false); + } + } + } + } + + private void singleClickActuator(String currentLineContent) { + setDescription(currentLineContent); + fixInterfaceNameList(currentLineContent); + } + + private void doubleClickActuator(String currentLineContent) { + tipListValueSelectAction(currentLineContent); + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/JavaScriptImplPane.java b/designer-base/src/main/java/com/fr/design/javascript/JavaScriptImplPane.java index 158c05d1e..6a83ad3d2 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/JavaScriptImplPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/JavaScriptImplPane.java @@ -9,6 +9,8 @@ import com.fr.design.gui.itableeditorpane.UITableEditAction; import com.fr.design.gui.itableeditorpane.UITableEditorPane; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.hyperlink.AbstractHyperLinkPane; +import com.fr.design.javascript.jsapi.JSImplPopulateAction; +import com.fr.design.javascript.jsapi.JSImplUpdateAction; import com.fr.design.mainframe.DesignerContext; import com.fr.design.scrollruler.ModLineBorder; import com.fr.design.utils.gui.GUICoreUtils; @@ -17,10 +19,16 @@ import com.fr.js.JavaScriptImpl; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; -import javax.swing.*; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridLayout; +import javax.swing.BorderFactory; +import javax.swing.JPanel; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; -import java.awt.*; + import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -28,11 +36,11 @@ import java.util.List; public class JavaScriptImplPane extends AbstractHyperLinkPane { private static final int BOTTOM_BORDER = 12; private UITextField itemNameTextField; - private JSContentPane jsPane; + protected JSContentPane jsPane; private UITableEditorPane importedJsPane; private ReportletParameterViewPane parameterPane; private String[] defaultArgs; - + private boolean modal; public JavaScriptImplPane() { this(new String[0]); @@ -50,8 +58,57 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane { initComponents(); } + public JavaScriptImplPane(String[] args, boolean modal) { + this.modal = modal; + this.defaultArgs = args; + initComponents(); + } + protected void initComponents() { - parameterPane = new ReportletParameterViewPane(getChartParaType(), getValueEditorPane(), getValueEditorPane()); + parameterPane = createParameterViewPane(); + importedJsPane = createImportedJsPane(); + importedJsPane.setPreferredSize(new Dimension(265, 150)); + + jsPane = createJSContentPane(defaultArgs); + jsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_JavaScript"))); + + parameterPane.setPreferredSize(new Dimension(265, 150)); + JPanel topPane = new JPanel(new GridLayout(1,2)); + topPane.add(importedJsPane); + topPane.add(parameterPane); + + topPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM_BORDER, 0)); + + this.setLayout(new BorderLayout()); + this.add(topPane, BorderLayout.NORTH); + this.add(jsPane, BorderLayout.CENTER); + + this.reLayoutForChart(); + } + + protected JSContentPane createJSContentPane(String[] defaultArgs){ + JSContentPane jsContentPane= new JSContentPane(defaultArgs,modal); + jsContentPane.setJsImplUpdateAction(new JSImplUpdateAction() { + @Override + public void update(JavaScriptImpl javaScript) { + if(javaScript != null){ + updateBean(javaScript); + } + } + }); + jsContentPane.setJsImplPopulateAction(new JSImplPopulateAction() { + @Override + public void populate(JavaScriptImpl javaScript) { + if(javaScript != null){ + populateBean(javaScript); + } + } + }); + return jsContentPane; + } + + protected ReportletParameterViewPane createParameterViewPane(){ + ReportletParameterViewPane parameterPane = new ReportletParameterViewPane(getChartParaType(), getValueEditorPane(), getValueEditorPane()); parameterPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Parameter"))); parameterPane.addTableEditorListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { @@ -72,7 +129,10 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane { parameterChanger(list); } }); + return parameterPane; + } + protected UITableEditorPane createImportedJsPane(){ OneListTableModel model = new OneListTableModel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_ReportServerP_Import_JavaScript"), this) { public UITableEditAction[] createAction() { @@ -84,26 +144,12 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane { return new AddJsAction(); } }; - importedJsPane = new UITableEditorPane(model); + UITableEditorPane importedJsPane = new UITableEditorPane(model); importedJsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_ReportServerP_Import_JavaScript"))); - importedJsPane.setPreferredSize(new Dimension(265, 150)); - jsPane = new JSContentPane(defaultArgs); - jsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_JavaScript"))); + return importedJsPane; + } - parameterPane.setPreferredSize(new Dimension(265, 150)); - JPanel topPane = GUICoreUtils.createBorderLayoutPane( - importedJsPane, BorderLayout.CENTER, - parameterPane, BorderLayout.EAST - ); - topPane.setPreferredSize(new Dimension(300, 150)); - topPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM_BORDER, 0)); - this.setLayout(new BorderLayout()); - this.add(topPane, BorderLayout.NORTH); - this.add(jsPane, BorderLayout.CENTER); - - this.reLayoutForChart(); - } /** * 参数改变 @@ -140,10 +186,10 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane { if (javaScriptImpl == null) { javaScriptImpl = new JavaScriptImpl(); jsPane.reset(); - }else{ + } else { jsPane.populate(javaScriptImpl.getContent()); } - + jsPane.updateJSImpl(javaScriptImpl); int rowCount = javaScriptImpl.getJSImportSize(); String[] value = new String[rowCount]; for (int i = 0; i < rowCount; i++) { @@ -160,6 +206,7 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane { public JavaScriptImpl updateBean() { JavaScriptImpl javaScript = new JavaScriptImpl(); updateBean(javaScript); + jsPane.updateJSImpl(javaScript); return javaScript; } diff --git a/designer-base/src/main/java/com/fr/design/javascript/NewJavaScriptImplPane.java b/designer-base/src/main/java/com/fr/design/javascript/NewJavaScriptImplPane.java new file mode 100644 index 000000000..23226c6dd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/NewJavaScriptImplPane.java @@ -0,0 +1,23 @@ +package com.fr.design.javascript; + + +import com.fr.js.JavaScriptImpl; + + +public class NewJavaScriptImplPane extends JavaScriptImplPane { + public NewJavaScriptImplPane(String[] args) { + super(args); + } + + protected JSContentPane createJSContentPane(String[] defaultArgs){ + return new JSContentWithDescriptionPane(defaultArgs); + } + + public void populate(JavaScriptImpl javaScript) { + if (javaScript != null) { + populateBean(javaScript); + } else { + jsPane.reset(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/jsapi/CategoryTreeNodesUserObject.java b/designer-base/src/main/java/com/fr/design/javascript/jsapi/CategoryTreeNodesUserObject.java new file mode 100644 index 000000000..7b568eff7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/jsapi/CategoryTreeNodesUserObject.java @@ -0,0 +1,21 @@ +package com.fr.design.javascript.jsapi; + +import com.fr.design.i18n.Toolkit; + +public class CategoryTreeNodesUserObject implements JSAPIUserObject { + private String value; + + public CategoryTreeNodesUserObject(String value) { + this.value = value; + } + + @Override + public String getValue() { + return value; + } + + @Override + public String getDisplayText() { + return Toolkit.i18nText(value); + } +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPITreeHelper.java b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPITreeHelper.java new file mode 100644 index 000000000..a5def0596 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPITreeHelper.java @@ -0,0 +1,155 @@ +package com.fr.design.javascript.jsapi; + +import com.fr.general.IOUtils; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.swing.tree.DefaultMutableTreeNode; + +public class JSAPITreeHelper { + private static final String JSAPI_PATH = "com/fr/design/javascript/jsapi/jsapi.json"; + private static final String CATEGORY_PATH = "com/fr/design/javascript/jsapi/category.json"; + private static JSONObject categoryJSON ; + private static JSONObject jsapiJSON ; + + static { + jsapiJSON = createJSON(JSAPI_PATH); + categoryJSON = createJSON(CATEGORY_PATH); + } + + private static JSONObject createJSON(String path) { + StringBuilder jsonString = new StringBuilder(StringUtils.EMPTY); + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(IOUtils.readResource(path)))) { + String s; + while ((s = bufferedReader.readLine()) != null) { + jsonString.append(s); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return new JSONObject(jsonString.toString()); + } + + + public static void createJSAPITree(DefaultMutableTreeNode rootNode) { + createJSAPITree(categoryJSON, rootNode); + } + + public static String getDirectCategory(String name) { + if (jsapiJSON != null) { + Iterator it = jsapiJSON.keys(); + while (it.hasNext()) { + String key = it.next(); + JSONArray nameArray = jsapiJSON.optJSONArray(key); + for (int i = 0; i < nameArray.length(); i++) { + if (StringUtils.equals(nameArray.getString(i), name)) { + return key; + } + } + } + } + return null; + } + + private static void createJSAPITree(JSONObject jsonObject, DefaultMutableTreeNode rootNode) { + if (jsonObject != null && rootNode != null) { + Iterator it = jsonObject.keys(); + while (it.hasNext()) { + String key = it.next(); + JSONObject subNode = jsonObject.optJSONObject(key); + if (subNode.size() == 0) { + rootNode.add(new DefaultMutableTreeNode(new CategoryTreeNodesUserObject(key))); + } else { + DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(new CategoryTreeNodesUserObject(key)); + rootNode.add(treeNode); + createJSAPITree(subNode, treeNode); + } + } + } + } + + private static List getAllSubNodes(String name) { + return getAllSubNodes(name, categoryJSON); + } + + public static List getAllNames() { + ArrayList result = new ArrayList<>(); + if (jsapiJSON != null) { + Iterator it = jsapiJSON.keys(); + while (it.hasNext()) { + String key = it.next(); + JSONArray nameArray = jsapiJSON.optJSONArray(key); + for (int i = 0; i < nameArray.length(); i++) { + result.add(nameArray.getString(i)); + } + } + } + return result; + } + + public static List getNames(String category) { + ArrayList result = new ArrayList<>(); + List subCategories = getAllSubNodes(category); + if (jsapiJSON != null) { + for (String subCategory : subCategories) { + if (jsapiJSON.containsKey(subCategory)) { + JSONArray nameArray = jsapiJSON.optJSONArray(subCategory); + for (int i = 0; i < nameArray.length(); i++) { + result.add(nameArray.getString(i)); + } + } + } + } + return result; + } + + private static List getAllSubNodes(String name, JSONObject jsonObject) { + ArrayList result = new ArrayList<>(); + if (jsonObject != null) { + Iterator it = jsonObject.keys(); + while (it.hasNext()) { + String key = it.next(); + JSONObject subNode = jsonObject.optJSONObject(key); + if (subNode.size() == 0) { + if (StringUtils.equals(key, name)) { + result.add(key); + return result; + } + } else { + if (StringUtils.equals(key, name)) { + result.add(key); + result.addAll(getAllSubNodes(subNode)); + return result; + } else { + result.addAll(getAllSubNodes(name, subNode)); + } + } + } + } + return result; + } + + private static List getAllSubNodes(JSONObject jsonObject) { + ArrayList result = new ArrayList<>(); + if (jsonObject != null) { + Iterator it = jsonObject.keys(); + while (it.hasNext()) { + String key = it.next(); + JSONObject subNode = jsonObject.optJSONObject(key); + if (subNode.size() == 0) { + result.add(key); + } else { + result.add(key); + result.addAll(getAllSubNodes(subNode)); + } + } + } + return result; + } +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPIUserObject.java b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPIUserObject.java new file mode 100644 index 000000000..6790ec71e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPIUserObject.java @@ -0,0 +1,9 @@ +package com.fr.design.javascript.jsapi; + + +public interface JSAPIUserObject { + + String getValue(); + + String getDisplayText(); +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplPopulateAction.java b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplPopulateAction.java new file mode 100644 index 000000000..c33d7fe0e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplPopulateAction.java @@ -0,0 +1,7 @@ +package com.fr.design.javascript.jsapi; + +import com.fr.js.JavaScriptImpl; + +public interface JSImplPopulateAction { + void populate(JavaScriptImpl javaScript); +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplUpdateAction.java b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplUpdateAction.java new file mode 100644 index 000000000..b812d8b87 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplUpdateAction.java @@ -0,0 +1,7 @@ +package com.fr.design.javascript.jsapi; + +import com.fr.js.JavaScriptImpl; + +public interface JSImplUpdateAction { + void update(JavaScriptImpl javaScript); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java index be841f79a..2534de526 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java @@ -28,6 +28,8 @@ import com.fr.design.fun.impl.AbstractTemplateTreeShortCutProvider; import com.fr.design.gui.iprogressbar.ProgressDialog; import com.fr.design.gui.iscrollbar.UIScrollBar; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker; +import com.fr.design.mainframe.share.mini.MiniShopNativeTaskManager; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.mainframe.vcs.common.VcsHelper; @@ -157,6 +159,11 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta @Override public void windowClosing(WindowEvent e) { + // 检查mini商城是否存在未结束的后台任务 + if (!MiniShopDisposingChecker.check()) { + return; + } + // 关闭前check if (!TemplateSavingChecker.check()) { return; 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 f1a40ccdc..f37b817e9 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 @@ -2,6 +2,7 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; import com.fr.base.Parameter; +import com.fr.base.TRL; import com.fr.base.extension.FileExtension; import com.fr.base.io.BaseBook; import com.fr.base.iofile.attr.DesignBanCopyAttrMark; @@ -105,9 +106,9 @@ import javax.swing.JOptionPane; import javax.swing.SwingConstants; import javax.swing.undo.UndoManager; import java.awt.BorderLayout; -import java.io.ByteArrayOutputStream; import java.awt.Dimension; import java.awt.FontMetrics; +import java.io.ByteArrayOutputStream; import java.util.Set; import java.util.concurrent.Callable; @@ -1000,7 +1001,7 @@ public abstract class JTemplate> return true; } - public boolean isNewCreateTpl(){ + public boolean isNewCreateTpl() { return isNewCreateTpl; } @@ -1543,7 +1544,7 @@ public abstract class JTemplate> /** * 设置新引擎后,有不支持的功能时,设计器中模板的标题需要加上“兼容模式”或者“不支持分页引擎”来提示用户 - * */ + */ private String compatibilityTip() { if (!CptAndCptxCompatibilityUtil.isEngineXEnable(this.getTarget(), getEditingFILE().getPath())) { return StringUtils.EMPTY; @@ -1888,6 +1889,15 @@ public abstract class JTemplate> templateThemeButton.setToolTipText(name); } + /** + * 定位 + * + * @param trl + */ + public void navigate(TRL trl) { + + } + public void generateForBiddenTemplate() { } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/form/FormECDesignerProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/form/FormECDesignerProvider.java index 88a462307..2dc68704e 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/form/FormECDesignerProvider.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/form/FormECDesignerProvider.java @@ -1,10 +1,6 @@ package com.fr.design.mainframe.form; -import java.awt.Dimension; -import java.awt.image.BufferedImage; - -import javax.swing.JComponent; - +import com.fr.base.TRL; import com.fr.design.designer.TargetComponent; import com.fr.design.mainframe.JTemplate; import com.fr.design.menu.MenuDef; @@ -12,6 +8,10 @@ import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; import com.fr.form.FormElementCaseProvider; +import javax.swing.JComponent; +import java.awt.Dimension; +import java.awt.image.BufferedImage; + public interface FormECDesignerProvider { String XML_TAG = "FormElementCaseDesigner"; @@ -92,4 +92,6 @@ public interface FormECDesignerProvider { void refreshPropertyPane(); void removeSelection(); + + default void navigate(TRL trl) {} } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java index 1cb8e5d1a..621956ce6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java @@ -1,31 +1,46 @@ package com.fr.design.mainframe.loghandler; +import com.finebi.cbb.base.tuple.Pair; import com.fr.base.BaseUtils; +import com.fr.base.TRL; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; import com.fr.design.ui.util.UIUtil; +import com.fr.file.FILEFactory; import com.fr.general.ComparatorUtils; import com.fr.general.log.Log4jConfig; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; - +import com.fr.stable.project.ProjectConstants; import com.fr.third.apache.logging.log4j.Level; import com.fr.third.apache.logging.log4j.core.LogEvent; +import com.fr.third.guava.base.Splitter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; +import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JTextPane; import javax.swing.KeyStroke; +import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultEditorKit; import javax.swing.text.Document; +import javax.swing.text.Element; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; +import javax.swing.text.html.HTML; +import javax.swing.text.html.HTMLDocument; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -36,8 +51,14 @@ import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.io.IOException; import java.text.SimpleDateFormat; +import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Date; +import java.util.Deque; +import java.util.List; +import java.util.regex.Pattern; import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; @@ -61,6 +82,8 @@ public class DesignerLogHandler { private static final String ACTION_MAP_KEY = "clear"; + private static final Pattern pattern = Pattern.compile("\\([^(]*.(?>cpt|frm|cptx)[^)]*\\)"); + public static DesignerLogHandler getInstance() { return HOLDER.singleton; @@ -215,13 +238,61 @@ public class DesignerLogHandler { popup.show(jTextArea, event.getX(), event.getY()); checkEnabled(); } + if (event.getButton() == MouseEvent.BUTTON1) { + String url = findTplLinkFromMouseEvent(event); + if (StringUtils.isNotEmpty(url)) { + navigate(url); + } + } } }); } + /** + * 将模板定位链接导航到指定的位置 + * + * @param href 模板定位链接 + */ + private void navigate(String href) { + if (!href.startsWith(TRL.PREFIX)) { + return; + } + TRL trl = new TRL(href); + DesignerContext.getDesignerFrame().openTemplate(FILEFactory.createFILE(ProjectConstants.REPORTLETS_NAME + FILEFactory.SEPARATOR + trl.getTemplatePath())); + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (currentEditingTemplate != null) { + currentEditingTemplate.navigate(trl); + } + } + + /** + * 鼠标事件中定位到模板链接 + * + * @param event 鼠标事件 + * @return 模板链接 + */ + private String findTplLinkFromMouseEvent(MouseEvent event) { + JEditorPane editor = (JEditorPane) event.getSource(); + int pos = editor.getUI().viewToModel(editor, event.getPoint()); + if (pos >= 0 && editor.getDocument() instanceof HTMLDocument) { + HTMLDocument hdoc = (HTMLDocument) editor.getDocument(); + Element elem = hdoc.getCharacterElement(pos); + Object a = elem.getAttributes().getAttribute(HTML.Tag.A); + if (a instanceof AttributeSet) { + AttributeSet set = (AttributeSet) a; + String url = (String) set.getAttribute(HTML.Attribute.HREF); + if (StringUtils.isNotEmpty(url)) { + return url; + } + } + } + return StringUtils.EMPTY; + } + private JTextPane initLogJTextArea() { final JTextPane resultPane = new JTextPane(); + resultPane.setContentType("text/html"); InputMap inputMap = resultPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, DEFAULT_MODIFIER), DefaultEditorKit.copyAction); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, DEFAULT_MODIFIER), DefaultEditorKit.selectAllAction); @@ -294,6 +365,9 @@ public class DesignerLogHandler { SimpleAttributeSet attrSet = new SimpleAttributeSet(); if (style == DesignerLogger.ERROR_INT) { + if (renderLink(str)) { + return; + } StyleConstants.setForeground(attrSet, Color.RED); StyleConstants.setBold(attrSet, true); } else if (style == DesignerLogger.WARN_INT) { @@ -314,6 +388,86 @@ public class DesignerLogHandler { } } + /** + * 渲染模板链接 + * + * @param str 可能包含模板链接字符串 + * @return 是否处理成功 + */ + private boolean renderLink(String str) { + Document doc = jTextArea.getStyledDocument(); + if (doc instanceof HTMLDocument) { + String[] tplLink = findTplLink(str); + return tplLink != null + && tplLink.length > 0 + && link2Html(str, tplLink); + } + return false; + } + + /** + * 处理模板链接 + * + * @param s 含有模板链接 + * @param tplLink 模板链接 + * @return 是否处理成功 + */ + private boolean link2Html(String s, String[] tplLink) { + List lineSeg = splitLineSeg(s, tplLink); + String html = buildHtml(lineSeg, tplLink); + try { + Document doc = jTextArea.getStyledDocument(); + HTMLDocument htmlDocument = (HTMLDocument) doc; + htmlDocument.insertAfterEnd(htmlDocument.getCharacterElement(doc.getLength()), html); + } catch (BadLocationException | IOException ignored) { + // 这里出问题不记录日志否则会导致死循环 + return false; + } + return true; + } + + @NotNull + private String buildHtml(List lineSeg, String[] tplLink) { + StringBuilder sb = new StringBuilder(""); + for (int i = 0; i < tplLink.length; i++) { + sb.append("") + .append(lineSeg.get(i)) + .append("") + .append(tplLink[i]) + .append(""); + } + if (lineSeg.size() > tplLink.length) { + sb.append("").append(lineSeg.get(lineSeg.size() - 1)).append(""); + } + sb.append(""); + return sb.toString(); + } + + /** + * 将非公式部分切割为数组 + */ + @NotNull + private List splitLineSeg(String s, String[] tplLink) { + String seg = s.replaceAll("\\n", "
"); + List lineSeg = new ArrayList<>(2); + List lineSegTmp = new ArrayList<>(); + String tmp = seg; + for (String link : tplLink) { + lineSegTmp = Splitter.on(link).omitEmptyStrings().splitToList(tmp); + lineSeg.add(lineSegTmp.get(0)); + if (lineSegTmp.size() > 1) { + tmp = lineSegTmp.get(1); + } + } + if (lineSegTmp.size() > 1) { + lineSeg.add(lineSegTmp.get(1)); + } + return lineSeg; + } + + private String appendLocaleMark(String str, int style) { if (style == DesignerLogger.ERROR_INT) { @@ -375,4 +529,34 @@ public class DesignerLogHandler { }; } + + /** + * 尝试找到模板链接 + * + * @param s 可能含有模板链接的字符串 + * @return 模板链接 + */ + @Nullable + public static String[] findTplLink(String s) { + List list = new ArrayList<>(); + // 栈配对 + Deque> stack = new ArrayDeque<>(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '(') { + stack.push(new Pair<>(c, i)); + } else if (c == ')') { + Pair left = stack.peek(); + if (left != null && left.getFirst() == '(') { + Pair pop = stack.pop(); + String link = s.substring(pop.getSecond(), i + 1); + if (link.contains(ProjectConstants.CPT_SUFFIX) + || link.contains(ProjectConstants.FRM_SUFFIX)) { + list.add(link); + } + } + } + } + return list.toArray(new String[0]); + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/PatternStyle.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/PatternStyle.java deleted file mode 100644 index c4ebcf225..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/PatternStyle.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fr.design.mainframe.predefined; - -import com.fr.config.predefined.PredefinedStyle; -//import com.fr.predefined.PredefinedPatternStyleManager; - - -/** - * Created by kerry on 2020-08-31 - */ -public enum PatternStyle { - DARK_STYLE(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Dark_Pattern")) { - @Override - public PredefinedStyle getPredefinedStyle() { -// return PredefinedPatternStyleManager.INSTANCE.getDarkMode(); - return new PredefinedStyle(); - } - }, - LIGHT_STYLE(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Light_Pattern")) { - @Override - public PredefinedStyle getPredefinedStyle() { -// return PredefinedPatternStyleManager.INSTANCE.getLightMode(); - return new PredefinedStyle(); - } - }; - - - private String name; - - - PatternStyle(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } - - public abstract PredefinedStyle getPredefinedStyle(); - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java deleted file mode 100644 index 3508b3519..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.fr.design.mainframe.predefined.ui; - -import com.fr.base.BaseUtils; -import com.fr.base.GraphHelper; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.mainframe.predefined.ui.dialog.PredefinedStyleEditDialog; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.preview.PredefinedStylePreviewPane; -import com.fr.general.ComparatorUtils; -import com.fr.general.IOUtils; -import com.fr.stable.Constants; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -/** - * Created by kerry on 2020-08-25 - */ -public class PredefinedStyleBlock extends JPanel { - private PredefinedStyle previewObject; - private PredefinedStyleSelectPane parentPane; - private Icon markedMode = IOUtils.readIcon("/com/fr/design/form/images/marker_selected.png"); - private static final Color BORDER_COLOR = new Color(141, 194, 249); - - private boolean mouseOver = false; - - private MouseListener mouseListener = new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - setSelect(); - } - - @Override - public void mousePressed(MouseEvent e) { - - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { - mouseOver = true; - PredefinedStyleBlock.this.repaint(); - } - - @Override - public void mouseExited(MouseEvent e) { - mouseOver = false; - PredefinedStyleBlock.this.repaint(); - } - }; - - - public PredefinedStyleBlock(PredefinedStyle previewObject, PredefinedStyleSelectPane selectPane, boolean supportEdit) { - this.previewObject = previewObject; - this.parentPane = selectPane; - initPane(supportEdit); - this.addMouseListener(mouseListener); - } - - private void setSelect() { - this.parentPane.setSelectedPreviewPane(this); - } - - @Override - public void paint(Graphics g) { - super.paint(g); - boolean isSelected = ComparatorUtils.equals(this, this.parentPane.getSelectedPreviewPane()); - if (ComparatorUtils.equals(this.parentPane.getCurrentApplicateStyle(), this.previewObject.getStyleName())) { - markedMode.paintIcon(this, g, 176, 0); - } - if (isSelected || this.mouseOver) { - g.setColor(BORDER_COLOR); - Rectangle rectangle = new Rectangle(1, 1, this.getWidth() - 2, this.getHeight() - 2); - GraphHelper.draw(g, rectangle, Constants.LINE_MEDIUM); - } - } - - - private void initPane(boolean supportEdit) { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - PredefinedStylePreviewPane content = new PredefinedStylePreviewPane(0.387, 0.384); - content.setParent(this); - content.setPreferredSize(new Dimension(200, 180)); - UILabel label = new UILabel(previewObject.getStyleName()); - label.setToolTipText(previewObject.getStyleName()); - label.setPreferredSize(new Dimension(167, 25)); - - - JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - panel.setBorder(BorderFactory.createEmptyBorder(0,9,2,5)); - panel.add(label, BorderLayout.WEST); - if (supportEdit) { - addEditButton(panel); - } - - this.add(content, BorderLayout.CENTER); - this.add(panel, BorderLayout.SOUTH); - this.setPreferredSize(new Dimension(200, 210)); - panel.setBackground(Color.WHITE); - this.setBackground(Color.WHITE); - content.refresh(this.previewObject); - - } - - private void addEditButton(JPanel panel) { - UIButton editButton = new UIButton(BaseUtils.readIcon("/com/fr/design/icon/icon_edit.png")); - editButton.setPreferredSize(new Dimension(24, 24)); - editButton.setBorderPainted(false); - editButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - PredefinedStyleEditPane editPane = PredefinedStyleEditPane.createEditPane(parentPane); - PredefinedStyleEditDialog editDialog = new PredefinedStyleEditDialog( - SwingUtilities.getWindowAncestor(PredefinedStyleBlock.this), editPane, previewObject.isBuiltIn()); - editPane.populate(PredefinedStyleBlock.this.previewObject); - editDialog.setVisible(true); - } - }); - panel.add(editButton, BorderLayout.EAST); - - } - - public PredefinedStyle update() { - return this.previewObject; - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleEditPane.java deleted file mode 100644 index 33698d7c1..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleEditPane.java +++ /dev/null @@ -1,374 +0,0 @@ -package com.fr.design.mainframe.predefined.ui; - -import com.fr.base.ChartColorMatching; -import com.fr.base.ChartPreStyleConfig; -import com.fr.base.Style; -import com.fr.base.background.ColorBackground; -import com.fr.config.predefined.ColorFillStyle; -import com.fr.config.predefined.PredefinedCellStyle; -import com.fr.config.predefined.PredefinedCellStyleConfig; -import com.fr.config.predefined.PredefinedColorStyle; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.config.predefined.PredefinedStyleConfig; -import com.fr.config.ServerPreferenceConfig; -import com.fr.design.dialog.FineJOptionPane; -import com.fr.design.file.HistoryTemplateListCache; -import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; -import com.fr.design.gui.frpane.AttributeChangeListener; -import com.fr.design.gui.frpane.UITabbedPane; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itextfield.UITextField; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.detail.ChartStyleSettingPane; -import com.fr.design.mainframe.predefined.ui.detail.ColorFillStylePane; -import com.fr.design.mainframe.predefined.ui.detail.PredefinedBackgroundSettingPane; -import com.fr.design.mainframe.predefined.ui.detail.ComponentStyleSettingPane; -import com.fr.design.mainframe.predefined.ui.detail.CellStyleListControlPane; -import com.fr.design.mainframe.predefined.ui.preview.PredefinedStylePreviewPane; -import com.fr.design.ui.util.UIUtil; -import com.fr.design.utils.DesignUtils; -import com.fr.general.FRFont; -import com.fr.log.FineLoggerFactory; -import com.fr.stable.StringUtils; -import com.fr.transaction.Configurations; -import com.fr.transaction.WorkerFacade; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Created by kerry on 2020-08-26 - */ -public class PredefinedStyleEditPane extends AbstractAttrNoScrollPane { - private static final Color TIP_COLOR = Color.decode("#8F8F92"); - - private PredefinedStylePreviewPane previewPane; - private UITextField styleNameField; - private PredefinedBackgroundSettingPane backgroundSettingPane; - private CellStyleListControlPane cellStyleSettingPane; - private ComponentStyleSettingPane componentStyleSettingPane; - private ChartStyleSettingPane chartStyleSettingPane; - private PredefinedStyleSelectPane selectPane; - private ColorFillStylePane colorFillStylePane; - private boolean isPopulating = false; - private UITabbedPane uiTabbedPane; - - private boolean isLightMode = true; - - @Override - protected JPanel createContentPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - jPanel.add(createLeftPane(), BorderLayout.WEST); - jPanel.add(createRightPane(), BorderLayout.CENTER); - - this.addAttributeChangeListener(new AttributeChangeListener() { - @Override - public void attributeChange() { - if (!isPopulating) { - valueChangeAction(); - } - } - }); - return jPanel; - } - - public void valueChangeAction() { - boolean displayFormBackground = backgroundSettingPane.currentFormBackground() || uiTabbedPane.getSelectedIndex() == 3; - previewPane.refresh(this.update(), displayFormBackground); - } - - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Edit"); - } - - private PredefinedStyleEditPane(PredefinedStyleSelectPane selectPane, boolean newEditPane) { - this.selectPane = selectPane; - this.styleNameField.setEnabled(newEditPane); - } - - public static PredefinedStyleEditPane createEditPane(PredefinedStyleSelectPane selectPane) { - return new PredefinedStyleEditPane(selectPane, false); - } - - public static PredefinedStyleEditPane createNewEditPane(PredefinedStyleSelectPane selectPane) { - return new PredefinedStyleEditPane(selectPane, true); - } - - - private JPanel createLeftPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel titlePane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Overall_Preview")); - previewPane = new PredefinedStylePreviewPane(); - previewPane.setPreferredSize(new Dimension(517, 500)); - - titlePane.add(previewPane); - jPanel.add(titlePane, BorderLayout.CENTER); - return jPanel; - } - - private JPanel createRightPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel styleNamePane = createStyleNamePane(); - jPanel.add(styleNamePane, BorderLayout.NORTH); - - JPanel basicSettingPane = createBasicSettingPane(); - jPanel.add(basicSettingPane, BorderLayout.CENTER); - - JPanel customDetailPane = createCustomDetailPane(); - jPanel.add(customDetailPane, BorderLayout.SOUTH); - return jPanel; - } - - private JPanel createStyleNamePane() { - JPanel jPanel = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(5, 26, 8); - jPanel.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Name"))); - this.styleNameField = new UITextField(); - this.styleNameField.setPreferredSize(new Dimension(160, 20)); - jPanel.add(this.styleNameField); - return jPanel; - } - - private JPanel createBasicSettingPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel titlePane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Basic_Setting")); - JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - colorFillStylePane = new ColorFillStylePane(); - contentPane.add(colorFillStylePane); - titlePane.add(contentPane); - jPanel.add(titlePane, BorderLayout.CENTER); - titlePane.setSize(new Dimension(348, 157)); - return jPanel; - } - - private JPanel createCustomDetailPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel titlePane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Custom_Detail")); - titlePane.setLayout(FRGUIPaneFactory.createLeftZeroLayout()); - jPanel.add(titlePane, BorderLayout.CENTER); - uiTabbedPane = new UITabbedPane(); - uiTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Template_Background"), createTemplateBackgroundSettingPane()); - uiTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Cell_Style"), createCellStyleSettingPane()); - uiTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Chart_Style"), createChartStyleSettingPane()); - uiTabbedPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Component_Style"), createComponentStyleSettingPane()); - uiTabbedPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - valueChangeAction(); - } - }); - titlePane.add(uiTabbedPane); - uiTabbedPane.setPreferredSize(new Dimension(323, 298)); - titlePane.setPreferredSize(new Dimension(333, 320)); - return jPanel; - } - - - private JPanel createTemplateBackgroundSettingPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - jPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); - this.backgroundSettingPane = new PredefinedBackgroundSettingPane(); - jPanel.setPreferredSize(new Dimension(309, 248)); - UIScrollPane scrollPane = new UIScrollPane(this.backgroundSettingPane); - scrollPane.setBorder(BorderFactory.createEmptyBorder()); - jPanel.add(new UIScrollPane(this.backgroundSettingPane)); - return jPanel; - } - - private JPanel createCellStyleSettingPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - jPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5)); - this.cellStyleSettingPane = new CellStyleListControlPane(); - this.cellStyleSettingPane.registerAttrChangeListener(new AttributeChangeListener() { - @Override - public void attributeChange() { - valueChangeAction(); - } - }); - jPanel.add(this.cellStyleSettingPane); - return jPanel; - } - - - private JPanel createChartStyleSettingPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - jPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); - this.chartStyleSettingPane = new ChartStyleSettingPane(); - jPanel.add(this.chartStyleSettingPane); - return jPanel; - } - - - private JPanel createComponentStyleSettingPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - jPanel.setLayout(new BorderLayout(0, 5)); - jPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); - this.componentStyleSettingPane = new ComponentStyleSettingPane(); - UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_ComponentStyle_Setting_Tip")); - label.setForeground(TIP_COLOR); - jPanel.add(label, BorderLayout.NORTH); - jPanel.add(this.componentStyleSettingPane, BorderLayout.CENTER); - return jPanel; - } - - - public void populate(PredefinedStyle previewObject) { - isPopulating = true; - isLightMode = previewObject.isLightMode(); - styleNameField.setText(previewObject.getStyleName()); - this.backgroundSettingPane.populateBean(previewObject.getPredefinedBackground()); - this.cellStyleSettingPane.populateBean(previewObject.getCellStyleConfig()); - this.componentStyleSettingPane.populateBean(previewObject.getComponentStyle()); - this.colorFillStylePane.populateBean(previewObject.getPredefinedColorStyle()); - this.chartStyleSettingPane.populateBean(previewObject.getPredefinedChartStyle()); - previewPane.refresh(previewObject); - isPopulating = false; - } - - public PredefinedStyle update() { - PredefinedStyle predefinedStyle = new PredefinedStyle(); - predefinedStyle.setLightMode(isLightMode); - predefinedStyle.setStyleName(this.styleNameField.getText()); - PredefinedCellStyleConfig cellStyleConfig = this.cellStyleSettingPane.updateBean(); - predefinedStyle.setCellStyleConfig(cellStyleConfig); - - predefinedStyle.setPredefinedBackground(this.backgroundSettingPane.updateBean()); - predefinedStyle.setComponentStyle(this.componentStyleSettingPane.updateBean()); - - PredefinedColorStyle colorStyle = this.colorFillStylePane.update(); - updateCellStyleByColorStyle(colorStyle, cellStyleConfig); - predefinedStyle.setPredefinedColorStyle(colorStyle); - predefinedStyle.setPredefinedChartStyle(this.chartStyleSettingPane.updateBean()); - return predefinedStyle; - } - - private void updateCellStyleByColorStyle(PredefinedColorStyle colorStyle, PredefinedCellStyleConfig cellStyleConfig) { - PredefinedCellStyle headerStyle = cellStyleConfig.getStyle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); - PredefinedCellStyle highlightStyle = cellStyleConfig.getStyle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text")); - ColorFillStyle colorFillStyle = colorStyle.getColorFillStyle(); - List colorList = new ArrayList<>(); - if (colorFillStyle == null || colorFillStyle.getColorList().size() == 0){ - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - String defaultName = config.getCurrentStyle(); - ChartColorMatching defaultStyle = (ChartColorMatching) config.getPreStyle(defaultName); - if (defaultStyle != null) { - colorList = defaultStyle.getColorList(); - } - } else { - colorList = colorFillStyle.getColorList(); - } - if (colorList.size() < 2) { - return; - } - if (headerStyle != null) { - Style style = headerStyle.getStyle(); - Color color = colorList.get(0); - headerStyle.setStyle(style.deriveBackground(ColorBackground.getInstance(color))); - } - if (highlightStyle != null) { - Style style = highlightStyle.getStyle(); - Color color = colorList.get(1); - FRFont font = style.getFRFont(); - font.setForeground(color); - highlightStyle.setStyle(style.deriveFRFont(font)); - } - } - - public boolean saveStyle() { - PredefinedStyle previewObject; - try { - previewObject = update(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - return false; - } - if (this.styleNameField.isEnabled() && !validateRepeat(previewObject.getStyleName())) { - return false; - } - if (!saveStyle(previewObject)) { - return false; - } - HistoryTemplateListCache.getInstance().repaintCurrentEditingTemplate(); - return true; - } - - private boolean saveStyle(PredefinedStyle previewObject) { - PredefinedStyleConfig config = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig(); - if (StringUtils.isEmpty(previewObject.getStyleName())) { - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(PredefinedStyleEditPane.this), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Name_Cannot_Empty")); - - return false; - } - config.add(previewObject); - PredefinedStyleConfig sortedConfig = resortConfigStyles(previewObject, config); -// Configurations.modify(new WorkerFacade(ServerPreferenceConfig.class) { -// @Override -// public void run() { -// ServerPreferenceConfig.getInstance().setPreferenceStyleConfig(sortedConfig); -// } -// }); - selectPane.refreshPane(); - return true; - } - - public void saveAsNewStyle(String styleName) { - PredefinedStyle previewObject; - try { - previewObject = update(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - return; - } - previewObject.setStyleName(styleName); - if (validateRepeat(styleName)) { - saveStyle(previewObject); - } - } - - private boolean validateRepeat(String styleName) { - PredefinedStyleConfig config = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig(); - if (config.getStyle(styleName) != null) { - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(PredefinedStyleEditPane.this), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Name_Repeat")); - - return false; - } - return true; - } - - private PredefinedStyleConfig resortConfigStyles(PredefinedStyle priorityStyle, PredefinedStyleConfig config){ - PredefinedStyleConfig sortedConfig = new PredefinedStyleConfig(); - PredefinedStyle defaultStyle = config.getDefaultPredefinedStyle(); - if (defaultStyle != null) { - sortedConfig.add(defaultStyle); - config.removeStyle(defaultStyle.getStyleName()); - sortedConfig.setDefaultPredefinedStyle(defaultStyle.getStyleName()); - } - if (priorityStyle != null && !priorityStyle.isDefaultStyle()) { - sortedConfig.add(priorityStyle); - config.removeStyle(priorityStyle.getStyleName()); - } - Iterator iterator = config.getPredefinedStyleIterator(); - while (iterator.hasNext()) { - PredefinedStyle entry = iterator.next(); - sortedConfig.add(entry); - } - sortedConfig.setCompatibleStyleName(config.getCompatibleStyleName()); - return sortedConfig; - } - - - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleSelectPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleSelectPane.java deleted file mode 100644 index 227c9e30d..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleSelectPane.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.fr.design.mainframe.predefined.ui; - -import com.fr.config.ServerPreferenceConfig; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.dialog.BasicPane; -import com.fr.design.event.ChangeListener; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.layout.FRGUIPaneFactory; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import java.util.Iterator; -import java.awt.BorderLayout; -import java.awt.Dimension; - -/** - * Created by kerry on 2020-08-26 - */ -public class PredefinedStyleSelectPane extends BasicPane { - private PredefinedStyleBlock selectedBlock; - private boolean editable; - private JPanel contentPane; - private String currentApplicateStyle; - private ChangeListener changeListener; - - - public PredefinedStyleSelectPane(String currentApplicateStyle, boolean editable) { - this.editable = editable; - this.currentApplicateStyle = currentApplicateStyle; - initPane(); - } - - public void registerChangeListener(ChangeListener changeListener) { - this.changeListener = changeListener; - - } - - - private void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - contentPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(5, 8); - createContentPane(); - UIScrollPane scrollPane = new UIScrollPane(contentPane); - scrollPane.setPreferredSize(new Dimension(630, 480)); - scrollPane.setBorder(BorderFactory.createEmptyBorder()); - this.add(scrollPane, BorderLayout.CENTER); - } - - - public void createContentPane() { - contentPane.removeAll(); - Iterator iterator = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig().getPredefinedStyleIterator(); - int rowCount = (ServerPreferenceConfig.getInstance().getPreferenceStyleConfig().getPredefinedSize() +2)/ 3; - contentPane.setPreferredSize(new Dimension(618, 220 * rowCount)); - while (iterator.hasNext()) { - PredefinedStyle tmpStyle = iterator.next(); - - if (tmpStyle != null) { - PredefinedStyleBlock tmpPanel = - new PredefinedStyleBlock(tmpStyle, this, this.editable); - contentPane.add(tmpPanel); - } - } - } - - - public String getCurrentApplicateStyle() { - return currentApplicateStyle; - } - - public void refreshPane() { - createContentPane(); - this.validate(); - this.repaint(); - } - - @Override - protected String title4PopupWindow() { - return null; - } - - public void setSelectedPreviewPane(PredefinedStyleBlock selectedPreviewPane) { - this.selectedBlock = selectedPreviewPane; - if (changeListener != null) { - changeListener.fireChanged(null); - } - this.repaint(); - } - - public PredefinedStyleBlock getSelectedPreviewPane() { - return selectedBlock; - } - - public PredefinedStyle update() { - if (this.selectedBlock == null){ - return null; - } - return this.selectedBlock.update(); - } - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleSettingPane.java deleted file mode 100644 index bd849414f..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleSettingPane.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.fr.design.mainframe.predefined.ui; - -import com.fr.config.predefined.PredefinedNameStyleProvider; -import com.fr.design.file.HistoryTemplateListCache; -import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; -import com.fr.design.gui.frpane.AttributeChangeListener; -import com.fr.design.gui.ibutton.UIRadioButton; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.JTemplate; -import com.fr.design.mainframe.predefined.ui.preview.StyleSettingPreviewPane; -import javax.swing.ButtonGroup; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * Created by kerry on 2020-09-02 - */ -public abstract class PredefinedStyleSettingPane extends AbstractAttrNoScrollPane { - protected StyleSettingPreviewPane previewPane; - protected UIRadioButton predefinedRadioBtn; - private UIRadioButton customRadioBtn; - private JPanel customDetailPane; - private JPanel predefinedSettingPane; - private CardLayout tabbedPane; - private JPanel center; - private boolean isPopulating = false; - - - public void setPopulating(boolean populating) { - isPopulating = populating; - } - - protected void initContentPane() { - leftContentPane = createContentPane(); - this.add(leftContentPane, BorderLayout.CENTER); - } - - @Override - protected JPanel createContentPane() { - JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - previewPane = createPreviewPane(); - JPanel previewTitlePane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview")); - if (previewPane != null) { - previewTitlePane.setPreferredSize(new Dimension(407, 527)); - previewTitlePane.add(previewPane); - contentPane.add(previewTitlePane, BorderLayout.WEST); - } - - customDetailPane = createCustomDetailPane(); - predefinedSettingPane = createPredefinedSettingPane(); - - JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel jPanel = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(10, 20, 10); - jPanel.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style"))); - predefinedRadioBtn = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Predefined")); - customRadioBtn = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Custom")); - - tabbedPane = new CardLayout(); - center = new JPanel(tabbedPane); - center.add(predefinedSettingPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Predefined")); - center.add(customDetailPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Custom")); - predefinedRadioBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - populateCustomPane(); - tabbedPane.show(center, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Predefined")); - } - }); - customRadioBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - tabbedPane.show(center, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Custom")); - } - }); - jPanel.add(predefinedRadioBtn); - jPanel.add(customRadioBtn); - - ButtonGroup layoutBG = new ButtonGroup(); - layoutBG.add(predefinedRadioBtn); - layoutBG.add(customRadioBtn); - centerPane.add(jPanel, BorderLayout.NORTH); - centerPane.add(center, BorderLayout.CENTER); - contentPane.add(centerPane, BorderLayout.CENTER); - this.addAttributeChangeListener(new AttributeChangeListener() { - @Override - public void attributeChange() { - if (isPopulating) { - return; - } - if (previewPane != null) { - previewPane.refresh(); - } - } - }); - return contentPane; - } - - - protected abstract StyleSettingPreviewPane createPreviewPane(); - - protected abstract JPanel createCustomDetailPane(); - - protected JPanel createPredefinedSettingPane() { - return new JPanel(); - } - - protected void populate(PredefinedNameStyleProvider nameStyle) { - this.predefinedRadioBtn.setSelected(nameStyle.usePredefinedStyle()); - this.customRadioBtn.setSelected(!nameStyle.usePredefinedStyle()); - if (nameStyle.usePredefinedStyle()) { - tabbedPane.show(center, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Predefined")); - } else { - tabbedPane.show(center, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Custom")); - } - - } - - protected String getPredefinedStyleName() { - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - return template.getTemplatePredefinedStyle(); - } - - - /** - * 用于在切换到预定义样式后重置自定义样式的设置 - */ - protected abstract void populateCustomPane(); - - - /** - * 展示数据 - * - * @param ob 待展示的对象 - */ - public abstract void populateBean(T ob); - - /** - * 保存数据 - * - * @return 待保存的对象 - */ - public abstract T updateBean(); - - /** - * 保存数据 - * - * @param ob 待保存的对象 - */ - public void updateBean(T ob) { - - } - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/ReportPredefinedStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/ReportPredefinedStylePane.java deleted file mode 100644 index b29e7ffdf..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/ReportPredefinedStylePane.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.fr.design.mainframe.predefined.ui; - -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.dialog.BasicPane; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.JTemplate; - -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.FlowLayout; - -/** - * Created by kerry on 2020-08-28 - */ -public class ReportPredefinedStylePane extends BasicPane { - private PredefinedStyleSelectPane selectPane; - private JTemplate currentTemplate; - - public ReportPredefinedStylePane(JTemplate jTemplate) { - this.currentTemplate = jTemplate; - initPane(); - } - - private void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel jPanel = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Select")); - jPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - JPanel subPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - this.selectPane = new PredefinedStyleSelectPane(currentTemplate.getTemplatePredefinedStyle(), false); - subPanel.add(this.selectPane, BorderLayout.CENTER); - jPanel.add(subPanel, BorderLayout.CENTER); - this.add(jPanel, BorderLayout.CENTER); - } - - public void update() { - PredefinedStyle style = selectPane.update(); - if (style != null) { -// currentTemplate.resetPredefinedStyle(style.getStyleName()); - } - } - - public void refresh() { - this.selectPane.refreshPane(); - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Template_Style"); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/ServerPredefinedStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/ServerPredefinedStylePane.java deleted file mode 100644 index cc0cbf15f..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/ServerPredefinedStylePane.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.fr.design.mainframe.predefined.ui; - - -import com.fr.base.BaseUtils; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.config.predefined.PredefinedStyleConfig; -import com.fr.config.ServerPreferenceConfig; -import com.fr.design.actions.UpdateAction; -import com.fr.design.event.ChangeEvent; -import com.fr.design.event.ChangeListener; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.mainframe.predefined.PatternStyle; -import com.fr.design.dialog.BasicPane; -import com.fr.design.dialog.FineJOptionPane; -import com.fr.design.gui.itoolbar.UIToolbar; -import com.fr.design.i18n.Toolkit; -import com.fr.design.icon.IconPathConstants; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.dialog.PredefinedStyleEditDialog; -import com.fr.design.menu.MenuDef; -import com.fr.design.menu.ToolBarDef; -import com.fr.design.utils.DesignUtils; -import com.fr.stable.StringUtils; -import com.fr.transaction.Configurations; -import com.fr.transaction.WorkerFacade; - -import javax.swing.BorderFactory; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSeparator; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -/** - * Created by kerry on 2020-08-25 - */ -public class ServerPredefinedStylePane extends BasicPane { - - private static final Color TIP_COLOR = Color.decode("#8F8F92"); - private RemoveAction removeAction; - - private PredefinedStyleSelectPane selectPane; - - - public ServerPredefinedStylePane() { - initPane(); - } - - private void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel jPanel = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Manager")); - jPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - jPanel.setLayout(FRGUIPaneFactory.createLeftZeroLayout()); - JPanel subPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - subPanel.add(createControlPane(), BorderLayout.NORTH); - PredefinedStyle style = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig().getDefaultPredefinedStyle(); - - this.selectPane = new PredefinedStyleSelectPane(style == null ? StringUtils.EMPTY : style.getStyleName(), true); - this.selectPane.registerChangeListener(new ChangeListener() { - @Override - public void fireChanged(ChangeEvent event) { - PredefinedStyle selectStyle = selectPane.getSelectedPreviewPane().update(); - removeAction.setEnabled(!selectStyle.isBuiltIn()); - } - }); - this.selectPane.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - if (selectPane.getSelectedPreviewPane() != null) { - removeAction.setEnabled(true); - } - } - - @Override - public void mousePressed(MouseEvent e) { - - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { - - } - - @Override - public void mouseExited(MouseEvent e) { - - } - }); - JSeparator jSeparator = new JSeparator(); - subPanel.add(jSeparator, BorderLayout.CENTER); - subPanel.add(this.selectPane, BorderLayout.SOUTH); - jPanel.add(subPanel); - this.add(jPanel, BorderLayout.CENTER); - this.repaint(); - } - - - private JPanel createControlPane() { - MenuDef addMenuDef = new MenuDef(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Action_Add")); - addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); - createAddMenuDef(addMenuDef); - ToolBarDef toolbarDef = new ToolBarDef(); - removeAction = new RemoveAction(); - removeAction.setEnabled(false); - toolbarDef.addShortCut(addMenuDef, removeAction); - UIToolbar toolBar = ToolBarDef.createJToolBar(); - toolBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - toolbarDef.updateToolBar(toolBar); - JPanel toolbarPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - toolbarPane.add(toolBar, BorderLayout.CENTER); - UILabel tipLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Manager_Tip")); - tipLabel.setForeground(TIP_COLOR); - tipLabel.setHorizontalTextPosition(UILabel.RIGHT); - toolbarPane.add(tipLabel, BorderLayout.EAST); - toolbarPane.setPreferredSize(new Dimension(620, 30)); - return toolbarPane; - } - - private void createAddMenuDef(MenuDef addMenuDef) { - addMenuDef.setRePaint(true); - addMenuDef.addShortCut(new CreateStyleAction(PatternStyle.DARK_STYLE)); - addMenuDef.addShortCut(new CreateStyleAction(PatternStyle.LIGHT_STYLE)); - - } - - - public void update() { - PredefinedStyle style = selectPane.update(); - if (style != null) { - PredefinedStyleConfig config = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig(); - config.setDefaultPredefinedStyle(style.getStyleName()); -// Configurations.modify(new WorkerFacade(ServerPreferenceConfig.class) { -// @Override -// public void run() { -// ServerPreferenceConfig.getInstance().setPreferenceStyleConfig(config); -// } -// }); - } - - } - - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Server_Style"); - } - - private class RemoveAction extends UpdateAction { - - public RemoveAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove")); - this.setMnemonic('R'); - this.setSmallIcon(BaseUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); - } - - @Override - public void actionPerformed(ActionEvent e) { - PredefinedStyle previewObject = ServerPredefinedStylePane.this.selectPane.update(); - int selVal = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(ServerPredefinedStylePane.this), - Toolkit.i18nText("Fine-Design_Predefined_Remove_Style_Confirm", previewObject.getStyleName()), - Toolkit.i18nText("Fine-Design_Basic_Delete"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - if (selVal == JOptionPane.YES_OPTION) { - removeStyle(previewObject.getStyleName()); - ServerPredefinedStylePane.this.selectPane.refreshPane(); - } - } - } - - - private class CreateStyleAction extends UpdateAction { - private PatternStyle style; - - public CreateStyleAction(PatternStyle style) { - this.style = style; - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Create_Parttern_Style") + style.getName()); - this.setMnemonic('R'); - } - - @Override - public void actionPerformed(ActionEvent e) { - createNewPatternStylePane(); - } - - private void createNewPatternStylePane() { - PredefinedStyleEditPane editPane = PredefinedStyleEditPane.createNewEditPane(selectPane); - PredefinedStyleEditDialog editDialog = new PredefinedStyleEditDialog( - SwingUtilities.getWindowAncestor(ServerPredefinedStylePane.this), editPane); - PredefinedStyle predefinedStyle = style.getPredefinedStyle(); - predefinedStyle.setStyleName(StringUtils.EMPTY); - editPane.populate(predefinedStyle); - editDialog.setVisible(true); - } - } - - - private void removeStyle(String name) { - PredefinedStyleConfig config = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig(); - config.removeStyle(name); -// Configurations.modify(new WorkerFacade(ServerPreferenceConfig.class) { -// @Override -// public void run() { -// ServerPreferenceConfig.getInstance().setPreferenceStyleConfig(config); -// } -// }); - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/CellStyleListControlPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/CellStyleListControlPane.java deleted file mode 100644 index 3c966c3c4..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/CellStyleListControlPane.java +++ /dev/null @@ -1,308 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail; - -import com.fr.base.BaseUtils; -import com.fr.base.Style; -import com.fr.config.predefined.PredefinedCellStyle; -import com.fr.config.predefined.PredefinedCellStyleConfig; -import com.fr.design.actions.UpdateAction; -import com.fr.design.beans.BasicBeanPane; -import com.fr.design.dialog.BasicPane; -import com.fr.design.dialog.FineJOptionPane; -import com.fr.design.gui.NameInspector; -import com.fr.design.gui.controlpane.JListControlPane; -import com.fr.design.gui.controlpane.NameObjectCreator; -import com.fr.design.gui.controlpane.NameableCreator; -import com.fr.design.gui.controlpane.ShortCut4JControlPane; -import com.fr.design.gui.controlpane.UnrepeatedNameHelper; -import com.fr.design.gui.frpane.AttributeChangeListener; -import com.fr.design.gui.ilist.ListModelElement; -import com.fr.design.gui.ilist.ModNameActionListener; -import com.fr.design.gui.style.AlignmentPane; -import com.fr.design.gui.style.FormatPane; -import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.detail.cell.CustomPredefinedStylePane; -import com.fr.design.menu.ShortCut; -import com.fr.general.ComparatorUtils; -import com.fr.general.NameObject; -import com.fr.invoke.Reflect; -import com.fr.log.FineLoggerFactory; -import com.fr.stable.Nameable; -import com.fr.stable.StringUtils; - -import javax.swing.BorderFactory; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSeparator; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -/** - * Created by kerry on 2020-09-27 - */ -public class CellStyleListControlPane extends JListControlPane { - private boolean namePermitted = true; - private AttributeChangeListener attributeChangeListener; - - - - public CellStyleListControlPane() { - super(); - this.addModNameActionListener(new ModNameActionListener() { - public void nameModed(int index, String oldName, String newName) { - if (ComparatorUtils.equals(oldName, newName) || ComparatorUtils.equals(newName, NameInspector.ILLEGAL_NAME_HOLDER)) { - return; - } - namePermitted = true; - String[] allNames = nameableList.getAllNames(); - allNames[index] = StringUtils.EMPTY; - if (StringUtils.isEmpty(newName)) { - showTipDialogAndReset(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Empty_Name"), index); - return; - } - if (isNameRepeated(new List[]{Arrays.asList(allNames)}, newName)) { - showTipDialogAndReset(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Duplicate_Name", newName), index); - return; - } - populateSelectedValue(); - } - }); - } - - - - public void registerAttrChangeListener(AttributeChangeListener listener){ - this.attributeChangeListener = listener; - } - - - private void showTipDialogAndReset(String content, int index) { - nameableList.stopEditing(); - - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(CellStyleListControlPane.this), - content, - Toolkit.i18nText("Fine-Design_Basic_Alert"), - JOptionPane.WARNING_MESSAGE); - setIllegalIndex(index); - namePermitted = false; - } - - @Override - public NameableCreator[] createNameableCreators() { - return new NameableCreator[]{ - new CellStyleNameObjectCreator(Toolkit.i18nText("Fine-Design_Predefined_Cell_New_Style"), - PredefinedCellStyle.class, CustomPredefinedStylePaneNoBorder.class) { - @Override - public boolean acceptDefaultNameObject(Object ob) { - return ((PredefinedCellStyle) ob).isDefaultStyle(); - } - }, - new CellStyleNameObjectCreator(Toolkit.i18nText("Fine-Design_Predefined_Cell_New_Style"), - PredefinedCellStyle.class, CustomPredefinedStylePane.class)}; - } - - @Override - public BasicBeanPane createPaneByCreators(NameableCreator creator) { - CustomPredefinedStylePane stylePane = (CustomPredefinedStylePane) super.createPaneByCreators(creator); - stylePane.registerAttrChangeListener(attributeChangeListener); - return stylePane; - } - - - - @Override - protected String title4PopupWindow() { - return StringUtils.EMPTY; - } - - protected void initComponentPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setCreators(this.createNameableCreators()); - initCardPane(); - JPanel leftPane = getLeftPane(); - JSeparator jSeparator = new JSeparator(SwingConstants.VERTICAL); - leftPane.setPreferredSize(new Dimension(70, 0)); - jSeparator.setPreferredSize(new Dimension(2, 0)); - cardPane.setPreferredSize(new Dimension(238, 0)); - cardPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); - JPanel mainSplitPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - mainSplitPane.add(leftPane, BorderLayout.WEST); - mainSplitPane.add(jSeparator, BorderLayout.CENTER); - mainSplitPane.add(cardPane, BorderLayout.EAST); - - this.add(mainSplitPane, BorderLayout.CENTER); - this.checkButtonEnabled(); - } - - protected ShortCut4JControlPane[] createShortcuts() { - return new ShortCut4JControlPane[]{ - createAddItemShortCut4JControlPane(), - new RemoveItemShortCut4JControlPane(new RemoveItemAction()) - }; - } - - - private static class CustomPredefinedStylePaneNoBorder extends CustomPredefinedStylePane { - @Override - protected List initPaneList() { - paneList = new ArrayList(); - paneList.add(new FormatPane()); - paneList.add(new AlignmentPane()); - return paneList; - } - - } - - - private ShortCut4JControlPane createAddItemShortCut4JControlPane (){ - ShortCut shortCut = shortCutFactory.createAddItemUpdateAction(new NameableCreator[]{ - new CellStyleNameObjectCreator(Toolkit.i18nText("Fine-Design_Predefined_Cell_New_Style"), - PredefinedCellStyle.class, CustomPredefinedStylePane.class)}); - return new AddItemShortCut4JControlPane(shortCut); - } - - private class AddItemShortCut4JControlPane extends ShortCut4JControlPane{ - AddItemShortCut4JControlPane(ShortCut shortCut) { - this.shortCut = shortCut; - } - - - @Override - public void checkEnable() { - this.shortCut.setEnabled(true); - } - } - - - private class RemoveItemShortCut4JControlPane extends ShortCut4JControlPane { - RemoveItemShortCut4JControlPane(ShortCut shortCut) { - this.shortCut = shortCut; - } - - @Override - public void checkEnable() { - ListModelElement selectModel = CellStyleListControlPane.this.getSelectedValue(); - if (selectModel != null) { - NameObject selectNameObject = (NameObject) selectModel.wrapper; - PredefinedCellStyle cellStyle = (PredefinedCellStyle) (selectNameObject.getObject()); - this.shortCut.setEnabled(!cellStyle.isBuiltIn() && !cellStyle.isDefaultStyle()); - } else { - this.shortCut.setEnabled(false); - } - - } - } - - - private class RemoveItemAction extends UpdateAction { - RemoveItemAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText(("Fine-Design_Basic_Action_Remove"))); - this.setMnemonic('R'); - this.setSmallIcon(BaseUtils - .readIcon("/com/fr/base/images/cell/control/remove.png")); - } - - @Override - public void actionPerformed(ActionEvent evt) { - CellStyleListControlPane.this.onRemoveItem(); - } - } - - - class CellStyleNameObjectCreator extends NameObjectCreator { - public CellStyleNameObjectCreator(String menuName, Class clazz, Class updatePane) { - super(menuName, clazz, updatePane); - } - - public Nameable createNameable(UnrepeatedNameHelper helper) { - Constructor constructor = null; - try { - constructor = clazzOfInitCase.getConstructor(); - PredefinedCellStyle cellStyle = constructor.newInstance(); - - cellStyle.setName(menuName); - cellStyle.setStyle(Style.getInstance()); - return new NameObject(helper.createUnrepeatedName(this.menuName()), cellStyle); - - } catch (NoSuchMethodException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } catch (IllegalAccessException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } catch (InstantiationException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } catch (InvocationTargetException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - return null; - } - /** - * - * @param ob - * @return - */ - public Object acceptObject2Populate(Object ob) { - if (ob instanceof NameObject) { - ob = ((NameObject) ob).getObject(); - } - if (clazzOfObject != null && clazzOfObject.isInstance(ob) && acceptDefaultNameObject(ob)) { - doSthChanged4Icon(ob); - return ob; - } - return null; - } - - public boolean acceptDefaultNameObject(Object ob) { - return !((PredefinedCellStyle) ob).isDefaultStyle(); - } - } - - - /** - * Populate - */ - public void populateBean(PredefinedCellStyleConfig ob) { - if (ob == null) { - return; - } - - List nameStyleList = new ArrayList(); - - Iterator styleNameIterator = ob.getStyleNameIterator(); - while (styleNameIterator.hasNext()) { - String name = (String) styleNameIterator.next(); - PredefinedCellStyle tmpStyle = ob.getStyle(name); - - if (tmpStyle != null) { - nameStyleList.add(new NameObject(name, tmpStyle)); - } - } - - NameObject[] nameObjects = new NameObject[nameStyleList.size()]; - nameStyleList.toArray(nameObjects); - - populate(nameObjects); - } - - - public PredefinedCellStyleConfig updateBean() { - Nameable[] nameables = this.update(); - PredefinedCellStyleConfig styleConfig = new PredefinedCellStyleConfig(); - for (int i = 0; i < nameables.length; i++) { - PredefinedCellStyle tmpStyle = (PredefinedCellStyle) ((NameObject) nameables[i]).getObject(); - tmpStyle.setName(nameables[i].getName()); - styleConfig.addStyle(tmpStyle); - } - return styleConfig; - } - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ChartStyleSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ChartStyleSettingPane.java deleted file mode 100644 index 6eb155eb6..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ChartStyleSettingPane.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.dialog.BasicPane; -import com.fr.design.dialog.MultiTabPane; -import com.fr.design.mainframe.predefined.ui.detail.chart.ChartAxisStylePane; -import com.fr.design.mainframe.predefined.ui.detail.chart.ChartBackgroundStylePane; -import com.fr.design.mainframe.predefined.ui.detail.chart.ChartDataSheetStylePane; -import com.fr.design.mainframe.predefined.ui.detail.chart.ChartLabelStylePane; -import com.fr.design.mainframe.predefined.ui.detail.chart.ChartLegendStylePane; -import com.fr.design.mainframe.predefined.ui.detail.chart.ChartTitleStylePane; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-16 - */ -public class ChartStyleSettingPane extends MultiTabPane { - - private ChartTitleStylePane chartTitleStylePane; - private ChartLegendStylePane chartLegendStylePane; - private ChartLabelStylePane chartLabelPane; - private ChartAxisStylePane chartAxisStylePane; - private ChartDataSheetStylePane chartDataSheetStylePane; - private ChartBackgroundStylePane chartBackgroundStylePane; - - public ChartStyleSettingPane() { - } - - @Override - protected void initLayout() { - super.initLayout(); - } - - @Override - protected List initPaneList() { - this.chartTitleStylePane = new ChartTitleStylePane(); - this.chartLegendStylePane = new ChartLegendStylePane(); - this.chartLabelPane = new ChartLabelStylePane(); - this.chartAxisStylePane = new ChartAxisStylePane(); - this.chartDataSheetStylePane = new ChartDataSheetStylePane(); - this.chartBackgroundStylePane = new ChartBackgroundStylePane(); - paneList = new ArrayList<>(); - paneList.add(this.chartTitleStylePane); - paneList.add(this.chartLegendStylePane); - paneList.add(this.chartLabelPane); - paneList.add(this.chartAxisStylePane); - paneList.add(this.chartDataSheetStylePane); - paneList.add(this.chartBackgroundStylePane); - return paneList; - } - - @Override - public void populateBean(PredefinedChartStyle ob) { - chartTitleStylePane.populate(ob); - chartLegendStylePane.populate(ob); - chartLabelPane.populate(ob); - chartAxisStylePane.populate(ob); - chartDataSheetStylePane.populate(ob); - chartBackgroundStylePane.populate(ob); - } - - @Override - public void updateBean(PredefinedChartStyle ob) { - - } - - - @Override - public PredefinedChartStyle updateBean() { - PredefinedChartStyle chartStyle = new PredefinedChartStyle(); - chartTitleStylePane.update(chartStyle); - chartLegendStylePane.update(chartStyle); - chartLabelPane.update(chartStyle); - chartAxisStylePane.update(chartStyle); - chartDataSheetStylePane.update(chartStyle); - chartBackgroundStylePane.update(chartStyle); - return chartStyle; - } - - - @Override - public boolean accept(Object ob) { - return false; - } - - @Override - public void reset() { - - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ComponentStyleSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ComponentStyleSettingPane.java deleted file mode 100644 index e2d306933..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ComponentStyleSettingPane.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail; - -import com.fr.config.predefined.PredefinedComponentStyle; -import com.fr.design.dialog.BasicPane; -import com.fr.design.dialog.MultiTabPane; -import com.fr.design.mainframe.predefined.ui.detail.component.ComponentFrameStylePane; -import com.fr.design.mainframe.predefined.ui.detail.component.ComponentTitleStylePane; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by kerry on 2020-09-01 - */ -public class ComponentStyleSettingPane extends MultiTabPane { - private ComponentFrameStylePane frameStylePane; - private ComponentTitleStylePane titleStylePane; - - public ComponentStyleSettingPane() { - } - - - @Override - protected List initPaneList() { - this.frameStylePane = new ComponentFrameStylePane(); - this.titleStylePane = ComponentTitleStylePane.createPredefinedSettingPane(); - paneList = new ArrayList(); - paneList.add(this.frameStylePane); - paneList.add(this.titleStylePane); - return paneList; - } - - @Override - public void populateBean(PredefinedComponentStyle ob) { - this.frameStylePane.populate(ob); - this.titleStylePane.populate(ob); - } - - @Override - public void updateBean(PredefinedComponentStyle ob) { - - } - - - @Override - public PredefinedComponentStyle updateBean() { - PredefinedComponentStyle componentStyle = new PredefinedComponentStyle(); - this.frameStylePane.update(componentStyle); - this.titleStylePane.update(componentStyle); - return componentStyle; - } - - - @Override - public boolean accept(Object ob) { - return false; - } - - @Override - public void reset() { - - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/PredefinedBackgroundSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/PredefinedBackgroundSettingPane.java deleted file mode 100644 index 05b02a564..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/PredefinedBackgroundSettingPane.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail; - -import com.fr.config.predefined.PredefinedBackground; -import com.fr.design.beans.BasicBeanPane; -import com.fr.design.gui.ibutton.UIButtonGroup; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.detail.background.BackgroundSettingPane; -import com.fr.design.mainframe.predefined.ui.detail.background.BackgroundWithAlphaSettingPane; - -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * Created by kerry on 2020-08-31 - */ -public class PredefinedBackgroundSettingPane extends BasicBeanPane { - private UIButtonGroup buttonGroup; - private BackgroundSettingPane reportBackgroundSettingPane; - private BackgroundWithAlphaSettingPane formBackgroundSettingPane; - - - public PredefinedBackgroundSettingPane() { - initPane(); - } - - private void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - reportBackgroundSettingPane = new BackgroundSettingPane(); - formBackgroundSettingPane = new BackgroundWithAlphaSettingPane(); - CardLayout tabbedPane = new CardLayout(); - JPanel center = new JPanel(tabbedPane); - center.add(reportBackgroundSettingPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plain_Report")); - center.add(formBackgroundSettingPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Decision_Report")); - this.buttonGroup = new UIButtonGroup(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plain_Report"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Decision_Report")}); - buttonGroup.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (buttonGroup.getSelectedIndex() == 0) { - tabbedPane.show(center, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plain_Report")); - } else { - tabbedPane.show(center, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Decision_Report")); - } - } - }); - - - this.add(buttonGroup, BorderLayout.NORTH); - - this.add(center, BorderLayout.CENTER); - this.buttonGroup.setSelectedIndex(0); - } - - public boolean currentFormBackground() { - return buttonGroup.getSelectedIndex() == 1; - } - - @Override - public void populateBean(PredefinedBackground predefinedBackground) { - reportBackgroundSettingPane.populateBean(predefinedBackground.getReportBackground()); - formBackgroundSettingPane.populateBean(predefinedBackground.getFormBackground()); - } - - @Override - public PredefinedBackground updateBean() { - PredefinedBackground predefinedBackground = new PredefinedBackground(); - predefinedBackground.setReportBackground(reportBackgroundSettingPane.updateBean()); - predefinedBackground.setFormBackground(formBackgroundSettingPane.updateBean()); - return predefinedBackground; - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Background_Setting"); - } - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/AbstractBackgroundDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/AbstractBackgroundDetailPane.java deleted file mode 100644 index 7cc1629bf..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/AbstractBackgroundDetailPane.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.design.event.UIObserverListener; -import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; -import com.fr.general.Background; - -import javax.swing.event.ChangeListener; - -/** - * Created by kerry on 2020-09-14 - */ -public abstract class AbstractBackgroundDetailPane extends BackgroundQuickPane { - @Override - public boolean accept(Background background) { - return false; - } - - @Override - public void populateBean(Background background) { - this.populate((T) background); - } - - @Override - public Background updateBean() { - return this.update(); - } - - @Override - public String title4PopupWindow() { - return null; - } - - @Override - public void reset() { - - } - - @Override - public void registerChangeListener(UIObserverListener listener) { - - } - - public abstract void populate(T background); - - public abstract T update(); - - public void addChangeListener(ChangeListener changeListener) { - - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/BackgroundSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/BackgroundSettingPane.java deleted file mode 100644 index 3efd0b447..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/BackgroundSettingPane.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.design.beans.BasicBeanPane; -import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; -import com.fr.general.Background; -import com.fr.log.FineLoggerFactory; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.util.ArrayList; - -/** - * Created by kerry on 2020-09-02 - */ -public class BackgroundSettingPane extends BasicBeanPane { - private ChangeListener changeListener = null; - private UIComboBox headCombobox; - private BackgroundQuickPane[] paneList; - - public BackgroundSettingPane() { - init(); - } - - private void init() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.add(createComboHeadPane(), BorderLayout.NORTH); - CardLayout cardlayout = new CardLayout(); - paneList = supportKindsOfBackgroundUI(); - final JPanel centerPane = new JPanel(cardlayout) { - @Override - public Dimension getPreferredSize() {// AUGUST:使用当前面板的的高度 - int index = headCombobox.getSelectedIndex(); - return new Dimension(super.getPreferredSize().width, paneList[index].getPreferredSize().height); - } - }; - centerPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); - for (BackgroundQuickPane pane : paneList) { - headCombobox.addItem(pane.title4PopupWindow()); - centerPane.add(pane, pane.title4PopupWindow()); - } - headCombobox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - cardlayout.show(centerPane, (String) headCombobox.getSelectedItem()); - } - }); - this.add(centerPane, BorderLayout.CENTER); - } - - public void addChangeListener(ChangeListener changeListener) { - this.changeListener = changeListener; - } - - - private JPanel createComboHeadPane() { - headCombobox = new UIComboBox(); - - JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( - new Component[][]{new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Fill")), headCombobox}}, - TableLayoutHelper.FILL_NONE, 33, 5); - headCombobox.setPreferredSize(new Dimension(160, 20)); - jPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); - return jPanel; - } - - protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { - java.util.List kinds = new ArrayList<>(); - kinds.add(new EmptyBackgroundPane()); - kinds.add(new ColorDetailPane()); - kinds.add(new TextureDetailObservePane()); - kinds.add(new PatternDetailPane()); - kinds.add(createImageSelectPane()); - kinds.add(new GradientDetailPane()); - return kinds.toArray(new BackgroundQuickPane[kinds.size()]); - } - - protected ImageDetailPane createImageSelectPane() { - ImageDetailPane imageDetailPane = new ImageDetailPane(); - imageDetailPane.registerChangeListener(new UIObserverListener() { - @Override - public void doChange() { - fireChangeListener(); - } - }); - return imageDetailPane; - } - - protected void fireChangeListener() { - if (changeListener != null) { - changeListener.stateChanged(null); - } - } - - - @Override - public void populateBean(Background background) { - for (int i = 0; i < paneList.length; i++) { - BackgroundQuickPane pane = paneList[i]; - if (pane.accept(background)) { - pane.populateBean(background); - headCombobox.setSelectedIndex(i); - return; - } - } - } - - @Override - public Background updateBean() { - int selectIndex = this.headCombobox.getSelectedIndex(); - try { - return paneList[selectIndex].updateBean(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - return null; - } - - @Override - protected String title4PopupWindow() { - return null; - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/BackgroundWithAlphaSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/BackgroundWithAlphaSettingPane.java deleted file mode 100644 index dba0dce23..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/BackgroundWithAlphaSettingPane.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.config.predefined.BackgroundWithAlpha; -import com.fr.design.beans.BasicBeanPane; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.gui.frpane.UINumberDragPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; - -/** - * Created by kerry on 2020-09-04 - */ -public class BackgroundWithAlphaSettingPane extends BasicBeanPane { - private BackgroundSettingPane backgroundSettingPane; - //透明度 - private UINumberDragPane numberDragPane; - - private double maxNumber = 100; - - - public BackgroundWithAlphaSettingPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - backgroundSettingPane = new FormBackgroundSettingPane(); - - JPanel eastpane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(2, 0); - this.numberDragPane = new UINumberDragPane(0, 100); - this.numberDragPane.setPreferredSize(new Dimension(148, 20)); - eastpane.add(numberDragPane); - eastpane.add(new UILabel("%")); - JPanel transparencyPane = TableLayoutHelper.createGapTableLayoutPane( - new Component[][]{new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha")), - eastpane}}, TableLayoutHelper.FILL_LASTCOLUMN, 18, 5); - transparencyPane.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); - - - Component[][] components = new Component[][]{ - new Component[]{backgroundSettingPane}, - new Component[]{transparencyPane}}; - - JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_NONE, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1); - this.add(panel, BorderLayout.CENTER); - } - - - public void addChangeListener(ChangeListener changeListener) { - this.backgroundSettingPane.addChangeListener(changeListener); - } - - - @Override - public void populateBean(BackgroundWithAlpha ob) { - backgroundSettingPane.populateBean(ob.getBackground()); - numberDragPane.populateBean(ob.getAlpha() * maxNumber); - } - - @Override - public BackgroundWithAlpha updateBean() { - BackgroundWithAlpha backgroundWithAlpha = new BackgroundWithAlpha(); - backgroundWithAlpha.setBackground(backgroundSettingPane.updateBean()); - backgroundWithAlpha.setAlpha((float) (numberDragPane.updateBean() / maxNumber)); - return backgroundWithAlpha; - } - - @Override - protected String title4PopupWindow() { - return null; - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java deleted file mode 100644 index 43d20d1bd..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.base.background.ColorBackground; -import com.fr.design.event.UIObserver; -import com.fr.design.event.UIObserverListener; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.style.color.NewColorSelectPane; -import com.fr.general.Background; -import java.awt.BorderLayout; - -/** - * Created by kerry on 2020-08-31 - */ -public class ColorDetailPane extends AbstractBackgroundDetailPane { - private ColorBackgroundSelectPane selectPane; - - - public ColorDetailPane() { - this.selectPane = new ColorBackgroundSelectPane(); - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.add(this.selectPane, BorderLayout.CENTER); - } - - @Override - public void populate(ColorBackground background) { - this.selectPane.setColor(background.getColor()); - } - - @Override - public ColorBackground update() { - return ColorBackground.getInstance(selectPane.getColor()); - } - - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Color"); - } - - @Override - public boolean accept(Background background) { - return background instanceof ColorBackground; - } - - class ColorBackgroundSelectPane extends NewColorSelectPane implements UIObserver { - protected UIObserverListener uiObserverListener; - - @Override - public void registerChangeListener(UIObserverListener listener) { - this.uiObserverListener = listener; - } - - @Override - public boolean shouldResponseChangeListener() { - return true; - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/EmptyBackgroundPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/EmptyBackgroundPane.java deleted file mode 100644 index 569db1023..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/EmptyBackgroundPane.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.general.Background; - -/** - * Created by kerry on 2020-09-01 - */ -public class EmptyBackgroundPane extends AbstractBackgroundDetailPane { - - @Override - public void populate(Background background) { - - } - - @Override - public Background update() { - return null; - } - - /** - * 名称 - * - * @return 名称 - */ - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Null"); - } - - public boolean accept(Background background) { - return background == null; - } - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/FormBackgroundSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/FormBackgroundSettingPane.java deleted file mode 100644 index 1a683df5c..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/FormBackgroundSettingPane.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.design.ExtraDesignClassManager; -import com.fr.design.event.UIObserverListener; -import com.fr.design.fun.BackgroundQuickUIProvider; -import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * Created by kerry on 2020-09-14 - */ -public class FormBackgroundSettingPane extends BackgroundSettingPane { - - public FormBackgroundSettingPane() { - super(); - } - - @Override - protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { - ColorDetailPane colorDetailPane = new ColorDetailPane(); - ImageDetailPane imageDetailPane = createImageSelectPane(); - GradientDetailPane gradientPane = new GradientDetailPane(); - //hugh:表单支持背景接口 - List kinds = new ArrayList(); - - kinds.add(new EmptyBackgroundPane()); - kinds.add(colorDetailPane); - kinds.add(imageDetailPane); - kinds.add(gradientPane); - - Set providers = ExtraDesignClassManager.getInstance().getArray(BackgroundQuickUIProvider.MARK_STRING); - for (BackgroundQuickUIProvider provider : providers) { - BackgroundQuickPane newTypePane = provider.appearanceForBackground(); - newTypePane.registerChangeListener(new UIObserverListener() { - @Override - public void doChange() { - fireChangeListener(); - } - }); - kinds.add(newTypePane); - } - - return kinds.toArray(new BackgroundQuickPane[kinds.size()]); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/GradientDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/GradientDetailPane.java deleted file mode 100644 index 74851c38f..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/GradientDetailPane.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.base.background.GradientBackground; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.event.UIObserver; -import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.ibutton.UIRadioButton; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.background.gradient.GradientBar; -import com.fr.general.Background; - -import javax.swing.ButtonGroup; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * 渐变色的面板,不是很pp,面板应用显得繁琐,有写可以写成控件类型,比如色彩选择的。。,可以做得花哨点 - * - * @author ben - */ -public class GradientDetailPane extends AbstractBackgroundDetailPane implements UIObserver { - private static final long serialVersionUID = -6854603990673031897L; - private UIObserverListener listener; - private UIRadioButton left2right, top2bottom; - private GradientBar gradientBar; - private ChangeListener changeListener = null; - - public GradientDetailPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - - JPanel gradientPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel blankJp = new JPanel(); - gradientBar = new GradientBar(4, 140); - blankJp.add(gradientBar); - - gradientPanel.add(gradientBar, BorderLayout.SOUTH); - - JPanel jp = new JPanel(new GridLayout(2, 1, 15, 10)); - - - left2right = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Page_Setup_Horizontal")); - jp.add(left2right); - left2right.setSelected(true); - left2right.addActionListener(reviewListener); - - top2bottom = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Page_Setup_Vertical")); - jp.add(top2bottom); - top2bottom.addActionListener(reviewListener); - - ButtonGroup toggle = new ButtonGroup(); - toggle.add(left2right); - toggle.add(top2bottom); - - Component[][] components = new Component[][]{ - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Gradient_Setting")), gradientPanel}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Gradient_Color")), jp} - }; - JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, - IntervalConstants.INTERVAL_W4, IntervalConstants.INTERVAL_L1); - this.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (listener != null) { - listener.doChange(); - } - } - }); - - - this.add(contentPane); - } - - @Override - public boolean accept(Background background) { - return background instanceof GradientBackground; - } - - - - public void populate(GradientBackground bg) { - this.gradientBar.getSelectColorPointBtnP1().setColorInner(bg.getStartColor()); - this.gradientBar.getSelectColorPointBtnP2().setColorInner(bg.getEndColor()); - if (bg.getDirection() == GradientBackground.LEFT2RIGHT) { - left2right.setSelected(true); - } else { - top2bottom.setSelected(true); - } - if (bg.isUseCell()) { - return; - } - double startValue = (double) bg.getBeginPlace(); - double endValue = (double) bg.getFinishPlace(); - gradientBar.setStartValue(startValue); - gradientBar.setEndValue(endValue); - this.gradientBar.repaint(); - } - - public GradientBackground update() { - GradientBackground gb = new GradientBackground( - gradientBar.getSelectColorPointBtnP1().getColorInner(), - gradientBar.getSelectColorPointBtnP2().getColorInner()); - if (left2right.isSelected()) { - gb.setDirection(GradientBackground.LEFT2RIGHT); - } else { - gb.setDirection(GradientBackground.TOP2BOTTOM); - } - if (gradientBar.isOriginalPlace()) { - gb.setUseCell(true); - } else { - gb.setUseCell(false); - gb.setBeginPlace((float) gradientBar.getStartValue()); - gb.setFinishPlace((float) gradientBar.getEndValue()); - } - return gb; - } - - - ActionListener reviewListener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - fireChagneListener(); - } - }; - - public void addChangeListener(ChangeListener changeListener) { - this.changeListener = changeListener; - gradientBar.addChangeListener(changeListener); - } - - public void fireChagneListener() { - if (this.changeListener != null) { - ChangeEvent evt = new ChangeEvent(this); - this.changeListener.stateChanged(evt); - } - } - - @Override - public void registerChangeListener(UIObserverListener listener) { - this.listener = listener; - } - - @Override - public boolean shouldResponseChangeListener() { - return true; - } - - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradient_Color"); - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ImageDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ImageDetailPane.java deleted file mode 100644 index 5873755f5..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ImageDetailPane.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.base.Style; -import com.fr.base.background.ImageBackground; -import com.fr.base.background.ImageFileBackground; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.event.UIObserver; -import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.frpane.ImgChooseWrapper; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.ibutton.UIRadioButton; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.background.image.ImageFileChooser; -import com.fr.design.style.background.image.ImagePreviewPane; -import com.fr.general.Background; -import com.fr.stable.Constants; - -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * Image background pane. - */ -public class ImageDetailPane extends AbstractBackgroundDetailPane implements UIObserver { - private UIObserverListener listener; - protected ImagePreviewPane previewPane = null; - private Style imageStyle = null; - private ChangeListener changeListener = null; - private ImageFileChooser imageFileChooser = null; - - private UIRadioButton defaultRadioButton = null; - private UIRadioButton tiledRadioButton = null; - private UIRadioButton extendRadioButton = null; - private UIRadioButton adjustRadioButton = null; - - - public ImageDetailPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.add(initSelectFilePane(), BorderLayout.CENTER); - imageFileChooser = new ImageFileChooser(); - imageFileChooser.setMultiSelectionEnabled(false); - previewPane = new ImagePreviewPane(); - this.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (listener != null) { - listener.doChange(); - } - } - }); - } - - public JPanel initSelectFilePane() { - JPanel selectFilePane = FRGUIPaneFactory.createBorderLayout_L_Pane(); - selectFilePane.setBorder(BorderFactory.createEmptyBorder()); - UIButton selectPictureButton = new UIButton( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Image_Select")); - selectPictureButton.setMnemonic('S'); - selectPictureButton.addActionListener(selectPictureActionListener); - selectPictureButton.setPreferredSize(new Dimension(160, 20)); - //布局 - defaultRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Default")); - tiledRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Titled")); - extendRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Extend")); - adjustRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Adjust")); - - defaultRadioButton.addActionListener(layoutActionListener); - tiledRadioButton.addActionListener(layoutActionListener); - extendRadioButton.addActionListener(layoutActionListener); - adjustRadioButton.addActionListener(layoutActionListener); - - JPanel jp = new JPanel(new GridLayout(4, 1, 15, 10)); - for (UIRadioButton button : imageLayoutButtons()) { - jp.add(button); - } - - ButtonGroup layoutBG = new ButtonGroup(); - layoutBG.add(defaultRadioButton); - layoutBG.add(tiledRadioButton); - layoutBG.add(extendRadioButton); - layoutBG.add(adjustRadioButton); - - defaultRadioButton.setSelected(true); - - Component[][] components = new Component[][]{ - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Image")), selectPictureButton}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Fill_Mode")), jp} - }; - JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_NONE, - IntervalConstants.INTERVAL_L4, IntervalConstants.INTERVAL_L1); - selectFilePane.add(centerPane, BorderLayout.CENTER); - return selectFilePane; - } - - protected UIRadioButton[] imageLayoutButtons() { - return new UIRadioButton[]{ - defaultRadioButton, - tiledRadioButton, - extendRadioButton, - adjustRadioButton - }; - } - - @Override - public boolean accept(Background background) { - return background instanceof ImageBackground; - } - - - /** - * Select picture. - */ - ActionListener selectPictureActionListener = new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - int returnVal = imageFileChooser.showOpenDialog(ImageDetailPane.this); - setImageStyle(); - ImgChooseWrapper.getInstance(previewPane, imageFileChooser, imageStyle, changeListener).dealWithImageFile(returnVal); - } - }; - - protected void setImageStyle() { - if (tiledRadioButton.isSelected()) { - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_TILED); - } else if (adjustRadioButton.isSelected()) { - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_ADJUST); - } else if (extendRadioButton.isSelected()) { - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_EXTEND); - } else { - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_CENTER); - } - } - - ActionListener layoutActionListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent evt) { - setImageStyle(); - changeImageStyle(); - } - - private void changeImageStyle() { - previewPane.setImageStyle(ImageDetailPane.this.imageStyle); - previewPane.repaint(); - } - }; - - @Override - public void populate(ImageBackground imageBackground) { - if (imageBackground.getLayout() == Constants.IMAGE_CENTER) { - defaultRadioButton.setSelected(true); - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_CENTER); - } else if (imageBackground.getLayout() == Constants.IMAGE_EXTEND) { - extendRadioButton.setSelected(true); - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_EXTEND); - } else if (imageBackground.getLayout() == Constants.IMAGE_ADJUST) { - adjustRadioButton.setSelected(true); - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_ADJUST); - } else { - tiledRadioButton.setSelected(true); - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_TILED); - } - previewPane.setImageStyle(ImageDetailPane.this.imageStyle); - if (imageBackground.getImage() != null) { - previewPane.setImageWithSuffix(imageBackground.getImageWithSuffix()); - previewPane.setImage(imageBackground.getImage()); - } - - fireChagneListener(); - } - - @Override - public ImageBackground update() { - ImageBackground imageBackground = new ImageFileBackground(previewPane.getImageWithSuffix()); - setImageStyle(); - imageBackground.setLayout(imageStyle.getImageLayout()); - return imageBackground; - } - - @Override - public void addChangeListener(ChangeListener changeListener) { - this.changeListener = changeListener; - } - - private void fireChagneListener() { - if (this.changeListener != null) { - ChangeEvent evt = new ChangeEvent(this); - this.changeListener.stateChanged(evt); - } - } - - @Override - public void registerChangeListener(UIObserverListener listener) { - this.listener = listener; - } - - - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Image"); - } - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/PatternDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/PatternDetailPane.java deleted file mode 100644 index 05667021c..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/PatternDetailPane.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.base.background.PatternBackground; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.event.UIObserver; -import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.background.impl.PatternBackgroundPane; -import com.fr.design.style.color.ColorSelectBox; -import com.fr.general.Background; -import com.fr.log.FineLoggerFactory; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.GridLayout; -import java.awt.LayoutManager; - -/** - * Created by kerry on 2020-08-31 - */ -public class PatternDetailPane extends AbstractBackgroundDetailPane implements UIObserver { - - private UIObserverListener listener; - private PatternNewBackgroundPane patternNewBackgroundPane; - - public PatternDetailPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - patternNewBackgroundPane = new PatternNewBackgroundPane(6); - this.add(patternNewBackgroundPane, BorderLayout.CENTER); - } - - @Override - public void registerChangeListener(UIObserverListener listener) { - this.listener = listener; - } - - @Override - public void populate(PatternBackground background) { - this.patternNewBackgroundPane.populate(background); - } - - @Override - public PatternBackground update() { - try { - return (PatternBackground) this.patternNewBackgroundPane.update(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - return null; - } - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Pattern"); - } - - - @Override - public boolean accept(Background background) { - return background instanceof PatternBackground; - } - - - @Override - public boolean shouldResponseChangeListener() { - return true; - } - - class PatternNewBackgroundPane extends PatternBackgroundPane { - private PatternNewBackgroundPane(int nColumn) { - super(nColumn); - } - - protected LayoutManager layoutOfTypePane(int nColumn) { - return new GridLayout(0, nColumn, 2, 2); - } - - protected void initComponents(int nColumn) { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setBorder(BorderFactory.createEmptyBorder()); - JPanel jPanel = new JPanel(); - jPanel.setLayout(layoutOfTypePane(nColumn)); - setChildrenOfTypePane(jPanel); - - foregroundColorPane = new ColorSelectBox(80); - backgroundColorPane = new ColorSelectBox(80); - foregroundColorPane.setSelectObject(Color.lightGray); - backgroundColorPane.setSelectObject(Color.black); - UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Pattern")); - label.setVerticalAlignment(SwingConstants.TOP); - Component[][] components = new Component[][]{ - new Component[]{label, jPanel}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_ForeBackground_Color")), foregroundColorPane}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Pattern_Color")), backgroundColorPane} - }; - JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, - IntervalConstants.INTERVAL_W4, IntervalConstants.INTERVAL_L1); - JPanel jPanel1 = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); - jPanel1.add(centerPane); - jPanel1.setBorder(BorderFactory.createEmptyBorder()); - this.add(jPanel1, BorderLayout.NORTH); - this.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (listener != null) { - listener.doChange(); - } - } - }); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/TextureDetailObservePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/TextureDetailObservePane.java deleted file mode 100644 index 189b811d9..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/TextureDetailObservePane.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.background; - -import com.fr.base.background.TextureBackground; -import com.fr.design.event.UIObserver; -import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.background.texture.TextureDetailPane; -import com.fr.general.Background; -import com.fr.log.FineLoggerFactory; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; - -/** - * Created by kerry on 2020-09-02 - */ -public class TextureDetailObservePane extends AbstractBackgroundDetailPane implements UIObserver { - private TextureDetailPane detailPane; - - private UIObserverListener listener; - - public TextureDetailObservePane() { - - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - detailPane = TextureDetailPane.createMiniTextureDetailPane(6); - - detailPane.setPreferredSize(new Dimension(160, 108)); - UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Texture")); - label.setPreferredSize(new Dimension(24, 108)); - label.setVerticalAlignment(SwingConstants.TOP); - JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( - new Component[][]{new Component[]{label, detailPane}}, TableLayoutHelper.FILL_LASTCOLUMN, 33, 5); - jPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); - - - detailPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - if (listener != null) { - listener.doChange(); - } - } - }); - this.add(jPanel, BorderLayout.CENTER); - } - - @Override - public void registerChangeListener(UIObserverListener listener) { - this.listener = listener; - - } - - @Override - public boolean shouldResponseChangeListener() { - return true; - } - - @Override - public void populate(TextureBackground background) { - this.detailPane.populate(background); - } - - @Override - public TextureBackground update() { - try { - return (TextureBackground) this.detailPane.update(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - return null; - } - - - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background_Texture"); - } - - @Override - public boolean accept(Background background) { - return background instanceof TextureBackground; - } - - - @Override - public void addChangeListener(ChangeListener changeListener) { - - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/cell/CustomPredefinedStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/cell/CustomPredefinedStylePane.java deleted file mode 100644 index 5e66afb8a..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/cell/CustomPredefinedStylePane.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.cell; - -import com.fr.base.ScreenResolution; -import com.fr.base.Style; -import com.fr.config.predefined.PredefinedCellStyle; -import com.fr.design.constants.UIConstants; -import com.fr.design.dialog.AttrScrollPane; -import com.fr.design.dialog.BasicPane; -import com.fr.design.dialog.BasicScrollPane; -import com.fr.design.dialog.MultiTabPane; -import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; -import com.fr.design.gui.frpane.AttributeChangeListener; -import com.fr.design.gui.style.AbstractBasicStylePane; -import com.fr.design.gui.style.AlignmentPane; -import com.fr.design.gui.style.BorderPane; -import com.fr.design.gui.style.FormatPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.utils.gui.GUICoreUtils; - -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.List; - - -/** - * 哎,复杂的原型图导致复杂的画法。非我所愿也 - * - * @author zhou - * @since 2012-5-24上午10:36:10 - */ -public class CustomPredefinedStylePane extends MultiTabPane { - private PredefinedCellStyle cellStyle; - private PreviewArea previewArea; - private boolean populating; - private AttributeChangeListener attributeChangeListener; - - - public CustomPredefinedStylePane() { - super(); - tabPane.setOneLineTab(true); - tabPane.setDrawLine(false); - tabPane.setBorder(BorderFactory.createLineBorder(UIConstants.SHADOW_GREY)); - tabPane.setLayout(new GridLayout(1, 3, 0, 0)); - } - - public void registerAttrChangeListener(AttributeChangeListener listener){ - this.attributeChangeListener = listener; - } - - private void fireAttrChangeListener() { - if (this.attributeChangeListener != null) { - this.attributeChangeListener.attributeChange(); - } - } - - /** - * @return - */ - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Custom_Style"); - } - - - /** - * - */ - public void reset() { - populateBean(null); - } - - @Override - /** - * - */ - public void populateBean(PredefinedCellStyle ob) { - this.populating = true; - this.cellStyle = ob; - for (int i = 0; i < paneList.size(); i++) { - ((AbstractBasicStylePane) paneList.get(i)).populateBean(ob.getStyle()); - previewArea.preview(ob.getStyle()); - } - this.populating = false; - } - - @Override - /** - * - */ - public PredefinedCellStyle updateBean() { - AbstractBasicStylePane basicStylePane = (AbstractBasicStylePane) paneList.get(tabPane.getSelectedIndex()); - this.cellStyle.setStyle(basicStylePane.update(this.cellStyle.getStyle())); - return this.cellStyle; - } - - - /** - * @param ob - * @return - */ - public boolean accept(Object ob) { - return ob instanceof PredefinedCellStyle; - } - - @Override - protected List initPaneList() { - paneList = new ArrayList(); - paneList.add(new FormatPane()); - paneList.add(new BorderPane()); - paneList.add(new AlignmentPane()); - return paneList; - } - - protected void initLayout() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - - JPanel jPanel = new JPanel(); - jPanel.setLayout(new BorderLayout(0, 4)); - - JPanel previewPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - previewArea = new PreviewArea(); - previewPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"), null)); - previewPane.add(previewArea, BorderLayout.CENTER); - - this.add(previewPane, BorderLayout.NORTH); - - this.add(jPanel, BorderLayout.CENTER); - jPanel.add(tabPane, BorderLayout.NORTH); - JPanel attrListenerPane = new AbstractAttrNoScrollPane() { - - @Override - protected void initContentPane() { - leftContentPane = createContentPane(); - this.add(leftContentPane, BorderLayout.CENTER); - } - - @Override - protected JPanel createContentPane() { - this.addAttributeChangeListener(new AttributeChangeListener() { - @Override - public void attributeChange() { - if (populating) { - return; - } - PredefinedCellStyle cellStyle = updateBean(); - if (cellStyle != null) { - previewArea.preview(cellStyle.getStyle()); - } - fireAttrChangeListener(); - } - }); - BasicScrollPane basicScrollPane = new AttrScrollPane() { - @Override - protected JPanel createContentPane() { - return centerPane; - } - }; - return basicScrollPane; - } - }; - jPanel.add(attrListenerPane, BorderLayout.CENTER); - } - - @Override - /** - * - */ - public void updateBean(PredefinedCellStyle ob) { - return; - } - - - - - /** - * 预览Style的面板 - * - * @author richer - */ - private static class PreviewArea extends JComponent { - - private String paintText = "Report"; - private Style style = Style.DEFAULT_STYLE; - - public PreviewArea() { - setPreferredSize(new Dimension(40, 30)); - } - - public void preview(Style style) { - this.style = style; - repaint(); - } - - @Override - public void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - int resolution = ScreenResolution.getScreenResolution(); - - if (style == Style.DEFAULT_STYLE) { - // 如果是默认的style,就只写"Report"上去 - Style.paintContent(g2d, paintText, style, getWidth() - 3, getHeight() - 3, resolution); - return; - } - - Style.paintBackground(g2d, style, getWidth() - 3, getHeight() - 3); - - Style.paintContent(g2d, paintText, style, getWidth() - 3, getHeight() - 3, resolution); - - Style.paintBorder(g2d, style, getWidth() - 3, getHeight() - 3); - } - - @Override - public Dimension getMinimumSize() { - return getPreferredSize(); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/AbstractChartStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/AbstractChartStylePane.java deleted file mode 100644 index 2fd47d6b2..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/AbstractChartStylePane.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.constants.LayoutConstants; -import com.fr.design.dialog.BasicPane; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayout; -import com.fr.design.layout.TableLayoutHelper; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Component; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-17 - */ -public abstract class AbstractChartStylePane extends BasicPane { - - public AbstractChartStylePane() { - initComponents(); - initPane(); - } - - protected abstract void initComponents(); - - protected void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - double e = 155; - double p = TableLayout.PREFERRED; - double[] columnSize = {p, e}; - JPanel gapTableLayoutPane = TableLayoutHelper.createGapTableLayoutPane(getComponent(), getRows(p), columnSize, 20, LayoutConstants.VGAP_LARGE); - gapTableLayoutPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); - UIScrollPane rightTopPane = new UIScrollPane(gapTableLayoutPane); - rightTopPane.setBorder(BorderFactory.createEmptyBorder()); - this.add(rightTopPane, BorderLayout.CENTER); - } - - protected abstract Component[][] getComponent(); - - protected abstract double[] getRows(double p); - - public abstract void populate(PredefinedChartStyle chartStyle); - - public abstract void update(PredefinedChartStyle chartStyle); -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartAxisStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartAxisStylePane.java deleted file mode 100644 index 4c6fc16dd..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartAxisStylePane.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; -import com.fr.design.style.color.ColorSelectBox; - -import java.awt.Component; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-16 - */ -public class ChartAxisStylePane extends AbstractChartStylePane { - - //轴标题字体样式 - private ChartFontPane titleFontPane; - - //轴标签字体样式 - private ChartFontPane labelFontPane; - - //轴线颜色 - private ColorSelectBox axisLineColor; - - protected void initComponents() { - titleFontPane = new ChartFontPane() { - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_Axis_Title_Character"); - } - }; - labelFontPane = new ChartFontPane() { - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Character"); - } - }; - axisLineColor = new ColorSelectBox(100); - } - - protected Component[][] getComponent() { - return new Component[][]{ - new Component[]{titleFontPane, null}, - new Component[]{labelFontPane, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Axis_Line_Color")), axisLineColor} - }; - } - - protected double[] getRows(double p) { - return new double[]{p, p, p}; - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Axis"); - } - - public void populate(PredefinedChartStyle chartStyle) { - titleFontPane.populate(chartStyle.getAxisTitleFont()); - labelFontPane.populate(chartStyle.getAxisLabelFont()); - axisLineColor.setSelectObject(chartStyle.getAxisLineColor()); - } - - - public void update(PredefinedChartStyle chartStyle) { - chartStyle.setAxisTitleFont(titleFontPane.update()); - chartStyle.setAxisLabelFont(labelFontPane.update()); - chartStyle.setAxisLineColor(axisLineColor.getSelectObject()); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartBackgroundStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartBackgroundStylePane.java deleted file mode 100644 index 0cb602eea..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartBackgroundStylePane.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.base.background.ImageBackground; -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; -import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; -import com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; -import com.fr.design.mainframe.backgroundpane.ImageBackgroundQuickPane; -import com.fr.design.mainframe.backgroundpane.NullBackgroundQuickPane; -import com.fr.design.mainframe.backgroundpane.VanChartGradientPane; -import com.fr.design.style.color.ColorSelectBox; -import com.fr.general.Background; -import com.fr.stable.Constants; - -import javax.swing.JPanel; -import java.util.ArrayList; -import java.util.List; -import java.awt.CardLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-17 - */ -public class ChartBackgroundStylePane extends AbstractChartStylePane { - - private UIComboBox typeComboBox; - private List paneList; - private JPanel centerPane; - //网格线颜色 - private ColorSelectBox mainGridColor; - - protected void initComponents() { - mainGridColor = new ColorSelectBox(100); - - typeComboBox = new UIComboBox(); - final CardLayout cardlayout = new CardLayout(); - initList(); - - centerPane = new JPanel(cardlayout) { - @Override - public Dimension getPreferredSize() {// AUGUST:使用当前面板的的高度 - int index = typeComboBox.getSelectedIndex(); - return new Dimension(super.getPreferredSize().width, paneList.get(index).getPreferredSize().height); - } - }; - for (int i = 0; i < paneList.size(); i++) { - BackgroundQuickPane pane = paneList.get(i); - typeComboBox.addItem(pane.title4PopupWindow()); - centerPane.add(pane, pane.title4PopupWindow()); - } - - typeComboBox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - cardlayout.show(centerPane, (String) typeComboBox.getSelectedItem()); - } - }); - } - - protected Component[][] getComponent() { - return new Component[][]{ - new Component[]{null, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Area_Background_Color")), typeComboBox}, - new Component[]{null, centerPane}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Grid_Line_Color")), mainGridColor} - }; - } - - protected double[] getRows(double p) { - return new double[]{p, p, p, p}; - } - - private void initList() { - paneList = new ArrayList<>(); - paneList.add(new NullBackgroundQuickPane()); - paneList.add(new ColorBackgroundQuickPane()); - paneList.add(new ImageBackgroundQuickPane(false)); - paneList.add(new VanChartGradientPane()); - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Background"); - } - - public void populate(PredefinedChartStyle chartStyle) { - Background background = chartStyle.getChartBackground(); - for (int i = 0; i < paneList.size(); i++) { - BackgroundQuickPane pane = paneList.get(i); - if (pane.accept(background)) { - pane.populateBean(background); - typeComboBox.setSelectedIndex(i); - break; - } - } - mainGridColor.setSelectObject(chartStyle.getGridMainLineColor()); - } - - public void update(PredefinedChartStyle chartStyle) { - chartStyle.setChartBackground(paneList.get(typeComboBox.getSelectedIndex()).updateBean()); - if (chartStyle.getChartBackground() instanceof ImageBackground) { - ((ImageBackground) chartStyle.getChartBackground()).setLayout(Constants.IMAGE_EXTEND); - } - chartStyle.setGridMainLineColor(mainGridColor.getSelectObject()); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartDataSheetStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartDataSheetStylePane.java deleted file mode 100644 index 2da8ee35f..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartDataSheetStylePane.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; -import com.fr.design.style.color.ColorSelectBox; - -import java.awt.Component; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-17 - */ -public class ChartDataSheetStylePane extends AbstractChartStylePane { - - //字体样式 - private ChartFontPane fontPane; - - //边框颜色 - private ColorSelectBox borderColor; - - protected void initComponents() { - fontPane = new ChartFontPane() { - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_DataSheet_Character"); - } - }; - borderColor = new ColorSelectBox(100); - } - - protected Component[][] getComponent() { - return new Component[][]{ - new Component[]{fontPane, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Border_Color")), borderColor} - }; - } - - protected double[] getRows(double p) { - return new double[]{p, p, p}; - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Data_Sheet"); - } - - public void populate(PredefinedChartStyle chartStyle) { - fontPane.populate(chartStyle.getDataSheetFont()); - borderColor.setSelectObject(chartStyle.getDataSheetBorderColor()); - } - - - public void update(PredefinedChartStyle chartStyle) { - chartStyle.setDataSheetFont(fontPane.update()); - chartStyle.setDataSheetBorderColor(borderColor.getSelectObject()); - } -} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartFontPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartFontPane.java deleted file mode 100644 index 93c0f8a6b..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartFontPane.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.base.BaseUtils; -import com.fr.base.FRContext; -import com.fr.base.Utils; -import com.fr.design.constants.LayoutConstants; -import com.fr.design.dialog.BasicPane; -import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.ibutton.UIColorButton; -import com.fr.design.gui.ibutton.UIToggleButton; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.TableLayout; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.FRFont; -import com.fr.general.GeneralUtils; - -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.Font; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-16 - */ -public class ChartFontPane extends BasicPane { - - public static final int FONT_START = 6; - public static final int FONT_END = 72; - private UIComboBox fontNameComboBox; - private UIComboBox fontSizeComboBox; - private UIToggleButton bold; - private UIToggleButton italic; - private UIColorButton fontColor; - private static Integer[] FONT_SIZES = new Integer[FONT_END - FONT_START + 1]; - - static { - for (int i = FONT_START; i <= FONT_END; i++) { - FONT_SIZES[i - FONT_START] = i; - } - } - - public ChartFontPane() { - initState(); - initComponents(); - } - - private void initState() { - fontNameComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); - fontSizeComboBox = new UIComboBox(FONT_SIZES); - bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); - italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); - fontColor = new UIColorButton(); - } - - protected void initComponents() { - Component[] components = new Component[]{ - fontColor, italic, bold - }; - JPanel buttonPane = new JPanel(new BorderLayout()); - buttonPane.add(fontSizeComboBox, BorderLayout.CENTER); - buttonPane.add(GUICoreUtils.createFlowPane(components, FlowLayout.LEFT, LayoutConstants.HGAP_LARGE), BorderLayout.EAST); - - this.setLayout(new BorderLayout()); - this.add(getContentPane(buttonPane), BorderLayout.CENTER); - - populate(FRContext.getDefaultValues().getFRFont()); - } - - protected JPanel getContentPane(JPanel buttonPane) { - double e = 155; - double p = TableLayout.PREFERRED; - double[] rows = {p, p, p}; - double[] columnSize = {p, e}; - UILabel text = new UILabel(getUILabelText(), SwingConstants.LEFT); - Component[][] components = { - new Component[]{null, null}, - new Component[]{text, fontNameComboBox}, - new Component[]{null, buttonPane} - }; - - return TableLayoutHelper.createGapTableLayoutPane(components, rows, columnSize, 20, LayoutConstants.VGAP_LARGE); - } - - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_Character"); - } - - public String title4PopupWindow() { - return null; - } - - public void populate(FRFont frFont) { - UIObserverListener listener = fontNameComboBox == null ? null : fontNameComboBox.getUiObserverListener(); - removeAllComboBoxListener(); - - if (frFont != null) { - fontNameComboBox.setSelectedItem(frFont.getFamily()); - bold.setSelected(frFont.isBold()); - italic.setSelected(frFont.isItalic()); - populateFontSize(frFont); - if (fontColor != null) { - fontColor.setColor(frFont.getForeground()); - } - } - - //更新结束后,注册监听器 - registerAllComboBoxListener(listener); - } - - private void populateFontSize(FRFont frFont) { - if (fontSizeComboBox != null) { - fontSizeComboBox.setSelectedItem(frFont.getSize()); - } - } - - private void removeAllComboBoxListener() { - fontNameComboBox.removeChangeListener(); - fontSizeComboBox.removeChangeListener(); - } - - private void registerAllComboBoxListener(UIObserverListener listener) { - fontNameComboBox.registerChangeListener(listener); - fontSizeComboBox.registerChangeListener(listener); - } - - /** - * 更新字 - * - * @return 更新字 - */ - public FRFont update() { - String name = GeneralUtils.objectToString(fontNameComboBox.getSelectedItem()); - - return FRFont.getInstance(name, updateFontStyle(), updateFontSize(), fontColor.getColor()); - } - - private int updateFontStyle() { - int style = Font.PLAIN; - if (bold.isSelected() && !italic.isSelected()) { - style = Font.BOLD; - } else if (!bold.isSelected() && italic.isSelected()) { - style = Font.ITALIC; - } else if (bold.isSelected() && italic.isSelected()) { - style = 3; - } - - return style; - } - - private float updateFontSize() { - return Float.parseFloat(GeneralUtils.objectToString(fontSizeComboBox.getSelectedItem())); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartLabelStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartLabelStylePane.java deleted file mode 100644 index b51535b82..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartLabelStylePane.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.gui.ibutton.UIButtonGroup; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-16 - */ -public class ChartLabelStylePane extends AbstractChartStylePane { - - private UIButtonGroup autoButton; - //字体样式 - private ChartFontPane chartFontPane; - - protected void initComponents() { - autoButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), - Toolkit.i18nText("Fine-Design_Chart_Custom")}); - chartFontPane = new ChartFontPane() { - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_Label_Character"); - } - }; - initListener(); - } - - protected Component[][] getComponent() { - return new Component[][]{ - new Component[]{null, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Style_Setting")), autoButton}, - new Component[]{chartFontPane, null} - }; - } - - protected double[] getRows(double p) { - return new double[]{p, p, p}; - } - - private void initListener() { - autoButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - checkPreButton(); - } - }); - } - - private void checkPreButton() { - chartFontPane.setVisible(autoButton.getSelectedIndex() == 1); - chartFontPane.setPreferredSize(autoButton.getSelectedIndex() == 1 ? new Dimension(0, 60) : new Dimension(0, 0)); - } - - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Label"); - } - - public void populate(PredefinedChartStyle chartStyle) { - autoButton.setSelectedIndex(chartStyle.isAutoLabelFont() ? 0 : 1); - chartFontPane.populate(chartStyle.getLabelFont()); - checkPreButton(); - } - - - public void update(PredefinedChartStyle chartStyle) { - chartStyle.setAutoLabelFont(autoButton.getSelectedIndex() == 0); - chartStyle.setLabelFont(chartFontPane.update()); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartLegendStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartLegendStylePane.java deleted file mode 100644 index c956dfcfd..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartLegendStylePane.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.i18n.Toolkit; - -import java.awt.Component; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-16 - */ -public class ChartLegendStylePane extends AbstractChartStylePane { - - //字体样式 - private ChartFontPane chartFontPane; - - protected void initComponents() { - chartFontPane = new ChartFontPane() { - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_Legend_Character"); - } - }; - } - - protected Component[][] getComponent() { - return new Component[][]{ - new Component[]{chartFontPane, null} - }; - } - - protected double[] getRows(double p) { - return new double[]{p}; - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Legend"); - } - - public void populate(PredefinedChartStyle chartStyle) { - chartFontPane.populate(chartStyle.getLegendFont()); - } - - - public void update(PredefinedChartStyle chartStyle) { - chartStyle.setLegendFont(chartFontPane.update()); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartTitleStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartTitleStylePane.java deleted file mode 100644 index d5bc56cd9..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/chart/ChartTitleStylePane.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.chart; - -import com.fr.config.predefined.PredefinedChartStyle; -import com.fr.design.i18n.Toolkit; - -import java.awt.Component; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-16 - */ -public class ChartTitleStylePane extends AbstractChartStylePane { - - //字体样式 - private ChartFontPane chartFontPane; - - protected void initComponents() { - chartFontPane = new ChartFontPane() { - public String getUILabelText() { - return Toolkit.i18nText("Fine-Design_Chart_Title_Character"); - } - }; - } - - protected Component[][] getComponent() { - return new Component[][]{ - new Component[]{chartFontPane, null} - }; - } - - protected double[] getRows(double p) { - return new double[]{p}; - } - - @Override - protected String title4PopupWindow() { - return Toolkit.i18nText("Fine-Design_Report_Title"); - } - - public void populate(PredefinedChartStyle chartStyle) { - chartFontPane.populate(chartStyle.getTitleFont()); - } - - - public void update(PredefinedChartStyle chartStyle) { - chartStyle.setTitleFont(chartFontPane.update()); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentFrameStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentFrameStylePane.java deleted file mode 100644 index 3d04a3cd5..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentFrameStylePane.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.component; - -import com.fr.base.GraphHelper; -import com.fr.base.Utils; -import com.fr.config.predefined.PredefinedComponentStyle; -import com.fr.design.gui.frpane.UINumberDragPane; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.ibutton.UIButtonUI; -import com.fr.design.gui.ibutton.UIColorButton; -import com.fr.design.gui.icombobox.LineComboBox; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.ispinner.UISpinner; -import com.fr.design.gui.style.BackgroundSpecialPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayout; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; -import com.fr.general.act.BorderPacker; -import com.fr.stable.Constants; - -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.geom.RoundRectangle2D; - -/** - * Created by kerry on 2020-09-01 - */ -public class ComponentFrameStylePane extends ComponentStylePane { - private final static String[] BORDER_STYLE = new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow")}; - private static final double ALPHA_MAX_NUMBER = 100; - private final static int[] BORDER_LINE_STYLE_ARRAY = new int[]{ - Constants.LINE_NONE, - Constants.LINE_THIN, //1px - Constants.LINE_MEDIUM, //2px - Constants.LINE_THICK, //3px - }; - - //渲染风格 - private UIComboBox borderStyleCombo; - //边框粗细 - private LineComboBox currentLineCombo; - //边框圆角 - private UISpinner borderCornerSpinner; - //边框颜色 - private UIColorButton currentLineColorPane; - //主体背景 - private BackgroundSpecialPane backgroundPane; - //透明度 - private UINumberDragPane numberDragPane; - - public ComponentFrameStylePane() { - initPane(); - } - - protected void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setBorder(BorderFactory.createEmptyBorder(6, 0, 0, 0)); - this.borderStyleCombo = new UIComboBox(BORDER_STYLE); - this.currentLineCombo = new LineComboBox(BORDER_LINE_STYLE_ARRAY); - this.currentLineColorPane = new UIColorButton(null); - this.borderCornerSpinner = new UISpinner(0, 1000, 1, 0); - currentLineColorPane.setUI(getButtonUI(currentLineColorPane)); - currentLineColorPane.set4ToolbarButton(); - currentLineColorPane.setPreferredSize(new Dimension(20, 20)); - JPanel buttonPane = new JPanel(new BorderLayout()); - buttonPane.add(currentLineColorPane, BorderLayout.WEST); - backgroundPane = new BackgroundSpecialPane(); - JPanel transparencyPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - this.numberDragPane = new UINumberDragPane(0, 100); - transparencyPane.add(numberDragPane, BorderLayout.CENTER); - transparencyPane.add(new UILabel(" %"), BorderLayout.EAST); - - double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p, p, p, p, p, p}; - double[] columnSize = {p, 157}; - JPanel rightTopContentPane = TableLayoutHelper.createCommonTableLayoutPane(new JComponent[][]{ - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), borderStyleCombo}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Line")), currentLineCombo}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Color")), buttonPane}, - getBorderCornerSpinnerComp(), - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Background")), backgroundPane}, - {new UILabel(""), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, - {new UILabel(""), transparencyPane}, - }, rowSize, columnSize, 10); - UIScrollPane rightTopPane = new UIScrollPane(rightTopContentPane); - rightTopPane.setBorder(BorderFactory.createEmptyBorder()); - this.add(rightTopPane, BorderLayout.CENTER); - } - - - private JComponent[] getBorderCornerSpinnerComp() { - return new JComponent[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius") + ":"), borderCornerSpinner}; - } - - - protected UIButtonUI getButtonUI(final UIColorButton uiColorButton) { - return new UIButtonUI() { - - public void paint(Graphics g, JComponent c) { - UIButton b = (UIButton) c; - g.setColor(Color.black); - GraphHelper.draw(g, new RoundRectangle2D.Double(1, 1, b.getWidth() - 2, b.getHeight() - 2, 0, 0), 1); - - if (b.getModel().isEnabled()) { - g.setColor(uiColorButton.getColor()); - } else { - g.setColor(new Color(Utils.filterRGB(uiColorButton.getColor().getRGB(), 50))); - } - g.fillRect(2, 2, b.getWidth() - 3, b.getHeight() - 3); - } - }; - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Frame"); - } - - - @Override - public void populate(PredefinedComponentStyle componentStyle) { - BorderPacker borderStyle = componentStyle.getBorderStyle(); - this.borderStyleCombo.setSelectedIndex(borderStyle.getBorderStyle()); - this.borderCornerSpinner.setValue(borderStyle.getBorderRadius()); - this.currentLineCombo.setSelectedLineStyle(borderStyle.getBorder()); - this.currentLineColorPane.setColor(borderStyle.getColor()); - this.backgroundPane.populateBean(borderStyle.getBackground()); - numberDragPane.populateBean(borderStyle.getAlpha() * ALPHA_MAX_NUMBER); - } - - @Override - public void update(PredefinedComponentStyle componentStyle) { - BorderPacker style = componentStyle.getBorderStyle(); - style.setBorderStyle(borderStyleCombo.getSelectedIndex()); - style.setBorderRadius((int) borderCornerSpinner.getValue()); - style.setBorder(currentLineCombo.getSelectedLineStyle()); - style.setColor(currentLineColorPane.getColor()); - style.setBackground(backgroundPane.update()); - style.setAlpha((float) (numberDragPane.updateBean() / ALPHA_MAX_NUMBER)); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentMarginStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentMarginStylePane.java deleted file mode 100644 index b36702fb7..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentMarginStylePane.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.component; - -import com.fr.config.predefined.PredefinedComponentStyle; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.ispinner.UISpinner; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayout; -import com.fr.design.layout.TableLayoutHelper; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import java.awt.BorderLayout; -import java.awt.Component; - -/** - * Created by kerry on 2020-09-01 - */ -public class ComponentMarginStylePane extends ComponentStylePane { - protected UISpinner top; - protected UISpinner bottom; - protected UISpinner left; - protected UISpinner right; - - public ComponentMarginStylePane() { - initBoundPane(0, 0, 0, 0); - } - - public void initBoundPane(int t, int b, int l, int r) { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - top = new UISpinner(0, Integer.MAX_VALUE, 1, t); - bottom = new UISpinner(0, Integer.MAX_VALUE, 1, b); - left = new UISpinner(0, Integer.MAX_VALUE, 1, l); - right = new UISpinner(0, Integer.MAX_VALUE, 1, r); - top.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); - bottom.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); - left.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); - right.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); - UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); - label.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); - label.setVerticalAlignment(SwingConstants.TOP); - JPanel panel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ - new Component[]{label, createRightPane()}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1); - this.add(panel); - } - - - public JPanel createRightPane() { - double f = TableLayout.FILL; - double p = TableLayout.PREFERRED; - double[] rowSize = {p, p}; - double[] columnSize = {f, f}; - int[][] rowCount = {{1, 1}, {1, 1}}; - Component[][] components1 = new Component[][]{ - new Component[]{top, bottom}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Top"), SwingConstants.CENTER), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Bottom"), SwingConstants.CENTER)} - }; - Component[][] components2 = new Component[][]{ - new Component[]{left, right}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Left"), SwingConstants.CENTER), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Right"), SwingConstants.CENTER)} - }; - JPanel northPanel = TableLayoutHelper.createGapTableLayoutPane(components1, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L6); - northPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, IntervalConstants.INTERVAL_L1, 0)); - JPanel centerPanel = TableLayoutHelper.createGapTableLayoutPane(components2, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L6); - JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); - panel.add(northPanel, BorderLayout.NORTH); - panel.add(centerPanel, BorderLayout.CENTER); - return panel; - } - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Base_Margin"); - } - - @Override - public void populate(PredefinedComponentStyle componentStyle) { - this.top.setValue(componentStyle.getTop()); - this.bottom.setValue(componentStyle.getBottom()); - this.left.setValue(componentStyle.getLeft()); - this.right.setValue(componentStyle.getRight()); - } - - @Override - public void update(PredefinedComponentStyle componentStyle) { - componentStyle.setTop((int) this.top.getValue()); - componentStyle.setBottom((int) this.bottom.getValue()); - componentStyle.setLeft((int) this.left.getValue()); - componentStyle.setRight((int) this.right.getValue()); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentStylePane.java deleted file mode 100644 index 9d858cfea..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentStylePane.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.component; - -import com.fr.config.predefined.PredefinedComponentStyle; -import com.fr.design.dialog.BasicPane; - - -/** - * Created by kerry on 2020-09-01 - */ -public abstract class ComponentStylePane extends BasicPane { - - public abstract void populate(PredefinedComponentStyle componentStyle); - - public abstract void update(PredefinedComponentStyle componentStyle); -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentTitleStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentTitleStylePane.java deleted file mode 100644 index 73dc56106..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/component/ComponentTitleStylePane.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.detail.component; - -import com.fr.base.BaseUtils; -import com.fr.base.Utils; -import com.fr.config.predefined.PredefinedComponentStyle; -import com.fr.design.constants.LayoutConstants; -import com.fr.design.constants.UIConstants; -import com.fr.design.formula.TinyFormulaPane; -import com.fr.design.gui.ibutton.UIButtonGroup; -import com.fr.design.gui.ibutton.UIColorButton; -import com.fr.design.gui.ibutton.UIToggleButton; -import com.fr.design.gui.icombobox.LineComboBox; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.style.BackgroundNoImagePane; -import com.fr.design.gui.style.FRFontPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayout; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; -import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.form.ui.LayoutBorderStyle; -import com.fr.form.ui.WidgetTitle; -import com.fr.general.FRFont; -import com.fr.general.act.BorderPacker; -import com.fr.general.act.TitlePacker; -import com.fr.stable.ArrayUtils; -import com.fr.stable.Constants; -import com.fr.stable.StringUtils; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; - -/** - * Created by kerry on 2020-09-01 - */ -public class ComponentTitleStylePane extends ComponentStylePane { - private final static Dimension BUTTON_SIZE = new Dimension(24, 20); - //标题内容 - private TinyFormulaPane formulaPane; - //标题格式 - private UIComboBox fontNameComboBox; - private UIComboBox fontSizeComboBox; - private UIColorButton colorSelectPane; - private UIToggleButton bold; - private UIToggleButton italic; - private UIToggleButton underline; - private LineComboBox underlineCombo; - //对齐方式 - private UIButtonGroup hAlignmentPane; - //标题背景 - private BackgroundNoImagePane titleBackgroundPane; - - public static ComponentTitleStylePane createPredefinedSettingPane(){ - return new ComponentTitleStylePane(true); - } - - public static ComponentTitleStylePane createStyleSettingPane(){ - return new ComponentTitleStylePane(false); - } - - private ComponentTitleStylePane(boolean isPredefined) { - initPane(isPredefined); - } - - protected void initPane(boolean isPredefined) { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setBorder(BorderFactory.createEmptyBorder(6, 0,0,0)); - formulaPane = new TinyFormulaPane(); - fontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); - fontNameComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); - fontNameComboBox.setPreferredSize(new Dimension(105 , 20)); - JPanel fontSizeTypePane = new JPanel(new BorderLayout(3, 0)); - fontSizeTypePane.add(fontSizeComboBox, BorderLayout.CENTER); - fontSizeTypePane.add(fontNameComboBox, BorderLayout.EAST); - - Icon[] hAlignmentIconArray = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), - BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), - BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png"),}; - Integer[] hAlignment = new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}; - hAlignmentPane = new UIButtonGroup(hAlignmentIconArray, hAlignment); - hAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left") - , com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right")}); - JPanel hPaneContainer = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); - hPaneContainer.add(hAlignmentPane); - - titleBackgroundPane = new BackgroundNoImagePane(); - - double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p, p, p, p, p, p}; - double[] columnSize = {p, 157}; - JComponent[][] jComponents = new JComponent[][]{ - {new UILabel(com.fr.design.i18n.Toolkit.i18nText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Char"))), fontSizeTypePane}, - {new UILabel(""), initFontButtonPane()}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Alignment-Style")), hAlignmentPane}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background")), titleBackgroundPane}}; - - JComponent[][] displayComponents = createDisplayComponentArray(isPredefined, jComponents); - JPanel rightBottomContentPane = TableLayoutHelper.createCommonTableLayoutPane(displayComponents, rowSize, columnSize, 10); - - UIScrollPane jPanel = new UIScrollPane(rightBottomContentPane); - jPanel.setBorder(BorderFactory.createEmptyBorder()); - this.add(jPanel, BorderLayout.CENTER); - } - - private JComponent[][] createDisplayComponentArray(boolean isPredefined, JComponent[][] baseComponents) { - if (isPredefined) { - return baseComponents; - } - JComponent[][] titleComponent = new JComponent[][]{{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), formulaPane}}; - return ArrayUtils.addAll(titleComponent, baseComponents); - - } - - protected JPanel initFontButtonPane() { - colorSelectPane = new UIColorButton(); - bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); - italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); - underline = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); - bold.setPreferredSize(BUTTON_SIZE); - italic.setPreferredSize(BUTTON_SIZE); - underline.setPreferredSize(BUTTON_SIZE); - underline.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - underlineCombo.setVisible(underline.isSelected()); - } - }); - underlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY); - Component[] components_font = new Component[]{ - colorSelectPane, italic, bold, underline - }; - JPanel buttonPane = new JPanel(new BorderLayout()); - buttonPane.add(GUICoreUtils.createFlowPane(components_font, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL)); - JPanel combinePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - combinePane.add(buttonPane, BorderLayout.WEST); - combinePane.add(underlineCombo, BorderLayout.CENTER); - initAllNames(); - setToolTips(); - return combinePane; - - } - - protected void initAllNames() { - fontNameComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); - fontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); - colorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); - italic.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); - bold.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); - underline.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); - underlineCombo.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Line_Style")); - } - - protected void setToolTips() { - colorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); - italic.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); - bold.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); - underline.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); - } - - - @Override - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Title"); - } - - @Override - public void populate(PredefinedComponentStyle componentStyle) { - BorderPacker borderStyle = componentStyle.getBorderStyle(); - TitlePacker widgetTitle = borderStyle == null ? new WidgetTitle() : borderStyle.getTitle(); - widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; - - populateFormula(widgetTitle); - populateFont(widgetTitle); - - hAlignmentPane.setSelectedItem(widgetTitle.getPosition()); - - titleBackgroundPane.populateBean(widgetTitle.getBackground()); - } - - private void populateFormula(TitlePacker widgetTitle) { - this.formulaPane.populateBean(widgetTitle.getTextObject().toString()); - } - - protected void populateFont(TitlePacker widgetTitle) { - FRFont frFont = widgetTitle.getFrFont(); - this.fontSizeComboBox.setSelectedItem(frFont.getSize()); - this.fontNameComboBox.setSelectedItem(frFont.getFamily()); - this.colorSelectPane.setColor(frFont.getForeground()); - this.colorSelectPane.repaint(); - bold.setSelected(frFont.isBold()); - italic.setSelected(frFont.isItalic()); - int line = frFont.getUnderline(); - if (line == Constants.LINE_NONE) { - underline.setSelected(false); - underlineCombo.setVisible(false); - } else { - underline.setSelected(true); - underlineCombo.setVisible(true); - this.underlineCombo.setSelectedLineStyle(line); - } - } - - @Override - public void update(PredefinedComponentStyle componentStyle) { - BorderPacker style = componentStyle.getBorderStyle(); - TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); - String titleText = formulaPane.updateBean(); - title.setTextObject(titleText); - style.setType(StringUtils.isEmpty(titleText) ? LayoutBorderStyle.STANDARD : LayoutBorderStyle.TITLE); - FRFont frFont = title.getFrFont(); - frFont = frFont.applySize((Integer) fontSizeComboBox.getSelectedItem()); - frFont = frFont.applyName(fontNameComboBox.getSelectedItem().toString()); - frFont = frFont.applyForeground(colorSelectPane.getColor()); - frFont = updateItalicBold(frFont); - int line = underline.isSelected() ? this.underlineCombo.getSelectedLineStyle() : Constants.LINE_NONE; - frFont = frFont.applyUnderline(line); - title.setFrFont(frFont); - title.setPosition((Integer) hAlignmentPane.getSelectedItem()); - title.setBackground(titleBackgroundPane.update()); - style.setTitle(title); - } - - private FRFont updateItalicBold(FRFont frFont) { - int italic_bold = frFont.getStyle(); - boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC); - boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC); - if (italic.isSelected() && !isItalic) { - italic_bold += Font.ITALIC; - } else if (!italic.isSelected() && isItalic) { - italic_bold -= Font.ITALIC; - } - frFont = frFont.applyStyle(italic_bold); - if (bold.isSelected() && !isBold) { - italic_bold += Font.BOLD; - } else if (!bold.isSelected() && isBold) { - italic_bold -= Font.BOLD; - } - frFont = frFont.applyStyle(italic_bold); - return frFont; - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/PredefinedStyleEditDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/PredefinedStyleEditDialog.java deleted file mode 100644 index 0bfe1f117..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/PredefinedStyleEditDialog.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.dialog; - -import com.fr.config.ServerPreferenceConfig; -import com.fr.config.predefined.PredefinedStyleConfig; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itextfield.UITextField; -import com.fr.design.mainframe.predefined.ui.PredefinedStyleEditPane; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.stable.StringUtils; - -import javax.swing.BorderFactory; -import javax.swing.JDialog; - -import javax.swing.JPanel; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -/** - * Created by kerry on 2020-08-26 - */ -public class PredefinedStyleEditDialog extends JDialog { - - public PredefinedStyleEditDialog(Window parent, PredefinedStyleEditPane contentPane) { - this(parent, contentPane, false); - } - - - public PredefinedStyleEditDialog(Window parent, PredefinedStyleEditPane contentPane, boolean isBuiltIn) { - super(parent, ModalityType.APPLICATION_MODAL); - - this.setTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Edit")); - this.setResizable(false); - JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); - this.setContentPane(defaultPane); - - UIButton saveBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Save")); - saveBtn.setEnabled(!isBuiltIn); - saveBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if(contentPane.saveStyle()){ - dialogExit(); - } - } - }); - UIButton saveAsBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Save_As_New")); - saveAsBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - SaveAsNewStyleDialog saveAsNewStyleDialog = new SaveAsNewStyleDialog(PredefinedStyleEditDialog.this, contentPane); - saveAsNewStyleDialog.setVisible(true); - - } - }); - UIButton cancelBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Cancel")); - cancelBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - dialogExit(); - } - }); - JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); - buttonPanel.add(saveBtn); - buttonPanel.add(saveAsBtn); - buttonPanel.add(cancelBtn); - - defaultPane.add(contentPane, BorderLayout.CENTER); - defaultPane.add(buttonPanel, BorderLayout.SOUTH); - - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - dialogExit(); - } - }); - - - this.setSize(new Dimension(900, 600)); - GUICoreUtils.centerWindow(this); - } - - public void dialogExit() { - this.dispose(); - } - - class SaveAsNewStyleDialog extends JDialog { - private UITextField textField; - private UILabel tipLabel; - - public SaveAsNewStyleDialog(Window parent, PredefinedStyleEditPane editPane) { - super(parent, ModalityType.APPLICATION_MODAL); - - this.setTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Save_As_New")); - this.setResizable(false); - UIButton confirm = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm")); - confirm.setEnabled(false); - confirm.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - String name = textField.getText(); - if (valid(name)) { - editPane.saveAsNewStyle(name); - dialogExit(); - PredefinedStyleEditDialog.this.dialogExit(); - } else { - tipLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Name_Repeat")); - } - } - }); - UIButton cancle = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Cancel")); - cancle.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - dialogExit(); - } - }); - JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); - JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); - buttonPanel.add(confirm); - buttonPanel.add(cancle); - - JPanel panel = createSaveAsPane(confirm); - - - defaultPane.add(panel, BorderLayout.CENTER); - defaultPane.add(buttonPanel, BorderLayout.SOUTH); - - this.setContentPane(defaultPane); - - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - dialogExit(); - } - }); - - - this.setSize(new Dimension(300, 140)); - GUICoreUtils.centerWindow(this); - } - - private JPanel createSaveAsPane(UIButton confirm) { - JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel centerPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(20, 5); - centerPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Name"))); - textField = new UITextField(); - textField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - confirm.setEnabled(StringUtils.isNotEmpty(textField.getText())); - } - - @Override - public void removeUpdate(DocumentEvent e) { - - } - - @Override - public void changedUpdate(DocumentEvent e) { - - } - }); - textField.setPreferredSize(new Dimension(180, 20)); - centerPane.add(textField); - panel.add(centerPane, BorderLayout.CENTER); - tipLabel = new UILabel(); - tipLabel.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 0)); - tipLabel.setForeground(Color.RED); - panel.add(tipLabel, BorderLayout.SOUTH); - return panel; - - - } - - - public void dialogExit() { - this.dispose(); - } - - private boolean valid(String name) { - PredefinedStyleConfig config = ServerPreferenceConfig.getInstance().getPreferenceStyleConfig(); - return !config.containStyle(name); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/ReportPredefinedStyleDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/ReportPredefinedStyleDialog.java deleted file mode 100644 index 658032a68..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/ReportPredefinedStyleDialog.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.dialog; - -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.ReportPredefinedStylePane; -import com.fr.design.mainframe.predefined.ui.ServerPredefinedStylePane; -import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.workspace.WorkContext; - -import javax.swing.JDialog; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -/** - * Created by kerry on 2020-08-26 - */ -public class ReportPredefinedStyleDialog extends JDialog { - - - public ReportPredefinedStyleDialog(Window parent, ReportPredefinedStylePane contentPane) { - super(parent, ModalityType.APPLICATION_MODAL); - - this.setTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Template_Style")); - this.setResizable(false); - JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); - this.setContentPane(defaultPane); - UIButton managerBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Style_Manager")); - managerBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - ServerPredefinedStylePane predefinedStylePane = new ServerPredefinedStylePane(); - ServerPredefinedStyleDialog dialog = new ServerPredefinedStyleDialog(ReportPredefinedStyleDialog.this, predefinedStylePane); - dialog.setVisible(true); - dialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - contentPane.refresh(); - } - }); - } - }); - - - UIButton settingBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Applicate_Style")); - settingBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - contentPane.update(); - dialogExit(); - } - }); - - UIButton cancelBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Cancel")); - cancelBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - dialogExit(); - } - }); - JPanel southPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - - if (WorkContext.getCurrent().isRoot()){ - JPanel buttonPanel1 = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); - buttonPanel1.add(managerBtn); - southPane.add(buttonPanel1, BorderLayout.CENTER); - } - - JPanel buttonPanel2 = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); - buttonPanel2.add(settingBtn); - buttonPanel2.add(cancelBtn); - - southPane.add(buttonPanel2, BorderLayout.EAST); - - defaultPane.add(contentPane, BorderLayout.CENTER); - defaultPane.add(southPane, BorderLayout.SOUTH); - - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - dialogExit(); - } - }); - - - this.setSize(new Dimension(660, 600)); - GUICoreUtils.centerWindow(this); - } - - public void dialogExit() { - this.dispose(); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/ServerPredefinedStyleDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/ServerPredefinedStyleDialog.java deleted file mode 100644 index 439bb3ec2..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/dialog/ServerPredefinedStyleDialog.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.dialog; - -import com.fr.design.mainframe.predefined.ui.ServerPredefinedStylePane; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.utils.gui.GUICoreUtils; - -import javax.swing.JDialog; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -/** - * Created by kerry on 2020-08-26 - */ -public class ServerPredefinedStyleDialog extends JDialog { - - - public ServerPredefinedStyleDialog(Window parent, ServerPredefinedStylePane contentPane) { - super(parent, ModalityType.APPLICATION_MODAL); - this.setTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Predefined_Server_Style")); - this.setResizable(false); - JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); - this.setContentPane(defaultPane); - - UIButton settingBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Set_Default")); - settingBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - contentPane.update(); - dialogExit(); - } - }); - - UIButton cancelBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Cancel")); - cancelBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - dialogExit(); - } - }); - JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); - buttonPanel.add(settingBtn); - buttonPanel.add(cancelBtn); - - defaultPane.add(contentPane, BorderLayout.CENTER); - defaultPane.add(buttonPanel, BorderLayout.SOUTH); - - addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - dialogExit(); - } - }); - - - this.setSize(new Dimension(660, 600)); - GUICoreUtils.centerWindow(this); - } - - public void dialogExit(){ - this.dispose(); - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ChartPreStylePreView.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ChartPreStylePreView.java deleted file mode 100644 index 1ca9163cb..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ChartPreStylePreView.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.preview; - -import com.fr.base.chart.BaseChartCollection; -import com.fr.base.chart.BaseChartPainter; -import com.fr.base.chart.chartdata.CallbackEvent; -import com.fr.base.chart.result.WebChartIDInfo; -import com.fr.chart.chartattr.ChartCollection; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.gui.chart.MiddleChartComponent; -import com.fr.general.Background; -import com.fr.script.Calculator; -import com.fr.stable.core.PropertyChangeListener; - -import javax.swing.BorderFactory; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; - -/** - * @author Bjorn - * @version 10.0 - * Created by Bjorn on 2020-09-28 - */ -public class ChartPreStylePreView extends MiddleChartComponent { - - private ChartCollection chartCollection; - - private double scaleX = 1.0; - private double scaleY = 1.0; - - private CallbackEvent callbackEvent; - - private static final int BOUNDS = 10; - - private Background componentBackground; - - public ChartPreStylePreView() { - } - - public ChartPreStylePreView(ChartCollection cc) { - this(cc, 1.0, 1.0); - } - - public ChartPreStylePreView(ChartCollection cc, double scaleX, double scaleY) { - this.scaleX = scaleX; - this.scaleY = scaleY; - this.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10)); - populate(cc); - } - - public void setCallbackEvent(CallbackEvent callbackEvent) { - this.callbackEvent = callbackEvent; - } - - public void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - g2d.translate(BOUNDS, BOUNDS); - g2d.scale(scaleX, scaleY); - super.paintComponent(g); - drawChart(g2d); - g2d.scale(1 / scaleX, 1 / scaleY); - g2d.translate(-BOUNDS, -BOUNDS); - } - - private void drawChart(Graphics2D g2d) { - Dimension d = getBounds().getSize(); - int chartWidth = (int) (d.width / scaleX) - BOUNDS * 2; - int chartHeight = (int) (d.height / scaleX) - BOUNDS * 2; - if (componentBackground != null) { - Graphics clipg = g2d.create(0, 0, chartWidth, chartHeight); - componentBackground.paint(clipg, clipg.getClipBounds()); - } - BaseChartPainter painter = chartCollection.createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), - WebChartIDInfo.createEmptyDesignerInfo(), chartWidth, chartHeight); - painter.paint(g2d, chartWidth, chartHeight, 0, null, callbackEvent); - } - - public void refresh(PredefinedStyle style) { - /*VanChart vanChart = chartCollection.getSelectedChartProvider(VanChart.class); - List chartThemeStyleProviders = vanChart.getChartPreStyleProvider(); - for (ChartThemeStyleProvider chartThemeStyleProvider : chartThemeStyleProviders) { - chartThemeStyleProvider.updateThemeStyle(style); - } - componentBackground = style.getComponentStyle().getBorderStyle().getBackground(); - vanChart.attrChange();*/ - } - - @Override - public void populate(BaseChartCollection cc) { - this.chartCollection = (ChartCollection) cc; - } - - @Override - public BaseChartCollection update() { - return this.chartCollection; - } - - @Override - public void addStopEditingListener(PropertyChangeListener l) { - - } - - - @Override - public void reset() { - - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ComponentPreviewPane.java deleted file mode 100644 index 1c829c0ee..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ComponentPreviewPane.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.preview; - -import com.fr.base.FRContext; -import com.fr.base.GraphHelper; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.general.Background; -import com.fr.general.FRFont; -import com.fr.general.act.BorderPacker; -import com.fr.general.act.TitlePacker; -import com.fr.stable.Constants; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; - -/** - * Created by kerry on 2020-09-04 - */ -public abstract class ComponentPreviewPane extends StyleSettingPreviewPane { - private PredefinedStyle style = new PredefinedStyle(); - private static final int SMALL_GAP = 10; - private static final int GAP = 10; - private JPanel contentPane; - private TitlePreviewPane titlePane; - - - public ComponentPreviewPane() { - this.setBackground(null); - this.setOpaque(false); - this.contentPane = createContentPane(); - this.titlePane = new TitlePreviewPane(); - this.titlePane.setPreferredSize(new Dimension(484, 35)); - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10)); - - this.add(titlePane, BorderLayout.NORTH); - this.add(contentPane, BorderLayout.CENTER); - } - - protected abstract JPanel createContentPane(); - - public void refresh() { - this.repaint(); - } - - public void refresh(PredefinedStyle style) { - this.style = style; - } - - public void paintComponents(Graphics g) { - BorderPacker borderStyle = style.getComponentStyle().getBorderStyle(); - - updateBorders(g, borderStyle); - - paintTitle(g, borderStyle.getTitle()); - - paintContentPane(g, borderStyle); - - super.paintComponents(g); - } - - private void paintContentPane(Graphics g, BorderPacker borderStyle) { - - Graphics clipg; - clipg = g.create(10, 40, this.contentPane.getWidth(), this.contentPane.getHeight()); - if (borderStyle.getBackground() != null) { - borderStyle.getBackground().paint(clipg, clipg.getClipBounds()); - } - clipg.dispose(); - } - - private void paintTitle(Graphics g, TitlePacker titlePacker) { - Background background = titlePacker.getBackground(); - if (background != null) { - background.paint(g, new Rectangle2D.Double(10, 5, this.titlePane.getWidth(), this.titlePane.getHeight())); - } - titlePane.setTitleObject(titlePacker); - titlePane.paintComponent(g); - } - - private void updateBorders(Graphics g, BorderPacker borderStyle) { - if (borderStyle != null) { - borderStyle.paint(g, new Rectangle2D.Double(SMALL_GAP, SMALL_GAP, getWidth() - GAP, getHeight() - SMALL_GAP - GAP)); - } - } - - - private class TitlePreviewPane extends JPanel { - private FRFont frFont = null; - private int titlePosition = Constants.LEFT; - - public TitlePreviewPane() { - this.setBackground(null); - this.setOpaque(false); - frFont = FRContext.getDefaultValues().getFRFont(); - } - - @Override - public void paint(Graphics g) { - - } - - public void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - Dimension d = getSize(); - if (frFont == null) { - return; - } - FontMetrics fm = getFontMetrics(frFont); - if (this.isEnabled()) { - g2d.setColor(frFont.getForeground()); - } else { - g2d.setColor(new Color(237, 237, 237)); - } - g2d.setFont(frFont.applyResolutionNP(96)); - String paintText = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Preview_Title_Text"); - int startY = 0, startX = 0; - startX = (d.width - fm.stringWidth(paintText)) / 2; - startY = (d.height - fm.getHeight()) / 2 + fm.getAscent(); - if (this.titlePosition == Constants.LEFT) { - startX = GAP; - } else if (this.titlePosition == Constants.RIGHT) { - startX = d.width - fm.stringWidth(paintText) - GAP - fm.getMaxAdvance(); - } - GraphHelper.drawString(g2d, paintText, startX, startY); - - } - - public void setTitleObject(TitlePacker titlePacker) { - this.frFont = titlePacker.getFrFont(); - this.titlePosition = titlePacker.getPosition(); - } - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ElementCasePreview.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ElementCasePreview.java deleted file mode 100644 index a7ec75e89..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/ElementCasePreview.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.preview; - -import com.fr.base.ScreenResolution; -import com.fr.base.Style; -import com.fr.config.predefined.PredefinedCellStyle; -import com.fr.config.predefined.PredefinedCellStyleConfig; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.log.FineLoggerFactory; -import com.fr.third.javax.annotation.Nonnull; -import javax.swing.JComponent; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -/** - * Created by kerry on 2020-09-04 - */ -public class ElementCasePreview extends ComponentPreviewPane { - private static final List PREVIEW_DATA_LIST = new ArrayList<>(); - private static final String BLANK_CHAR = " "; - private List gridRowPanes; - - static { - readPreviewData(); - } - - private static void readPreviewData() { - try { - InputStream inputStream = ElementCasePreview.class.getResourceAsStream("/com/fr/design/mainframe/predefined/previewData"); - BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, - StandardCharsets.UTF_8)); - String lineTxt = null; - while ((lineTxt = br.readLine()) != null) { - String[] data = lineTxt.split(BLANK_CHAR); - PREVIEW_DATA_LIST.add(data); - } - br.close(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - - @Override - protected JPanel createContentPane() { - gridRowPanes = new ArrayList<>(); - JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); - jPanel.setOpaque(false); - jPanel.setBackground(null); - for (int i = 0; i < PREVIEW_DATA_LIST.size(); i++) { - GridRowPane gridRowPane = new GridRowPane(PREVIEW_DATA_LIST.get(i), Style.DEFAULT_STYLE); - gridRowPanes.add(gridRowPane); - jPanel.add(gridRowPane); - } - return jPanel; - } - - - public void refresh(PredefinedStyle style) { - super.refresh(style); - PredefinedCellStyleConfig cellStyleConfig = style.getCellStyleConfig(); - for (int i = 0; i < gridRowPanes.size(); i++) { - Style renderStyle = getMainContentStyle(cellStyleConfig); - if (i == 0) { - renderStyle = getReportHeaderStyle(cellStyleConfig); - } - if (i == PREVIEW_DATA_LIST.size() - 1) { - renderStyle = getHighLightStyle(cellStyleConfig); - } - gridRowPanes.get(i).preview(renderStyle); - } - } - - - private Style getReportHeaderStyle(PredefinedCellStyleConfig config) { - return getCellStyle(config, Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); - } - - private Style getMainContentStyle(PredefinedCellStyleConfig config) { - return getCellStyle(config, Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text")); - } - - private Style getHighLightStyle(PredefinedCellStyleConfig config) { - return getCellStyle(config, Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text")); - } - - @Nonnull - private Style getCellStyle(PredefinedCellStyleConfig config, String styleName) { - PredefinedCellStyle cellStyle = config.getStyle(styleName); - if (cellStyle == null) { - return Style.DEFAULT_STYLE; - } - return cellStyle.getStyle(); - } - - - class GridRowPane extends JPanel { - private List gridPreviews = new ArrayList<>(); - - public GridRowPane(String[] data, Style style) { - this.setOpaque(false); - this.setBackground(null); - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel panel = FRGUIPaneFactory.createNColumnGridInnerContainer_Pane(4, 0, 0); - panel.setOpaque(false); - panel.setBackground(null); - for (String text : data) { - GridPreview gridPreview = new GridPreview(text); - gridPreviews.add(gridPreview); - panel.add(gridPreview); - } - this.add(panel, BorderLayout.CENTER); - preview(style); - } - - public void preview(Style style) { - for (GridPreview grid : gridPreviews) { - grid.preview(style); - } - } - } - - - private static class GridPreview extends JComponent { - - private Style style = Style.DEFAULT_STYLE; - private String value; - - public GridPreview(String value) { - this.value = value; - setPreferredSize(new Dimension(125, 30)); - } - - public void preview(Style style) { - this.style = style; - } - - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - int resolution = ScreenResolution.getScreenResolution(); - - if (style == Style.DEFAULT_STYLE) { - Style.paintContent(g2d, value, style, getWidth() - 3, getHeight() - 3, resolution); - return; - } - - Style.paintBackground(g2d, style, getWidth(), getHeight()); - - Style.paintContent(g2d, value, style, getWidth() - 3, getHeight() - 3, resolution); - - Style.paintBorder(g2d, style, getWidth() , getHeight() ); - } - - - @Override - public Dimension getMinimumSize() { - return getPreferredSize(); - } - } - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/PredefinedStylePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/PredefinedStylePreviewPane.java deleted file mode 100644 index 5b6d20049..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/PredefinedStylePreviewPane.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.preview; - -import com.fr.base.background.ColorBackground; -import com.fr.base.chart.chartdata.CallbackEvent; -import com.fr.chart.chartattr.ChartCollection; -import com.fr.chart.chartattr.Title; -import com.fr.chart.charttypes.ChartTypeManager; -import com.fr.config.predefined.PredefinedStyle; -import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.utils.ComponentUtils; -import com.fr.general.Background; -import com.fr.log.FineLoggerFactory; -import com.fr.plugin.chart.attr.axis.VanChartAxis; -import com.fr.plugin.chart.base.AttrLabel; -import com.fr.plugin.chart.base.VanChartTools; -import com.fr.plugin.chart.column.VanChartColumnPlot; -import com.fr.plugin.chart.vanchart.VanChart; - -import javax.swing.JComponent; -import javax.swing.JPanel; -import java.util.ArrayList; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; - -/** - * Created by kerry on 2020-09-06 - */ -public class PredefinedStylePreviewPane extends StyleSettingPreviewPane implements CallbackEvent { - private ElementCasePreview elementCasePreview; - private Background background; - private double scaleX = 1.0; - private double scaleY = 1.0; - private ChartPreStylePreView columnChartPane; - - private int COLUMN_CHART_WIDTH = 517; - private int COLUMN_CHART_HEIGHT = 290; - - private JPanel parent; - - public PredefinedStylePreviewPane() { - this(1.0, 1.0); - } - - public PredefinedStylePreviewPane(double scaleX, double scaleY) { - this.scaleX = scaleX; - this.scaleY = scaleY; - this.setBackground(Color.WHITE); - this.elementCasePreview = new ElementCasePreview(); - this.add(initChartPreViewPane()); - this.elementCasePreview.setPreferredSize(new Dimension(517, 200)); - this.add(this.elementCasePreview); - } - - public void setParent(JPanel parent) { - this.parent = parent; - } - - private JPanel initChartPreViewPane() { - columnChartPane = new ChartPreStylePreView(initVanColumnChart()); - columnChartPane.setPreferredSize(new Dimension(COLUMN_CHART_WIDTH, COLUMN_CHART_HEIGHT)); - columnChartPane.setCallbackEvent(this); - - JPanel panel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - panel.add(columnChartPane); - return panel; - } - - //柱形图 - private ChartCollection initVanColumnChart() { - try { - VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID)[0].clone(); - VanChartTools vanChartTools = chart.getVanChartTools(); - vanChartTools.setSort(false); - vanChartTools.setExport(false); - vanChartTools.setFullScreen(false); - VanChartColumnPlot plot = chart.getPlot(); - AttrLabel defaultAttrLabel = plot.getDefaultAttrLabel(); - defaultAttrLabel.setEnable(true); - defaultAttrLabel.getAttrLabelDetail().getBorder().setBorderStyle(0); - defaultAttrLabel.getAttrLabelDetail().getBackground().setBackground(null); - plot.getConditionCollection().getDefaultAttr().addDataSeriesCondition(defaultAttrLabel); - plot.getLegend().setLegendVisible(false); - plot.getDataSheet().setVisible(true); - - VanChartAxis defaultYAxis = plot.getDefaultYAxis(); - Title title = new Title(); - title.setTextObject(Toolkit.i18nText("Fine-Design_Chart_Axis_Title")); - title.getTextAttr().setRotation(-90); - defaultYAxis.setTitle(title); - defaultYAxis.setShowAxisTitle(true); - - ChartCollection chartCollection = new ChartCollection(chart); - return chartCollection; - } catch (Exception ex) { - FineLoggerFactory.getLogger().error(ex.getMessage(), ex); - } - return null; - } - - @Override - public void refresh() { - - } - - @Override - public void paint(Graphics g) { - ((Graphics2D) g).scale(scaleX, scaleY); - // 禁止双缓冲 - ArrayList dbcomponents = new ArrayList(); - ComponentUtils.disableBuffer(this.elementCasePreview, dbcomponents); - - if (background == null) { - background = ColorBackground.getInstance(Color.WHITE); - } - background.paint(g, new Rectangle2D.Double(0, 0, 517, 500)); - this.columnChartPane.paintComponent(g); - - g.translate(0, COLUMN_CHART_HEIGHT); - this.elementCasePreview.paintComponents(g); - g.translate(0, -COLUMN_CHART_HEIGHT); - // 恢复双缓冲 - ComponentUtils.resetBuffer(dbcomponents); - - } - - @Override - public void paintComponents(Graphics g) { - super.paintComponents(g); - if (background != null) { - background.paint(g, new Rectangle2D.Double(0, 0, this.getWidth(), this.getHeight())); - } - } - - public void refresh(PredefinedStyle style) { - refresh(style, false); - } - - public void refresh(PredefinedStyle style, boolean displayFormBackground) { - elementCasePreview.refresh(style); - columnChartPane.refresh(style); - background = displayFormBackground ? style.getFormBackground().getBackground() : style.getReportBackground(); - this.repaint(); - } - - @Override - public void callback() { - if (parent != null) { - parent.repaint(); - } else { - this.repaint(); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/StyleSettingPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/StyleSettingPreviewPane.java deleted file mode 100644 index 4fff5841e..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/preview/StyleSettingPreviewPane.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.fr.design.mainframe.predefined.ui.preview; - -import javax.swing.JPanel; - -/** - * Created by kerry on 2020-08-31 - */ -public abstract class StyleSettingPreviewPane extends JPanel { - public StyleSettingPreviewPane() { - - } - - - public abstract void refresh(); - - -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java b/designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java index cec7fbc8f..244582612 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java @@ -34,6 +34,10 @@ public class ComponentShareUtil { return localeMark.getValue(); } + public static boolean isShowMiniShopWindow() { + return isShowOnlineWidgetRepoPane(); + } + /** * 判断是否可触达 * diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopDisposingChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopDisposingChecker.java new file mode 100644 index 000000000..dd76befe6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopDisposingChecker.java @@ -0,0 +1,37 @@ +package com.fr.design.mainframe.share.mini; + +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; + +import javax.swing.JOptionPane; +import java.awt.Component; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/8 + */ +public class MiniShopDisposingChecker { + + public static boolean check() { + return check(DesignerContext.getDesignerFrame()); + } + + public static boolean check(Component optionParentComponent) { + if (MiniShopNativeTaskManager.getInstance().hasExecutingTasks()) { + int result = FineJOptionPane.showConfirmDialog( + optionParentComponent, + Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Close_Tip"), + "", + FineJOptionPane.YES_NO_OPTION + ); + if (result == JOptionPane.YES_OPTION) { + MiniShopNativeTaskManager.getInstance().cancelAllExecutingTasks(); + return true; + } + return false; + } + return true; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTask.java b/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTask.java new file mode 100644 index 000000000..9144f2fa0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTask.java @@ -0,0 +1,11 @@ +package com.fr.design.mainframe.share.mini; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/8 + */ +public interface MiniShopNativeTask { + void execute(); + void cancel(); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTaskManager.java b/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTaskManager.java new file mode 100644 index 000000000..514ff84c8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/mini/MiniShopNativeTaskManager.java @@ -0,0 +1,42 @@ +package com.fr.design.mainframe.share.mini; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/8 + */ +public class MiniShopNativeTaskManager { + private MiniShopNativeTaskManager() { + } + private static class HOLDER { + private static final MiniShopNativeTaskManager singleton = new MiniShopNativeTaskManager(); + } + public static MiniShopNativeTaskManager getInstance() { + return MiniShopNativeTaskManager.HOLDER.singleton; + } + + + private static final Set executingTasks = new HashSet<>(); + + public void addStartedTask(MiniShopNativeTask task) { + executingTasks.add(task); + } + + public void removeCompletedTask(MiniShopNativeTask task) { + executingTasks.remove(task); + } + + public boolean hasExecutingTasks() { + return !executingTasks.isEmpty(); + } + + public void cancelAllExecutingTasks() { + for (MiniShopNativeTask executingTask: executingTasks) { + executingTask.cancel(); + } + executingTasks.clear(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java index 9e88dfba1..92acb5c71 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java @@ -206,7 +206,7 @@ public abstract class TemplateThemeProfilePane extends }); } - public UIButton createSaveButton() { + public UIButton createSaveButton(final TemplateThemeProfileDialog profileDialog) { saveButton = new UIButton(); saveButton.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save")); saveButton.setEnabled(false); @@ -224,6 +224,7 @@ public abstract class TemplateThemeProfilePane extends @Override public void run() { DesignerToastMsgUtil.toastPrompt(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save_Successfully")); + profileDialog.exit(); } }); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java index da0649d80..bf65b9be2 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java @@ -7,6 +7,7 @@ import com.fr.design.mainframe.theme.TemplateThemeGridPagesPane; import com.fr.design.mainframe.theme.TemplateThemeGridPane; import javax.swing.JPanel; +import java.awt.Window; /** * @author Starryi @@ -19,13 +20,17 @@ public class TemplateThemeGridPagesDialog extends TemplateThemeDialog implements protected TemplateThemeGridPagesPane overallPane; - public TemplateThemeGridPagesDialog() { - super(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"), CONTENT_WIDTH, CONTENT_HEIGHT); + public TemplateThemeGridPagesDialog(Window parentWindow) { + super(parentWindow, Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"), CONTENT_WIDTH, CONTENT_HEIGHT); setupContentPane(); setupActionButtons(); } + public TemplateThemeGridPagesDialog() { + this(DesignerContext.getDesignerFrame()); + } + @Override protected JPanel createContentPane() { overallPane = new TemplateThemeGridPagesPane(this); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java index a76597f8e..0a26a6691 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java @@ -90,7 +90,7 @@ public class TemplateThemeProfileDialog extends Templat })); } - uiButtonList.add(profilePane.createSaveButton()); + uiButtonList.add(profilePane.createSaveButton(TemplateThemeProfileDialog.this)); uiButtonList.add(profilePane.createSaveAsButton(TemplateThemeProfileDialog.this)); uiButtonList.add(createCancelButton()); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java index 420a7ed43..9818e60b5 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java @@ -1,11 +1,18 @@ package com.fr.design.mainframe.theme.dialog; +import java.awt.Window; + /** * @author Starryi * @version 1.0 * Created by Starryi on 2021/8/13 */ public class TemplateThemeUsingDialog extends TemplateThemeGridPagesDialog { + public TemplateThemeUsingDialog(Window parentWindow) { + super(parentWindow); + overallPane.showThemeUsingPane(); + } + public TemplateThemeUsingDialog() { super(); overallPane.showThemeUsingPane(); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java index ec36c2970..4a1446025 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java @@ -8,13 +8,11 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.mainframe.predefined.ui.detail.background.BackgroundSettingPane; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; -import javax.swing.SwingConstants; import java.awt.BorderLayout; import java.awt.Component; diff --git a/designer-base/src/main/java/com/fr/design/report/fit/AdaptiveFrmFitAttrModel.java b/designer-base/src/main/java/com/fr/design/report/fit/AdaptiveFrmFitAttrModel.java index 9e60c6cc8..8c5e8858a 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/AdaptiveFrmFitAttrModel.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/AdaptiveFrmFitAttrModel.java @@ -13,11 +13,7 @@ import com.fr.report.fit.ReportFitAttr; public class AdaptiveFrmFitAttrModel extends AbstractFitAttrModelProvider { public FitType[] getFitTypes() { - return new FitType[]{ - FitType.DOUBLE_FIT, - FitType.HORIZONTAL_FIT, - FitType.NOT_FIT - }; + return new FitType[0]; } public String getFitName() { diff --git a/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java b/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java index 2c38d597c..48d6a5686 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java @@ -2,27 +2,17 @@ package com.fr.design.report.fit; import com.fr.design.ExtraDesignClassManager; import com.fr.design.beans.BasicBeanPane; -import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.report.fit.menupane.FitPreviewPane; -import com.fr.design.report.fit.menupane.FitRadioGroup; -import com.fr.design.report.fit.menupane.FontRadioGroup; import com.fr.design.report.fit.provider.FitAttrModelProvider; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.ComparatorUtils; import com.fr.report.fit.ReportFitAttr; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ItemListener; import java.util.ArrayList; -import java.util.Arrays; import java.util.Comparator; import java.util.Set; import java.util.stream.Collectors; @@ -35,11 +25,8 @@ public abstract class BaseFitAttrPane extends BasicBeanPane { protected UILabel belowSetLabel; protected UIComboBox itemChoose; protected java.util.List fitAttrModelList = new ArrayList<>(); + private ReportFitConfigPane fitConfigPane; - public FontRadioGroup fontRadioGroup; - public FitRadioGroup adaptRadioGroup; - public JPanel attrJPanel; - public FitPreviewPane previewJPanel; public FitAttrModel fitAttrModel; private static final int BELOW_SET_COMPONENT_HSPACE = 8; @@ -64,128 +51,27 @@ public abstract class BaseFitAttrPane extends BasicBeanPane { protected void populateModel(FitAttrModel fitAttrModel) { this.fitAttrModel = fitAttrModel; - if (attrJPanel != null) { - contentJPanel.remove(attrJPanel); + if (fitConfigPane != null) { + contentJPanel.remove(fitConfigPane); } - if (previewJPanel != null) { - contentJPanel.remove(previewJPanel); - } - - fontRadioGroup = new FontRadioGroup(); - adaptRadioGroup = new FitRadioGroup(); - initAttrJPanel(); - initPreviewJPanel(); + this.fitConfigPane = fitAttrModel instanceof CptFitAttrModel ? new ReportFitConfigPane(fitAttrModel, true) : new FormFitConfigPane(fitAttrModel, true); + contentJPanel.add(fitConfigPane); } - - protected void initAttrJPanel() { - int colCount = fitAttrModel.getFitTypes().length + 1; - Component[][] components = new Component[2][colCount]; - initFitRadioGroup(fontRadioGroup, i18nText("Fine-Designer_Fit-Font"), new String[]{i18nText("Fine-Designer_Fit"), i18nText("Fine-Designer_Fit-No")}, components[0]); - initFitRadioGroup(adaptRadioGroup, fitAttrModel.getFitName(), Arrays.stream(fitAttrModel.getFitTypes()).map(FitType::description).toArray(String[]::new), components[1]); - - double[] rowSize = new double[2]; - double[] columnSize = new double[colCount]; - for (int i = 0; i < rowSize.length; i++) { - rowSize[i] = 20; - } - for (int i = 0; i < columnSize.length; i++) { - if (i == 0) { - columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.firstColumn").getWidth(); - } else { - columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.column").getWidth(); - } - } - - attrJPanel = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); - attrJPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); - contentJPanel.add(attrJPanel); - } - - private void initFitRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { - components[0] = new UILabel(name); - for (int i = 0; i < options.length; i++) { - - if (options[i] != null) { - UIRadioButton fontFitRadio = new UIRadioButton(options[i]); - fitRadioGroup.add(fontFitRadio); - components[i + 1] = fontFitRadio; - } else { - components[i + 1] = null; - } - } - fitRadioGroup.addActionListener(getPreviewActionListener()); - } - - protected ActionListener getPreviewActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - refreshPreviewJPanel(); - } - }; - } - - protected void refreshPreviewJPanel() { - String previewIndex = getPreviewIndex(); - previewJPanel.refreshPreview(previewIndex, fontRadioGroup.isEnabled()); - } - - protected String getPreviewIndex() { - return getStateInPC(adaptRadioGroup.getSelectRadioIndex()) + "" + fontRadioGroup.getSelectRadioIndex(); - } - - protected void initPreviewJPanel() { - previewJPanel = new FitPreviewPane(); - previewJPanel.setBorder(BorderFactory.createEmptyBorder(0, getPreviewJPanelLeft(), 0, 0)); - contentJPanel.add(previewJPanel); - } - - private int getPreviewJPanelLeft() { - int left = 0; - if (belowSetLabel.getPreferredSize() != null) { - left = belowSetLabel.getPreferredSize().width + BELOW_SET_COMPONENT_HSPACE; - } - return left; - } - - protected int getStateInPC(int index) { - FitType[] fitTypes = fitAttrModel.getFitTypes(); - return fitTypes[index].getState(); - } - - protected int getOptionIndex(int state) { - FitType[] fitTypes = fitAttrModel.getFitTypes(); - for (int i = 0; i < fitTypes.length; i++) { - if (ComparatorUtils.equals(state, fitTypes[i].getState())) { - return i; - } - } - return 0; - } - - @Override public void populateBean(ReportFitAttr ob) { - fontRadioGroup.selectIndexButton(ob.isFitFont() ? 0 : 1); - adaptRadioGroup.selectIndexButton(getOptionIndex(ob.fitStateInPC())); - refreshPreviewJPanel(); + this.fitConfigPane.populateBean(ob); } @Override public ReportFitAttr updateBean() { - ReportFitAttr reportFitAttr = new ReportFitAttr(); - reportFitAttr.setFitFont(fontRadioGroup.isFontFit()); - reportFitAttr.setFitStateInPC(getStateInPC(adaptRadioGroup.getSelectRadioIndex())); - return reportFitAttr; + return this.fitConfigPane.updateBean(); } public void setEnabled(boolean enabled) { super.setEnabled(enabled); - fontRadioGroup.setEnabled(enabled); - adaptRadioGroup.setEnabled(enabled); - refreshPreviewJPanel(); + this.fitConfigPane.setEnabled(enabled); } @Override diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java b/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java index 1d1ac02f0..2a834eebd 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java @@ -3,6 +3,8 @@ package com.fr.design.report.fit; import com.fr.design.mainframe.JTemplate; import com.fr.report.fit.ReportFitAttr; +import java.util.Arrays; + public interface FitAttrModel { /** * @Description 名称,比如:普通报表、决策报表等 @@ -19,6 +21,12 @@ public interface FitAttrModel { **/ FitType[] getFitTypes(); + /** + * @Description 表格自适应选项名称集合 + **/ + default String[] getFitTypeNames(){ + return Arrays.stream(getFitTypes()).map(FitType::description).toArray(String[]::new); + } /** * @Description 获取全局的自适应属性 @@ -41,4 +49,5 @@ public interface FitAttrModel { * @param: jTemplate **/ boolean isAvailable(JTemplate jTemplate); + } diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FitType.java b/designer-base/src/main/java/com/fr/design/report/fit/FitType.java index 00aceb6eb..dd4888b4e 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/FitType.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/FitType.java @@ -60,6 +60,17 @@ public enum FitType { return DEFAULT; } + public static FitType parseByFitState(int state) { + + for (FitType attrState : values()) { + if (attrState.state == state) { + return attrState; + } + } + + return DEFAULT; + } + public int getState() { return this.state; } diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FormFitAttrModelType.java b/designer-base/src/main/java/com/fr/design/report/fit/FormFitAttrModelType.java new file mode 100644 index 000000000..c43aa057d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/FormFitAttrModelType.java @@ -0,0 +1,128 @@ +package com.fr.design.report.fit; + + +import com.fr.design.designer.properties.items.Item; +import com.fr.form.fit.common.LightTool; +import com.fr.form.main.BodyScaleAttrTransformer; +import com.fr.form.main.Form; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.form.ui.container.WBodyLayoutType; +import com.fr.form.ui.container.WFitLayout; + +public enum FormFitAttrModelType { + PLAIN_FORM_FIT_ATTR_MODEL { + @Override + public FitAttrModel getFitAttrModel() { + return new FrmFitAttrModel(); + } + + @Override + public Item[] getFitLayoutScaleAttr() { + return new Item[]{ + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WFitLayout.STATE_FULL), + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Horizontal_Adaptive"), WFitLayout.STATE_ORIGIN)}; + + } + + @Override + public Item[] getAbsoluteLayoutSaleAttr() { + return new Item[]{ + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WAbsoluteLayout.STATE_FIT), + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit-No"), WAbsoluteLayout.STATE_FIXED) + }; + } + + + @Override + public int getScaleAttrShowIndex(WFitLayout wFitLayout) { + int scale = wFitLayout.getScaleAttr(); + if (wFitLayout.getBodyLayoutType() == WBodyLayoutType.FIT) { + return BodyScaleAttrTransformer.getFitBodyCompStateFromScaleAttr(scale); + } else { + return BodyScaleAttrTransformer.getAbsoluteBodyCompStateFromScaleAttr(scale); + } + } + + @Override + public int parseScaleAttrFromShowIndex(int showIndex, WBodyLayoutType wBodyLayoutType) { + if (wBodyLayoutType == WBodyLayoutType.FIT) { + if (showIndex == 0) { + return WFitLayout.SCALE_FULL; + } else { + return WFitLayout.SCALE_HOR; + } + } else { + if (showIndex == 0) { + return WFitLayout.SCALE_FULL; + } else { + return WFitLayout.SCALE_NO; + } + } + } + + + }, + NEW_FORM_FIT_ATTR_MODEL { + @Override + public FitAttrModel getFitAttrModel() { + return new AdaptiveFrmFitAttrModel(); + } + + @Override + public Item[] getFitLayoutScaleAttr() { + return new Item[]{ + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WFitLayout.STATE_FULL), + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Horizontal_Adaptive"), WFitLayout.STATE_ORIGIN), + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit-No"), 2)}; + } + + @Override + public Item[] getAbsoluteLayoutSaleAttr() { + return new Item[]{ + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WFitLayout.STATE_FULL), + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Horizontal_Adaptive"), WFitLayout.STATE_ORIGIN), + new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit-No"), 2)}; + } + + + @Override + public int getScaleAttrShowIndex(WFitLayout wFitLayout) { + int scale = wFitLayout.getScaleAttr(); + if (scale == WFitLayout.SCALE_NO) { + return 2; + } else if (scale == WFitLayout.SCALE_HOR) { + return 1; + } else { + return 0; + } + } + + @Override + public int parseScaleAttrFromShowIndex(int showIndex, WBodyLayoutType wBodyLayoutType) { + if (showIndex == 0) { + return WFitLayout.SCALE_FULL; + } else if (showIndex == 1) { + return WFitLayout.SCALE_HOR; + } else { + return WFitLayout.SCALE_NO; + } + } + + + }; + + public abstract FitAttrModel getFitAttrModel(); + + public abstract Item[] getFitLayoutScaleAttr(); + + public abstract Item[] getAbsoluteLayoutSaleAttr(); + + public abstract int getScaleAttrShowIndex(WFitLayout wFitLayout); + + public abstract int parseScaleAttrFromShowIndex(int showIndex, WBodyLayoutType wBodyLayoutType); + + + public static FormFitAttrModelType parse(Form form) { + return LightTool.containNewFormFlag(form) ? NEW_FORM_FIT_ATTR_MODEL : PLAIN_FORM_FIT_ATTR_MODEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java b/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java new file mode 100644 index 000000000..d88a3a16e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java @@ -0,0 +1,163 @@ +package com.fr.design.report.fit; + +import com.fr.base.svg.SVGLoader; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.imenu.UIPopupMenu; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.report.fit.menupane.FitRadioGroup; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.ComparatorUtils; +import com.fr.report.fit.ReportFitAttr; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class FormFitConfigPane extends ReportFitConfigPane { + private static final int ICON_OFFSET_X = 25; + private static final int ICON_OFFSET_Y = 3; + private static final int ICON_SIZE = 16; + private static final Image HOVER_IMAGE = SVGLoader.load("/com/fr/design/icon/icon_ec_default_fit.svg"); + private static final int DEFAULT_ITEM = 0; + + private static final int CUSTOM_ITEM = 1; + + public FormFitConfigPane(FitAttrModel fitAttrModel) { + this(fitAttrModel, false); + } + + public FormFitConfigPane(FitAttrModel fitAttrModel, boolean globalConfig) { + super(fitAttrModel, globalConfig); + } + + protected JPanel initECConfigPane() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + if (fitAttrModel.getFitTypeNames().length != 0) { + Component[] ecComponents = new Component[fitAttrModel.getFitTypeNames().length + 1]; + initRadioGroup(ecConfigRadioGroup, fitAttrModel.getFitName(), fitAttrModel.getFitTypeNames(), ecComponents); + jPanel.add(createSubAttrPane(ecComponents), BorderLayout.CENTER); + jPanel.add(createTipPane(), BorderLayout.SOUTH); + } + return jPanel; + } + + protected void initRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { + components[0] = new UILabel(name); + for (int i = 0; i < options.length; i++) { + if (options[i] != null) { + UIRadioButton fontFitRadio = ComparatorUtils.equals(options[i], Toolkit.i18nText("Fine-Designer_Fit-Default")) ? new UIRadioButtonWithIcon(options[i]) : new UIRadioButton(options[i]); + fitRadioGroup.add(fontFitRadio); + components[i + 1] = fontFitRadio; + } else { + components[i + 1] = null; + } + } + fitRadioGroup.addActionListener(getPreviewActionListener()); + } + + private class UIRadioButtonWithIcon extends UIRadioButton { + private final JPopupMenu popupMenu; + private NewFitPreviewPane ecFitPreviewPane; + + public UIRadioButtonWithIcon(String text) { + super(text); + popupMenu = this.createPopupMenu(); + initMouseListener(); + } + + private JPopupMenu createPopupMenu() { + UIPopupMenu uiPopupMenu = new UIPopupMenu() { + @Override + protected void paintBorder(Graphics g) { + + } + }; + uiPopupMenu.setLayout(new BorderLayout(0, 0)); + uiPopupMenu.setOpaque(false); + uiPopupMenu.add(ecFitPreviewPane = new NewFitPreviewPane(FitType.HORIZONTAL_FIT), BorderLayout.CENTER); + ecFitPreviewPane.setPreferredSize(new Dimension(300, 204)); + return uiPopupMenu; + } + + private void initMouseListener() { + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + super.mouseExited(e); + hidePreviewPane(); + } + }); + int defaultTextWidth = calculateStartX(); + this.addMouseMotionListener(new MouseAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + super.mouseMoved(e); + if (new Rectangle(ICON_OFFSET_X + defaultTextWidth, ICON_OFFSET_Y, ICON_SIZE, ICON_SIZE).contains(e.getPoint())) { + showPreviewPane(e); + } else { + hidePreviewPane(); + } + + } + }); + } + + public void showPreviewPane(MouseEvent e) { + popupMenu.setVisible(true); + ecFitPreviewPane.refreshPreview(fontRadioGroup.isFontFit()); + GUICoreUtils.showPopupMenu(popupMenu, this, e.getX() + 10, e.getY() + 10); + } + + public void hidePreviewPane() { + if (popupMenu != null && popupMenu.isVisible()) { + popupMenu.setVisible(false); + } + } + + + @Override + public void paint(Graphics g) { + super.paint(g); + g.drawImage(HOVER_IMAGE, calculateStartX() + ICON_OFFSET_X, ICON_OFFSET_Y, null); + } + + private int calculateStartX() { + FontMetrics metrics = this.getFontMetrics(this.getFont()); + return metrics.stringWidth(this.getText()); + } + } + + private JPanel createTipPane() { + JPanel jPanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); + UILabel label1 = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_FIT_Config_Tip1")); + jPanel.add(label1); + label1.setForeground(Color.lightGray); + UILabel label2 = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_FIT_Config_Tip2")); + jPanel.add(label2); + label2.setForeground(Color.lightGray); + return jPanel; + } + + protected void refreshPreviewJPanel() { + previewJPanel.refreshPreview(fontRadioGroup.isFontFit()); + } + + protected void populateECConfigRadioGroup(int fitStateInPC) { + ecConfigRadioGroup.selectIndexButton(fitStateInPC == 0 ? DEFAULT_ITEM : CUSTOM_ITEM); + } + + protected void updateECConfigRadioGroup(ReportFitAttr reportFitAttr) { + reportFitAttr.setFitStateInPC(ecConfigRadioGroup.getSelectRadioIndex()); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java b/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java index c4bdaf6de..81ee474de 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java @@ -17,7 +17,7 @@ public class FrmFitAttrModel implements FitAttrModel { @Override public String getFitName() { - return Toolkit.i18nText("Fine-Designer_Fit-Element"); + return Toolkit.i18nText("Fine-Design_Form_PC_FIT_Config_EC_Label"); } public FitType[] getFitTypes() { @@ -29,6 +29,13 @@ public class FrmFitAttrModel implements FitAttrModel { }; } + @Override + public String[] getFitTypeNames() { + return new String[]{ + Toolkit.i18nText("Fine-Designer_Fit-Default"), Toolkit.i18nText("Fine-Design_Basic_Custom") + }; + } + @Override public ReportFitAttr getGlobalReportFitAttr() { return ReportFitConfig.getInstance().getFrmFitAttr(); diff --git a/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java b/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java new file mode 100644 index 000000000..2bc69cedc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java @@ -0,0 +1,79 @@ +package com.fr.design.report.fit; + +import com.fr.base.GraphHelper; +import com.fr.general.FRFont; + +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; + + +public class NewFitPreviewPane extends JPanel { + private boolean fitFont = false; + private FitType fitType = FitType.DOUBLE_FIT; + private static final Color DEFAULT_PAINT_COLOR = Color.decode("#419BF9"); + private static final int FIT_FONT_SIZE = 15; + private static final int NO_FIT_FONT_SIZE = 10; + private static final Dimension NO_FIT_CONTAINER_DIMENSION = new Dimension(230, 80); + + public NewFitPreviewPane(){ + + } + + public NewFitPreviewPane(FitType fitType){ + this.fitType = fitType; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + g.setColor(Color.GRAY); + GraphHelper.drawRect(g, 1, 1, this.getWidth() - 2, this.getHeight() - 2); + g.setColor(DEFAULT_PAINT_COLOR); + FRFont textFont = FRFont.getInstance(FRFont.DEFAULT_FONTNAME, Font.PLAIN, fitFont ? FIT_FONT_SIZE : NO_FIT_FONT_SIZE); + g.setFont(textFont); + Dimension dimension = calculateCellDimension(); + GraphHelper.drawLine(g, 1, dimension.height, dimension.width * 2 - 1, dimension.height); + GraphHelper.drawLine(g, dimension.width, 1, dimension.width, dimension.height * 2 - 1); + GraphHelper.drawRect(g, 1, 1, dimension.width * 2 - 2, dimension.height * 2 - 2); + double startX = calculateTextDrawStartX(dimension.width, this.getFontMetrics(textFont), "text1"); + double startY = calculateTextDrawStartY(dimension.height); + GraphHelper.drawString(g, "text1", startX, startY); + GraphHelper.drawString(g, "text2", dimension.width + startX, startY); + GraphHelper.drawString(g, "text3", startX, dimension.height + startY); + GraphHelper.drawString(g, "text4", dimension.width + startX, dimension.height + startY); + } + + private Dimension calculateCellDimension() { + if (fitType == FitType.DOUBLE_FIT) { + return new Dimension(this.getWidth() / 2, this.getHeight() / 2); + } else if (fitType == FitType.NOT_FIT) { + return new Dimension(NO_FIT_CONTAINER_DIMENSION.width / 2, NO_FIT_CONTAINER_DIMENSION.height / 2); + } else { + return new Dimension(this.getWidth() / 2, NO_FIT_CONTAINER_DIMENSION.height / 2); + } + } + + private double calculateTextDrawStartX(int containerWidth, FontMetrics fontMetrics, String text) { + return (containerWidth - fontMetrics.stringWidth(text)) / 2.0D; + } + + private double calculateTextDrawStartY(int containerHeight) { + return containerHeight / 2.0D; + } + + public void refreshPreview(boolean fitFont, FitType fitType) { + this.fitFont = fitFont; + this.fitType = fitType; + repaint(); + } + + public void refreshPreview(boolean fitFont) { + this.fitFont = fitFont; + repaint(); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java b/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java new file mode 100644 index 000000000..158089602 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java @@ -0,0 +1,172 @@ +package com.fr.design.report.fit; + +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.DesignSizeI18nManager; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.report.fit.menupane.FitRadioGroup; +import com.fr.design.report.fit.menupane.FontRadioGroup; +import com.fr.general.ComparatorUtils; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import static com.fr.design.i18n.Toolkit.i18nText; + +public class ReportFitConfigPane extends JPanel { + public FontRadioGroup fontRadioGroup; + public FitRadioGroup ecConfigRadioGroup; + protected NewFitPreviewPane previewJPanel; + protected FitAttrModel fitAttrModel; + protected boolean globalConfig; + + + public ReportFitConfigPane(FitAttrModel fitAttrModel, boolean globalConfig) { + this.fitAttrModel = fitAttrModel; + this.globalConfig = globalConfig; + initComponent(); + } + + private void initComponent() { + JPanel contentJPanel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(false, FlowLayout.LEFT, 0, 0); + this.add(contentJPanel); + fontRadioGroup = new FontRadioGroup(); + ecConfigRadioGroup = new FitRadioGroup(); + contentJPanel.add(initAttrJPanel()); + contentJPanel.add(initPreviewJPanel()); + } + + private JPanel initAttrJPanel() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + Component[] fontComponents = new Component[3]; + initRadioGroup(fontRadioGroup, i18nText("Fine-Designer_Fit-Font"), new String[]{i18nText("Fine-Designer_Fit"), i18nText("Fine-Designer_Fit-No")}, fontComponents); + jPanel.add(createSubAttrPane(fontComponents), BorderLayout.NORTH); + jPanel.add(initECConfigPane(), BorderLayout.CENTER); + return jPanel; + } + + protected JPanel initECConfigPane() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + Component[] ecComponents = new Component[fitAttrModel.getFitTypeNames().length + 1]; + initRadioGroup(ecConfigRadioGroup, fitAttrModel.getFitName(), fitAttrModel.getFitTypeNames(), ecComponents); + jPanel.add(createSubAttrPane(ecComponents), BorderLayout.CENTER); + return jPanel; + } + + + protected JPanel createSubAttrPane(Component[] components) { + double[] rowSize = new double[]{20}; + double[] columnSize = new double[components.length]; + for (int i = 0; i < columnSize.length; i++) { + if (i == 0) { + columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.firstColumn").getWidth(); + } else { + columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.column").getWidth(); + } + } + + JPanel attrJPanel = TableLayoutHelper.createTableLayoutPane(new Component[][]{components}, rowSize, columnSize); + attrJPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); + return attrJPanel; + } + + protected void initRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { + components[0] = new UILabel(name); + for (int i = 0; i < options.length; i++) { + + if (options[i] != null) { + UIRadioButton fontFitRadio = new UIRadioButton(options[i]); + fitRadioGroup.add(fontFitRadio); + components[i + 1] = fontFitRadio; + } else { + components[i + 1] = null; + } + } + fitRadioGroup.addActionListener(getPreviewActionListener()); + } + + protected ActionListener getPreviewActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + refreshPreviewJPanel(); + } + }; + } + + public void refreshPreviewJPanel(FitType fitType) { + previewJPanel.refreshPreview(fontRadioGroup.isFontFit(), fitType); + } + + protected void refreshPreviewJPanel() { + previewJPanel.refreshPreview(fontRadioGroup.isFontFit(), FitType.parse(updateBean())); + } + + private JPanel initPreviewJPanel() { + JPanel wrapperPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + previewJPanel = new NewFitPreviewPane(); + wrapperPane.add(previewJPanel, BorderLayout.CENTER); + int leftIndent = globalConfig ? (int) DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.firstColumn").getWidth() : 0; + wrapperPane.setBorder(BorderFactory.createEmptyBorder(0, leftIndent, 0, 0)); + wrapperPane.setPreferredSize(new Dimension(300 + leftIndent, 204)); + return wrapperPane; + } + + + public void populateBean(ReportFitAttr ob) { + fontRadioGroup.selectIndexButton(ob.isFitFont() ? 0 : 1); + populateECConfigRadioGroup(ob.fitStateInPC()); + refreshPreviewJPanel(); + } + + protected void populateECConfigRadioGroup(int fitStateInPC){ + ecConfigRadioGroup.selectIndexButton(getOptionIndex(fitStateInPC)); + } + + + protected void updateECConfigRadioGroup(ReportFitAttr reportFitAttr){ + reportFitAttr.setFitStateInPC(getStateInPC(ecConfigRadioGroup.getSelectRadioIndex())); + } + + public ReportFitAttr updateBean() { + ReportFitAttr reportFitAttr = new ReportFitAttr(); + reportFitAttr.setFitFont(fontRadioGroup.isFontFit()); + updateECConfigRadioGroup(reportFitAttr); + return reportFitAttr; + } + + + protected int getStateInPC(int index) { + FitType[] fitTypes = fitAttrModel.getFitTypes(); + if (index > fitTypes.length - 1) { + return index; + } + return fitTypes[index].getState(); + } + + protected int getOptionIndex(int state) { + FitType[] fitTypes = fitAttrModel.getFitTypes(); + for (int i = 0; i < fitTypes.length; i++) { + if (ComparatorUtils.equals(state, fitTypes[i].getState())) { + return i; + } + } + return 0; + } + + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + fontRadioGroup.setEnabled(enabled); + ecConfigRadioGroup.setEnabled(enabled); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/selection/Selectedable.java b/designer-base/src/main/java/com/fr/design/selection/Selectedable.java index 5e78482e8..890005443 100644 --- a/designer-base/src/main/java/com/fr/design/selection/Selectedable.java +++ b/designer-base/src/main/java/com/fr/design/selection/Selectedable.java @@ -1,25 +1,29 @@ package com.fr.design.selection; +import com.fr.base.TRL; + /** - * * @author zhou * @since 2012-7-26上午10:20:32 */ public interface Selectedable { - public S getSelection(); + S getSelection(); + + void setSelection(S selectElement); - public void setSelection(S selectElement); + /** + * Adds a ChangeListener to the listener list. + */ + void addSelectionChangeListener(SelectionListener selectionListener); - /** - * Adds a ChangeListener to the listener list. - */ - public void addSelectionChangeListener(SelectionListener selectionListener); + /** + * removes a ChangeListener from the listener list. + */ + void removeSelectionChangeListener(SelectionListener selectionListener); - /** - * removes a ChangeListener from the listener list. - */ - public void removeSelectionChangeListener(SelectionListener selectionListener); + // august:这儿就不要加fireSelectionChangeListener方法了。因为这个方法一般要定义成私有的,不然外部随即的调用! + default void navigate(TRL trl) { - // august:这儿就不要加fireSelectionChangeListener方法了。因为这个方法一般要定义成私有的,不然外部随即的调用! + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationFactory.java b/designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationFactory.java new file mode 100644 index 000000000..b303d491f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationFactory.java @@ -0,0 +1,33 @@ +package com.fr.design.startup; + +import org.jetbrains.annotations.NotNull; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/11 + */ +public class FineStartupNotificationFactory { + private static final FineStartupNotificationProvider DEFAULT = Install4jStartupNotificationProvider.getInstance(); + private static FineStartupNotificationProvider provider; + + public FineStartupNotificationFactory() { + } + + public static FineStartupNotificationProvider getNotification() { + return provider; + } + + public static void setLogger(@NotNull FineStartupNotificationProvider provider) { + FineStartupNotificationFactory.provider = provider; + } + + public static void reset() { + provider = DEFAULT; + } + + + static { + provider = DEFAULT; + } +} diff --git a/designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationProvider.java b/designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationProvider.java new file mode 100644 index 000000000..b90390a70 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/startup/FineStartupNotificationProvider.java @@ -0,0 +1,14 @@ +package com.fr.design.startup; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/11 + */ +public interface FineStartupNotificationProvider { + void registerStartupListener(Listener listener); + + interface Listener { + void startupPerformed(String parameters); + } +} diff --git a/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java b/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java new file mode 100644 index 000000000..dbc7be2b7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.startup; + +import com.install4j.api.launcher.StartupNotification; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/11 + */ +public class Install4jStartupNotificationProvider implements FineStartupNotificationProvider { + + private Install4jStartupNotificationProvider() { + } + private static final Install4jStartupNotificationProvider INSTANCE = new Install4jStartupNotificationProvider(); + public static Install4jStartupNotificationProvider getInstance() { + return INSTANCE; + } + + @Override + public void registerStartupListener(Listener listener) { + boolean supported = false; + try { + supported = Class.forName("com.install4j.api.launcher.StartupNotification") != null; + } catch (Throwable ignored) {} + + if (supported) { + StartupNotification.registerStartupListener(new StartupNotification.Listener() { + @Override + public void startupPerformed(String parameters) { + listener.startupPerformed(parameters); + } + }); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/AbstractPopBox.java b/designer-base/src/main/java/com/fr/design/style/AbstractPopBox.java index 4df9b7514..9cff473c1 100644 --- a/designer-base/src/main/java/com/fr/design/style/AbstractPopBox.java +++ b/designer-base/src/main/java/com/fr/design/style/AbstractPopBox.java @@ -10,8 +10,6 @@ import javax.swing.JWindow; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.util.ArrayList; -import java.util.List; import java.awt.AWTEvent; import java.awt.Dimension; import java.awt.Point; @@ -21,6 +19,8 @@ import java.awt.Window; import java.awt.event.AWTEventListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; /** * @author kunsnat E-mail:kunsnat@gmail.com diff --git a/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java b/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java index d755d4e05..0b56fc0ad 100644 --- a/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java +++ b/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java @@ -17,8 +17,11 @@ import com.teamdev.jxbrowser.engine.EngineOptions; import com.teamdev.jxbrowser.engine.RenderingMode; import com.teamdev.jxbrowser.event.Observer; import com.teamdev.jxbrowser.js.JsObject; +import com.teamdev.jxbrowser.net.Network; import com.teamdev.jxbrowser.net.Scheme; +import com.teamdev.jxbrowser.net.callback.VerifyCertificateCallback; import com.teamdev.jxbrowser.view.swing.BrowserView; +import org.jetbrains.annotations.Nullable; import java.awt.BorderLayout; @@ -108,6 +111,17 @@ public class NewModernUIPane extends ModernUIPane { } Engine engine = Engine.newInstance(builder.build()); + if (DesignerEnvManager.getEnvManager().isOpenDebug()) { + // 调试模式下,禁止HTTPS证书验证,使得可以正常访问商城测试服务器等 + Network network = engine.network(); + network.set(VerifyCertificateCallback.class, new VerifyCertificateCallback() { + @Nullable + @Override + public Response on(Params params) { + return VerifyCertificateCallback.Response.valid(); + } + }); + } browser = engine.newBrowser(); // 初始化的时候,就把命名空间对象初始化好,确保window.a.b.c("a.b.c"为命名空间)对象都是初始化过的 diff --git a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java index f066d648a..f9fb484a6 100644 --- a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java @@ -5,6 +5,7 @@ import com.fr.base.ServerConfig; import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; +import com.fr.design.deeplink.DeepLinkCore; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.fun.DesignerEnvProcessor; import com.fr.design.gui.UILookAndFeel; @@ -26,10 +27,15 @@ import com.fr.start.ServerStarter; import com.fr.value.NotNullLazyValue; import com.fr.workspace.WorkContext; import org.jetbrains.annotations.NotNull; + import javax.swing.SwingUtilities; import javax.swing.UIManager; +import java.awt.Color; import java.awt.Desktop; import java.awt.Font; +import java.awt.Frame; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -213,6 +219,14 @@ public class DesignUtils { DesignerContext.getDesignerFrame().openTemplate(new FileFILE(f)); } }); + } else { + String url = line; + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + DeepLinkCore.getInstance().receiveDeeplink2(url); + } + }); } } } diff --git a/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java b/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java index d464dec79..a5a6803d3 100644 --- a/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java @@ -21,7 +21,7 @@ public class LoadingUtils { public static JPanel createLoadingPane() { JPanel jPanel = new JPanel(); UILabel loadingLabel = new UILabel(LOADING_ICON); - UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Open_Template_Loading")); + UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Loading")); tipLabel.setForeground(TIP_COLOR); jPanel.setLayout(new LayoutManager() { @Override diff --git a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java index 426fd18e2..30f55d7ef 100644 --- a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java +++ b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java @@ -47,9 +47,9 @@ import com.fr.stable.StringUtils; import com.fr.stable.os.windows.WindowsDetector; import com.fr.stable.project.ProjectConstants; import com.fr.workspace.WorkContext; - import com.fr.workspace.Workspace; import com.fr.workspace.WorkspaceEvent; + import javax.swing.AbstractAction; import javax.swing.AbstractListModel; import javax.swing.ActionMap; @@ -202,6 +202,16 @@ public class FILEChooserPane extends BasicPane { return INSTANCE; } + public static FILEChooserPane getInstanceWithDesignatePath(String path, FILEFilter filter) { + INSTANCE.showLoc = false; + INSTANCE.showEnv = false; + INSTANCE.showWebReport = false; + INSTANCE.setDesignateModel(path); + INSTANCE.removeAllFilter(); + INSTANCE.addChooseFILEFilter(filter, 0); + return INSTANCE; + } + public static FILEChooserPane getMultiEnvInstance(boolean showLoc, boolean showWebReport) { INSTANCE.showEnv = true; INSTANCE.showLoc = showLoc; @@ -499,7 +509,7 @@ public class FILEChooserPane extends BasicPane { } private String calProperFileName(String fileName, ChooseFileFilter fileFilter) { - if(fileFilter == null){ + if (fileFilter == null) { return fileName; } String filterExtension = fileFilter.getExtensionString(); @@ -516,10 +526,10 @@ public class FILEChooserPane extends BasicPane { return fileNameWithOutExtension + filterExtension; } - private boolean isMapping(String fromExtension, String toExtension){ - if(FileExtension.CPTX.matchExtension(fromExtension)){ + private boolean isMapping(String fromExtension, String toExtension) { + if (FileExtension.CPTX.matchExtension(fromExtension)) { return FileExtension.CPT.matchExtension(toExtension); - }else if(FileExtension.CPT.matchExtension(fromExtension)){ + } else if (FileExtension.CPT.matchExtension(fromExtension)) { return FileExtension.CPTX.matchExtension(toExtension); } return false; @@ -678,7 +688,7 @@ public class FILEChooserPane extends BasicPane { * 移除文件后缀的方法 * 解决cptx文件的另存为操作默认会出现双后缀的bug(xxx.cptx.cpt) **/ - private String removeSuffix(String text){ + private String removeSuffix(String text) { return FileExtension.CPTX.matchExtension(text) ? text.substring(0, text.length() - FileExtension.CPTX.getSuffix().length()) : text; } @@ -783,7 +793,7 @@ public class FILEChooserPane extends BasicPane { ChooseFileFilter supportedTypes = new ChooseFileFilter(FRContext.getFileNodes().getSupportedTypes(), appName + Toolkit.i18nText("Fine-Design_Report_Template_File")); Set providers = ExtraReportClassManager.getInstance().getArray(ReportSupportedFileProvider.XML_TAG); for (ReportSupportedFileProvider provider : providers) { - for (FileExtension fileExtension : provider.getFileExtensions()){ + for (FileExtension fileExtension : provider.getFileExtensions()) { supportedTypes.addExtension(fileExtension.getExtension()); } } @@ -884,7 +894,7 @@ public class FILEChooserPane extends BasicPane { saveDictionary(); dialogExit(); } else { - FineJOptionPane.showMessageDialog(this, Toolkit.i18nText("Fine-Design_Basic_App_Template_Report_Not_Exist")); + FineJOptionPane.showMessageDialog(this, Toolkit.i18nText("Fine-Design_Basic_App_File_Not_Exist")); return; } } @@ -915,7 +925,7 @@ public class FILEChooserPane extends BasicPane { if (access(selectedFile) && access(currentDirectory)) { if (selectedFile.exists()) { int selVal = FineJOptionPane.showConfirmDialog(dialog, Toolkit.i18nText("Fine-Design_Basic_Utils_Would_You_Like_To_Cover_The_Current_File") + " ?", - Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (selVal == JOptionPane.YES_OPTION) { option = JOPTIONPANE_OK_OPTION; saveDictionary(); @@ -1031,6 +1041,14 @@ public class FILEChooserPane extends BasicPane { setPlaceListModel(new PlaceListModel()); } + private void setDesignateModel(String path) { + if (placesList == null) { + return; + } + setPlaceListModel(new DesignateRemotePlaceListModel(path)); + } + + private void setMultiPlaceListModel() { if (placesList == null) { return; @@ -1125,6 +1143,7 @@ public class FILEChooserPane extends BasicPane { private abstract class AbstractPlaceListModel extends AbstractListModel { + private static final long serialVersionUID = 8473695327688235386L; protected List filesOfSystem = new ArrayList(); protected void processSystemFile() { @@ -1157,7 +1176,8 @@ public class FILEChooserPane extends BasicPane { protected void setCD(final FILE lastDirectory) { for (int i = 0; i < this.getSize(); i++) { FILE file = this.getElementAt(i); - if (ComparatorUtils.equals(lastDirectory.prefix(), file.prefix())) { + //前缀相同不代表能用啊,比如说 repolets 和 resource ,都是 env下的,但就不该去显示resource下的文件呀 + if (ComparatorUtils.equals(lastDirectory.prefix(), file.prefix()) && lastDirectory.getPath() != null && lastDirectory.getPath().startsWith(file.getPath())) { setCurrentDirectory(lastDirectory); return; } @@ -1166,7 +1186,60 @@ public class FILEChooserPane extends BasicPane { } } + /** + * 一个简单的指定远程目录的 placelistmodel + */ + private class DesignateRemotePlaceListModel extends AbstractPlaceListModel { + private static final long serialVersionUID = -6340666958714469249L; + + private FileNodeFILE envFILE; + + public DesignateRemotePlaceListModel(String path) { + envFILE = new DesignateFileNodeFILE(new FileNode(path, true)) { + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_Basic_Utils_Report_Env_Directory_Designate"); + } + }; + } + + @Override + public FILE getElementAt(int index) { + if (index < 1) { + return envFILE; + } + throw new IndexOutOfBoundsException(); + } + + @Override + public int getSize() { + return 1; + } + + @Override + protected void setCD(FILE lastDirectory) { + setCurrentDirectory(envFILE); + } + + /** + * 简单的重写了标签的FileNodeFILE + */ + private class DesignateFileNodeFILE extends FileNodeFILE { + + public DesignateFileNodeFILE(FileNode node) { + super(node); + } + + @Override + public Icon getIcon() { + return BaseUtils.readIcon("/com/fr/base/images/oem/logo.png"); + } + } + } + + private class PlaceListModel extends AbstractPlaceListModel { + private static final long serialVersionUID = 6138969918807381364L; private FileNodeFILE envFILE; private FileNodeFILE webReportFILE; @@ -1217,6 +1290,7 @@ public class FILEChooserPane extends BasicPane { private class MultiLocalEnvPlaceListModel extends AbstractPlaceListModel { + private static final long serialVersionUID = 6300018896958532154L; private List envFiles = new ArrayList(); private FileNodeFILE webReportFILE; diff --git a/designer-base/src/main/java/com/fr/file/FILEFactory.java b/designer-base/src/main/java/com/fr/file/FILEFactory.java index 3d48bab34..d55848378 100644 --- a/designer-base/src/main/java/com/fr/file/FILEFactory.java +++ b/designer-base/src/main/java/com/fr/file/FILEFactory.java @@ -1,6 +1,5 @@ package com.fr.file; -import com.fr.base.FRContext; import com.fr.design.file.NodeAuthProcessor; import com.fr.file.filetree.FileNode; import com.fr.workspace.WorkContext; @@ -10,6 +9,7 @@ public class FILEFactory { public static final String FILE_PREFIX = "file://"; public static final String ENV_PREFIX = "env://"; public static final String WEBREPORT_PREFIX = "webreport://"; + public static final String SEPARATOR = "/"; private FILEFactory() { } diff --git a/designer-base/src/main/java/com/fr/file/filter/ChooseFileFilter.java b/designer-base/src/main/java/com/fr/file/filter/ChooseFileFilter.java index 147e1946d..0f6057d0a 100644 --- a/designer-base/src/main/java/com/fr/file/filter/ChooseFileFilter.java +++ b/designer-base/src/main/java/com/fr/file/filter/ChooseFileFilter.java @@ -31,6 +31,15 @@ public class ChooseFileFilter extends FileFilter implements FILEFilter, java.io. this(extension, null); } + public ChooseFileFilter(boolean noRestrict) { + if (noRestrict) { + this.filters = null; + this.fullDescription = FileExtension.ALL.getExtension(); + } else { + this.filters = new ArrayList<>(); + } + } + public ChooseFileFilter(String extension, String description) { this(); if (extension != null) { @@ -314,4 +323,4 @@ public class ChooseFileFilter extends FileFilter implements FILEFilter, java.io. return (o instanceof ChooseFileFilter) && ComparatorUtils.equals(((ChooseFileFilter) o).getDescription(), getDescription()); } -} \ No newline at end of file +} diff --git a/designer-base/src/main/resources/com/fr/design/icon/icon_ec_default_fit.svg b/designer-base/src/main/resources/com/fr/design/icon/icon_ec_default_fit.svg new file mode 100644 index 000000000..4deb67b0d --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/icon/icon_ec_default_fit.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/edit/advancedEditor.svg b/designer-base/src/main/resources/com/fr/design/images/edit/advancedEditor.svg new file mode 100644 index 000000000..6ddc105cb --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/edit/advancedEditor.svg @@ -0,0 +1,10 @@ + + + 高级编辑 + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/asc.svg b/designer-base/src/main/resources/com/fr/design/images/sort/asc.svg deleted file mode 100644 index 67dd9e829..000000000 --- a/designer-base/src/main/resources/com/fr/design/images/sort/asc.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - 升序备份 - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/des.svg b/designer-base/src/main/resources/com/fr/design/images/sort/des.svg deleted file mode 100644 index 2fcef077e..000000000 --- a/designer-base/src/main/resources/com/fr/design/images/sort/des.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - 降序 - - - - - - - - - - - - - - \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/nosort.svg b/designer-base/src/main/resources/com/fr/design/images/sort/nosort.svg deleted file mode 100644 index ca04928fc..000000000 --- a/designer-base/src/main/resources/com/fr/design/images/sort/nosort.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - 不排序 - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/javascript/jsapi/category.json b/designer-base/src/main/resources/com/fr/design/javascript/jsapi/category.json new file mode 100644 index 000000000..ece3628ab --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/javascript/jsapi/category.json @@ -0,0 +1,46 @@ +{ + "Fine-Design_JSAPI_Public_Module": { + "Fine-Design_JSAPI_Public_Module_Global": { + "Fine-Design_JSAPI_Public_Module_Global_Universal": {}, + "Fine-Design_JSAPI_Public_Module_Global_FR": {}, + "Fine-Design_JSAPI_Public_Module_Global_FS": {}, + "Fine-Design_JSAPI_Public_Module_Global_Mobile": {} + }, + "Fine-Design_JSAPI_Public_Module_Widget": { + "Fine-Design_JSAPI_Public_Module_Widget_Get": {}, + "Fine-Design_JSAPI_Public_Module_Widget_Universal": {}, + "Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar": {}, + "Fine-Design_JSAPI_Public_Module_Button_Widget_Peculiar": {}, + "Fine-Design_JSAPI_Public_Module_Combobox_Widget_Peculiar": {} + }, + "Fine-Design_JSAPI_Public_Module_Table": { + "Fine-Design_JSAPI_Public_Module_Table_Marquee": {}, + "Fine-Design_JSAPI_Public_Module_Table_Scrollbar": {}, + "Fine-Design_JSAPI_Public_Module_Table_Cell_Style": {}, + "Fine-Design_JSAPI_Public_Module_Table_Row_Height_Col_Width": {}, + "Fine-Design_JSAPI_Public_Module_Table_Cell_Value": {}, + "Fine-Design_JSAPI_Public_Module_Table_Cell_Radius": {} + }, + "Fine-Design_JSAPI_Public_Module_Toolbar": { + "Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button": {} + }, + "Fine-Design_JSAPI_Public_Module_Report_Page": { + "Fine-Design_JSAPI_Public_Module_Report_Page_Jump": {}, + "Fine-Design_JSAPI_Public_Module_Report_Page_Number_Get": {} + }, + "Fine-Design_JSAPI_Public_Module_Report_Export": {} + }, + "Fine-Design_JSAPI_Cpt": { + "Fine-Design_JSAPI_Cpt_Page_Preview": { + "Fine-Design_JSAPI_Cpt_Page_Preview_Folding_Tree": {} + }, + "Fine-Design_JSAPI_Cpt_Write_Preview": {}, + "Fine-Design_JSAPI_Cpt_View_Preview": { + "Fine-Design_JSAPI_Cpt_View_Preview_Report_Location": {} + } + }, + "Fine-Design_JSAPI_Form": { + "Fine-Design_JSAPI_Form_Component_Get": {}, + "Fine-Design_JSAPI_Form_Component_Tab": {} + } +} \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/javascript/jsapi/images/connectFailed.svg b/designer-base/src/main/resources/com/fr/design/javascript/jsapi/images/connectFailed.svg new file mode 100644 index 000000000..6b0dfbc66 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/javascript/jsapi/images/connectFailed.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/javascript/jsapi/jsapi.json b/designer-base/src/main/resources/com/fr/design/javascript/jsapi/jsapi.json new file mode 100644 index 000000000..dcad37392 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/javascript/jsapi/jsapi.json @@ -0,0 +1,33 @@ +{ + "Fine-Design_JSAPI_Public_Module_Global_Universal": ["_g()", "getParameterContainer", "parameterCommit", "loadContentPane", "getPreviewType"], + "Fine-Design_JSAPI_Public_Module_Global_FR": [ "servletURL", "serverURL", "server", "fineServletURL", "SessionMgr.getSessionID", "showDialog", "closeDialog", + "doHyperlinkByGet", "doHyperlinkByPost", "doURLPrint", "Msg", "remoteEvaluate", "jsonEncode", "jsonDecode", + "ajax", "isEmpty", "isArray", "cellStr2ColumnRow", "columnRow2CellStr"], + "Fine-Design_JSAPI_Public_Module_Global_FS": ["signOut", "tabPane.closeActiveTab", "tabPane.addItem"], + "Fine-Design_JSAPI_Public_Module_Global_Mobile": ["location", "Mobile.getDeviceInfo"], + "Fine-Design_JSAPI_Public_Module_Widget_Get": ["this", "this.options.form", "getWidgetByName"], + "Fine-Design_JSAPI_Public_Module_Widget_Universal": ["getValue", "getText", "setValue", "visible", "invisible", "setVisible", "isVisible", "setEnable", "isEnabled", + "reset", "getType", "setWaterMark", "fireEvent", "setPopupStyle"], + "Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar":["setMaxAndMinDate"], + "Fine-Design_JSAPI_Public_Module_Button_Widget_Peculiar":["doClick"], + "Fine-Design_JSAPI_Public_Module_Combobox_Widget_Peculiar":["setName4Empty"], + "Fine-Design_JSAPI_Public_Module_Table_Marquee":["startMarquee", "stopMarquee"], + "Fine-Design_JSAPI_Public_Module_Table_Scrollbar":["setHScrollBarVisible", "setVScrollBarVisible"], + "Fine-Design_JSAPI_Public_Module_Table_Cell_Style":["addEffect"], + "Fine-Design_JSAPI_Public_Module_Table_Row_Height_Col_Width":["setRowHeight", "setColWidth"], + "Fine-Design_JSAPI_Public_Module_Table_Cell_Value":["getCellValue", "setCellValue"], + "Fine-Design_JSAPI_Public_Module_Table_Cell_Radius":["setCellRadius"], + "Fine-Design_JSAPI_Public_Module_Toolbar":["toolBarFloat", "setStyle","getToolbar"], + "Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button":["changeFormat"], + "Fine-Design_JSAPI_Public_Module_Report_Page_Jump":["gotoPreviousPage", "gotoNextPage", "gotoLastPage", "gotoFirstPage", "gotoPage"], + "Fine-Design_JSAPI_Public_Module_Report_Page_Number_Get":["getCurrentPageIndex", "getReportTotalPage", "currentPageIndex", "reportTotalPage"], + "Fine-Design_JSAPI_Public_Module_Report_Export":["exportReportToExcel", "exportReportToImage", "exportReportToPDF", "exportReportToWord"], + "Fine-Design_JSAPI_Cpt_Page_Preview_Folding_Tree":["expandNodeLayer", "collapseNodeLayer", "expandAllNodeLayer", "collapseAllNodeLayer"], + "Fine-Design_JSAPI_Cpt_Write_Preview":["getWidgetByCell", "appendReportRC", "appendReportRow", + "deleteReportRC", "deleteRows", "refreshAllSheets", "loadSheetByIndex", "loadSheetByName", "isDirtyPage", + "isAutoStash", "writeReport", "verifyAndWriteReport", "verifyReport", "importExcel", "importExcel_Clean", + "importExcel_Append", "importExcel_Cover", "stash", "clear"], + "Fine-Design_JSAPI_Cpt_View_Preview_Report_Location":["centerReport"], + "Fine-Design_JSAPI_Form_Component_Get":["getAllWidgets"], + "Fine-Design_JSAPI_Form_Component_Tab":["showCardByIndex", "getShowIndex", "setTitleVisible"] +} \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/predefined/previewData b/designer-base/src/main/resources/com/fr/design/mainframe/predefined/previewData deleted file mode 100644 index cfcf502f3..000000000 --- a/designer-base/src/main/resources/com/fr/design/mainframe/predefined/previewData +++ /dev/null @@ -1,5 +0,0 @@ -城市 当月目标 当月实际完成 月度完成率 -南通市 324,646 324,646 100% -合肥市 248,938 348,938 140% -邵阳市 248,938 348,938 140% -合计 1,071,460 1,371,460 128% diff --git a/designer-base/src/test/java/com/fr/design/javascript/jsapi/JSAPITreeHelperTest.java b/designer-base/src/test/java/com/fr/design/javascript/jsapi/JSAPITreeHelperTest.java new file mode 100644 index 000000000..e0d5ae7c9 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/javascript/jsapi/JSAPITreeHelperTest.java @@ -0,0 +1,31 @@ +package com.fr.design.javascript.jsapi; + +import java.util.List; +import javax.swing.tree.DefaultMutableTreeNode; +import junit.framework.TestCase; + +public class JSAPITreeHelperTest extends TestCase { + public void testGetName(){ + List names = JSAPITreeHelper.getNames("Fine-Design_JSAPI_Public_Module_Toolbar"); + assertEquals(names.size(),4); + assertTrue(names.contains( "toolBarFloat")); + assertTrue(names.contains( "setStyle")); + assertTrue(names.contains( "getToolbar")); + assertTrue(names.contains( "changeFormat")); + List allNames = JSAPITreeHelper.getAllNames(); + assertEquals(allNames.size(),16); + } + + public void testGetDirectCategory(){ + String directCategory = JSAPITreeHelper.getDirectCategory("_g()"); + assertEquals(directCategory,"Fine-Design_JSAPI_Public_Module_Global_Universal"); + directCategory = JSAPITreeHelper.getDirectCategory("showCardByIndex"); + assertEquals(directCategory,"Fine-Design_JSAPI_Form_Component_Tab"); + } + + public void testCreateJSAPITree(){ + DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); + JSAPITreeHelper.createJSAPITree(rootNode); + assertEquals(2,rootNode.getChildCount()); + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/loghandler/DesignerLogHandlerTest.java b/designer-base/src/test/java/com/fr/design/mainframe/loghandler/DesignerLogHandlerTest.java new file mode 100644 index 000000000..c7dd1de70 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/loghandler/DesignerLogHandlerTest.java @@ -0,0 +1,50 @@ +package com.fr.design.mainframe.loghandler; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author vito + * @version 10.0 + * Created by vito on 2022/1/25 + */ +public class DesignerLogHandlerTest { + + @Test + public void findTplLink() { + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)", "(公式定位测试/单sheet2(2).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式计算错误:(公式定位测试/单sheet2(1).cpt:0:A1),出错公式(公式定位测试/单sheet2(2).cpt:0:A1),的飞机啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).frm:0:A1)", "(公式定位测试/单sheet2(2).frm:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式计算错误:(公式定位测试/单sheet2(1).frm:0:A1),出错公式(公式定位测试/单sheet2(2).frm:0:A1),的飞机啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式计算错误:(公式定位测试/单sheet2(1).cpt:0:A1)的飞机啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式(计算错误:(公式定位测试/单sheet2(1).cpt:0:A1)的飞机啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式)计算错误:(公式定位测试/单sheet2(1).cpt:0:A1)的飞机啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式计算错误:(公式定位测试/单sheet2(1).cpt:0:A1)的飞机)啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式计算错误:(公式定位测试/单sheet2(1).cpt:0:A1)的飞机(啊") + ); + Assert.assertArrayEquals( + new String[]{"(公式定位测试/单sheet2(1).cpt:0:A1)"}, + DesignerLogHandler.findTplLink("错误代码:11300310 公式(0fdasf)计算错误:(公式定位测试/单sheet2(1).cpt:0:A1)的飞机啊") + ); + } +} \ No newline at end of file diff --git a/designer-base/src/test/resources/com/fr/design/javascript/jsapi/category.json b/designer-base/src/test/resources/com/fr/design/javascript/jsapi/category.json new file mode 100644 index 000000000..2d0e50ba0 --- /dev/null +++ b/designer-base/src/test/resources/com/fr/design/javascript/jsapi/category.json @@ -0,0 +1,17 @@ +{ + "Fine-Design_JSAPI_Public_Module": { + "Fine-Design_JSAPI_Public_Module_Global": { + "Fine-Design_JSAPI_Public_Module_Global_Universal": {}, + "Fine-Design_JSAPI_Public_Module_Global_Mobile": {} + }, + "Fine-Design_JSAPI_Public_Module_Widget": { + "Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar": {} + }, + "Fine-Design_JSAPI_Public_Module_Toolbar": { + "Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button": {} + } + }, + "Fine-Design_JSAPI_Form": { + "Fine-Design_JSAPI_Form_Component_Tab": {} + } +} \ No newline at end of file diff --git a/designer-base/src/test/resources/com/fr/design/javascript/jsapi/jsapi.json b/designer-base/src/test/resources/com/fr/design/javascript/jsapi/jsapi.json new file mode 100644 index 000000000..4ff0a321e --- /dev/null +++ b/designer-base/src/test/resources/com/fr/design/javascript/jsapi/jsapi.json @@ -0,0 +1,8 @@ +{ + "Fine-Design_JSAPI_Public_Module_Global_Universal": ["_g()", "getParameterContainer", "parameterCommit", "loadContentPane", "getPreviewType"], + "Fine-Design_JSAPI_Public_Module_Global_Mobile": ["location", "Mobile.getDeviceInfo"], + "Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar":["setMaxAndMinDate"], + "Fine-Design_JSAPI_Public_Module_Toolbar":["toolBarFloat", "setStyle","getToolbar"], + "Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button":["changeFormat"], + "Fine-Design_JSAPI_Form_Component_Tab":["showCardByIndex", "showCardByIndex", "getShowIndex", "setTitleVisible"] +} \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java index 3de9aaa09..a04acb83d 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java @@ -4,29 +4,45 @@ package com.fr.design.mainframe.chart.gui; * Created by hufan on 2016/10/20. */ +import com.fr.base.BaseFormula; +import com.fr.base.Utils; import com.fr.chart.base.AttrChangeConfig; import com.fr.chart.base.AttrChangeType; +import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartattr.SwitchTitle; import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.formula.TinyFormulaPane; import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ibutton.UIToggleButton; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; -import com.fr.design.i18n.Toolkit; - +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import javax.swing.BorderFactory; +import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.SwingConstants; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; import java.awt.Dimension; +import java.awt.FlowLayout; 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.util.ArrayList; +import java.util.List; /** * 图表切换设置面板 @@ -40,6 +56,7 @@ public class ChangeConfigPane extends BasicBeanPane { private static final int CONSTANT_TEN = 10; private static final int CONSTANT_THIRTY = 30; private static final int CONSTANT_ZERO = 0; + private static final int COL_COUNT = 4; private JPanel contentPane; //配置方式按钮 private UIButtonGroup configStyleButton; @@ -56,23 +73,44 @@ public class ChangeConfigPane extends BasicBeanPane { private ColorSelectBoxWithOutTransparent colorSelectBox4carousel; private UIButtonGroup switchStyleGroup; + private JPanel chartTypesPane; + private List switchTitles = new ArrayList<>(); + private JPanel switchTitlePane = new JPanel(); + private List changeChartButtons = new ArrayList<>(); + private int selectedChart; // 设置面板里面选取的图表,不是真正切换的图表 public ChangeConfigPane(){ + init(); + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 15)); + this.add(createScrollPane(), BorderLayout.CENTER); + } + + private JPanel createScrollPane() { + return new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return contentPane; + } + }; + } + + private void init() { initButtonGroup(); configPane = createConfigPane(); contentPane = createContentPane(); contentPane.setBorder(BorderFactory.createEmptyBorder(CONSTANT_TEN, CONSTANT_THIRTY, CONSTANT_TEN, CONSTANT_THIRTY)); - this.add(contentPane, BorderLayout.CENTER); } private JPanel createContentPane() { double p = TableLayout.PREFERRED; double f = TableLayout.FILL; double[] columnSize = {p, f}; - double[] rowSize = {p,p}; + double[] rowSize = {p, p, p}; Component[][] components = new Component[][]{ new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Change_Style")),configStyleButton}, new Component[]{configPane, null}, + new Component[]{createButtonContentPane(), null} }; return TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); } @@ -147,14 +185,84 @@ public class ChangeConfigPane extends BasicBeanPane { return TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Basic_Background"), colorSelectBox4button, EDIT_AREA_WIDTH); } + private JPanel createButtonContentPane() { + JPanel buttonContentPane = new JPanel(new BorderLayout()); + + chartTypesPane = new JPanel(); + chartTypesPane.setLayout(new BoxLayout(chartTypesPane, BoxLayout.Y_AXIS)); + chartTypesPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + switchTitlePane.setLayout(new CardLayout()); + + JPanel titleEditPane = TableLayout4VanChartHelper.createGapTableLayoutPane( + Toolkit.i18nText("Fine-Design_Chart_Switch_Title_Label"), + switchTitlePane, + EDIT_AREA_WIDTH + ); + titleEditPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + + buttonContentPane.add(chartTypesPane, BorderLayout.NORTH); + buttonContentPane.add(titleEditPane, BorderLayout.CENTER); + + UIExpandablePane expandablePane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Chart_Button_And_Rotation_Content"), 20, buttonContentPane) { + protected void setcontentPanelontentPanelBorder() { + + } + }; + expandablePane.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); + return expandablePane; + } + + private void populateButtonContentPane(ChartCollection collection) { + int count = collection.getChartCount(); + int select = collection.getSelectedIndex(); + + JPanel pane = null; + for (int i = 0; i < count; i++) { + if (i % COL_COUNT == 0) { + pane = new JPanel(new FlowLayout(FlowLayout.LEFT)); + chartTypesPane.add(pane); + } + + ChangeChartButton button = new ChangeChartButton(i, collection); + changeChartButtons.add(button); + button.setSelected(i == select); + pane.add(button); + + populateSwitchTitlePane(i, collection); + } + + showSwitchTitleCard(collection.getChartName(select)); + chartTypesPane.revalidate(); + switchTitlePane.revalidate(); + selectedChart = select; + } + + private void populateSwitchTitlePane(int chartIndex, ChartCollection collection) { + Chart chart = collection.getChart(chartIndex, Chart.class); + SwitchTitle switchTitle = chart.getSwitchTitle(); + Object content = switchTitle.getContent(); + String result = StringUtils.EMPTY; + if (content != null) { + if (content instanceof BaseFormula) { + result = ((BaseFormula) content).getContent(); + } else { + result = Utils.objectToString(content); + } + } + TinyFormulaPane title = new TinyFormulaPane(); + title.populateBean(result); + switchTitles.add(title); + switchTitlePane.add(title, collection.getChartName(chartIndex)); + } + private JPanel createButtonConfigPane() { double p = TableLayout.PREFERRED; double f = TableLayout.FILL; double[] columnSize = {p, f}; - double[] rowSize = {p,p}; + double[] rowSize = {p, p, p}; Component[][] components = new Component[][]{ - new Component[]{createTitleStylePane(),null}, - new Component[]{createButtonBackgroundColorPane(),null}, + new Component[]{createTitleStylePane(), null}, + new Component[]{createButtonBackgroundColorPane(), null}, }; return TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); @@ -195,6 +303,7 @@ public class ChangeConfigPane extends BasicBeanPane { //按钮切换界面 styleAttrPane.populate(changeConfigAttr.getStyleAttr()); colorSelectBox4button.setSelectObject(changeConfigAttr.getButtonColor()); + populateButtonContentPane(ob); //轮播切换界面 timeInterval.setValue(changeConfigAttr.getTimeInterval()); @@ -224,10 +333,68 @@ public class ChangeConfigPane extends BasicBeanPane { changeConfigAttr.setTimeInterval((int) timeInterval.getValue()); changeConfigAttr.setCarouselColor(colorSelectBox4carousel.getSelectObject()); changeConfigAttr.setShowArrow(switchStyleGroup.getSelectedIndex() == 0); + + updateSwitchTitle(ob); + } + + private void updateSwitchTitle(ChartCollection collection) { + int count = collection.getChartCount(); + for (int i = 0; i < count; i++) { + String titleString = switchTitles.get(i).updateBean(); + Object titleObj; + if (StableUtils.maybeFormula(titleString)) { + titleObj = BaseFormula.createFormulaBuilder().build(titleString); + } else { + titleObj = titleString; + } + collection.getChart(i, Chart.class).setSwitchTitle(new SwitchTitle(titleObj)); + } } @Override protected String title4PopupWindow() { return Toolkit.i18nText("Fine-Design_Chart_Change_Config_Attributes"); } + + private class ChangeChartButton extends UIToggleButton { + private static final int BUTTON_WIDTH = 52; + private static final int BUTTON_HEIGHT = 20; + + private ChartCollection collection; + private int buttonIndex; + + public ChangeChartButton(int i, ChartCollection collection) { + super(collection.getChartName(i)); + this.collection = collection; + this.buttonIndex = i; + } + + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + resetChangeChartButtons(); + showSwitchTitleCard(collection.getChartName(buttonIndex)); + ChangeChartButton.this.setSelected(true); + selectedChart = buttonIndex; + } + }; + } + + public Dimension getPreferredSize() { + return new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT); + } + } + + private void resetChangeChartButtons() { + for (ChangeChartButton changeChartButton : changeChartButtons) { + changeChartButton.setSelected(false); + } + } + + private void showSwitchTitleCard(String chartName) { + CardLayout cardLayout = (CardLayout) switchTitlePane.getLayout(); + cardLayout.show(switchTitlePane, chartName); + } } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java index d4e1f64e7..54c3bd33d 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java @@ -19,14 +19,14 @@ import com.fr.van.chart.designer.TableLayout4VanChartHelper; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JPanel; -import java.util.ArrayList; -import java.util.List; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; /** @@ -40,7 +40,7 @@ public class CategoryPlotMoreCateReportDataContentPane extends CategoryPlotRepor private JPanel boxPane; private UIButton addButton; - private ArrayList formualList = new ArrayList(); + private List formualList = new ArrayList(); private UIObserverListener uiobListener = null; public List getFormualList() { @@ -193,7 +193,7 @@ public class CategoryPlotMoreCateReportDataContentPane extends CategoryPlotRepor reportDefinition.clearMoreCate(); updateMoreCate(reportDefinition, plot); - + collection.updateAxisCategoryStyles(); } } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java index 3bf0225ef..4c809e64f 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java @@ -15,9 +15,13 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.mainframe.chart.gui.ChartDataPane; import com.fr.design.utils.gui.GUICoreUtils; - -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -39,7 +43,7 @@ public class CategoryPlotMoreCateTableDataContentPane extends CategoryPlotTableD private JPanel boxPane; - private ArrayList boxList = new ArrayList(); + private List boxList = new ArrayList(); private UIButton addButton; private UIObserverListener uiobListener = null; @@ -242,6 +246,7 @@ public class CategoryPlotMoreCateTableDataContentPane extends CategoryPlotTableD normal.clearMoreCate(); updateMoreCate(normal, plot); } + collection.updateAxisCategoryStyles(); } protected void updateMoreCate(NormalTableDataDefinition normal, Plot plot) { diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisPane.java index 35b6d63e7..75a3c0f2c 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisPane.java @@ -54,7 +54,7 @@ public class VanChartCustomAxisPane extends BasicScrollPane { } if(axisPane != null) { - axisPane.populateBean((VanChartCustomPlot) chart.getPlot()); + axisPane.populateBean((VanChart) chart); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisTabPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisTabPane.java index 93ac30c52..5f9927c6b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisTabPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomAxisTabPane.java @@ -87,11 +87,16 @@ public class VanChartCustomAxisTabPane extends VanChartCustomPlotTabPane customPlotList = plot.getCustomPlotList(); ArrayList plotOrder = plot.getDiffAxisOrder(); @@ -100,12 +105,13 @@ public class VanChartCustomAxisTabPane extends VanChartCustomPlotTabPane switchButton; + private ColorSelectBoxWithOutTransparent colorSelect; + private UINumberDragPaneWithPercent opacity; + + private JPanel centerPane; + + public VanChartGanttTimeLinePane() { + this.setLayout(new BorderLayout()); + this.add(createSwitchButtonPane(), BorderLayout.NORTH); + this.add(createCenterPane(), BorderLayout.CENTER); + } + + private JPanel createSwitchButtonPane() { + double[] columnSize = {TableLayout.PREFERRED, TableLayout.FILL}; + double[] rowSize = {TableLayout.PREFERRED, TableLayout.PREFERRED}; + String[] array = new String[]{Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Not_Show"), Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Show")}; + switchButton = new UIButtonGroup<>(array); + switchButton.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + setCenterPaneVisibility(); + } + }); + UILabel text = new UILabel(Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Current_Line"), SwingConstants.LEFT); + return TableLayout4VanChartHelper.createGapTableLayoutPane(new Component[][] { + new Component[]{null, null}, + new Component[] {text, switchButton} + }, rowSize, columnSize); + } + + private JPanel createCenterPane() { + double[] columnSize = {TableLayout.FILL, TableLayout4VanChartHelper.EDIT_AREA_WIDTH}; + double[] rowSize = {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}; + + colorSelect = new ColorSelectBoxWithOutTransparent(100); + opacity = new UINumberDragPaneWithPercent(0, 100); + + centerPane = TableLayout4VanChartHelper.createGapTableLayoutPane(new Component[][] { + new Component[]{null, null}, + new Component[] {new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), colorSelect}, + new Component[] {new UILabel(Toolkit.i18nText("Fine-Design_Report_Alpha")), opacity} + }, rowSize, columnSize); + + centerPane.setVisible(false); + + return centerPane; + } + + public void populateBean(Plot plot) { + if (plot instanceof VanChartGanttPlot) { + VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; + setShowTimeLine(ganttPlot.isShowTimeLine()); + setTimeLineColor(ganttPlot.getTimeLineColor()); + setTimeLineOpacity(ganttPlot.getTimeLineOpacity()); + + centerPane.setVisible(ganttPlot.isShowTimeLine()); + } + } + + public void updateBean(Plot plot) { + if (plot instanceof VanChartGanttPlot) { + VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; + ganttPlot.setShowTimeLine(isShowTimeLine()); + ganttPlot.setTimeLineColor(getTimeLineColor()); + ganttPlot.setTimeLineOpacity(getTimeLineOpacity()); + } + } + + private void setCenterPaneVisibility() { + centerPane.setVisible(switchButton.getSelectedIndex() == 1); + } + + public boolean isShowTimeLine() { + return switchButton.getSelectedIndex() == 1; + } + + public void setShowTimeLine(boolean showTimeLine) { + switchButton.setSelectedIndex(showTimeLine ? 1 : 0); + } + + public Color getTimeLineColor() { + return colorSelect.getSelectObject(); + } + + public void setTimeLineColor(Color timeLineColor) { + colorSelect.setSelectObject(timeLineColor); + } + + public double getTimeLineOpacity() { + return opacity.updateBean(); + } + + public void setTimeLineOpacity(double timeLineOpacity) { + opacity.populateBean(timeLineOpacity); + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java index e8379e78b..ef532d12b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java @@ -1,5 +1,6 @@ package com.fr.van.chart.designer.style.axis; +import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.ConditionAttr; import com.fr.chart.chartglyph.ConditionCollection; @@ -41,6 +42,7 @@ public class VanChartAxisPane extends BasicBeanPane { protected VanChartAxisPlot editingPlot; protected VanChartStylePane parent; + private Chart chart; public VanChartAxisPane(VanChartAxisPlot plot, VanChartStylePane parent){ this.editingPlot = plot; @@ -188,6 +190,7 @@ public class VanChartAxisPane extends BasicBeanPane { if(chart == null){ return; } + this.chart = chart; Plot plot = chart.getPlot(); populateBean(plot); @@ -208,10 +211,12 @@ public class VanChartAxisPane extends BasicBeanPane { } for(VanChartAxis axis : editingPlot.getXAxisList()){ + axis.setChart(chart); VanChartXYAxisPaneInterface axisPane = xAxisPaneMap.get(axis.getAxisName()); axisPane.populate(axis); } for(VanChartAxis axis : editingPlot.getYAxisList()){ + axis.setChart(chart); VanChartXYAxisPaneInterface axisPane = yAxisPaneMap.get(axis.getAxisName()); axisPane.populate(axis); } @@ -237,6 +242,7 @@ public class VanChartAxisPane extends BasicBeanPane { if(chart == null){ return; } + this.chart = chart; Plot plot = chart.getPlot(); @@ -281,4 +287,8 @@ public class VanChartAxisPane extends BasicBeanPane { public VanChart updateBean() { return null; } + + public void setChart(Chart chart) { + this.chart = chart; + } } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPaneHelper.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPaneHelper.java new file mode 100644 index 000000000..770043af9 --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPaneHelper.java @@ -0,0 +1,30 @@ +package com.fr.van.chart.designer.style.axis; + +import com.fr.design.layout.TableLayout; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; +import com.fr.design.mainframe.chart.mode.ChartEditContext; +import com.fr.van.chart.designer.TableLayout4VanChartHelper; + +import javax.swing.JPanel; + +public class VanChartAxisPaneHelper { + public static ChartTextAttrPane createAxisTextAttrPane() { + return ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() { + protected double getEdithAreaWidth() { + return TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; + } + } : new ChartTextAttrPane() { + @Override + protected JPanel getContentPane(JPanel buttonPane) { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double e = TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; + double[] columnSize = {f, e}; + double[] rowSize = {p, p, p}; + + return TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), rowSize, columnSize); + } + }; + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java new file mode 100644 index 000000000..5deb49831 --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java @@ -0,0 +1,166 @@ +package com.fr.van.chart.designer.style.axis; + +import com.fr.base.BaseFormula; +import com.fr.chart.base.TextAttr; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.frpane.UINumberDragPane; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.TableLayout; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; +import com.fr.design.utils.gui.UIComponentUtils; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.plugin.chart.attr.axis.VanChartAxisLabelStyle; +import com.fr.van.chart.designer.TableLayout4VanChartHelper; +import com.fr.van.chart.designer.style.axis.component.AxisLabelDisplayComboBox; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class VanChartAxisStyleSettingPane extends BasicBeanPane { + private static final double ROTATION_MAX = 90.0; + + private AxisLabelDisplayComboBox labelDisplayComboBox; + private JPanel labelDisplayPane; + private ChartTextAttrPane labelTextAttrPane; + private UINumberDragPane labelTextRotation; + private UIButtonGroup labelGapStyle; + private UITextField labelGapValue; + private JPanel labelGapPane; + private JPanel labelGapValuePane; + private JPanel contentPane; + + private boolean showLabelDisplayPane = true; + + public VanChartAxisStyleSettingPane(boolean showLabelDisplayPane, ChartTextAttrPane textAttrPane) { + this.showLabelDisplayPane = showLabelDisplayPane; + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double s = TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; + double[] column = {f, s}; + double[] row = {p, p, p}; + + labelDisplayComboBox = new AxisLabelDisplayComboBox(); + labelDisplayPane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Show"), labelDisplayComboBox, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); + labelDisplayPane.setVisible(showLabelDisplayPane); + + labelTextAttrPane = textAttrPane; + labelTextRotation = new UINumberDragPane(-ROTATION_MAX, ROTATION_MAX); + + labelGapStyle = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Automatic"), Toolkit.i18nText("Fine-Design_Chart_Fixed")}); + labelGapValue = new UITextField(); + labelGapPane = createLabelGapPane(row, column); + + this.setLayout(new BorderLayout()); + contentPane = new JPanel(new BorderLayout()); + contentPane.add(labelDisplayPane, BorderLayout.NORTH); + contentPane.add(labelTextAttrPane, BorderLayout.CENTER); + contentPane.add(labelGapPane, BorderLayout.SOUTH); + this.add(contentPane, BorderLayout.NORTH); + initListner(); + } + + public VanChartAxisStyleSettingPane(ChartTextAttrPane textAttrPane) { + this(true, textAttrPane); + } + + @Override + public Dimension getPreferredSize() { + Dimension defaultSize = super.getPreferredSize(); + return new Dimension(defaultSize.width, contentPane.getPreferredSize().height); + } + + private void initListner() { + labelDisplayComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkLabelGapPane(); + } + }); + + labelGapStyle.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkLabelGapValuePane(); + } + }); + } + + private void checkLabelGapPane() { + if (labelGapPane != null) { + boolean visible = true; + + if (showLabelDisplayPane && labelDisplayPane != null && labelDisplayComboBox != null) { + visible = labelDisplayComboBox.getSelectedIndex() == 0; + } + + labelGapPane.setVisible(visible); + } + } + + private void checkLabelGapValuePane() { + if (labelGapValuePane != null && labelGapStyle != null) { + labelGapValuePane.setVisible(labelGapStyle.getSelectedIndex() == 1); + } + } + + @Override + public void populateBean(VanChartAxisLabelStyle style) { + labelDisplayComboBox.populateBean(style.getLabelDisplay()); + labelTextAttrPane.populate(style.getTextAttr()); + labelTextRotation.populateBean((double) style.getTextAttr().getRotation()); + labelGapStyle.setSelectedIndex(style.isAutoLabelGap() ? 0 : 1); + labelGapValue.setText(style.getLabelIntervalNumber().getContent()); + + checkLabelGapPane(); + checkLabelGapValuePane(); + } + + @Override + public VanChartAxisLabelStyle updateBean() { + VanChartAxisLabelStyle style = new VanChartAxisLabelStyle(); + style.setLabelDisplay(labelDisplayComboBox.updateBean()); + TextAttr textAttr = style.getTextAttr(); + labelTextAttrPane.update(textAttr); + textAttr.setRotation(labelTextRotation.updateBean().intValue()); + style.setTextAttr(textAttr); + style.setAutoLabelGap(labelGapStyle.getSelectedIndex() == 0); + if (style.isAutoLabelGap()) { + style.setLabelIntervalNumber(BaseFormula.createFormulaBuilder().build("0")); + } else { + style.setLabelIntervalNumber(BaseFormula.createFormulaBuilder().build(labelGapValue.getText())); + } + return style; + } + + @Override + protected String title4PopupWindow() { + return null; + } + + private JPanel createLabelGapPane(double[] row, double[] col) { + Component[][] gapComponents = new Component[][]{ + new Component[]{null, null}, + new Component[]{ + FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Chart_TextRotation")), + UIComponentUtils.wrapWithBorderLayoutPane(labelTextRotation) + }, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Label_Interval")), labelGapStyle} + }; + + JPanel gapDetailPane = TableLayout4VanChartHelper.createGapTableLayoutPane(gapComponents, row, col); + labelGapValuePane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText(""), labelGapValue, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); + + JPanel panel = new JPanel(new BorderLayout()); + panel.add(gapDetailPane, BorderLayout.CENTER); + panel.add(labelGapValuePane, BorderLayout.SOUTH); + + return panel; + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java index aff9d64c3..a6f667100 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java @@ -3,7 +3,9 @@ package com.fr.van.chart.designer.style.axis; import com.fr.base.BaseFormula; import com.fr.base.BaseUtils; import com.fr.base.Utils; +import com.fr.base.chart.chartdata.TopDefinitionProvider; import com.fr.chart.base.TextAttr; +import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Title; import com.fr.design.beans.FurtherBasicBeanPane; import com.fr.design.formula.TinyFormulaPane; @@ -13,30 +15,27 @@ import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.ibutton.UIToggleButton; import com.fr.design.gui.icombobox.LineComboBox; import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.style.FormatPane; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; -import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; import com.fr.design.mainframe.chart.gui.style.ColorSelectBoxWithThemeStyle; -import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.FRWidgetFactory; import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.attr.axis.VanChartAxisLabelStyle; import com.fr.plugin.chart.base.OverlapHandleType; import com.fr.plugin.chart.base.VanChartConstants; import com.fr.plugin.chart.type.AxisTickLineType; import com.fr.stable.Constants; import com.fr.stable.CoreConstants; import com.fr.stable.StableUtils; -import com.fr.stable.StringUtils; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.component.VanChartHtmlLabelPane; import com.fr.van.chart.designer.style.VanChartStylePane; -import com.fr.van.chart.designer.style.axis.component.AxisLabelDisplayComboBox; +import com.fr.van.chart.designer.style.axis.component.VanChartCategoryStylePaneWithCheckBox; import javax.swing.BorderFactory; import javax.swing.Icon; @@ -47,16 +46,21 @@ import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; /** * 坐标轴的基础配置项。分类,时间,值等公共的部分。 */ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { - private static final long serialVersionUID = -5717246802333308973L; private static final double ROTATION_MAX = 90.0; + private static final String WHOLE_DISPLAY = "wholeDisplay"; // 整体显示 + private static final String LAYER_DISPLAY = "layerDisplay"; // 分层显示 + protected UIButtonGroup showTitle; protected TinyFormulaPane titleContent; protected UIButtonGroup titleAlignPane; @@ -66,24 +70,19 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected JPanel titlePane; protected UIButtonGroup showLabel; - protected ChartTextAttrPane labelTextAttrPane; - protected UINumberDragPane labelTextRotation; - - private AxisLabelDisplayComboBox labelDisplayComboBox; - - //轴标签缩略间隔显示 恢复用注释。下面6行删除。 - protected UITextField labelGapValue; + protected UIButtonGroup showLogic; private UIButtonGroup overlapHandleTypeGroup; - protected UIButtonGroup labelGapStyle; //轴标签缩略间隔显示 恢复用注释。取消注释。 //protected UISpinner labelGapValue; - protected JPanel labelPanel; - private JPanel labelGapPane; - private JPanel labelGapStylePane; - private JPanel labelGapValuePane; - private JPanel labelDisplayPane; + protected JPanel labelContentPane; + private VanChartAxisStyleSettingPane labelPane; + private JPanel showLogicPane; + private JPanel labelStylePane; + private JPanel categoryStylePane; + private VanChartAxisStyleSettingPane wholeDisplayLabelPanel; + private List categoryStyles = new ArrayList<>(); protected LineComboBox axisLineStyle; @@ -107,6 +106,8 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected JPanel centerPane; private VanChartHtmlLabelPane htmlLabelPane; + private VanChartStylePane parent; + public VanChartBaseAxisPane() { this(true); } @@ -117,6 +118,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { } public void setParentPane(VanChartStylePane parent) { + this.parent = parent; htmlLabelPane.setParent(parent); } @@ -214,189 +216,102 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected JPanel createLabelPane(double[] row, double[] col) { initLabelComponents(); - labelGapPane = createLabelGapPane(row, col); - labelPanel = createLabelDetailPanel(); + labelPane = new VanChartAxisStyleSettingPane(showLabelDisplay(), getChartTextAttrPane()); + wholeDisplayLabelPanel = new VanChartAxisStyleSettingPane(showLabelDisplay(), getChartTextAttrPane()); + wholeDisplayLabelPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); addComponentsListener(); JPanel showLabelPane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Axis_Label"), showLabel); + JPanel labelContentPane = createLabelContentPane(); JPanel labelPane = new JPanel(new BorderLayout()); labelPane.add(showLabelPane, BorderLayout.NORTH); - labelPane.add(labelPanel, BorderLayout.CENTER); + labelPane.add(labelContentPane, BorderLayout.CENTER); return TableLayout4VanChartHelper.createExpandablePaneWithTitle(PaneTitleConstants.CHART_STYLE_LABEL_TITLE, labelPane); } private void initLabelComponents() { showLabel = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Use_Show"), Toolkit.i18nText("Fine-Design_Chart_Hidden")}); - - labelDisplayComboBox = new AxisLabelDisplayComboBox(); - labelDisplayPane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Show"), labelDisplayComboBox, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); - labelDisplayPane.setVisible(showLabelDisplay()); - - labelTextAttrPane = getChartTextAttrPane(); - labelTextRotation = new UINumberDragPane(-ROTATION_MAX, ROTATION_MAX); - labelGapStyle = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Automatic"), Toolkit.i18nText("Fine-Design_Chart_Fixed")}); - labelGapValue = new UITextField(); - } - - private JPanel createLabelGapPane(double[] row, double[] col) { - Component[][] gapComponents = new Component[][]{ - new Component[]{null, null}, - new Component[]{ - FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Chart_TextRotation")), - UIComponentUtils.wrapWithBorderLayoutPane(labelTextRotation) - }, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Label_Interval")), labelGapStyle} - }; - - JPanel gapDetailPane = TableLayout4VanChartHelper.createGapTableLayoutPane(gapComponents, row, col); - labelGapValuePane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText(""), labelGapValue, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); - - JPanel panel = new JPanel(new BorderLayout()); - panel.add(gapDetailPane, BorderLayout.CENTER); - panel.add(labelGapValuePane, BorderLayout.SOUTH); - - return panel; - } - - private JPanel createLabelDetailPanel() { - JPanel panel = new JPanel(new BorderLayout()); - panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); - - panel.add(labelDisplayPane, BorderLayout.NORTH); - panel.add(labelTextAttrPane, BorderLayout.CENTER); - panel.add(labelGapPane, BorderLayout.SOUTH); - - return panel; + showLogic = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Axis_Style_Whole_Display"), Toolkit.i18nText("Fine-Design_Chart_Axis_Style_Layer_Display")}); + initButtonGroupListener(); } - private void addComponentsListener() { - // 显示/隐藏 - showLabel.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - checkLabelPane(); - } - }); - - // 间隔/缩略/换行 - labelDisplayComboBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - checkLabelGapPane(); - } - }); - - // 自动/固定 - labelGapStyle.addActionListener(new ActionListener() { + private void initButtonGroupListener() { + showLogic.addChangeListener(new ChangeListener() { @Override - public void actionPerformed(ActionEvent e) { - checkLabelGapValuePane(); + public void stateChanged(ChangeEvent e) { + showLabelStyleCard(); } }); } -// protected JPanel createLabelPane(double[] row, double[] col){ -// double p = TableLayout.PREFERRED; -// showLabel = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Use_Show"), Toolkit.i18nText("Fine-Design_Chart_Hidden")}); -// labelTextAttrPane = getChartTextAttrPane(); -// -// JPanel rotationPane = createLabelRotationPane(col); -// JPanel overlapPane = createLabelOverlapPane(); -// -// -// Component[][] components = new Component[][]{ -// new Component[]{labelTextAttrPane, null}, -// new Component[]{rotationPane, null}, -// new Component[]{overlapPane, null}, -// }; -// -// JPanel showLabelPane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Axis_Label"),showLabel); -// labelPanel = TableLayout4VanChartHelper.createGapTableLayoutPane(components, new double[]{p, p, p}, col); -// labelPanel.setBorder(BorderFactory.createEmptyBorder(0,10,0,0)); -// showLabel.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// checkLabelPane(); -// } -// }); -// JPanel jPanel = new JPanel(new BorderLayout()); -// jPanel.add(showLabelPane, BorderLayout.NORTH); -// jPanel.add(labelPanel, BorderLayout.CENTER); -// return TableLayout4VanChartHelper.createExpandablePaneWithTitle(PaneTitleConstants.CHART_STYLE_LABEL_TITLE, jPanel); -// } - - private JPanel createLabelRotationPane(double[] col) { - labelTextRotation = new UINumberDragPane(-ROTATION_MAX, ROTATION_MAX); - - Component[][] gapComponents = new Component[][]{ - new Component[]{ - FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Chart_TextRotation")), - UIComponentUtils.wrapWithBorderLayoutPane(labelTextRotation) - } - }; - return TableLayout4VanChartHelper.createGapTableLayoutPane(gapComponents, new double[]{TableLayout.PREFERRED}, col); + private void showLabelStyleCard() { + CardLayout layout = (CardLayout) labelStylePane.getLayout(); + if (showLogic.getSelectedIndex() == 0) { + layout.show(labelStylePane, WHOLE_DISPLAY); + } else { + layout.show(labelStylePane, LAYER_DISPLAY); + } + labelStylePane.revalidate(); } - private JPanel createLabelOverlapPane() { - - labelGapStyle = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Automatic"), Toolkit.i18nText("Fine-Design_Chart_Fixed")}); - labelGapStylePane = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Label_Interval"), labelGapStyle, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); - - //轴标签缩略间隔显示 恢复用注释。取消注释。 - //labelGapValue = new UISpinner(0, Integer.MAX_VALUE, 1, 1); - labelGapValuePane = TableLayout4VanChartHelper.createGapTableLayoutPane(StringUtils.EMPTY, labelGapValue, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); - - JPanel panel = new JPanel(new BorderLayout(0, 0)); - addOverlapGroupButton(panel); - panel.add(labelGapStylePane, BorderLayout.CENTER); - panel.add(labelGapValuePane, BorderLayout.SOUTH); - - labelGapStyle.addActionListener(new ActionListener() { + /** + * 创建显示逻辑以及其下面面板 + * + * @return + */ + private JPanel createLabelContentPane() { + labelContentPane = new JPanel(new BorderLayout()); + showLogicPane = new JPanel(new BorderLayout()); + labelStylePane = new JPanel(new CardLayout()) { @Override - public void actionPerformed(ActionEvent e) { - checkLabelGapValuePane(); + public Dimension getPreferredSize() { + switch (showLogic.getSelectedIndex()) { + case 0: + return wholeDisplayLabelPanel.getPreferredSize(); + case 1: + return categoryStylePane.getPreferredSize(); + case -1: + default: + return super.getPreferredSize(); + } } - }); - - return panel; + }; + labelStylePane.add(wholeDisplayLabelPanel, WHOLE_DISPLAY); + labelStylePane.add(createCategoryStylePane(), LAYER_DISPLAY); + showLogicPane.add(TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Show_Logic"), showLogic), BorderLayout.NORTH); + showLogicPane.add(labelStylePane, BorderLayout.CENTER); + showLogicPane.setVisible(false); + labelContentPane.add(labelPane, BorderLayout.NORTH); + labelContentPane.add(showLogicPane, BorderLayout.CENTER); + return labelContentPane; } - protected void addOverlapGroupButton(JPanel panel) { - overlapHandleTypeGroup = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Label_OverlapAbbreviate"), Toolkit.i18nText("Fine-Design_Chart_Label_OverlapInterval")}, - new OverlapHandleType[]{OverlapHandleType.ABBREVIATE, OverlapHandleType.INTERVAL}); - JPanel north = TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Label_WhenOverlap"), overlapHandleTypeGroup, TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH); - - panel.add(north, BorderLayout.NORTH); + /** + * 创建多分类轴标签设置面板 + * + * @return + */ + private JPanel createCategoryStylePane() { + categoryStylePane = new JPanel(new BorderLayout()); + categoryStylePane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + return categoryStylePane; + } - overlapHandleTypeGroup.addChangeListener(new ChangeListener() { + private void addComponentsListener() { + // 显示/隐藏 + showLabel.addActionListener(new ActionListener() { @Override - public void stateChanged(ChangeEvent e) { - checkLabelGapAndStylePane(); + public void actionPerformed(ActionEvent e) { + checkLabelPane(); } }); - } protected ChartTextAttrPane getChartTextAttrPane() { - return ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() { - protected double getEdithAreaWidth() { - return TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; - } - } : new ChartTextAttrPane() { - @Override - protected JPanel getContentPane(JPanel buttonPane) { - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double e = TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; - double[] columnSize = {f, e}; - double[] rowSize = {p, p, p}; - - return TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), rowSize, columnSize); - } - }; + return VanChartAxisPaneHelper.createAxisTextAttrPane(); } protected JPanel createLineStylePane(double[] row, double[] col) { @@ -537,7 +452,6 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected void checkAllUse() { checkCardPane(); checkLabelPane(); - checkLabelGapPane(); checkTitlePane(); //区域显示策略 恢复用注释。删除下面一行。 checkMaxProPortionUse(); @@ -570,14 +484,8 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected void checkLabelPane() { if (showLabel != null) { boolean enabled = showLabel.getSelectedIndex() == 0; - if (labelPanel != null) { - labelPanel.setVisible(enabled); - } - if (enabled) { - //轴标签缩略间隔显示 恢复用注释。下面1行删除。 - checkLabelGapValuePane(); - //轴标签缩略间隔显示 恢复用注释。取消注释。 - //checkLabelGapAndStylePane(); + if (labelContentPane != null) { + labelContentPane.setVisible(enabled); } } } @@ -588,39 +496,6 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { } } - private void checkLabelGapAndStylePane() { - if (overlapHandleTypeGroup != null && labelGapStylePane != null) { - boolean visible = overlapHandleTypeGroup.getSelectedItem() == OverlapHandleType.INTERVAL; - - labelGapStylePane.setVisible(visible); - } - checkLabelGapValuePane(); - } - - protected void checkLabelGapPane() { - if (labelGapPane != null) { - boolean visible = true; - - if (showLabelDisplay() && labelDisplayPane != null && labelDisplayComboBox != null) { - visible = labelDisplayComboBox.getSelectedIndex() == 0; - } - - labelGapPane.setVisible(visible); - } - } - - protected void checkLabelGapValuePane() { - if (labelGapValuePane != null && labelGapStyle != null) { - boolean visible = labelGapStyle.getSelectedIndex() == 1; - //轴标签缩略间隔显示 恢复用注释。取消注释。 -// if (overlapHandleTypeGroup != null) { -// visible = visible && overlapHandleTypeGroup.getSelectedItem() == OverlapHandleType.INTERVAL; -// } - labelGapValuePane.setVisible(visible); - } - } - - /** * 是否是指定类型 * @@ -698,29 +573,134 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { if (showLabel != null) { showLabel.setSelectedIndex(axis.isShowAxisLabel() ? 0 : 1); } - TextAttr labelTextAttr = axis.getTextAttr(); - if (labelTextAttrPane != null) { - labelTextAttrPane.populate(labelTextAttr); + + labelPane.populateBean(getAxisLabelStyle(axis)); + populateShowLogicPane(axis); + switchLabelPane(axis); + labelContentPane.validate(); + } + + /** + * 切换显示是单分类样式设置面板还是多分类样式设置面板 + */ + private void switchLabelPane(VanChartAxis axis) { + labelPane.setVisible(!axis.isMultiCategory()); + showLogicPane.setVisible(axis.isMultiCategory()); + } + + private void populateShowLogicPane(VanChartAxis axis) { + if (showLogic != null) { + showLogic.setSelectedIndex(axis.getLabelDisplayMode()); } - if (labelTextRotation != null) { - labelTextRotation.populateBean((double) labelTextAttr.getRotation()); + populateWholeDisplayPane(axis); + populateLayerDisplayPane(axis); + showLabelStyleCard(); + labelStylePane.revalidate(); + } + + /** + * populate整体显示那个card面板 + */ + private void populateWholeDisplayPane(VanChartAxis axis) { + wholeDisplayLabelPanel.populateBean(getAxisLabelStyle(axis)); + } + + private VanChartAxisLabelStyle getAxisLabelStyle(VanChartAxis axis) { + VanChartAxisLabelStyle style = new VanChartAxisLabelStyle(); + style.setLabelDisplay(axis.getLabelDisplay()); + style.setTextAttr(axis.getTextAttr()); + style.setAutoLabelGap(axis.isAutoLabelGap()); + style.setLabelIntervalNumber(axis.getLabelNumber()); + return style; + } + + /** + * populate分层显示那个card面板 + * + * @param axis + */ + private void populateLayerDisplayPane(VanChartAxis axis) { + Chart chart = axis.getChart(); + if (chart == null) { + return; } - //轴标签缩略间隔显示 恢复用注释。取消注释。 -// if (overlapHandleTypeGroup != null) { -// overlapHandleTypeGroup.setSelectedItem(axis.getOverlapHandleType()); -// } - if (labelDisplayComboBox != null) { - labelDisplayComboBox.populateBean(axis.getLabelDisplay()); + categoryStylePane.removeAll(); + categoryStyles.clear(); + populateCateLabelStyle(axis); + + categoryStylePane.revalidate(); + } + + + /** + * populate分类标签 + * + * @param axis + */ + private void populateCateLabelStyle(VanChartAxis axis) { + Chart chart = axis.getChart(); + int size; + TopDefinitionProvider definition = chart.getFilterDefinition(); + size = definition == null ? 1 : definition.getMoreCateSize() + 1; + + for (int i = 0; i < size; i++) { + populateCategoryStyles(axis, i); + } + } + + private void populateCategoryStyles(VanChartAxis axis, int index) { + VanChartCategoryStylePaneWithCheckBox pane = new VanChartCategoryStylePaneWithCheckBox(parent, this, Toolkit.i18nText("Fine-Design_Chart_Style_Category") + (index + 1)); + VanChartAxisLabelStyle style = populateAxisCategoryStyles(axis, index); + pane.populate(style); + categoryStyles.add(pane); + categoryStylePane.add(createCateLableStylePanel(), BorderLayout.NORTH); + + } + + private VanChartAxisLabelStyle populateAxisCategoryStyles(VanChartAxis axis, int index) { + VanChartAxisLabelStyle style; + if (axis.getCategoryStylesSize() > index && axis.getCategoryStyle(index) != null) { + style = axis.getCategoryStyle(index); + } else { + style = new VanChartAxisLabelStyle(); + axis.addCategoryStyle(style); } - if (labelGapStyle != null) { - labelGapStyle.setSelectedIndex(axis.isAutoLabelGap() ? 0 : 1); + return style; + } + + private JPanel createCateLableStylePanel() { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double e = TableLayout4VanChartHelper.EDIT_AREA_WIDTH; + double[] row = getCateLableStylePaneRow(); + double[] column = {f, p}; + + JPanel content = TableLayoutHelper.createTableLayoutPane(getCateLabelStyleComponents(), row, column); + + Component[][] components = new Component[][]{ + new Component[]{null, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Style_Category")), content} + }; + + return TableLayoutHelper.createTableLayoutPane(components, new double[]{p, p}, new double[]{f, e}); + } + + private Component[][] getCateLabelStyleComponents() { + Component[][] components = new Component[categoryStyles.size()][]; + for (int i = 0; i < categoryStyles.size(); i++) { + components[i] = new Component[2]; + components[i][0] = categoryStyles.get(i); + components[i][1] = null; } - if (labelGapValue != null) { - //轴标签缩略间隔显示 恢复用注释。下面1行删除。 - labelGapValue.setText(axis.getLabelNumber().getContent()); - //轴标签缩略间隔显示 恢复用注释。取消注释。 - //labelGapValue.setValue(axis.getIntervalNumber()); + return components; + } + + private double[] getCateLableStylePaneRow() { + double[] row = new double[categoryStyles.size()]; + for (int i = 0; i < categoryStyles.size(); i++) { + row[i] = TableLayout.PREFERRED; } + return row; } //轴线样式 @@ -837,33 +817,50 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { if (showLabel != null) { axis.setShowAxisLabel(showLabel.getSelectedIndex() == 0); } - TextAttr labelTextAttr = axis.getTextAttr(); - if (labelTextAttrPane != null) { - labelTextAttrPane.update(labelTextAttr); - } - if (labelTextRotation != null) { - labelTextAttr.setRotation(labelTextRotation.updateBean().intValue()); - } - //轴标签缩略间隔显示 恢复用注释。取消注释。 -// if (overlapHandleTypeGroup != null) { -// axis.setOverlapHandleType(overlapHandleTypeGroup.getSelectedItem()); -// } - if (labelDisplayComboBox != null) { - axis.setLabelDisplay(labelDisplayComboBox.updateBean()); + if (!axis.isMultiCategory()) { + axis.setLabelDisplayMode(VanChartAxis.WHOLE_DISPLAY); + updateLabelPaneStyle(axis, labelPane); + } else { + updateShowLogicPane(axis); } - if (labelGapStyle != null) { - axis.setAutoLabelGap(labelGapStyle.getSelectedIndex() == 0); + switchLabelPane(axis); + } + + private void updateShowLogicPane(VanChartAxis axis) { + if (showLogic != null) { + axis.setLabelDisplayMode(showLogic.getSelectedIndex()); } - if (labelGapValue != null) { - //轴标签缩略间隔显示 恢复用注释。下面5行删除。 - if (axis.isAutoLabelGap()) { - axis.setLabelIntervalNumber(BaseFormula.createFormulaBuilder().build("1")); - } else { - axis.setLabelIntervalNumber(BaseFormula.createFormulaBuilder().build(labelGapValue.getText())); - } - //轴标签缩略间隔显示 恢复用注释。取消注释。 - //axis.setIntervalNumber((int) labelGapValue.getValue()); + + updateWholeDisplayPane(axis); + updateLayerDisplayPane(axis); + } + + /** + * update整体显示那个card面板 + */ + private void updateWholeDisplayPane(VanChartAxis axis) { + updateLabelPaneStyle(axis, wholeDisplayLabelPanel); + } + + private void updateLabelPaneStyle(VanChartAxis axis, VanChartAxisStyleSettingPane pane) { + VanChartAxisLabelStyle style = pane.updateBean(); + axis.setLabelDisplay(style.getLabelDisplay()); + axis.setTextAttr(style.getTextAttr()); + axis.setAutoLabelGap(style.isAutoLabelGap()); + axis.setLabelIntervalNumber(style.getLabelIntervalNumber()); + } + + /** + * update分层显示那个card面板 + * + * @param axis + */ + private void updateLayerDisplayPane(VanChartAxis axis) { + List styles = new ArrayList<>(); + for (VanChartCategoryStylePaneWithCheckBox categoryStyle : categoryStyles) { + styles.add(categoryStyle.update()); } + axis.setCategoryStyles(styles); } //轴线样式 diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartTimeAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartTimeAxisPane.java index 1a0b78982..500667963 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartTimeAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartTimeAxisPane.java @@ -85,11 +85,6 @@ public class VanChartTimeAxisPane extends VanChartBaseAxisPane { return false; } - @Override - protected void addOverlapGroupButton(JPanel panel) { - //do nothing - } - private JPanel createValueDefinition(){ timeMinMaxValuePane = new TimeMinMaxValuePane(); return TableLayout4VanChartHelper.createExpandablePaneWithTitle(Toolkit.i18nText("Fine-Design_Chart_Value_Definition"), timeMinMaxValuePane); diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartValueAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartValueAxisPane.java index 7633d0c1e..032642c93 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartValueAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartValueAxisPane.java @@ -66,11 +66,6 @@ public class VanChartValueAxisPane extends VanChartBaseAxisPane { return false; } - @Override - protected void addOverlapGroupButton(JPanel panel) { - //do nothing - } - protected JPanel createMinMaxValuePane(double[] row, double[] col){ JPanel panel = createCommenValuePane(row,col); return TableLayout4VanChartHelper.createExpandablePaneWithTitle(Toolkit.i18nText("Fine-Design_Chart_Value_Definition"), panel); diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java new file mode 100644 index 000000000..acc87572f --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java @@ -0,0 +1,97 @@ +package com.fr.van.chart.designer.style.axis.component; + +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; +import com.fr.design.gui.frpane.UIBubbleFloatPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.i18n.Toolkit; +import com.fr.plugin.chart.attr.axis.VanChartAxisLabelStyle; +import com.fr.stable.Constants; +import com.fr.van.chart.designer.style.axis.VanChartAxisPaneHelper; +import com.fr.van.chart.designer.style.axis.VanChartAxisStyleSettingPane; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class VanChartCategoryStylePaneWithCheckBox extends JPanel { + private UICheckBox checkBox; // 复选框 + private UIButton settingButton; // 设置按钮 + private VanChartAxisStyleSettingPane settingPane; // 设置弹窗面板 + + private JPanel showOnPane; + private AbstractAttrNoScrollPane parent; + + private VanChartAxisLabelStyle axis; + + public VanChartCategoryStylePaneWithCheckBox(AbstractAttrNoScrollPane parent, JPanel showOnPane, String checkBoxName) { + this.parent = parent; + this.showOnPane = showOnPane; + + this.setLayout(new BorderLayout()); + checkBox = new UICheckBox(checkBoxName); + checkBox.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + checkBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + /* 为什么需要这句话呢?因为这个checkBox是动态加上去的,没有走最上层父组件ChartStylePane的initAllListener方法, + * 所以不会触发update监听,下面的bubble弹窗则是不属于ChartStylePane的单独悬浮组件,也只能这样触发update监听 + */ + if(parent != null){ + parent.attributeChanged(); + } + } + }); + settingButton = new UIButton(Toolkit.i18nText("Fine-Design_Chart_Axis_Style_Setting")); + + this.add(checkBox, BorderLayout.CENTER); + this.add(settingButton, BorderLayout.EAST); + + initListener(); + } + + private void initListener() { + if(settingButton != null) { + settingButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if (settingPane == null) { + settingPane = new VanChartAxisStyleSettingPane(VanChartAxisPaneHelper.createAxisTextAttrPane()); + } + + Point comPoint = settingButton.getLocationOnScreen(); + Point arrowPoint = new Point(comPoint.x +settingButton.getWidth() - 25, comPoint.y + settingButton.getHeight()); + Dimension size = settingPane.getPreferredSize(); + UIBubbleFloatPane pane = new UIBubbleFloatPane(Constants.LEFT, arrowPoint, settingPane, size.width, 230) { + + @Override + public void updateContentPane() { + axis = settingPane.updateBean(); + if(parent != null){//条件属性没有parent + parent.attributeChanged(); + } + } + }; + pane.show(showOnPane, axis); + super.mouseReleased(e); + } + }); + } + } + + public void populate(VanChartAxisLabelStyle style) { + this.axis = style; + checkBox.setSelected(axis.isShowLabel()); + } + + public VanChartAxisLabelStyle update() { + axis.setShowLabel(checkBox.isSelected()); + return axis; + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java index 91de3ed35..aa2c2a3fd 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java @@ -1,5 +1,6 @@ package com.fr.van.chart.designer.style.axis.gauge; +import com.fr.chart.base.TextAttr; import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; @@ -35,6 +36,7 @@ public class VanChartGaugeDetailAxisPane extends VanChartValueAxisPane { private static final long serialVersionUID = -9213466625457882224L; + private ChartTextAttrPane labelTextAttrPane; private ColorSelectBox mainTickColor; private ColorSelectBox secTickColor; @@ -83,12 +85,12 @@ public class VanChartGaugeDetailAxisPane extends VanChartValueAxisPane { protected JPanel createLabelPane(double[] row, double[] col) { showLabel = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Use_Show"), Toolkit.i18nText("Fine-Design_Chart_Hidden")}); labelTextAttrPane = getChartTextAttrPane(); - labelPanel = new JPanel(new BorderLayout()); - labelPanel.add(labelTextAttrPane); - labelPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); + labelContentPane = new JPanel(new BorderLayout()); + labelContentPane.add(labelTextAttrPane); + labelContentPane.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); JPanel panel = new JPanel(new BorderLayout(0, 6)); panel.add(TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_Axis_Label"), showLabel), BorderLayout.NORTH); - panel.add(labelPanel, BorderLayout.CENTER); + panel.add(labelContentPane, BorderLayout.CENTER); showLabel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -183,6 +185,7 @@ public class VanChartGaugeDetailAxisPane extends VanChartValueAxisPane { public void populateBean(VanChartAxis axis) { VanChartGaugeAxis gaugeAxis = (VanChartGaugeAxis) axis; + labelTextAttrPane.populate(axis.getTextAttr()); if (mainTickColor != null) { mainTickColor.setSelectObject(gaugeAxis.getMainTickColor()); } @@ -194,6 +197,8 @@ public class VanChartGaugeDetailAxisPane extends VanChartValueAxisPane { public void updateBean(VanChartAxis axis) { VanChartGaugeAxis gaugeAxis = (VanChartGaugeAxis) axis; + TextAttr textAttr = axis.getTextAttr(); + labelTextAttrPane.update(textAttr); if (mainTickColor != null) { gaugeAxis.setMainTickColor(mainTickColor.getSelectObject()); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartGantAreaPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartGantAreaPane.java new file mode 100644 index 000000000..382a91827 --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartGantAreaPane.java @@ -0,0 +1,15 @@ +package com.fr.van.chart.designer.style.background; + +import com.fr.chart.chartattr.Plot; +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; +import com.fr.van.chart.designer.style.VanChartStylePane; + +public class VanChartGantAreaPane extends VanChartAreaPane { + public VanChartGantAreaPane(Plot plot, VanChartStylePane parent) { + super(plot, parent); + } + + protected void initPlotPane(boolean b, AbstractAttrNoScrollPane parent) { + plotPane = new VanChartGantPlotAreaBackgroundPane(parent); + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartGantPlotAreaBackgroundPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartGantPlotAreaBackgroundPane.java new file mode 100644 index 000000000..fbea84990 --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartGantPlotAreaBackgroundPane.java @@ -0,0 +1,102 @@ +package com.fr.van.chart.designer.style.background; + +import com.fr.chart.chartattr.Chart; +import com.fr.chart.chartattr.Plot; +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.chart.gui.ColorSelectBoxWithOutTransparent; +import com.fr.plugin.chart.gantt.VanChartGanttPlot; +import com.fr.van.chart.designer.TableLayout4VanChartHelper; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + +public class VanChartGantPlotAreaBackgroundPane extends VanChartAreaBackgroundPane { + private ColorSelectBoxWithOutTransparent axisColorPane; + private ColorSelectBoxWithOutTransparent contentColorPane; + + public VanChartGantPlotAreaBackgroundPane(AbstractAttrNoScrollPane parent) { + super(true, parent); + } + + @Override + protected JPanel createContentPane() { + JPanel contentPane = new JPanel(new BorderLayout()); + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {f}; + double[] rowSize = {p, p}; + Component[][] components = new Component[][]{ + new Component[]{createAxisBorderPane()}, + new Component[]{createContentBorderPane()} + }; + + contentPane.add(TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize), BorderLayout.CENTER); + return contentPane; + } + + @Override + public void updateBean(Chart chart) { + if (chart == null) { + chart = new Chart(); + } + + Plot plot = chart.getPlot(); + if (plot instanceof VanChartGanttPlot) { + VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; + ganttPlot.setAxisBorderColor(axisColorPane.getSelectObject()); + ganttPlot.setContentBorderColor(contentColorPane.getSelectObject()); + } + } + + @Override + public void populateBean(Chart chart) { + if (chart == null) { + chart = new Chart(); + } + + Plot plot = chart.getPlot(); + if (plot instanceof VanChartGanttPlot) { + VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; + axisColorPane.setSelectObject(ganttPlot.getAxisBorderColor()); + contentColorPane.setSelectObject(ganttPlot.getContentBorderColor()); + } + } + + private JPanel createAxisBorderPane() { + axisColorPane = new ColorSelectBoxWithOutTransparent(100); + return TableLayout4VanChartHelper.createExpandablePaneWithTitle( + Toolkit.i18nText("Fine-Design_Chart_Gant_Axis_Border"), + createBorderPane(axisColorPane) + ); + } + + private JPanel createContentBorderPane() { + contentColorPane = new ColorSelectBoxWithOutTransparent(100); + return TableLayout4VanChartHelper.createExpandablePaneWithTitle( + Toolkit.i18nText("Fine-Design_Chart_Gant_Content_Border"), + createBorderPane(contentColorPane) + ); + } + + private JPanel createBorderPane(ColorSelectBoxWithOutTransparent colorPane) { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {f, TableLayout4VanChartHelper.EDIT_AREA_WIDTH}; + double[] rowSize = {p, p}; + + Component[][] components = new Component[][]{ + new Component[]{null, null}, + new Component[]{ + new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), + colorPane + } + }; + + return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/VanChartGanttStylePane.java b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/VanChartGanttStylePane.java index b12e0579f..7d1de704f 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/VanChartGanttStylePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/VanChartGanttStylePane.java @@ -4,6 +4,8 @@ import com.fr.chart.chartattr.Plot; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.frpane.AttributeChangeListener; import com.fr.van.chart.designer.style.VanChartStylePane; +import com.fr.van.chart.designer.style.background.VanChartAreaPane; +import com.fr.van.chart.designer.style.background.VanChartGantAreaPane; import com.fr.van.chart.gantt.designer.style.axis.GanttProcessAxisPane; import com.fr.van.chart.gantt.designer.style.axis.GanttTimeAxisPane; @@ -31,4 +33,8 @@ public class VanChartGanttStylePane extends VanChartStylePane { private void addProjectAxisPane(List paneList, Plot plot) { paneList.add(new GanttProcessAxisPane()); } + + protected VanChartAreaPane createVanChartAreaPane() { + return new VanChartGantAreaPane(getChart().getPlot(), VanChartGanttStylePane.this); + } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/series/VanChartGanttSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/series/VanChartGanttSeriesPane.java index 9236773e7..a62f054e7 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/series/VanChartGanttSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/series/VanChartGanttSeriesPane.java @@ -5,6 +5,7 @@ import com.fr.design.beans.BasicBeanPane; import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.icombobox.LineComboBox; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.gui.ChartStylePane; @@ -14,6 +15,7 @@ import com.fr.plugin.chart.gantt.VanChartGanttPlot; import com.fr.stable.CoreConstants; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.component.VanChartBeautyPane; +import com.fr.van.chart.designer.component.VanChartGanttTimeLinePane; import com.fr.van.chart.designer.component.VanChartMarkerPane; import com.fr.van.chart.designer.component.marker.VanChartCommonMarkerPane; import com.fr.van.chart.designer.style.series.VanChartAbstractPlotSeriesPane; @@ -30,6 +32,8 @@ public class VanChartGanttSeriesPane extends VanChartAbstractPlotSeriesPane { private LineComboBox lineWidth;//线型 private ColorSelectBoxWithOutTransparent colorSelect;//颜色 + private VanChartGanttTimeLinePane timeLinePane; + public VanChartGanttSeriesPane(ChartStylePane parent, Plot plot) { super(parent, plot); } @@ -45,7 +49,8 @@ public class VanChartGanttSeriesPane extends VanChartAbstractPlotSeriesPane { new Component[]{createGanntStylePane()}, new Component[]{createLinkLinePane()}, new Component[]{createMarkerPane()}, - new Component[]{createLargeDataModelPane()} + new Component[]{createLargeDataModelPane()}, + new Component[]{createGuideLinePane()} }; contentPane = TableLayoutHelper.createTableLayoutPane(components, row, col); @@ -96,6 +101,11 @@ public class VanChartGanttSeriesPane extends VanChartAbstractPlotSeriesPane { return TableLayout4VanChartHelper.createExpandablePaneWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Gannt_Marker"), markerPane); } + protected JPanel createGuideLinePane() { + timeLinePane = new VanChartGanttTimeLinePane(); + return TableLayout4VanChartHelper.createExpandablePaneWithTitle(Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Identify"), timeLinePane); + } + @Override public void populateBean(Plot plot) { super.populateBean(plot); @@ -104,10 +114,10 @@ public class VanChartGanttSeriesPane extends VanChartAbstractPlotSeriesPane { VanChartGanttPlot ganttPlot = (VanChartGanttPlot)plot; seriesNewLine.setSelectedIndex(ganttPlot.isSeriesNewLineEnable() ? 0 : 1); - lineWidth.setSelectedLineStyle(ganttPlot.getLineWidth()); colorSelect.setSelectObject(ganttPlot.getLineColor()); + timeLinePane.populateBean(plot); } } @@ -121,6 +131,7 @@ public class VanChartGanttSeriesPane extends VanChartAbstractPlotSeriesPane { ganttPlot.setLineWidth(lineWidth.getSelectedLineStyle()); ganttPlot.setLineColor(colorSelect.getSelectObject()); + timeLinePane.updateBean(plot); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/tooltip/VanChartFormatComBoxWithCheckBox.java b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/tooltip/VanChartFormatComBoxWithCheckBox.java index 95da8ea98..f17d07a24 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/tooltip/VanChartFormatComBoxWithCheckBox.java +++ b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/style/tooltip/VanChartFormatComBoxWithCheckBox.java @@ -53,7 +53,7 @@ public class VanChartFormatComBoxWithCheckBox extends JPanel { } }); - formatComBox.setPreferredSize(new Dimension(40, 20)); + formatComBox.setPreferredSize(new Dimension(55, 20)); if (showSelectBox()) { this.add(isSelectedBox, BorderLayout.CENTER); diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java index 174f56ea2..b296da48b 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java @@ -1,35 +1,24 @@ package com.fr.design.designer.beans; -import java.awt.Graphics; -import java.awt.event.MouseEvent; -import java.util.ArrayList; - -import javax.swing.JComponent; -import javax.swing.JPopupMenu; - import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.events.DesignerEditor; import com.fr.design.designer.creator.PropertyGroupPane; +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + /** * 组件适配器接口 * 主要目的是为具体组件提供特殊设计行为 */ public interface ComponentAdapter { - /** - * 在组件选择面板上选择了组件类型后,在设计界面上跟随鼠标移动用来代表当前要添加组件的图形 - * 一般使用组件自身的图形代替。 - * - * @param component 要添加的组件 - * @param g 当前设计器的图形上下文对象 - */ - void paintComponentMascot(Graphics g); - /** * 当鼠标在此设计组件上右键点击时,该方法根据上下文和组件类型提供弹出响应的菜单 * - * @param 引发弹出菜单的鼠标事件 + * @param e 引发弹出菜单的鼠标事件 * * @return 弹出菜单 */ @@ -49,7 +38,7 @@ public interface ComponentAdapter { /** * 提供双击设计器的编辑器 - * @param bean 鼠标双击的被设计组件 + * * @return 被设计的编辑器 */ public DesignerEditor getDesignerEditor(); @@ -57,5 +46,5 @@ public interface ComponentAdapter { /** * 实例化组件的适配器后,在这儿进行初始化 */ - void initialize(); + void initialize(); } \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java index 3c0c2bd5f..bbc7670a4 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java @@ -3,11 +3,15 @@ package com.fr.design.designer.beans; import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.adapters.layout.DefaultDesignerBaseOperate; import com.fr.design.designer.beans.adapters.layout.DesignerBaseOperate; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.treeview.DefaultXCreatorTreeCellRender; import com.fr.design.designer.treeview.XCreatorTreeCellRender; +import java.awt.Dimension; +import java.awt.Graphics; + /** * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类, * 对于界面设计工具来说还需一些特殊的行为。 @@ -135,9 +139,46 @@ public interface LayoutAdapter { return true; } + /** + * 拖拽开始 + * + * @param xCreator + * @param selectionModel + */ void dragStart(XCreator xCreator, SelectionModel selectionModel); + /** + * 拖拽经过 + * + * @param xCreator + * @param selectionModel + * @param x + * @param y + */ default void dragOver(XCreator xCreator, SelectionModel selectionModel, int x, int y) { }; + + /** + * 组件正在被拖拽时的处理逻辑 + * + * @param model + */ + void dragging(DraggingModel model); + + /** + * 绘制组件拖拽阴影 + * + * @param g 当前设计器的图形上下文对象 + * @param xCreator 被拖拽的组件 + */ + void paintComponentMascot(Graphics g, XCreator xCreator); + + /** + * 描述组件被拖拽的时候应该显示的尺寸 + * + * @param creator 被拖拽的组件 + * @return 组件大小 + */ + Dimension getDragSize(XCreator creator); } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java index cb7a7a620..d97b85c5a 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java @@ -23,13 +23,9 @@ import com.fr.stable.core.PropertyChangeAdapter; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.JPopupMenu; -import java.awt.AlphaComposite; import java.awt.Component; import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; import java.beans.IntrospectionException; import java.util.ArrayList; import java.util.Collections; @@ -63,19 +59,6 @@ public class CompositeComponentAdapter implements ComponentAdapter { } } - @Override - public void paintComponentMascot(Graphics g) { - //自适应交叉点渲染有点问题,拖拽的控件设置成半透明 - Graphics2D g2d = (Graphics2D) g; - AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f); - g2d.setComposite(composite); - BufferedImage im = new BufferedImage(xCreator.getWidth(), xCreator.getHeight(), BufferedImage.TYPE_INT_ARGB); - xCreator.paint(im.getGraphics()); - g.drawImage(im, 0, 0, xCreator.initEditorSize().width - 1, xCreator.initEditorSize().height - 1, null); - g.setColor(XCreatorConstants.RESIZE_BOX_BORDER_COLOR); - g.drawRect(0, 0, xCreator.initEditorSize().width - 1, xCreator.initEditorSize().height - 1); - } - @Override public JPopupMenu getContextPopupMenu(MouseEvent e) { JPopupMenu popupMenu = new JPopupMenu(); diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java index 7d287e5a5..e0f79e65e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java @@ -4,16 +4,23 @@ import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.beans.painters.NullPainter; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.design.form.util.XCreatorConstants; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.general.ComparatorUtils; +import java.awt.AlphaComposite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.LayoutManager; +import java.awt.image.BufferedImage; public abstract class AbstractLayoutAdapter implements LayoutAdapter { @@ -209,4 +216,28 @@ public abstract class AbstractLayoutAdapter implements LayoutAdapter { selectionModel.removeCreator(xCreator, xCreator.getWidth(), xCreator.getHeight()); selectionModel.setSelectedCreator(container); } + + @Override + public void dragging(DraggingModel model) { + + } + + @Override + public void paintComponentMascot(Graphics g, XCreator xCreator) { + //自适应交叉点渲染有点问题,拖拽的控件设置成半透明 + int dragWidth = this.getDragSize(xCreator).width, dragHeight = this.getDragSize(xCreator).height; + Graphics2D g2d = (Graphics2D) g; + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f); + g2d.setComposite(composite); + BufferedImage im = new BufferedImage(xCreator.getWidth(), xCreator.getHeight(), BufferedImage.TYPE_INT_ARGB); + xCreator.paint(im.getGraphics()); + g.drawImage(im, 0, 0, dragWidth - 1, dragHeight - 1, null); + g.setColor(XCreatorConstants.RESIZE_BOX_BORDER_COLOR); + g.drawRect(0, 0, dragWidth - 1, dragHeight - 1); + } + + @Override + public Dimension getDragSize(XCreator xCreator) { + return xCreator.initEditorSize(); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java index e4426f61a..5bdfe3c29 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java @@ -3,10 +3,12 @@ package com.fr.design.designer.beans.adapters.layout; import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter; import com.fr.design.designer.creator.*; import com.fr.design.designer.properties.BoundsGroupModel; import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel; +import com.fr.design.mainframe.FormDesigner; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.ui.Widget; @@ -15,6 +17,7 @@ import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import java.awt.*; +import java.awt.event.MouseEvent; public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { //是不是添加到父容器上 @@ -345,4 +348,16 @@ public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container; return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout); } + + @Override + public void dragging(DraggingModel model) { + FormDesigner designer = model.getDesigner(); + MouseEvent dragEvent = model.getCurrentDragEvent(); + designer.getStateModel().dragging(dragEvent); + } + + @Override + public Dimension getDragSize(XCreator xCreator) { + return xCreator.getSize(); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java index 5a31bab40..f4c045861 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java @@ -6,12 +6,13 @@ import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.PaddingMargin; -import com.fr.form.ui.container.WBorderLayout; import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; import com.fr.general.ComparatorUtils; -import java.awt.*; -import java.util.*; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.util.ArrayList; /** * 这个类用作fit和absolute的父类,存放公共的方法 @@ -1182,5 +1183,4 @@ public class FRBodyLayoutAdapter extends AbstractLayoutAdapter { this.isCalculateChildPos = false; return childPosition; } - } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java index 9871d1b32..3814dc600 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java @@ -8,6 +8,7 @@ import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; @@ -22,6 +23,8 @@ import com.fr.design.designer.properties.FRFitLayoutConstraints; import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel; import com.fr.design.designer.treeview.XCreatorTreeCellRender; import com.fr.design.fun.FormWidgetOptionProvider; +import com.fr.design.mainframe.FormCreatorDropTarget; +import com.fr.design.mainframe.FormDesigner; import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.LayoutBorderStyle; import com.fr.form.ui.container.WAbsoluteLayout; @@ -34,6 +37,7 @@ import com.fr.general.act.BorderPacker; import java.awt.Component; import java.awt.Dimension; import java.awt.Rectangle; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -1244,4 +1248,26 @@ public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { public void dragOver(XCreator xCreator, SelectionModel selectionModel,int x, int y) { frLayoutState.dragOver(xCreator, selectionModel,x,y); } + + @Override + public void dragging(DraggingModel model) { + FormDesigner designer = model.getDesigner(); + MouseEvent lastPressEvent = model.getStartDragEvent(); + MouseEvent dragEvent = model.getCurrentDragEvent(); + XCreator creator = model.getCreator(); + if ((lastPressEvent == null) || (creator == null)) { + return; + } + + if (dragEvent.getPoint().distance(lastPressEvent.getPoint()) > 5) { + if (creator.isSupportDrag()) { + designer.bindTransferHandler(lastPressEvent); + designer.fireParentLayoutDragStart(creator); + designer.setDropTarget(new FormCreatorDropTarget(designer, creator)); + // 触发状态添加模式事件 + designer.repaint(); + } + dragEvent.consume(); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListener.java b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListener.java new file mode 100644 index 000000000..04d6cd72c --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListener.java @@ -0,0 +1,9 @@ +package com.fr.design.designer.beans.events; + +import java.util.EventListener; + +public interface AddingWidgetListener extends EventListener { + void beforeAdded(); + + void afterAdded(boolean addResult); +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListenerTable.java b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListenerTable.java new file mode 100644 index 000000000..5d0889c35 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListenerTable.java @@ -0,0 +1,44 @@ +package com.fr.design.designer.beans.events; + +import com.fr.general.ComparatorUtils; + +import javax.swing.SwingUtilities; +import java.util.ArrayList; +import java.util.List; + +public class AddingWidgetListenerTable { + protected List listeners = new ArrayList<>(); + + public AddingWidgetListenerTable() { + + } + + public void addListener(AddingWidgetListener listener) { + if (listener == null) { + return; + } + for (int i = 0; i < listeners.size(); i++) { + if (ComparatorUtils.equals(listener, listeners.get(i))) { + listeners.set(i, listener); + return; + } + } + listeners.add(listener); + } + + public void beforeAdded() { + for (final AddingWidgetListener listener : listeners) { + listener.beforeAdded(); + } + } + + public void afterAdded(boolean addResult) { + for (final AddingWidgetListener listener : listeners) { + listener.afterAdded(addResult); + } + } + + public void clearListeners() { + listeners.clear(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java index ba0cf5dd0..c47188d4e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java @@ -1,17 +1,6 @@ package com.fr.design.designer.beans.models; -import com.fr.design.designer.beans.AdapterBus; -import com.fr.design.designer.beans.ComponentAdapter; -import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter; import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.mainframe.FormDesigner; -import com.fr.design.utils.ComponentUtils; -import com.fr.general.ComparatorUtils; - -import java.awt.Rectangle; /** * 添加状态下的model @@ -20,128 +9,16 @@ public class AddingModel { // 当前要添加的组件 private XCreator creator; - // 记录当前鼠标的位置信息 - private int currentX; - private int currentY; - private boolean added; private boolean addedIllegal = false; // 有时候是添加完成了,但是添加会造成某些控件size不合法,例如tab - public AddingModel(FormDesigner designer, XCreator xCreator) { - this.creator = xCreator; - instantiateCreator(designer); - // 初始的时候隐藏该组件的图标 - currentY = -this.creator.getWidth(); - currentX = -this.creator.getHeight(); - } - - /** - * 待说明 - * - * @param designer 设计器 - */ - public void instantiateCreator(FormDesigner designer) { - - ModelUtil.renameWidgetName(designer.getTarget(), creator); - ComponentAdapter adapter = new CompositeComponentAdapter(designer, creator); - adapter.initialize(); - creator.addNotify(); - creator.putClientProperty(AdapterBus.CLIENT_PROPERTIES, adapter); - } - - public AddingModel(XCreator xCreator, int x, int y) { + public AddingModel(XCreator xCreator) { this.creator = xCreator; - this.creator.backupCurrentSize(); - this.creator.backupParent(); - currentX = x - (xCreator.initEditorSize().width / 2); - currentY = y - (xCreator.initEditorSize().height / 2); - } - - /** - * 隐藏当前组件的图标 - */ - public void reset() { - currentX = -this.creator.getWidth(); - currentY = -this.creator.getHeight(); - } - - public String getXCreatorName(FormDesigner designer, XCreator x) { - String def = x.createDefaultName(); - if (x.acceptType(XWParameterLayout.class)) { - return def; - } - int i = 0; - while (designer.getTarget().isNameExist(def + i)) { - i++; - } - return def + i; - } - - - public int getCurrentX() { - return currentX; - } - - public int getCurrentY() { - return currentY; - } - - - /** - * 移动组件图标到鼠标事件发生的位置 - * - * @param x 坐标 - * @param y 坐标 - */ - public void moveTo(int x, int y) { - currentX = x - (this.creator.initEditorSize().width / 2); - currentY = y - (this.creator.initEditorSize().height / 2); } public XCreator getXCreator() { return this.creator; } - public boolean need2paint(){ - return currentX + this.creator.getWidth() > 0 && currentY + this.creator.getHeight() > 0; - } - - /** - * 当前组件是否已经添加到某个容器中 - * - * @return 是返回true - */ - public boolean isCreatorAdded() { - return added; - } - - /** - * 加入容器 - * - * @param designer 设计器 - * @param container 容器 - * @param x 坐标 - * @param y 坐标 - * @return 成功返回true - */ - public boolean add2Container(FormDesigner designer, XLayoutContainer container, int x, int y) { - //考虑不同布局嵌套的情况,获取顶层容器 - XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(container); - if (xLayoutContainer != null) { - container = xLayoutContainer; - } - Rectangle rect = ComponentUtils.getRelativeBounds(container); - if (!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())) { - added = container.getLayoutAdapter().addBean(creator, - x + designer.getHorizontalScaleValue(), - y + designer.getVerticalScaleValue() ); - return added; - } - added = container.getLayoutAdapter().addBean(creator, - x + designer.getHorizontalScaleValue() - rect.x, - y + designer.getVerticalScaleValue() - rect.y); - return added; - } - public boolean isAddedIllegal() { return addedIllegal; } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/DraggingModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/DraggingModel.java new file mode 100644 index 000000000..95e003faf --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/DraggingModel.java @@ -0,0 +1,88 @@ +package com.fr.design.designer.beans.models; + +import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.mainframe.FormDesigner; + +import java.awt.event.MouseEvent; + +public class DraggingModel { + private FormDesigner designer; + private XCreator creator; + private MouseEvent startDragEvent; + private MouseEvent currentDragEvent; + private int creatorLeftTopX = -999; // 隐藏 + private int creatorLeftTopY = -999; // 隐藏 + + public DraggingModel() { + + } + + public DraggingModel designer(FormDesigner designer) { + this.designer = designer; + return this; + } + + public DraggingModel startDragEvent(MouseEvent startDragEvent) { + this.startDragEvent = startDragEvent; + return this; + } + + public DraggingModel currentDragEvent(MouseEvent dragEvent) { + this.currentDragEvent = dragEvent; + return this; + } + + public DraggingModel creator(XCreator creator) { + this.creator = creator; + return this; + } + + public FormDesigner getDesigner() { + return designer; + } + + public MouseEvent getStartDragEvent() { + return startDragEvent; + } + + public MouseEvent getCurrentDragEvent() { + return currentDragEvent; + } + + public XCreator getCreator() { + return creator; + } + + /** + * 获取被拖拽组件当前随着鼠标移动时应当所在的左上角横坐标 + * + * @return + */ + public int getCreatorLeftTopX() { + return creatorLeftTopX; + } + + /** + * 获取被拖拽组件当前随着鼠标移动时应当所在的左上角纵坐标 + * + * @return + */ + public int getCreatorLeftTopY() { + return creatorLeftTopY; + } + + public void moveTo(int x, int y) { + XLayoutContainer container = designer.getDraggingHotspotLayout(); + LayoutAdapter adapter = container.getLayoutAdapter(); + + creatorLeftTopX = x - adapter.getDragSize(creator).width / 2; + creatorLeftTopY = y - adapter.getDragSize(creator).height / 2; + } + + public void reset() { + creatorLeftTopX = -creator.getWidth(); + creatorLeftTopY = -creator.getHeight(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java index 3b676921b..390c45825 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java @@ -36,7 +36,7 @@ public class StateModel { private SelectionModel selectionModel; // 当前鼠标进入拖拽区域的位置类型 - private Direction driection; + private Direction direction; // 当前拖拽的起始位置 private int currentX; @@ -74,7 +74,7 @@ public class StateModel { * @return direction方向 */ public Direction getDirection() { - return driection; + return direction; } /** @@ -96,7 +96,7 @@ public class StateModel { * @return 非outer且选中为空 */ public boolean dragable() { - return ((driection != Location.outer) && !selecting); + return ((direction != Location.outer) && !selecting); } /** @@ -108,7 +108,7 @@ public class StateModel { addable = false; designer.setPainter(null); - if (driection != Location.inner) { + if (direction != Location.inner) { return; } @@ -283,7 +283,7 @@ public class StateModel { */ public void startResizing(MouseEvent e) { if (!selectionModel.getSelection().isEmpty()) { - driection.backupBounds(designer); + direction.backupBounds(designer); } currentX = getMouseXY(e).x; currentY = getMouseXY(e).y; @@ -409,7 +409,7 @@ public class StateModel { * 重置 */ public void reset() { - driection = Location.outer; + direction = Location.outer; aspectRatioLocked = false; dragging = false; selecting = false; @@ -429,9 +429,9 @@ public class StateModel { * @param dir 拉伸方向 */ public void setDirection(Direction dir) { - if (driection != dir) { - this.driection = dir; - driection.updateCursor(designer); + if (direction != dir) { + this.direction = dir; + direction.updateCursor(designer); } } @@ -495,7 +495,7 @@ public class StateModel { FormSelection selection = this.selectionModel.getSelection(); this.aspectRatioLocked = selection.isCreatorAspectRatioLockedInAbsLayout(designer) || (this.selectionModel.getSelection().isCreatorInAbsLayout(designer) && e.isShiftDown()); - driection.drag(getMouseXY(e).x - currentX, getMouseXY(e).y - currentY, designer); + direction.drag(getMouseXY(e).x - currentX, getMouseXY(e).y - currentY, designer); this.dragging = true; } @@ -552,4 +552,15 @@ public class StateModel { + designer.getArea().getVerticalValue()); } + public boolean isDraggingSize() { + return direction == Location.left + || direction == Location.left_top + || direction == Location.left_bottom + || direction == Location.right + || direction == Location.right_top + || direction == Location.right_bottom + || direction == Location.top + || direction == Location.bottom; + } + } \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java b/designer-form/src/main/java/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java index f99864c62..16fd4ce3c 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java @@ -180,16 +180,21 @@ public class XBorderStyleWidgetCreator extends XWidgetCreator{ this.setBackground4Painting(null, 0.0); } } - - private void clearTitleWidget() { - if (acceptType(XWFitLayout.class)) { - return; - } - XWTitleLayout parent = (XWTitleLayout) this.getParent(); - if (parent.getComponentCount() > 1) { - parent.remove(parent.getTitleCreator()); - } - } + + private void clearTitleWidget() { + if (acceptType(XWFitLayout.class)) { + return; + } + XWTitleLayout parent = (XWTitleLayout) this.getParent(); + if (parent.getComponentCount() > 1) { + parent.remove(parent.getTitleCreator()); + WTitleLayout layout = parent.toData(); + Rectangle rec = new Rectangle(layout.getBodyBoundsWidget().getBounds()); + //删除标题组件后,容器高度为body高度+标题组件的高度 + rec.height += WTitleLayout.TITLE_HEIGHT; + layout.updateChildBounds(rec); + } + } /** * 设置样式为标题样式时,对应组件加上标题 diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java b/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java index 14fc9ea24..792e97045 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java @@ -54,6 +54,7 @@ import java.beans.IntrospectionException; import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.StringJoiner; /** * @author richer @@ -943,4 +944,14 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo return false; } + + @Override + public String toString() { + return new StringJoiner(", ", XCreator.class.getSimpleName() + "[", "]") + .add("data=" + data) + .add("shareId='" + shareId + "'") + .add("isHelpBtnOnFocus=" + isHelpBtnOnFocus) + .add("selected=" + selected) + .toString(); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java b/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java index bdaf40d22..2f4a69937 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java @@ -20,6 +20,7 @@ import com.fr.form.FormProvider; import com.fr.form.ui.ElementCaseEditor; import com.fr.form.ui.ElementCaseEditorProvider; import com.fr.report.fit.ReportFitAttr; +import com.fr.report.fit.ReportFitConfig; import com.fr.stable.ArrayUtils; import com.fr.stable.CoreGraphHelper; import com.fr.stable.core.PropertyChangeAdapter; @@ -127,7 +128,8 @@ public class XElementCase extends XBorderStyleWidgetCreator implements FormEleme private CRPropertyDescriptor getReportFitEditor() { this.designer = WidgetPropertyPane.getInstance().getEditingFormDesigner(); FitProvider wbTpl = designer.getTarget(); - ReportFitAttr fitAttr = wbTpl.getReportFitAttr(); + //这边获取到的全局要考虑到服务器的配置 + ReportFitAttr fitAttr = wbTpl.getReportFitAttr() == null ? ReportFitConfig.getInstance().getFrmFitAttr() : wbTpl.getReportFitAttr(); ElementCaseEditor editor = this.toData(); //兼容之前报表块(之前三个选项为:默认 横向 双向 现在是:横向 双向 不自适应) if (editor.getFitStateInPC() == 0) { diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java b/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java index 01d09fe4c..83a4c01b0 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java @@ -13,9 +13,11 @@ import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.widget.editors.PaddingMarginEditor; import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor; import com.fr.design.parameter.ParameterBridge; +import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WLayout; import com.fr.general.Background; +import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; import com.fr.stable.core.PropertyChangeAdapter; @@ -24,6 +26,7 @@ import javax.swing.JComponent; import java.awt.Component; import java.awt.Dimension; import java.awt.LayoutManager; +import java.awt.Rectangle; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.beans.IntrospectionException; @@ -474,14 +477,6 @@ public abstract class XLayoutContainer extends XBorderStyleWidgetCreator impleme return 0; } - /** - * 切换到非添加状态 - * - * @param designer 表单设计器 - */ - public void stopAddingState(FormDesigner designer) { - } - /** * 寻找最近的为自适应布局的父容器 * @@ -617,4 +612,15 @@ public abstract class XLayoutContainer extends XBorderStyleWidgetCreator impleme public boolean isComponent() { return true; } + + public boolean addWidgetToContainer(XCreator creator, int x, int y) { + //考虑不同布局嵌套的情况,获取顶层容器 + XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(this); + XLayoutContainer container = xLayoutContainer != null ? xLayoutContainer : this; + Rectangle rect = ComponentUtils.getRelativeBounds(container); + if (!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())) { + return container.getLayoutAdapter().addBean(creator, x, y); + } + return container.getLayoutAdapter().addBean(creator, x - rect.x, y - rect.y); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java index fdc01be1e..e09b31fb0 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java @@ -179,18 +179,6 @@ public class XWCardMainBorderLayout extends XWBorderLayout { } } - /** - * 切换到非添加状态 - * - * @return designer 表单设计器 - */ - @Override - public void stopAddingState(FormDesigner designer){ - designer.stopAddingState(); - return; - } - - /** * 添加card区域 * diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java index ceb334028..850378af2 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java @@ -187,15 +187,6 @@ public class XWCardTagLayout extends XWHorizontalBoxLayout { return DEFAULT_NAME; } - /** - * 切换到非添加状态 - * - * @return designer 表单设计器 - */ - @Override - public void stopAddingState(FormDesigner designer) { - designer.stopAddingState(); - } //新增时去tabFitLayout名字中最大的Index+1,防止重名 private int getTabNameIndex() { diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTitleLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTitleLayout.java index 7cdca0a0b..9695eee18 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTitleLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTitleLayout.java @@ -166,18 +166,7 @@ public class XWCardTitleLayout extends XWBorderLayout { XWCardTagLayout xwCardTagLayout = (XWCardTagLayout) this.getComponent(0); this.addTagPart(xwCardTagLayout); } - - /** - * 切换到非添加状态 - * - * @return designer 表单设计器 - */ - @Override - public void stopAddingState(FormDesigner designer){ - designer.stopAddingState(); - return; - } - + /** * 该布局隐藏,无需对边框进行操作 * @param border 边框 diff --git a/designer-form/src/main/java/com/fr/design/fit/FormFitAttrAction.java b/designer-form/src/main/java/com/fr/design/fit/FormFitAttrAction.java new file mode 100644 index 000000000..dad6e9be9 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/FormFitAttrAction.java @@ -0,0 +1,85 @@ +package com.fr.design.fit; + +import com.fr.design.actions.JTemplateAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.UIDialog; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.report.fit.FormFitAttrModelType; +import com.fr.form.main.Form; +import com.fr.report.fit.FitProvider; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.KeyStroke; +import java.awt.Dimension; +import java.awt.event.ActionEvent; + +public class FormFitAttrAction extends JTemplateAction { + private static final MenuKeySet REPORT_FIT_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'T'; + } + + @Override + public String getMenuName() { + return Toolkit.i18nText("Fine-Designer_PC_Fit_Attr"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + + public FormFitAttrAction(JTemplate jTemplate) { + super(jTemplate); + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(REPORT_FIT_ATTR); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon("/com/fr/design/images/reportfit/fit"); + } + + /** + * Action触发事件 + * + * @param e 事件 + */ + @Override + public void actionPerformed(ActionEvent e) { + final JTemplate jwb = getEditingComponent(); + if (jwb == null || !(jwb.getTarget() instanceof Form)) { + return; + } + JForm jForm = (JForm) jwb; + Form wbTpl = jForm.getTarget(); + ReportFitAttr fitAttr = wbTpl.getReportFitAttr(); + FormFitAttrPane formFitAttrPane = new FormFitAttrPane(jForm, FormFitAttrModelType.parse(wbTpl)); + showReportFitDialog(fitAttr, jwb, wbTpl, formFitAttrPane); + } + + private void showReportFitDialog(ReportFitAttr fitAttr, final JTemplate jwb, final FitProvider wbTpl, final BasicBeanPane attrPane) { + attrPane.populateBean(fitAttr); + UIDialog dialog = attrPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + fireEditingOk(jwb, wbTpl, attrPane.updateBean(), fitAttr); + } + }, new Dimension(660, 600)); + dialog.setVisible(true); + } + + private void fireEditingOk(final JTemplate jwb, final FitProvider wbTpl, ReportFitAttr newReportFitAttr, ReportFitAttr oldReportFitAttr) { + wbTpl.setReportFitAttr(newReportFitAttr); + jwb.fireTargetModified(); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/FormFitAttrPane.java b/designer-form/src/main/java/com/fr/design/fit/FormFitAttrPane.java new file mode 100644 index 000000000..51eda6d36 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/FormFitAttrPane.java @@ -0,0 +1,377 @@ +package com.fr.design.fit; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XOccupiedLayout; +import com.fr.design.designer.creator.XWAbsoluteBodyLayout; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.XWScaleLayout; +import com.fr.design.designer.properties.items.FRLayoutTypeItems; +import com.fr.design.designer.properties.items.Item; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.FormSelectionUtils; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.report.fit.FitType; +import com.fr.design.report.fit.FormFitAttrModelType; +import com.fr.design.report.fit.FormFitConfigPane; +import com.fr.design.report.fit.ReportFitConfigPane; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.form.main.Form; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.WAbsoluteBodyLayout; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.form.ui.container.WBodyLayoutType; +import com.fr.form.ui.container.WFitLayout; +import com.fr.form.ui.container.WSortLayout; +import com.fr.general.ComparatorUtils; +import com.fr.general.act.BorderPacker; +import com.fr.log.FineLoggerFactory; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import static com.fr.design.i18n.Toolkit.i18nText; +import static javax.swing.JOptionPane.*; + +public class FormFitAttrPane extends BasicBeanPane { + + private UIComboBox layoutComboBox; + private UIComboBox scaleComboBox; + private FormFitAttrModelType fitAttrModelType; + + protected UIComboBox itemChoose; + + private JForm jForm; + private ReportFitConfigPane fitConfigPane; + + public FormFitAttrPane(JForm jForm, FormFitAttrModelType fitAttrModelType) { + this.fitAttrModelType = fitAttrModelType; + this.jForm = jForm; + initComponents(); + } + + + private void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(12, 5, 0, 5)); + this.add(createReportFitSettingPane(), BorderLayout.CENTER); + this.add(createReportLayoutSettingPane(), BorderLayout.NORTH); + + } + + + private JPanel createReportLayoutSettingPane() { + JPanel jPanel = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Layout")); + jPanel.add(createAreaScalePane(), BorderLayout.CENTER); + jPanel.setPreferredSize(new Dimension(640, 84)); + return jPanel; + } + + protected String[] getItemNames() { + return new String[]{Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings"), + Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")}; + } + + + private JPanel createReportFitSettingPane() { + JPanel jPanel = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Content_Attr")); + JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + jPanel.add(contentPane, BorderLayout.CENTER); + UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Settings")); + label.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0)); + contentPane.add(label, BorderLayout.WEST); + label.setPreferredSize(new Dimension(100, 0)); + label.setVerticalAlignment(SwingConstants.TOP); + itemChoose = new UIComboBox(getItemNames()); + itemChoose.setPreferredSize(new Dimension(160, 20)); + Form form = jForm.getTarget(); + itemChoose.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + if (isTemplateSingleSet()) { + if (form != null) { + ReportFitAttr fitAttr = form.getReportFitAttr(); + populate(fitAttr); + } + } else { + populate(fitAttrModelType.getFitAttrModel().getGlobalReportFitAttr()); + } + } + } + }); + JPanel centerPane = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); + centerPane.add(itemChoose); + centerPane.add(fitConfigPane = new FormFitConfigPane(this.fitAttrModelType.getFitAttrModel())); + contentPane.add(centerPane, BorderLayout.CENTER); + return jPanel; + } + + public void populate(ReportFitAttr reportFitAttr) { + if (reportFitAttr == null) { + reportFitAttr = fitAttrModelType.getFitAttrModel().getGlobalReportFitAttr(); + } + + this.setEnabled(isTemplateSingleSet()); + fitConfigPane.populateBean(reportFitAttr); + } + + + public ReportFitAttr updateBean() { + updateLayoutType(); + if (!isTemplateSingleSet()) { + return null; + } else { + return fitConfigPane.updateBean(); + } + } + + private void updateLayoutType() { + XLayoutContainer xLayoutContainer = this.jForm.getRootComponent(); + if (xLayoutContainer == null || !xLayoutContainer.acceptType(XWFitLayout.class)) { + return; + } + XWFitLayout xwFitLayout = (XWFitLayout) xLayoutContainer; + WFitLayout wFitLayout = xwFitLayout.toData(); + int state = layoutComboBox.getSelectedIndex(); + WBodyLayoutType selectType = WBodyLayoutType.parse(state); + if (selectType != wFitLayout.getBodyLayoutType()) { + wFitLayout.setLayoutType(selectType); + //从自适应布局切换到绝对布局 + if (selectType == WBodyLayoutType.ABSOLUTE) { + switchLayoutFromFit2Absolute(xwFitLayout); + } else { + //从绝对布局切换到自适应布局 + switchLayoutFromAbsolute2Fit(xwFitLayout); + } + } + wFitLayout.setCompatibleScaleAttr(fitAttrModelType.parseScaleAttrFromShowIndex(this.scaleComboBox.getSelectedIndex(), wFitLayout.getBodyLayoutType())); + } + + + private void switchLayoutFromFit2Absolute(XWFitLayout xWFitLayout) { + try { + WFitLayout layout = xWFitLayout.toData(); + WAbsoluteBodyLayout wAbsoluteBodyLayout = new WAbsoluteBodyLayout("body"); + wAbsoluteBodyLayout.setCompState(WAbsoluteLayout.STATE_FIXED); + // 切换布局类型时,保留body背景样式 + wAbsoluteBodyLayout.setBorderStyleFollowingTheme(layout.isBorderStyleFollowingTheme()); + wAbsoluteBodyLayout.setBorderStyle((BorderPacker) (layout.getBorderStyle().clone())); + Component[] components = xWFitLayout.getComponents(); + Rectangle[] backupBounds = getBackupBoundsFromFitLayout(xWFitLayout); + xWFitLayout.removeAll(); + layout.resetStyle(); + XWAbsoluteBodyLayout xwAbsoluteBodyLayout = xWFitLayout.getBackupParent() == null ? new XWAbsoluteBodyLayout(wAbsoluteBodyLayout, new Dimension(0, 0)) : (XWAbsoluteBodyLayout) xWFitLayout.getBackupParent(); + xWFitLayout.setFixLayout(false); + xWFitLayout.getLayoutAdapter().addBean(xwAbsoluteBodyLayout, 0, 0); + for (int i = 0; i < components.length; i++) { + XCreator xCreator = (XCreator) components[i]; + xCreator.setBounds(backupBounds[i]); + //部分控件被ScaleLayout包裹着,绝对布局里面要放出来 + if (xCreator.acceptType(XWScaleLayout.class)) { + if (xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator()) { + Component component = xCreator.getComponent(0); + component.setBounds(xCreator.getBounds()); + } + } + if (!xCreator.acceptType(XOccupiedLayout.class)) { + xwAbsoluteBodyLayout.add(xCreator); + } + + } + copyLayoutAttr(layout, xwAbsoluteBodyLayout.toData()); + xWFitLayout.setBackupParent(xwAbsoluteBodyLayout); + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + formDesigner.getSelectionModel().setSelectedCreators( + FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{wAbsoluteBodyLayout})); + if (xwAbsoluteBodyLayout.toData() != null) { + xwAbsoluteBodyLayout.toData().setBorderStyleFollowingTheme(wAbsoluteBodyLayout.isBorderStyleFollowingTheme()); + xwAbsoluteBodyLayout.toData().setBorderStyle(wAbsoluteBodyLayout.getBorderStyle()); + } + xwAbsoluteBodyLayout.refreshStylePreviewEffect(); + if (xWFitLayout.toData() != null) { + xWFitLayout.toData().resetStyle(); + } + xWFitLayout.refreshStylePreviewEffect(); + formDesigner.switchBodyLayout(xwAbsoluteBodyLayout); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + + } + } + + private Rectangle[] getBackupBoundsFromFitLayout(XWFitLayout xWFitLayout) { + int count = xWFitLayout.getComponentCount(); + Rectangle[] rectangles = new Rectangle[count]; + for (int i = 0; i < count; i++) { + rectangles[i] = xWFitLayout.getComponent(i).getBounds(); + } + return rectangles; + } + + protected void copyLayoutAttr(WSortLayout srcLayout, WSortLayout destLayout) { + destLayout.clearListeners(); + destLayout.clearMobileWidgetList(); + for (int i = 0, len = srcLayout.getMobileWidgetListSize(); i < len; i++) { + destLayout.addMobileWidget(srcLayout.getMobileWidget(i)); + } + destLayout.setSorted(true); + for (int i = 0, len = srcLayout.getListenerSize(); i < len; i++) { + destLayout.addListener(srcLayout.getListener(i)); + } + srcLayout.clearListeners(); + srcLayout.clearMobileWidgetList(); + } + + + private void switchLayoutFromAbsolute2Fit(XWFitLayout xwFitLayout) { + XWAbsoluteBodyLayout xwAbsoluteBodyLayout = getAbsoluteBodyLayout(xwFitLayout); + if (xwAbsoluteBodyLayout == null) { + return; + } + WAbsoluteBodyLayout layout = xwAbsoluteBodyLayout.toData(); + WFitLayout wFitLayout = xwFitLayout.toData(); + wFitLayout.resetStyle(); + xwFitLayout.switch2FitBodyLayout(xwAbsoluteBodyLayout); + // 切换布局类型时,保留body背景样式 + if (wFitLayout != null) { + wFitLayout.setBorderStyleFollowingTheme(layout.isBorderStyleFollowingTheme()); + wFitLayout.setBorderStyle(layout.getBorderStyle()); + } + copyLayoutAttr(layout, xwFitLayout.toData()); + + copyLayoutAttr(layout, xwFitLayout.toData()); + xwFitLayout.refreshStylePreviewEffect(); + } + + private XWAbsoluteBodyLayout getAbsoluteBodyLayout(XWFitLayout xwFitLayout) { + if (xwFitLayout != null && xwFitLayout.getComponentCount() > 0) { + Component component = xwFitLayout.getComponent(0); + if (component instanceof XWAbsoluteBodyLayout) { + return (XWAbsoluteBodyLayout) component; + } + } + return null; + } + + private JPanel createAreaScalePane() { + initLayoutComboBox(); + + UILabel layoutTypeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")); + UILabel scaleModeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Scale_Setting")); + Component[][] components = new Component[][]{ + {layoutTypeLabel, layoutComboBox}, + {scaleModeLabel, scaleComboBox} + }; + JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(components, + TableLayoutHelper.FILL_LASTCOLUMN, 20, IntervalConstants.INTERVAL_L1); + JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + containerPane.add(contentPane, BorderLayout.CENTER); + + return containerPane; + } + + + public void initLayoutComboBox() { + Item[] items = FRLayoutTypeItems.ITEMS; + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (Item item : items) { + model.addElement(item); + } + scaleComboBox = new UIComboBox(model); + scaleComboBox.setModel(new DefaultComboBoxModel(fitAttrModelType.getFitLayoutScaleAttr())); + layoutComboBox = new UIComboBox(model); + layoutComboBox.setPreferredSize(new Dimension(160, 20)); + scaleComboBox.setPreferredSize(new Dimension(160, 20)); + WFitLayout wFitLayout = jForm.getTarget().getWFitLayout(); + layoutComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int selectIndex = layoutComboBox.getSelectedIndex(); + if (selectIndex == 0) { + if (wFitLayout.getBodyLayoutType() == WBodyLayoutType.ABSOLUTE) { + int selVal = FineJOptionPane.showConfirmDialog( + FormFitAttrPane.this, + Toolkit.i18nText("Fine-Design_Form_Layout_Switch_Tip"), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + OK_CANCEL_OPTION, + WARNING_MESSAGE + ); + if (OK_OPTION != selVal) { + layoutComboBox.setSelectedIndex(1); + return; + } + } + scaleComboBox.setModel(new DefaultComboBoxModel(fitAttrModelType.getFitLayoutScaleAttr())); + } else { + scaleComboBox.setModel(new DefaultComboBoxModel(fitAttrModelType.getAbsoluteLayoutSaleAttr())); + } + scaleComboBox.setSelectedIndex(0); + } + }); + + scaleComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + WBodyLayoutType selectBodyType = WBodyLayoutType.parse(layoutComboBox.getSelectedIndex()); + int state = fitAttrModelType.parseScaleAttrFromShowIndex(scaleComboBox.getSelectedIndex(), selectBodyType); + fitConfigPane.refreshPreviewJPanel(FitType.parseByFitState(state)); + } + }); + } + + + @Override + public void populateBean(ReportFitAttr reportFitAttr) { + WFitLayout wFitLayout = jForm.getTarget().getWFitLayout(); + layoutComboBox.setSelectedIndex(wFitLayout.getBodyLayoutType().getTypeValue()); + scaleComboBox.setSelectedIndex(fitAttrModelType.getScaleAttrShowIndex(wFitLayout)); + + if (reportFitAttr == null) { + itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings")); + } else { + itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")); + } + if (reportFitAttr == null) { + reportFitAttr = fitAttrModelType.getFitAttrModel().getGlobalReportFitAttr(); + } + setEnabled(isTemplateSingleSet()); + fitConfigPane.populateBean(reportFitAttr); + } + + private boolean isTemplateSingleSet() { + return ComparatorUtils.equals(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single"), itemChoose.getSelectedItem()); + } + + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + fitConfigPane.setEnabled(enabled); + } + + @Override + protected String title4PopupWindow() { + return i18nText("Fine-Designer_PC_Fit_Attr"); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/NewJForm.java b/designer-form/src/main/java/com/fr/design/fit/NewJForm.java index 0a12a7425..660a5c483 100644 --- a/designer-form/src/main/java/com/fr/design/fit/NewJForm.java +++ b/designer-form/src/main/java/com/fr/design/fit/NewJForm.java @@ -2,25 +2,27 @@ package com.fr.design.fit; import com.fr.base.DynamicUnitList; import com.fr.base.Parameter; +import com.fr.base.TRL; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.adapters.layout.FRFitLayoutAdapter; import com.fr.design.designer.beans.events.DesignerEditListener; import com.fr.design.designer.beans.events.DesignerEvent; import com.fr.design.designer.creator.XComponent; +import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; import com.fr.design.designer.creator.XElementCase; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWTitleLayout; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.mainframe.DesignerUIModeConfig; -import com.fr.design.preview.DeveloperPreview; -import com.fr.design.preview.FormAdaptivePreview; import com.fr.design.fit.toolbar.SwitchAction; import com.fr.design.fun.PreviewProvider; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.DesignerUIModeConfig; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.JForm; import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.preview.DeveloperPreview; +import com.fr.design.preview.FormAdaptivePreview; import com.fr.design.preview.FormPreview; import com.fr.design.preview.MobilePreview; import com.fr.design.utils.ComponentUtils; @@ -29,6 +31,7 @@ import com.fr.form.FormElementCaseProvider; import com.fr.form.fit.NewFormMarkAttr; import com.fr.form.main.Form; import com.fr.form.ui.ElementCaseEditor; +import com.fr.general.ComparatorUtils; import com.fr.stable.ArrayUtils; import javax.swing.JComponent; @@ -176,11 +179,13 @@ public class NewJForm extends JForm { FRFitLayoutAdapter layoutAdapter = (FRFitLayoutAdapter) adapter; layoutAdapter.setEdit(true); layoutAdapter.calculateBounds(backupBounds, xwTitleLayout.getBounds(), xwTitleLayout, row, difference); + } else { + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xwTitleLayout); + if (parent != null && parent.toData() != null) { + parent.toData().setBounds(xwTitleLayout.toData(), xwTitleLayout.getBounds()); + } } - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xwTitleLayout); - if (parent != null && parent.toData() != null) { - parent.toData().setBounds(xwTitleLayout.toData(), xwTitleLayout.getBounds()); - } + } @@ -215,6 +220,7 @@ public class NewJForm extends JForm { return new PreviewProvider[]{new FormPreview(), new MobilePreview()}; } + @Override public UIButton[] createExtraButtons() { UIButton[] extraButtons = super.createExtraButtons(); return addAdaptiveSwitchButton(extraButtons); @@ -228,4 +234,25 @@ public class NewJForm extends JForm { public boolean isNewJFrom() { return jFormType == null || jFormType.isNewType(); } + + @Override + public void navigate(TRL trl) { + String blockName = trl.unescapeNext(); + JForm.traversalXCreator(formDesign.getRootComponent(), xCreator -> { + if (!ComparatorUtils.equals(xCreator.toData().getWidgetName(), blockName)) { + return; + } + if (xCreator instanceof XElementCase) { + getFormDesign().getSelectionModel().selectACreator(xCreator); + xCreator.startEditing(); + if (getElementCaseDesign() != null) { + getElementCaseDesign().navigate(trl); + } + } else { + tabChanged(FORM_TAB); + getFormDesign().getSelectionModel().reset(); + getFormDesign().getSelectionModel().selectACreator(xCreator); + } + }, XCreator.class); + } } diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/FormPredefinedBackgroundPane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/FormPredefinedBackgroundPane.java deleted file mode 100644 index c862ac76d..000000000 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/FormPredefinedBackgroundPane.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.fr.design.gui.xpane; - -import com.fr.config.predefined.BackgroundWithAlpha; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.PredefinedStyleSettingPane; -import com.fr.design.mainframe.predefined.ui.detail.background.BackgroundWithAlphaSettingPane; -import com.fr.design.mainframe.predefined.ui.preview.StyleSettingPreviewPane; -import com.fr.form.ui.NameComponentBackground; -import com.fr.form.ui.NameFormBackground; - -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.geom.Rectangle2D; - -/** - * Created by kerry on 2020-09-02 - */ -public class FormPredefinedBackgroundPane extends PredefinedStyleSettingPane { - private BackgroundWithAlphaSettingPane backgroundPane; - - @Override - protected StyleSettingPreviewPane createPreviewPane() { - return new PreviewPane(); - } - - @Override - protected JPanel createCustomDetailPane() { - JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - backgroundPane = new BackgroundWithAlphaSettingPane(); - backgroundPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - previewPane.refresh(); - } - }); - panel.add(backgroundPane, BorderLayout.CENTER); - return panel; - } - - @Override - public void populateBean(NameComponentBackground ob) { - this.setPopulating(true); - super.populate(ob); - this.backgroundPane.populateBean(ob.createRealStyle()); - this.previewPane.refresh(); - this.setPopulating(false); - } - - - @Override - public NameComponentBackground updateBean() { - if (this.predefinedRadioBtn.isSelected()) { - return NameFormBackground.createPredefinedStyle(getPredefinedStyleName()); - } else { - return NameFormBackground.createCustomStyle(this.backgroundPane.updateBean()); - } - } - - private BackgroundWithAlpha getCurrentValue() { - if (this.predefinedRadioBtn.isSelected()) { - return updatePredefinedStyle(); - } else { - return this.backgroundPane.updateBean(); - } - } - - private BackgroundWithAlpha updatePredefinedStyle(){ - NameComponentBackground componentBackground = NameFormBackground.createPredefinedStyle(getPredefinedStyleName()); - return componentBackground.createRealStyle(); - } - - protected void populateCustomPane(){ - this.backgroundPane.populateBean(updatePredefinedStyle()); - } - - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"); - } - - class PreviewPane extends StyleSettingPreviewPane { - private BackgroundWithAlpha background; - - public PreviewPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setPreferredSize(new Dimension(390, 511)); - this.setBackground(Color.WHITE); - } - - - public void refresh() { - background = getCurrentValue(); - this.repaint(); - } - - @Override - public void paint(Graphics g) { - super.paint(g); - if (background != null && background.getBackground() != null) { - background.getBackground().paint(g, new Rectangle2D.Double(0, 0, this.getWidth(), this.getHeight())); - } - } - } - -} diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/PredefinedComponentStyleSettingPane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/PredefinedComponentStyleSettingPane.java deleted file mode 100644 index 6e245b019..000000000 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/PredefinedComponentStyleSettingPane.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.fr.design.gui.xpane; - -import com.fr.config.predefined.PredefinedComponentStyle; -import com.fr.design.beans.BasicBeanPane; -import com.fr.design.formula.TinyFormulaPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.predefined.ui.PredefinedStyleSettingPane; -import com.fr.design.mainframe.predefined.ui.detail.component.ComponentFrameStylePane; -import com.fr.design.mainframe.predefined.ui.detail.component.ComponentTitleStylePane; -import com.fr.design.mainframe.predefined.ui.preview.StyleSettingPreviewPane; -import com.fr.form.ui.LayoutBorderStyle; -import com.fr.form.ui.NameLayoutBorderStyle; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; - -/** - * Created by kerry on 2020-09-02 - */ -public class PredefinedComponentStyleSettingPane extends PredefinedStyleSettingPane { - private StyleSettingPane styleSettingPane; - private TinyFormulaPane formulaPane; - - @Override - protected StyleSettingPreviewPane createPreviewPane() { - return new PreviewPane(); - } - - protected JPanel createPredefinedSettingPane() { - JPanel jPanel = new JPanel(); - jPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); - jPanel.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content"))); - formulaPane = new TinyFormulaPane(); - formulaPane.setPreferredSize(new Dimension(158, 30)); - jPanel.add(formulaPane); - return jPanel; - - } - - @Override - protected JPanel createCustomDetailPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - styleSettingPane = new StyleSettingPane(); - jPanel.add(styleSettingPane, BorderLayout.CENTER); - return jPanel; - } - - @Override - public void populateBean(NameLayoutBorderStyle ob) { - this.setPopulating(true); - super.populate(ob); - this.formulaPane.populateBean(ob.getTitleText().toString()); - styleSettingPane.populateBean(ob); - this.previewPane.refresh(); - this.setPopulating(false); - } - - - @Override - public NameLayoutBorderStyle updateBean() { - if (predefinedRadioBtn.isSelected()) { - return updatePredefinedStyle(); - } - return styleSettingPane.updateBean(); - } - - private NameLayoutBorderStyle updatePredefinedStyle() { - NameLayoutBorderStyle layoutBorderStyle = NameLayoutBorderStyle.createPredefinedStyle(getPredefinedStyleName()); - layoutBorderStyle.setTitleText(formulaPane.updateBean()); - return layoutBorderStyle; - } - - protected void populateCustomPane() { - this.styleSettingPane.populateBean(updatePredefinedStyle()); - } - - @Override - public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Style"); - } - - class StyleSettingPane extends BasicBeanPane { - private ComponentFrameStylePane frameStylePane; - private ComponentTitleStylePane titleStylePane; - - public StyleSettingPane() { - initPane(); - } - - private void initPane() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel frame = FRGUIPaneFactory.createTitledBorderNoGapPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Frame")); - frameStylePane = new ComponentFrameStylePane(); - frameStylePane.setPreferredSize(new Dimension(233, 225)); - frame.add(frameStylePane); - - JPanel title = FRGUIPaneFactory.createTitledBorderNoGapPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title")); - titleStylePane = ComponentTitleStylePane.createStyleSettingPane(); - titleStylePane.setPreferredSize(new Dimension(233, 220)); - title.add(titleStylePane); - - this.add(frame, BorderLayout.NORTH); - this.add(title, BorderLayout.CENTER); - } - - @Override - public void populateBean(NameLayoutBorderStyle ob) { - PredefinedComponentStyle componentStyle = new PredefinedComponentStyle(); - componentStyle.setBorderStyle(ob.createRealStyle()); - frameStylePane.populate(componentStyle); - titleStylePane.populate(componentStyle); - } - - @Override - public NameLayoutBorderStyle updateBean() { - PredefinedComponentStyle componentStyle = update(); - NameLayoutBorderStyle nameLayoutBorderStyle = NameLayoutBorderStyle.createCustomStyle(componentStyle.getBorderStyle()); - return nameLayoutBorderStyle; - } - - public PredefinedComponentStyle update() { - PredefinedComponentStyle componentStyle = new PredefinedComponentStyle(); - frameStylePane.update(componentStyle); - titleStylePane.update(componentStyle); - return componentStyle; - } - - @Override - protected String title4PopupWindow() { - return null; - } - } - - class PreviewPane extends StyleSettingPreviewPane { - private LayoutBorderPreviewPane layoutBorderPreviewPane; - - public PreviewPane() { - this.setPreferredSize(new Dimension(390, 511)); - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.layoutBorderPreviewPane = new LayoutBorderPreviewPane(new LayoutBorderStyle()); - this.add(this.layoutBorderPreviewPane, BorderLayout.CENTER); - } - - public void refresh() { - NameLayoutBorderStyle componentStyle = PredefinedComponentStyleSettingPane.this.updateBean(); - this.layoutBorderPreviewPane.repaint((LayoutBorderStyle) componentStyle.createRealStyle()); - } - - } -} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/DesignerTransferHandler.java b/designer-form/src/main/java/com/fr/design/mainframe/DesignerTransferHandler.java deleted file mode 100644 index e5b11dd9a..000000000 --- a/designer-form/src/main/java/com/fr/design/mainframe/DesignerTransferHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.fr.design.mainframe; - -import com.fr.design.designer.beans.models.AddingModel; -import com.fr.design.file.HistoryTemplateListPane; - -import javax.swing.JComponent; -import javax.swing.TransferHandler; -import java.awt.datatransfer.Transferable; - -public class DesignerTransferHandler extends TransferHandler { - - private FormDesigner designer; - private AddingModel addingModel; - - public DesignerTransferHandler(FormDesigner designer, AddingModel addingModel) { - super("rootComponent"); - this.designer = designer; - this.addingModel = addingModel; - } - - protected void exportDone(JComponent source, Transferable data, int action) { - if (!addingModel.isCreatorAdded()) { - undoWhenAddingFailed(); - } - } - - private void undoWhenAddingFailed() { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); - if (jt != null) { - jt.undoToCurrent(); - } - } -} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java index b0463a685..0555cf172 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java @@ -1,6 +1,5 @@ package com.fr.design.mainframe; -import com.fr.base.BaseUtils; import com.fr.base.vcs.DesignerMode; import com.fr.common.inputevent.InputEventBaseOnOS; import com.fr.design.designer.beans.AdapterBus; @@ -25,25 +24,18 @@ import com.fr.design.designer.creator.cardlayout.XCardAddButton; import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; import com.fr.design.designer.creator.cardlayout.XWCardLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; -import com.fr.design.form.util.XCreatorConstants; -import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.gui.xpane.ToolTipEditor; -import com.fr.design.icon.IconPathConstants; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.general.ComparatorUtils; import com.fr.stable.ArrayUtils; -import com.fr.stable.Constants; -import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JPopupMenu; -import javax.swing.JWindow; import javax.swing.SwingUtilities; import javax.swing.event.MouseInputAdapter; -import java.awt.Color; import java.awt.Container; import java.awt.Cursor; import java.awt.Insets; @@ -95,9 +87,6 @@ public class EditingMouseListener extends MouseInputAdapter { private DesignerEditor currentEditor; private XCreator currentXCreator; - //备份开始拖动的位置和大小 - private Rectangle dragBackupBounds; - private int pressX; private int pressY; @@ -121,40 +110,12 @@ public class EditingMouseListener extends MouseInputAdapter { private XElementCase xElementCase; private XChartEditor xChartEditor; - private JWindow promptWindow = new JWindow(); - public EditingMouseListener(FormDesigner designer) { this.designer = designer; stateModel = designer.getStateModel(); selectionModel = designer.getSelectionModel(); - UIButton promptButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); - this.promptWindow.add(promptButton); - } - - private void promptUser(int x, int y, XLayoutContainer container) { - if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { - promptWidgetForbidEnter(x, y, container); - } else { - cancelPromptWidgetForbidEnter(); - } } - private void promptWidgetForbidEnter(int x, int y, XLayoutContainer container) { - container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM)); - int screenX = (int) designer.getArea().getLocationOnScreen().getX(); - int screenY = (int) designer.getArea().getLocationOnScreen().getY(); - this.promptWindow.setSize(promptWindow.getPreferredSize()); - this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); - promptWindow.setLocation(screenX + x + GAP, screenY + y + GAP); - promptWindow.setVisible(true); - } - - private void cancelPromptWidgetForbidEnter() { - designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); - promptWindow.setVisible(false); - } - - /** * 按下 * @@ -181,18 +142,14 @@ public class EditingMouseListener extends MouseInputAdapter { } if (dir == Location.outer) { - if (designer.isDrawLineMode()) { - designer.updateDrawLineMode(e); + if (selectionModel.hasSelectionComponent() + && selectionModel.getSelection().getRelativeBounds().contains( + designer.getHorizontalScaleValue() + e.getX(), + designer.getVerticalScaleValue() + e.getY())) { + lastPressEvent = e; + lastXCreator = selectionModel.getSelection().getSelectedCreator(); } else { - if (selectionModel.hasSelectionComponent() - && selectionModel.getSelection().getRelativeBounds().contains( - designer.getHorizontalScaleValue() + e.getX(), - designer.getVerticalScaleValue() + e.getY())) { - lastPressEvent = e; - lastXCreator = selectionModel.getSelection().getSelectedCreator(); - } else { - stateModel.startSelecting(e); - } + stateModel.startSelecting(e); } } else { stateModel.startResizing(e); @@ -258,13 +215,6 @@ public class EditingMouseListener extends MouseInputAdapter { private void mouseDraggingRelease(MouseEvent e) { // 当前鼠标所在的组件 XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY()); - if (designer.isWidgetsIntersect() && dragBackupBounds != null && hoveredComponent != null) { - XCreator selectionXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if (selectionXCreator != null) { - selectionXCreator.setBounds(dragBackupBounds.x, dragBackupBounds.y, dragBackupBounds.width, dragBackupBounds.height); - } - } - dragBackupBounds = null; // 拉伸时鼠标拖动过快,导致所在组件获取会为空 if (hoveredComponent == null && e.getY() < 0) { // bug63538 @@ -285,7 +235,6 @@ public class EditingMouseListener extends MouseInputAdapter { selectionModel.deleteSelection(); designer.setPainter(null); } - cancelPromptWidgetForbidEnter(); } } @@ -499,61 +448,51 @@ public class EditingMouseListener extends MouseInputAdapter { if (DesignerMode.isAuthorityEditing()) { return; } - boolean shiftSelecting = e.isShiftDown(); - boolean ctrlSelecting = InputEventBaseOnOS.isControlDown(e); - int currentCursorType = this.designer.getCursor().getType(); - boolean shiftResizing = e.isShiftDown() && ( Cursor.SW_RESIZE_CURSOR <= currentCursorType && currentCursorType <= Cursor.E_RESIZE_CURSOR); - if ((shiftSelecting || ctrlSelecting) && !shiftResizing && !stateModel.isSelecting()) { + if (SwingUtilities.isRightMouseButton(e)) { + return; + } + + if (isMultiKeySelectingDrag(e)) { stateModel.startSelecting(e); } - // 如果当前是左键拖拽状态,拖拽组件 - if (stateModel.dragable()) { - if (SwingUtilities.isRightMouseButton(e)) { - return; - } else { - stateModel.dragging(e); - // 获取e所在的焦点组件 - XCreator hotspot = designer.getComponentAt(e.getX(), e.getY()); - if (dragBackupBounds == null) { - XCreator selectingXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if (selectingXCreator != null) { - dragBackupBounds = new Rectangle(selectingXCreator.getX(), selectingXCreator.getY(), selectingXCreator.getWidth(), selectingXCreator.getHeight()); - } - } - // 拉伸时鼠标拖动过快,导致所在组件获取会为空 - if (hotspot == null) { - return; - } - // 获取焦点组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); - //提示组件是否可以拖入 - promptUser(e.getX(), e.getY(), container); - } - } else if (designer.isDrawLineMode()) { - if (stateModel.prepareForDrawLining()) { - stateModel.drawLine(e); - } - } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { - // 如果是拖拽选择区域状态,则更新选择区域 + + if (isSelectionDrag()) { stateModel.changeSelection(e); - } else { - if ((lastPressEvent == null) || (lastXCreator == null)) { - return; - } - if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { - //参数面板和自适应布局不支持拖拽 - if (lastXCreator.isSupportDrag()) { - designer.startDraggingComponent(lastXCreator, lastPressEvent, e.getX(), e.getY()); - } - e.consume(); - lastPressEvent = null; - } } + + // 调整大小这边单独提出来,不跟后面拖组件混在一起,实在不好管理 + if (stateModel.isDraggingSize()) { + stateModel.dragging(e); + } + + designer.startDraggingFormWidget(lastXCreator, lastPressEvent, e); e.translatePoint(oldX - e.getX(), oldY - e.getY()); designer.repaint(); } + /** + * 当前拖拽是否是正在shift或者control拖拽一个选择框 + * @param e + * @return + */ + private boolean isMultiKeySelectingDrag(MouseEvent e) { + boolean shiftSelecting = e.isShiftDown(); + boolean ctrlSelecting = InputEventBaseOnOS.isControlDown(e); + int currentCursorType = this.designer.getCursor().getType(); + boolean shiftResizing = e.isShiftDown() && ( Cursor.SW_RESIZE_CURSOR <= currentCursorType && currentCursorType <= Cursor.E_RESIZE_CURSOR); + return (shiftSelecting || ctrlSelecting) && !shiftResizing && !stateModel.isSelecting(); + } + + /** + * 是否正在拖拽选择框 + * + * @return + */ + private boolean isSelectionDrag() { + return stateModel.isSelecting() && selectionModel.getHotspotBounds() != null; + } + //当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout) { //双击的前后点击click为相同对象,过滤掉 @@ -718,7 +657,6 @@ public class EditingMouseListener extends MouseInputAdapter { if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR && !(e.isShiftDown() || InputEventBaseOnOS.isControlDown(e))) { designer.setCursor(Cursor.getDefaultCursor()); } - cancelPromptWidgetForbidEnter(); e.translatePoint(oldX - e.getX(), oldY - e.getY()); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java b/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java index 5eb354c6c..62e256379 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java @@ -1,40 +1,24 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; -import com.fr.base.chart.BaseChartCollection; -import com.fr.chart.chartattr.ChartCollection; -import com.fr.chartx.attr.ChartProvider; -import com.fr.design.DesignModelAdapter; -import com.fr.design.data.DesignTableDataManager; -import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.HoverPainter; import com.fr.design.designer.beans.Painter; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.beans.models.AddingModel; +import com.fr.design.designer.beans.events.AddingWidgetListener; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.designer.creator.XWFitLayout; import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.form.util.XCreatorConstants; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.icon.IconPathConstants; -import com.fr.design.mainframe.chart.info.ChartInfoCollector; -import com.fr.design.mod.bean.ChangeItem; -import com.fr.design.mod.bean.ContentChangeItem; -import com.fr.design.mod.event.TableDataModifyEvent; import com.fr.design.utils.ComponentUtils; -import com.fr.event.EventDispatcher; -import com.fr.form.share.SharableWidgetProvider; -import com.fr.form.share.ShareLoader; -import com.fr.form.share.editor.SharableEditorProvider; -import com.fr.form.ui.Widget; import com.fr.log.FineLoggerFactory; import com.fr.stable.Constants; -import com.fr.stable.StringUtils; import javax.swing.BorderFactory; import javax.swing.JOptionPane; @@ -45,15 +29,10 @@ import java.awt.Color; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; -import java.awt.Toolkit; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; /** * 添加模式下鼠标事件处理器。 @@ -65,124 +44,56 @@ public class FormCreatorDropTarget extends DropTarget { * 当前鼠标的设计组件 */ private Component current; - /** - * 当前添加模式对应的model - */ - private AddingModel addingModel; private static final int GAP = 30; private TabDragInner tabDragInner; - + private XCreator creator; private JWindow promptWindow = new JWindow(); private UIButton promptButton = new UIButton("", BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); - public FormCreatorDropTarget(FormDesigner designer) { + public FormCreatorDropTarget(FormDesigner designer, XCreator creator) { this.designer = designer; - this.addingModel = designer.getAddingModel(); + this.creator = creator; this.promptWindow.add(promptButton); this.tabDragInner = new TabDragInner(designer); + initAddingListener(); } - public void adding(int x, int y) { - // 当前鼠标所在的组件 - XCreator hoveredComponent = designer.getComponentAt(x, y); - // 获取该组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); - boolean success = false; - if (container != null) { - //XWCardTagLayout 切换添加状态到普通状态 - container.stopAddingState(designer); - - // 如果是容器,则调用其acceptComponent接受组件 - AddingModel model = designer.getAddingModel(); - - boolean chartEnter2Para = !addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class); - boolean formSubmit2Adapt = !addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class); - - if (model != null && !chartEnter2Para && !formSubmit2Adapt) { - tabDragInner.tryDragIn(); - success = model.add2Container(designer, container, x, y); + private void initAddingListener() { + designer.getAddingWidgetListeners().addListener(new AddingWidgetListener() { + @Override + public void beforeAdded() { + tabDragInner.setTabEditable(); } - cancelPromptWidgetForbidEnter(); - } - if (success) { - tabDragInner.reset(); - // 如果添加成功,则触发相应事件 - XCreator xCreator = container.acceptType(XWParameterLayout.class) ? designer.getParaComponent() : designer.getRootComponent(); - //SetSelection时要确保选中的是最顶层的布局 - //tab布局添加的时候是初始化了XWCardLayout,实际上最顶层的布局是XWCardMainBorderLayout - XCreator addingXCreator = addingModel.getXCreator(); - Widget widget = (addingXCreator.getBackupParent() != null && addingXCreator.getTopLayout() != null) ? (addingXCreator.getTopLayout().toData()) : addingXCreator.toData(); - //图表埋点 - dealChartBuryingPoint(widget); - if (addingXCreator.isShared()) { - if (container.acceptType(XWAbsoluteLayout.class)) { - // 绝对布局中新添加的共享组件默认锁定尺寸比例 - Rectangle bounds = new Rectangle(addingXCreator.getBounds()); - Widget addingWidget = addingXCreator.toData(); - if (addingWidget != null && bounds.width > 0 && bounds.height > 0) { - addingXCreator.toData().setAspectRatioLocked(true); - addingXCreator.toData().setAspectRatioBackup(1.0 * bounds.width / bounds.height); - } - } - String shareId = addingXCreator.getShareId(); - SharableEditorProvider sharableEditor = ShareLoader.getLoader().getSharedElCaseEditorById(shareId); - SharableWidgetProvider bindInfo = ShareLoader.getLoader().getElCaseBindInfoById(shareId); - Map tdNameMap = Collections.emptyMap(); - if (sharableEditor != null && bindInfo != null) { - tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true); - //合并数据集之后,可能会有数据集名称变化,做一下联动 - //共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集 - Map map = new HashMap<>(); - for (Map.Entry entry : tdNameMap.entrySet()) { - designer.getTarget().renameTableData(widget, entry.getKey(), entry.getValue()); - map.put(entry.getKey(), entry.getValue()); - } - if (!map.isEmpty()) { - DesignTableDataManager.fireDSChanged(map); - } + @Override + public void afterAdded(boolean addResult) { + if (addResult) { + tabDragInner.reset(); + } else { + undoWhenAddingFailed(); } - EventDispatcher.fire(TableDataModifyEvent.INSTANCE, new ContentChangeItem(tdNameMap, widget, ChangeItem.TABLE_DATA_NAME)); } - - designer.getSelectionModel().setSelectedCreators( - FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget})); - if (!addingModel.isAddedIllegal()) { - designer.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED); - } - tabDragInner.tryDragIn(); - } else { - Toolkit.getDefaultToolkit().beep(); - // 拖入失败 取消选中 - XCreator creator = addingModel.getXCreator(); - if (creator != null) { - creator.setSelected(false); - } - } - // 取消提示 - designer.setPainter(null); - // 切换添加状态到普通状态 - designer.stopAddingState(); + }); } private void entering(int x, int y) { // 将要添加的组件图标移动到鼠标下的位置 - addingModel.moveTo(x, y); + designer.updateDraggingPosition(x, y); designer.repaint(); } private void exiting() { cancelPromptWidgetForbidEnter(); // 隐藏组件图标 - addingModel.reset(); + designer.resetDraggingPosition(); designer.setPainter(null); designer.repaint(); } private void hovering(int x, int y) { // 当前位置移植鼠标e所在的位置 - addingModel.moveTo(x, y); + designer.updateDraggingPosition(x, y); // 获取e所在的焦点组件 XCreator hotspot = designer.getComponentAt(x, y); // 获取焦点组件所在的焦点容器 @@ -235,15 +146,15 @@ public class FormCreatorDropTarget extends DropTarget { rect.y -= designer.getArea().getVerticalValue(); painter.setRenderingBounds(rect); painter.setHotspot(new Point(x, y)); - painter.setCreator(addingModel.getXCreator()); + painter.setCreator(creator); } } private void promptUser(int x, int y, XLayoutContainer container) { - if (!addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class)) { + if (!creator.canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class)) { promptButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Para_Pane")); promptWidgetForbidEnter(x, y, container); - } else if (!addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { + } else if (!creator.canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { promptButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Adapt_Pane")); promptWidgetForbidEnter(x, y, container); } else { @@ -289,8 +200,15 @@ public class FormCreatorDropTarget extends DropTarget { int x = designer.getRelativeX(loc.x); int y = designer.getRelativeY(loc.y); hovering(x, y); - tabDragInner.canDragIn(designer.getComponentAt(x, y), x, y); - designer.draggingComponent(x, y); + tabDragInner.setTabDragInAble(designer.getComponentAt(x, y), x, y); + + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator); + if (parent!= null && parent.getLayoutAdapter()!=null){ + parent.getLayoutAdapter().dragOver(creator, designer.getSelectionModel(), x, y); + } + + // 触发状态添加模式事件 + designer.repaint(); } /** @@ -320,12 +238,11 @@ public class FormCreatorDropTarget extends DropTarget { */ @Override public synchronized void drop(DropTargetDropEvent dtde) { - try { dropXCreator(dtde); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - if (addingModel.getXCreator().isShared()) { + if (creator.isShared()) { FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Drag_Component_Error_Info"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Error"), @@ -335,40 +252,42 @@ public class FormCreatorDropTarget extends DropTarget { } dtde.rejectDrop(); } + designer.stopDragging(); + designer.clearDropTarget(); } private void dropXCreator(DropTargetDropEvent dtde) { - Point loc = dtde.getLocation(); - this.adding(designer.getRelativeX(loc.x), designer.getRelativeY(loc.y)); - // 放到事件末尾执行 - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // 拖拽释放后标记未选中 - for (XCreator xCreator : designer.getSelectionModel().getSelection().getSelectedCreators()) { - xCreator.setSelected(true); - } - } - }); - //针对在表单中拖入一个控件直接ctrl+s无反应 - designer.requestFocus(); - } + DraggingModel model = designer.getDraggingModel(); - private void dealChartBuryingPoint(Widget widget) { - List chartCollections = widget.getChartCollections(); - for (BaseChartCollection baseChartCollection : chartCollections) { - ChartCollection chartCollection = (ChartCollection) baseChartCollection; - for (int i = 0, size = chartCollection.getChartCount(); i < size; i++) { - ChartProvider chart = chartCollection.getChart(i, ChartProvider.class); - //是否是共享的复用组件 - boolean isReuse = StringUtils.isNotEmpty(this.addingModel.getXCreator().getShareId()); - ChartInfoCollector.getInstance().collection(chart, null, isReuse); - ChartInfoCollector.getInstance().checkTestChart(chart); - } + if (model != null) { + cancelPromptWidgetForbidEnter(); + Point loc = dtde.getLocation(); + int x = designer.getRelativeX(loc.x); + int y = designer.getRelativeY(loc.y); + designer.addWidgetToForm(creator, x, y); + // 放到事件末尾执行 + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // 拖拽释放后标记未选中 + for (XCreator xCreator : designer.getSelectionModel().getSelection().getSelectedCreators()) { + xCreator.setSelected(true); + } + } + }); + //针对在表单中拖入一个控件直接ctrl+s无反应 + designer.requestFocus(); } } public TabDragInner getTabDragInner() { return this.tabDragInner; } + + private void undoWhenAddingFailed() { + JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if (jt != null) { + jt.undoToCurrent(); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java index adc59581a..24ed004ff 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java @@ -1,14 +1,21 @@ package com.fr.design.mainframe; import com.fr.base.Parameter; +import com.fr.base.chart.BaseChartCollection; import com.fr.base.vcs.DesignerMode; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chartx.attr.ChartProvider; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.base.mode.DesignModeContext; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.designer.TargetComponent; import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.ComponentAdapter; +import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.Painter; import com.fr.design.designer.beans.actions.CopyAction; import com.fr.design.designer.beans.actions.CutAction; @@ -18,9 +25,11 @@ import com.fr.design.designer.beans.actions.MoveToBottomAction; import com.fr.design.designer.beans.actions.MoveToTopAction; import com.fr.design.designer.beans.actions.MoveUpAction; import com.fr.design.designer.beans.actions.PasteAction; +import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter; import com.fr.design.designer.beans.adapters.layout.DefaultDesignerBaseOperate; -import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter; import com.fr.design.designer.beans.adapters.layout.DesignerBaseOperate; +import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter; +import com.fr.design.designer.beans.events.AddingWidgetListenerTable; import com.fr.design.designer.beans.events.CreatorEventListenerTable; import com.fr.design.designer.beans.events.DesignerEditListener; import com.fr.design.designer.beans.events.DesignerEvent; @@ -28,6 +37,8 @@ import com.fr.design.designer.beans.location.Direction; import com.fr.design.designer.beans.location.Location; import com.fr.design.designer.beans.location.RootResizeDirection; import com.fr.design.designer.beans.models.AddingModel; +import com.fr.design.designer.beans.models.DraggingModel; +import com.fr.design.designer.beans.models.ModelUtil; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.beans.models.StateModel; import com.fr.design.designer.creator.XChartEditor; @@ -37,6 +48,7 @@ import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWAbsoluteBodyLayout; import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.designer.creator.XWBorderLayout; +import com.fr.design.designer.creator.XWFitLayout; import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; @@ -45,19 +57,27 @@ import com.fr.design.event.DesignerOpenedListener; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.form.util.XCreatorConstants; import com.fr.design.fun.RightSelectionHandlerProvider; +import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.MenuDef; import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; +import com.fr.design.mod.bean.ChangeItem; +import com.fr.design.mod.bean.ContentChangeItem; +import com.fr.design.mod.event.TableDataModifyEvent; import com.fr.design.parameter.ParaDefinitePane; import com.fr.design.parameter.ParameterPropertyPane; import com.fr.design.roleAuthority.RolesAlreadyEditedPane; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; +import com.fr.event.EventDispatcher; import com.fr.form.FormElementCaseContainerProvider; import com.fr.form.FormElementCaseProvider; import com.fr.form.main.Form; import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.share.SharableWidgetProvider; +import com.fr.form.share.ShareLoader; +import com.fr.form.share.editor.SharableEditorProvider; import com.fr.form.ui.EditorHolder; import com.fr.form.ui.PaddingMargin; import com.fr.form.ui.Widget; @@ -91,6 +111,7 @@ import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; +import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; @@ -99,7 +120,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -144,6 +168,7 @@ public class FormDesigner extends TargetComponent
implements TreeSelection private transient StateModel stateModel; // 添加状态下的model,存储添加状态下的临时状态,比如要添加的组件、当前鼠标位置等等 private transient AddingModel addingModel; + private transient DraggingModel draggingModel; // 当前负责额外渲染的painter,主要目的用来渲染添加组件的位置提示,它通常由外部类设置,在 // 设计器渲染时被调用渲染这些位置提示。 private transient Painter painter; @@ -170,6 +195,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection private static final int H_GAP = 105; private static final int SUBMIT_BUTTON_H_LOCATION = 270; + private AddingWidgetListenerTable addingWidgetListeners; + public FormDesigner(Form form) { this(form, null); } @@ -184,6 +211,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection this.setBackground(Color.WHITE); // 初始化 edit = new CreatorEventListenerTable(); + addingWidgetListeners = new AddingWidgetListenerTable(); selectionModel = new SelectionModel(this); stateModel = new StateModel(this); desigerMode = createFormDesignerTargetMode(); @@ -201,6 +229,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection populateParameterPropertyPane(); spacingLineDrawer = new FormSpacingLineDrawer(this); + clearDropTarget(); } @@ -603,6 +632,10 @@ public class FormDesigner extends TargetComponent implements TreeSelection return edit; } + public AddingWidgetListenerTable getAddingWidgetListeners() { + return addingWidgetListeners; + } + /** * 增加监听事件 * @@ -783,6 +816,35 @@ public class FormDesigner extends TargetComponent implements TreeSelection repaint(); } + /** + * 停止拖拽 + */ + public void stopDragging() { + draggingModel = null; + } + + public void clearDropTarget() { + this.setDropTarget(null); + } + + /** + * 更新拖拽model的位置 + */ + public void updateDraggingPosition(int x, int y) { + if (draggingModel != null) { + draggingModel.moveTo(x, y); + } + } + + /** + * 重置拖拽model的位置 + */ + public void resetDraggingPosition() { + if (draggingModel != null) { + draggingModel.reset(); + } + } + /** * 设置其UI类为DesignerUI,负责渲染 */ @@ -1109,8 +1171,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection return addingModel; } - public void setAddingModel(AddingModel addingModel) { - this.addingModel = addingModel; + public DraggingModel getDraggingModel() { + return draggingModel; } public XCreator getComponentAt(MouseEvent e) { @@ -1179,50 +1241,91 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 拖拽准备 + * 拖入新的组件 * - * @param xCreator 组件 + * @param xCreator + * @param startDragEvent + * @param currentDragEvent */ - public void startDraggingBean(XCreator xCreator) { - // 根据所选择的组件的BeanInfo生成相应的AddingModel - // AddingModel和StateModel不一样,适合当前选择的组件相关的 - addingModel = new AddingModel(this, xCreator); - this.setDropTarget(new FormCreatorDropTarget(this)); - // 触发状态添加模式事件 + public void startDraggingNewWidget(XCreator xCreator, MouseEvent startDragEvent, MouseEvent currentDragEvent) { + if (currentDragEvent == null) { + return; + } + + instantiateCreator(xCreator); + draggingModel = new DraggingModel() + .designer(this) + .creator(xCreator) + .startDragEvent(startDragEvent) + .currentDragEvent(currentDragEvent); + this.setDropTarget(new FormCreatorDropTarget(this, xCreator)); repaint(); } /** - * 拖拽时相关处理 + * 拖拽表单上的组件 * - * @param xCreator 组件 - * @param lastPressEvent 鼠标事件 - * @param x 坐标x - * @param y 坐标y - */ - public void startDraggingComponent(XCreator xCreator, MouseEvent lastPressEvent, int x, int y) { - // 根据所选择的组件的BeanInfo生成相应的AddingModel - // AddingModel和StateModel不一样,适合当前选择的组件相关的 - this.addingModel = new AddingModel(xCreator, x, y); - TransferHandler handler = new DesignerTransferHandler(this, addingModel); - setTransferHandler(handler); - handler.exportAsDrag(this, lastPressEvent, TransferHandler.COPY); - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); - parent.getLayoutAdapter().dragStart(xCreator, selectionModel); - this.setDropTarget(new FormCreatorDropTarget(this)); - // 触发状态添加模式事件 + * @param xCreator + * @param startDragEvent + * @param currentDragEvent + */ + public void startDraggingFormWidget(XCreator xCreator, MouseEvent startDragEvent, MouseEvent currentDragEvent) { + if (currentDragEvent == null) { + return; + } + backUpCreator(xCreator); + draggingModel = new DraggingModel() + .designer(this) + .creator(xCreator) + .startDragEvent(startDragEvent) + .currentDragEvent(currentDragEvent); + XLayoutContainer container = this.getDraggingHotspotLayout(); + LayoutAdapter adapter = container.getLayoutAdapter(); + adapter.dragging(this.getDraggingModel()); repaint(); } - public void draggingComponent(int x, int y){ - XCreator xCreator = this.addingModel.getXCreator(); + /** + * 绑定transferHandler,貌似这边用的还是低级的DND方式绑定的鼠标手势,高级的可参考ToolBarButton那边,"rootComponent"常量是 + * 从原来的DesignerTransferHandler里面直接搬来的,目前意义还不明确 + * + * @param e + */ + public void bindTransferHandler(MouseEvent e) { + TransferHandler handler = new TransferHandler("rootComponent"); + this.setTransferHandler(handler); + handler.exportAsDrag(this, e, TransferHandler.COPY); + } + + /** + * 触发父组件布局的dragStart事件,目前只在非固定布局下有用,用来删除占位块 + * + * @param xCreator + */ + public void fireParentLayoutDragStart(XCreator xCreator) { XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); - if (parent!= null && parent.getLayoutAdapter()!=null){ - parent.getLayoutAdapter().dragOver(xCreator, selectionModel, x, y); + if (parent != null) { + parent.getLayoutAdapter().dragStart(xCreator, selectionModel); } + } - // 触发状态添加模式事件 - repaint(); + /** + * 获取拖拽当前鼠标所在位置的布局 + * + * @return + */ + public XLayoutContainer getDraggingHotspotLayout() { + DraggingModel model = this.draggingModel; + MouseEvent dragEvent = model.getCurrentDragEvent(); + XCreator hotspot = this.getComponentAt(dragEvent.getX(), dragEvent.getY()); + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); + XLayoutContainer topLayout = container.getTopLayout(); + // REPORT-66939 Tab比较特殊,它是又多个LayoutContainer组成,直接返回container会导致误判,需要先找到最上层topLayout,取其父layout才是正确结果 + if (topLayout != null && container != topLayout) { + return (XLayoutContainer) topLayout.getParent(); + } else { + return container; + } } /** @@ -1424,7 +1527,10 @@ public class FormDesigner extends TargetComponent implements TreeSelection private DesignerBaseOperate getLayoutBaseOperate(){ FormSelection selection = this.getSelectionModel().getSelection(); XCreator creator = selection.getSelectedCreator(); - XLayoutContainer container = (XLayoutContainer) creator.getParent(); + XLayoutContainer container = null; + if (creator != null) { + container = (XLayoutContainer) creator.getParent(); + } if (container == null) { return new DefaultDesignerBaseOperate(); } @@ -1890,4 +1996,129 @@ public class FormDesigner extends TargetComponent implements TreeSelection public FormSpacingLineDrawer getSpacingLineDrawer() { return spacingLineDrawer; } + + public void instantiateCreator(XCreator creator) { + if (creator != null) { + ModelUtil.renameWidgetName(this.getTarget(), creator); + creator.addNotify(); + + ComponentAdapter adapter = new CompositeComponentAdapter(this, creator); + adapter.initialize(); + creator.putClientProperty(AdapterBus.CLIENT_PROPERTIES, adapter); + } + } + + public void backUpCreator(XCreator creator) { + if (creator != null) { + creator.backupCurrentSize(); + creator.backupParent(); + } + } + + public void addWidgetToForm(XCreator creator, int x, int y) { + if(creator == null) { + return; + } + + addingModel = new AddingModel(creator); + // 当前鼠标所在的组件 + XCreator hoveredComponent = this.getComponentAt(x, y); + // 获取该组件所在的焦点容器 + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); + boolean success = false; + if (container != null) { + // 如果是容器,则调用其acceptComponent接受组件 + boolean chartEnter2Para = !addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class); + boolean formSubmit2Adapt = !addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class); + + if (!chartEnter2Para && !formSubmit2Adapt) { + getAddingWidgetListeners().beforeAdded(); + success = container.addWidgetToContainer( + creator, + x + this.getHorizontalScaleValue(), + y + this.getVerticalScaleValue() + ); + } + getAddingWidgetListeners().afterAdded(success); + defaultAfterWidgetAdded(success, container); + } + + // 取消提示 + this.setPainter(null); + // 切换添加状态到普通状态 + this.stopAddingState(); + getAddingWidgetListeners().clearListeners(); + } + + private void dealChartBuryingPoint(Widget widget) { + List chartCollections = widget.getChartCollections(); + for (BaseChartCollection baseChartCollection : chartCollections) { + ChartCollection chartCollection = (ChartCollection) baseChartCollection; + for (int i = 0, size = chartCollection.getChartCount(); i < size; i++) { + ChartProvider chart = chartCollection.getChart(i, ChartProvider.class); + //是否是共享的复用组件 + boolean isReuse = StringUtils.isNotEmpty(this.addingModel.getXCreator().getShareId()); + ChartInfoCollector.getInstance().collection(chart, null, isReuse); + ChartInfoCollector.getInstance().checkTestChart(chart); + } + } + } + + + + private void defaultAfterWidgetAdded(boolean addResult, XLayoutContainer container) { + if (addResult) { + // 如果添加成功,则触发相应事件 + XCreator xCreator = container.acceptType(XWParameterLayout.class) ? this.getParaComponent() : this.getRootComponent(); + //SetSelection时要确保选中的是最顶层的布局 + //tab布局添加的时候是初始化了XWCardLayout,实际上最顶层的布局是XWCardMainBorderLayout + XCreator addingXCreator = addingModel.getXCreator(); + Widget widget = (addingXCreator.getBackupParent() != null && addingXCreator.getTopLayout() != null) ? (addingXCreator.getTopLayout().toData()) : addingXCreator.toData(); + //图表埋点 + dealChartBuryingPoint(widget); + if (addingXCreator.isShared()) { + if (container.acceptType(XWAbsoluteLayout.class)) { + // 绝对布局中新添加的共享组件默认锁定尺寸比例 + Rectangle bounds = new Rectangle(addingXCreator.getBounds()); + Widget addingWidget = addingXCreator.toData(); + if (addingWidget != null && bounds.width > 0 && bounds.height > 0) { + addingXCreator.toData().setAspectRatioLocked(true); + addingXCreator.toData().setAspectRatioBackup(1.0 * bounds.width / bounds.height); + } + } + + String shareId = addingXCreator.getShareId(); + SharableEditorProvider sharableEditor = ShareLoader.getLoader().getSharedElCaseEditorById(shareId); + SharableWidgetProvider bindInfo = ShareLoader.getLoader().getElCaseBindInfoById(shareId); + Map tdNameMap = Collections.emptyMap(); + if (sharableEditor != null && bindInfo != null) { + tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true); + //合并数据集之后,可能会有数据集名称变化,做一下联动 + //共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集 + Map map = new HashMap<>(); + for (Map.Entry entry : tdNameMap.entrySet()) { + this.getTarget().renameTableData(widget, entry.getKey(), entry.getValue()); + map.put(entry.getKey(), entry.getValue()); + } + if (!map.isEmpty()) { + DesignTableDataManager.fireDSChanged(map); + } + } + EventDispatcher.fire(TableDataModifyEvent.INSTANCE, new ContentChangeItem(tdNameMap, widget, ChangeItem.TABLE_DATA_NAME)); + } + + this.getSelectionModel().setSelectedCreators( + FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget})); + if (!addingModel.isAddedIllegal()) { + this.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED); + } + } else { + Toolkit.getDefaultToolkit().beep(); + // 拖入失败 取消选中 + XCreator creator = addingModel.getXCreator(); + if (creator != null) { + creator.setSelected(false); + } + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java index aab1b27b7..8307e945f 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java @@ -6,10 +6,9 @@ import com.fr.base.Utils; import com.fr.base.iofile.attr.WatermarkAttr; import com.fr.base.vcs.DesignerMode; import com.fr.design.constants.UIConstants; -import com.fr.design.designer.beans.AdapterBus; -import com.fr.design.designer.beans.ComponentAdapter; +import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.location.Direction; -import com.fr.design.designer.beans.models.AddingModel; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; @@ -117,11 +116,10 @@ public class FormDesignerUI extends ComponentUI { designer.getPainter().paint(g, designer.getArea().getHorizontalValue(), designer.getArea().getVerticalValue() + designer.getParaHeight()); } - AddingModel addingModel = designer.getAddingModel(); - if ((addingModel != null) && (addingModel.getXCreator() != null)) { + if (needPaintDraggingBean()) { // 当前正在添加的组件 - paintAddingBean(g, addingModel); + paintDraggingBean(g); } designer.getSpacingLineDrawer().draw(g); @@ -196,31 +194,42 @@ public class FormDesignerUI extends ComponentUI { } /** - * 渲染当前正在添加的组件,采用Renderer原理 + * 渲染当前正在拖拽的组件,采用Renderer原理 */ - private void paintAddingBean(Graphics g, final AddingModel addingModel) { - if (!addingModel.need2paint()) { - return; - } - XCreator bean = addingModel.getXCreator(); - int x = addingModel.getCurrentX(); - int y = addingModel.getCurrentY() ; - - int width = bean.initEditorSize().width; - int height = bean.initEditorSize().height; + private void paintDraggingBean(Graphics g) { + DraggingModel model = designer.getDraggingModel(); + XCreator bean = model.getCreator(); + int x = model.getCreatorLeftTopX(); + int y = model.getCreatorLeftTopY(); + + XLayoutContainer container = designer.getDraggingHotspotLayout(); + LayoutAdapter adapter = container.getLayoutAdapter(); + int width = adapter.getDragSize(bean).width; + int height = adapter.getDragSize(bean).height; Graphics clipg = g.create(x, y, width, height); ArrayList dbcomponents = new ArrayList(); // 禁止双缓冲行为 ComponentUtils.disableBuffer(bean, dbcomponents); - ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, bean); - // 调用ComponentAdapter的paintComponentMascot方法渲染该组件添加提示 - adapter.paintComponentMascot(clipg); + adapter.paintComponentMascot(clipg, bean); clipg.dispose(); // 恢复双缓冲 ComponentUtils.resetBuffer(dbcomponents); } + private boolean needPaintDraggingBean() { + DraggingModel draggingModel = designer.getDraggingModel(); + if (draggingModel == null || draggingModel.getCreator() == null) { + return false; + } + + XCreator creator = draggingModel.getCreator(); + int leftTopX = draggingModel.getCreatorLeftTopX(); + int leftTopY = draggingModel.getCreatorLeftTopY(); + + return leftTopX + creator.getWidth() > 0 && leftTopY + creator.getHeight() > 0; + } + private void paintAuthorityCreator(Graphics2D g2d, Rectangle creatorBounds) { back_or_selection_rect.setRect(creatorBounds.getX(), creatorBounds.getY(), diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java b/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java index 7a084c2f0..2f78a98f0 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java @@ -18,6 +18,10 @@ import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.share.ComponentShareUtil; +import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; +import com.fr.design.mainframe.share.util.OnlineShopUtils; import com.fr.design.module.DesignModuleFactory; import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.gui.LayoutUtils; @@ -262,7 +266,13 @@ public class FormParaWidgetPane extends JPanel { jPanel.addMouseListener(new MouseListener() { @Override public void mouseClicked(MouseEvent e) { - FormWidgetDetailPane.getInstance().enterWidgetLib(); + if (OnlineShopUtils.testConnection() && ComponentShareUtil.isShowMiniShopWindow()) { + MiniComponentShopDialog.getInstance().show(); + } else { + OnlineWidgetRepoPane.getInstance().switch2InternetErrorPane(); + FormWidgetDetailPane.getInstance().switch2Local(); + FormWidgetDetailPane.getInstance().enterWidgetLib(); + } } @Override 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 8d2748eb3..449aa5190 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 @@ -14,7 +14,6 @@ import com.fr.base.vcs.DesignerMode; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.DesignerEnvManager; -import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.FormMobileAttrAction; import com.fr.design.actions.TemplateParameterAction; import com.fr.design.actions.core.WorkBookSupportable; @@ -37,7 +36,7 @@ import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; import com.fr.design.file.HistoryTemplateListCache; -import com.fr.design.fun.FormAdaptiveConfigUIProcessor; +import com.fr.design.fit.FormFitAttrAction; import com.fr.design.fun.PreviewProvider; import com.fr.design.fun.PropertyItemPaneProvider; import com.fr.design.gui.frpane.HyperlinkGroupPane; @@ -66,7 +65,6 @@ import com.fr.design.menu.ToolBarDef; import com.fr.design.parameter.ParameterPropertyPane; import com.fr.design.preview.FormPreview; import com.fr.design.preview.MobilePreview; -import com.fr.design.report.fit.menupane.ReportFitAttrAction; import com.fr.design.roleAuthority.RolesAlreadyEditedPane; import com.fr.design.utils.gui.LayoutUtils; import com.fr.file.FILE; @@ -98,6 +96,7 @@ import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; import com.fr.stable.bridge.StableFactory; import com.fr.web.controller.ViewRequestConstants; +import org.jetbrains.annotations.Nullable; import javax.swing.BorderFactory; import javax.swing.Icon; @@ -127,7 +126,7 @@ public class JForm extends JTemplate implements BaseJForm implements BaseJForm implements BaseJForm implements BaseJForm implements BaseJForm implements BaseJForm implements BaseJForm implements BaseJForm { public int compare(OnlineShareWidget o1, OnlineShareWidget o2) { double t1 = getSortValue(o1, parameterMap); double t2 = getSortValue(o2, parameterMap); - return ComparatorUtils.compareCommonType(t2, t1); + // Comparator中比较double/float相等时,不允许误差. 否则会违背 "若x = y , y = z, 则x = z"的约定。 + // 因为允许误差的情况下,x和y间的误差在允许范围内,被判定相等,y和z间的误差在允许范围内,被判定相等, + // 但x和z间的误差可能超出允许范围,从而不相等,因此会违背上述约定。 + // 产生IllegalArgumentException: Comparison method violates its general contract! + return Double.compare(t2, t1); } }); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java index c23c82f10..91b51b399 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java @@ -16,8 +16,8 @@ import com.fr.design.mainframe.share.group.ui.GroupMoveDialog; import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupAction; import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupMenu; import com.fr.design.mainframe.share.ui.constants.ColorConstants; -import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoUpdater; import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; +import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoUpdater; import com.fr.design.mainframe.share.ui.local.LocalWidgetSelectPane; import com.fr.design.mainframe.share.ui.local.WidgetSelectedManager; import com.fr.design.mainframe.share.util.ShareComponentUtils; @@ -31,7 +31,6 @@ import com.fr.form.share.record.ShareWidgetInfoManager; import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; -import com.fr.general.FRFont; import com.fr.general.IOUtils; import com.fr.stable.Constants; import org.jetbrains.annotations.NotNull; @@ -61,7 +60,6 @@ import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; -import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import java.util.UUID; @@ -239,7 +237,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock if (xCreator == null) { return; } - WidgetToolBarPane.getTarget().startDraggingBean(xCreator); + WidgetToolBarPane.getTarget().startDraggingNewWidget(xCreator, lastPressEvent, e); lastPressEvent = null; this.setBorder(null); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java index 7f0e369f9..61c913201 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java @@ -13,21 +13,21 @@ import com.fr.design.login.DesignerLoginHelper; import com.fr.design.login.DesignerLoginSource; import com.fr.design.mainframe.WidgetToolBarPane; import com.fr.design.mainframe.share.collect.ComponentCollector; +import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetSelectPane; import com.fr.design.mainframe.share.ui.online.CarouselStateManger; -import com.fr.form.share.DefaultSharableWidget; -import com.fr.form.share.group.DefaultShareGroup; -import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; import com.fr.design.mainframe.share.util.DownloadUtils; import com.fr.design.mainframe.share.util.ShareComponentUtils; import com.fr.design.mainframe.share.util.ShareUIUtils; import com.fr.design.ui.util.UIUtil; +import com.fr.form.share.DefaultSharableWidget; +import com.fr.form.share.Group; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.bean.OnlineShareWidget; import com.fr.form.share.constants.ShareComponentConstants; +import com.fr.form.share.group.DefaultShareGroup; import com.fr.form.share.group.DefaultShareGroupManager; -import com.fr.form.share.Group; import com.fr.form.share.utils.ShareUtils; import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.Widget; @@ -163,6 +163,11 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { } } + @Override + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + } + @Override public void mouseDragged(MouseEvent e) { if (!getWidget().isCompatibleWithCurrentEnv()) { @@ -201,7 +206,7 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { } else { xCreator = ShareComponentUtils.createXCreator(creatorSource, shareId, bindInfo); } - WidgetToolBarPane.getTarget().startDraggingBean(xCreator); + WidgetToolBarPane.getTarget().startDraggingNewWidget(xCreator, lastPressEvent, e); lastPressEvent = null; this.setBorder(null); } @@ -332,41 +337,42 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { null, this ); - return; - } - //如果鼠标移动到布局内且布局不可编辑,画出编辑蒙层 - if (!isRightClickPopupMenuVisible() && (isMouseEnter || downloading)) { - Graphics2D g2d = (Graphics2D) g; - Composite oldComposite = g2d.getComposite(); - //画白色的编辑层 - g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 20 / 100.0F)); - g2d.setColor(COVER_COLOR); - g2d.fillRect(x, y, w, h); - g2d.setComposite(oldComposite); - //画编辑按钮图标 - BufferedImage image = (process > 0 || downloading) ? WIDGET_DOWNLOADING_ICON : WIDGET_DOWNLOAD_ICON; - g2d.drawImage( - image, - (x + w / 2 - 12), - (y + h / 2 - 16), - image.getWidth(), - image.getHeight(), - null, - this - ); - Stroke oldStroke = g2d.getStroke(); - g2d.setStroke(XCreatorConstants.STROKE); - g2d.setColor(Color.decode("#419BF9")); - double arcAngle = downloading ? (36 + 360 * 0.9 * process) : 0.0; - g2d.drawArc(x + w / 2 - 12, y + h / 2 - 16, 24, 24, 90, -(int) arcAngle); - g2d.setColor(Color.WHITE); - g2d.setStroke(oldStroke); - } + } else { + //如果鼠标移动到布局内且布局不可编辑,画出编辑蒙层 + if (!isRightClickPopupMenuVisible() && (isMouseEnter || downloading)) { + Graphics2D g2d = (Graphics2D) g; + Composite oldComposite = g2d.getComposite(); + //画白色的编辑层 + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 20 / 100.0F)); + g2d.setColor(COVER_COLOR); + g2d.fillRect(x, y, w, h); + g2d.setComposite(oldComposite); + //画编辑按钮图标 + BufferedImage image = (process > 0 || downloading) ? WIDGET_DOWNLOADING_ICON : WIDGET_DOWNLOAD_ICON; + g2d.drawImage( + image, + (x + w / 2 - 12), + (y + h / 2 - 16), + image.getWidth(), + image.getHeight(), + null, + this + ); + Stroke oldStroke = g2d.getStroke(); + g2d.setStroke(XCreatorConstants.STROKE); + g2d.setColor(Color.decode("#419BF9")); + double arcAngle = downloading ? (36 + 360 * 0.9 * process) : 0.0; + g2d.drawArc(x + w / 2 - 12, y + h / 2 - 16, 24, 24, 90, -(int) arcAngle); + g2d.setColor(Color.WHITE); + g2d.setStroke(oldStroke); + } - boolean isUnusable = !getWidget().isCompatibleWithCurrentEnv(); - if (isUnusable) { - paintUnusableMask((Graphics2D) g); + boolean isUnusable = !getWidget().isCompatibleWithCurrentEnv(); + if (isUnusable) { + paintUnusableMask((Graphics2D) g); + } } + if (this.parentPane != null) { this.parentPane.refreshShowPaneUI(); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineDownloadPackagePane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineDownloadPackagePane.java index 59a09c466..1d4990c7d 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineDownloadPackagePane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineDownloadPackagePane.java @@ -72,22 +72,6 @@ public class OnlineDownloadPackagePane extends OnlineWidgetSelectPane { return false; } - protected JPanel createWidgetPane() { - return new JPanel() { - @Override - public void paint(Graphics g) { - super.paint(g); - Graphics2D g2d = (Graphics2D) g; - Composite oldComposite = g2d.getComposite(); - AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.65f); - g2d.setComposite(composite); - g2d.setColor(Color.DARK_GRAY); - g2d.fillRect(0, 0, getWidth(), getHeight()); - g2d.setComposite(oldComposite); - } - }; - } - protected JPanel createContentPane(JPanel widgetPane) { JPanel panel = new JPanel() { @Override @@ -114,7 +98,20 @@ public class OnlineDownloadPackagePane extends OnlineWidgetSelectPane { parentPane.resetWidgetDetailPane(packageId, getSharableWidgetProviders()); } } - }); + }) { + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Composite oldComposite = g2d.getComposite(); + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.65f); + g2d.setComposite(composite); + g2d.setColor(Color.DARK_GRAY); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.setComposite(oldComposite); + + super.paint(g); + } + }; panel.add(downloadProgressPane); panel.add(widgetPane, BorderLayout.CENTER); return panel; @@ -125,10 +122,16 @@ public class OnlineDownloadPackagePane extends OnlineWidgetSelectPane { final com.fr.design.extra.Process downloadProcess = aDouble -> { OnlineDownloadPackagePane.this.process = 0.8 * aDouble; downloadProgressPane.updateProgress(process); + if (downloadProgressPane != null) { + downloadProgressPane.repaint(); + } }; final com.fr.design.extra.Process installProcess = aDouble -> { OnlineDownloadPackagePane.this.process = 0.8 + 0.2 * aDouble; downloadProgressPane.updateProgress(process); + if (downloadProgressPane != null) { + downloadProgressPane.repaint(); + } }; downloadProcess.process(0.0D); @@ -220,6 +223,9 @@ public class OnlineDownloadPackagePane extends OnlineWidgetSelectPane { File file = new File(filePath); installProcess.process(0.0D); downloadProgressPane.changeState(); + if (downloadProgressPane != null) { + downloadProgressPane.repaint(); + } InstallUtils.InstallResult result = null; try { if (file.exists()) { @@ -250,4 +256,12 @@ public class OnlineDownloadPackagePane extends OnlineWidgetSelectPane { } } } + + @Override + public void refreshShowPaneUI() { + if (downloadProgressPane != null && downloadProgressPane.isShowing()) { + downloadProgressPane.invalidate(); + downloadProgressPane.repaint(); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java index b9e430fe4..b4d3bcc68 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java @@ -1,29 +1,44 @@ package com.fr.design.mainframe.share.ui.online; import com.fr.base.BaseUtils; +import com.fr.base.Style; +import com.fr.config.constant.Constant; import com.fr.design.dialog.BasicPane; +import com.fr.design.form.util.FontTransformUtil; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.share.ui.base.LoadingPane; import com.fr.design.mainframe.share.ui.base.MouseClickListener; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; import com.fr.design.mainframe.share.util.OnlineShopUtils; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; import com.fr.form.share.bean.OnlineShareWidget; +import com.fr.general.FRFont; +import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; +import com.fr.stable.Constants; import com.fr.stable.StringUtils; import javax.swing.BorderFactory; +import javax.swing.BoxLayout; import javax.swing.JPanel; +import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.SwingWorker; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.util.List; import java.util.concurrent.ExecutionException; @@ -35,13 +50,8 @@ public class OnlineWidgetRepoPane extends BasicPane { private static final String MARKET_URL = "https://market.fanruan.com/reuse"; private static List[] sharableWidgets; private OnlineWidgetTabPane componentTabPane; - private JPanel centerPane; private boolean isShowPackagePanel = false; - private CardLayout cardLayout; - private Status currentStatus; - - - enum Status {LOADING, DISCONNECTED, NORMAL} + private LoadableContentPane loadableContentPane; public static boolean loadWidgets() { if (sharableWidgets != null){ @@ -82,16 +92,15 @@ public class OnlineWidgetRepoPane extends BasicPane { } private void initPane() { - cardLayout = new CardLayout(); - this.setLayout(cardLayout); - this.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); - this.centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.setLayout(new BorderLayout()); + + this.loadableContentPane = new LoadableContentPane(createInternetErrorPane()); + this.loadableContentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); - this.add(new LoadingPane(), Status.LOADING.name()); - this.add(this.centerPane, Status.NORMAL.name()); - this.add(createInternetErrorPane(), Status.DISCONNECTED.name()); + DisabledContentPane disabledContentPane = new DisabledContentPane(this.loadableContentPane); + this.add(disabledContentPane, BorderLayout.CENTER); - switchPane(Status.LOADING); + this.loadableContentPane.showLoading(); setContent(); } @@ -105,18 +114,15 @@ public class OnlineWidgetRepoPane extends BasicPane { } private void addCenterPane() { - this.centerPane.removeAll(); - this.centerPane.add(this.componentTabPane, BorderLayout.CENTER); - this.switchPane(Status.NORMAL); + JPanel contentPane = this.loadableContentPane.getContentPane(); + contentPane.removeAll(); + contentPane.setLayout(new BorderLayout()); + contentPane.add(this.componentTabPane, BorderLayout.CENTER); + this.loadableContentPane.showContent(); } public void switch2InternetErrorPane() { - switchPane(Status.DISCONNECTED); - } - - private void switchPane(Status status) { - this.currentStatus = status; - cardLayout.show(this, status.name()); + this.loadableContentPane.showError(); } private void synchronizedLoadingContent() { @@ -147,16 +153,18 @@ public class OnlineWidgetRepoPane extends BasicPane { if (componentTabPane != null) { componentTabPane.removeTabChangeListener(tabChangeListener); } - this.componentTabPane = new OnlineWidgetTabPane(sharableWidgets[0].toArray(new OnlineShareWidget[sharableWidgets[0].size()]), - sharableWidgets[1].toArray(new OnlineShareWidget[sharableWidgets[1].size()])); + this.componentTabPane = new OnlineWidgetTabPane( + sharableWidgets[0].toArray(new OnlineShareWidget[0]), + sharableWidgets[1].toArray(new OnlineShareWidget[0]) + ); this.componentTabPane.addTabChangeListener(tabChangeListener); } else { - switchPane(Status.DISCONNECTED); + this.loadableContentPane.showError(); } return loadWidgetsSuccess; } - private OnlineWidgetTabPane.TabChangeListener tabChangeListener = new OnlineWidgetTabPane.TabChangeListener() { + private final OnlineWidgetTabPane.TabChangeListener tabChangeListener = new OnlineWidgetTabPane.TabChangeListener() { @Override public void tabChange(int selectedIndex) { setShowPackagePanel(selectedIndex != 0); @@ -173,7 +181,7 @@ public class OnlineWidgetRepoPane extends BasicPane { private JPanel createInternetErrorPane() { JPanel panel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5); - UILabel imagePanel = new UILabel(BaseUtils.readIcon("/com/fr/base/images/share/internet_error.png")); + UILabel imagePanel = new UILabel(IOUtils.readIcon("/com/fr/base/images/share/internet_error.png")); imagePanel.setPreferredSize(new Dimension(240, 96)); imagePanel.setHorizontalAlignment(SwingConstants.CENTER); panel.add(imagePanel); @@ -240,4 +248,105 @@ public class OnlineWidgetRepoPane extends BasicPane { this.componentTabPane.completeEmbedFilter(); } } + + private static class LoadableContentPane extends JPanel { + private enum Status { + LOADING, + DISCONNECTED, + NORMAL + } + private final CardLayout cardLayout; + private final JPanel contentPane; + + public LoadableContentPane(JPanel errorPane) { + cardLayout = new CardLayout(); + this.setLayout(cardLayout); + + this.add(new LoadingPane(), Status.LOADING.name()); + contentPane = new JPanel(); + this.add(contentPane, Status.NORMAL.name()); + this.add(errorPane, Status.DISCONNECTED.name()); + } + + private void switchPane(Status status) { + cardLayout.show(this, status.name()); + } + + public void showLoading() { + switchPane(Status.LOADING); + } + + public void showError() { + switchPane(Status.DISCONNECTED); + } + + public void showContent() { + switchPane(Status.NORMAL); + } + + public JPanel getContentPane() { + return contentPane; + } + } + + private static class DisabledContentPane extends JPanel { + private final CardLayout cardLayout; + + public DisabledContentPane(JPanel contentPane) { + cardLayout = new CardLayout(); + this.setLayout(cardLayout); + + this.add(new MaskPane(), "Disabled"); + this.add(contentPane, "Enabled"); + + MiniComponentShopDialog.getInstance().addWindowAdapter(new WindowAdapter() { + @Override + public void windowOpened(WindowEvent e) { + super.windowOpened(e); + setEnabled(false); + } + + @Override + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + setEnabled(true); + } + }); + + setEnabled(true); + } + + @Override + public void setEnabled(boolean enabled) { + String constrains = enabled ? "Enabled" : "Disabled"; + cardLayout.show(this, constrains); + } + } + + private static class MaskPane extends JPanel { + private static final int PADDING = 30; + private final String text; + private final Style style; + public MaskPane() { + setLayout(new BorderLayout()); + + text = Toolkit.i18nText("Fine-Design_Share_Online_Repo_Pane_Forbidden_Tip"); + style = Style.getInstance(FRFont.getInstance().applyForeground(new Color(0x8F8F92))) + .deriveHorizontalAlignment(SwingConstants.CENTER) + .deriveVerticalAlignment(SwingConstants.CENTER) + .deriveTextStyle(Style.TEXTSTYLE_WRAPTEXT); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + Graphics2D g2d = (Graphics2D) g; + g.translate(PADDING, 0); + BaseUtils.drawStringStyleInRotation(g2d, this.getWidth() - PADDING * 2, this.getHeight(), text, style, FontTransformUtil.getDesignerFontResolution()); + g.translate(-PADDING, 0); + + } + } + } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java index 52ea26bc2..ca0e8aa6a 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java @@ -1,18 +1,30 @@ package com.fr.design.mainframe.share.ui.online; import com.fr.design.gui.ibutton.UITabGroup; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.EastRegionContainerPane; +import com.fr.design.mainframe.FormWidgetDetailPane; +import com.fr.design.mainframe.share.ComponentShareUtil; import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.mainframe.share.sort.OnlineWidgetSortType; -import com.fr.design.mainframe.share.ComponentShareUtil; import com.fr.design.mainframe.share.ui.online.embed.OnlineEmbedFilterShowPane; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; import com.fr.design.mainframe.share.ui.online.widgetpackage.OnlineWidgetPackagesShowPane; +import com.fr.design.mainframe.share.util.OnlineShopUtils; import com.fr.form.share.bean.OnlineShareWidget; import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; import javax.swing.JPanel; +import javax.swing.plaf.basic.BasicButtonUI; import java.awt.BorderLayout; import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.EventListener; import java.util.List; @@ -24,12 +36,16 @@ public class OnlineWidgetTabPane extends JPanel { private static final String COMPONENT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share"); private static final String COMPONENT_PACKAGE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Package"); private static final String COMPONENT_EMBED = "COMPONENT_EMBED"; + private static final int COMPONENT_PACKAGE_TAB_INDEX = 0; + private static final int COMPONENT_TAB_INDEX = 1; + private UITabGroup headGroup; private CardLayout cardLayout; private JPanel centerPane; private boolean packagePaneCreated = false; - private List tabChangeListeners; + private final List tabChangeListeners; private OnlineEmbedFilterShowPane embedFilterShowPane; + private OnlineWidgetPackagesShowPane widgetPackagesShowPane; public OnlineWidgetTabPane(OnlineShareWidget[] sharableWidgets, OnlineShareWidget[] sharableWidgetPackage) { tabChangeListeners = new ArrayList<>(); @@ -44,19 +60,20 @@ public class OnlineWidgetTabPane extends JPanel { this.centerPane.add(new OnlineWidgetShowPane(sharableWidgets), COMPONENT); this.centerPane.add( embedFilterShowPane = new OnlineEmbedFilterShowPane(new OnlineWidgetShowPane(sharableWidgets, OnlineWidgetSortType.SALES)), COMPONENT_EMBED); //延迟组件包面板的初始化,防止组件面板里组件的缩略图和组件包面板里组件的缩略图一起加载 - this.headGroup = new UITabGroup(new String[]{COMPONENT, COMPONENT_PACKAGE}) { + this.headGroup = new UITabGroup(new String[]{COMPONENT_PACKAGE, COMPONENT}) { public void tabChanged(int newSelectedIndex) { for (TabChangeListener changeListener : tabChangeListeners) { changeListener.tabChange(newSelectedIndex); } - if (newSelectedIndex == 0) { + if (newSelectedIndex == COMPONENT_TAB_INDEX) { cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT); } else { ComponentShareUtil.completeEmbedFilter(); ComponentCollector.getInstance().collectCmpPktClick(); //延迟组件包面板的初始化,防止组件面板里组件和缩略图和组件包面板里组件的缩略图一起加载 if (!packagePaneCreated) { - centerPane.add(new OnlineWidgetPackagesShowPane(sharableWidgetPackages), COMPONENT_PACKAGE); + widgetPackagesShowPane = new OnlineWidgetPackagesShowPane(sharableWidgetPackages); + centerPane.add(widgetPackagesShowPane, COMPONENT_PACKAGE); packagePaneCreated = true; } cardLayout.show(centerPane, COMPONENT_PACKAGE); @@ -64,15 +81,46 @@ public class OnlineWidgetTabPane extends JPanel { } }; - this.headGroup.setSelectedIndex(0); + this.headGroup.setSelectedIndex(COMPONENT_PACKAGE_TAB_INDEX); this.centerPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - jPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); - jPanel.add(headGroup, BorderLayout.CENTER); - this.add(jPanel, BorderLayout.NORTH); + JPanel fixedContentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + fixedContentPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + fixedContentPane.add(headGroup, BorderLayout.NORTH); + + fixedContentPane.add(createMiniShopEntryPane(), BorderLayout.CENTER); + this.add(fixedContentPane, BorderLayout.NORTH); this.add(centerPane, BorderLayout.CENTER); } + + + private JPanel createMiniShopEntryPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + JButton button = new JButton(Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Entry_Text")); + button.setPreferredSize(new Dimension(button.getWidth(), 20)); + button.setUI(new BasicButtonUI()); + button.setOpaque(true); + button.setBackground(Color.WHITE); + button.setForeground(new Color(0x419BF9)); + button.setBorder(BorderFactory.createLineBorder(new Color(0x419BF9), 1, true)); + + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (OnlineShopUtils.testConnection() && ComponentShareUtil.isShowMiniShopWindow()) { + MiniComponentShopDialog.getInstance().showFromOnlineRepoPane(); + FormWidgetDetailPane.getInstance().switch2Local(); + FormWidgetDetailPane.getInstance().enterWidgetLib(); + } else { + OnlineWidgetRepoPane.getInstance().switch2InternetErrorPane(); + } + } + }); + container.add(button, BorderLayout.NORTH); + return container; + } + public void completeEmbedFilter(){ if (embedFilterShowPane!= null){ embedFilterShowPane.completeEmbedFilter(); @@ -85,14 +133,18 @@ public class OnlineWidgetTabPane extends JPanel { } } public void refreshPane() { - this.headGroup.setSelectedIndex(0); - this.cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT); + this.headGroup.setSelectedIndex(COMPONENT_PACKAGE_TAB_INDEX); + this.cardLayout.show(centerPane, COMPONENT_PACKAGE); } public void refreshShowPaneUI(){ if (embedFilterShowPane != null) { this.embedFilterShowPane.refreshUI(); } + + if (headGroup.getSelectedIndex() == COMPONENT_PACKAGE_TAB_INDEX && widgetPackagesShowPane != null) { + widgetPackagesShowPane.refreshShowPaneUI(); + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/AsyncInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/AsyncInstallation.java new file mode 100644 index 000000000..42602b865 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/AsyncInstallation.java @@ -0,0 +1,38 @@ +package com.fr.design.mainframe.share.ui.online.installation; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/5 + */ +public abstract class AsyncInstallation implements Installation { + private AsyncActionListener actionListener; + + public void setActionListener(AsyncActionListener actionListener) { + this.actionListener = actionListener; + } + + protected void notifyProgress(double value) { + if (this.actionListener != null) { + this.actionListener.onProgress(value); + } + } + protected void notifySuccess() { + if (this.actionListener != null) { + this.actionListener.onSuccess(); + } + } + protected void notifyFailed() { + if (this.actionListener != null) { + this.actionListener.onFailed(); + } + } + + public abstract void cancel(); + + public interface AsyncActionListener { + void onProgress(double value); + void onSuccess(); + void onFailed(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java new file mode 100644 index 000000000..172bb7d9f --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentInstallation.java @@ -0,0 +1,148 @@ +package com.fr.design.mainframe.share.ui.online.installation; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.extra.Process; +import com.fr.design.login.DesignerLoginHelper; +import com.fr.design.login.DesignerLoginSource; +import com.fr.design.mainframe.share.collect.ComponentCollector; +import com.fr.design.mainframe.share.util.DownloadUtils; +import com.fr.design.mainframe.share.util.ShareComponentUtils; +import com.fr.form.share.Group; +import com.fr.form.share.bean.OnlineShareWidget; +import com.fr.form.share.group.DefaultShareGroup; +import com.fr.form.share.group.DefaultShareGroupManager; +import com.fr.form.share.utils.ShareUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; + +import javax.swing.SwingWorker; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/5 + */ +public class ComponentInstallation extends AsyncInstallation { + private final OnlineShareWidget widget; + private SwingWorker worker; + + public ComponentInstallation(OnlineShareWidget widget) { + this.widget = widget; + } + + @Override + public void install() { + if (!checkLoginStatus()) { + notifyFailed(); + return; + } + notifyProgress(0.0D); + worker = createWorker(); + worker.execute(); + } + + private SwingWorker createWorker() { + return new SwingWorker() { + + @Override + protected Boolean doInBackground() { + + String tempFilePath = fetchRemoteReuFile2TempDir(); + if (StringUtils.isEmpty(tempFilePath)) { + return false; + } + if (isCancelled()) { + return false; + } + ShareComponentUtils.checkReadMe(); + if (isCancelled()) { + return false; + } + installTempReuFile(tempFilePath); + StableUtils.deleteFile(new File(tempFilePath)); + return true; + } + + @Override + protected void done() { + boolean result = false; + try { + result = get(); + } catch (InterruptedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); + } catch (ExecutionException | CancellationException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + notifyProgress(0.0D); + if (result) { + notifySuccess(); + } else { + notifyFailed(); + } + } + }; + } + + private boolean checkLoginStatus() { + String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); + if (StringUtils.isEmpty(userName)) { + DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL); + return false; + } + return true; + } + + private String createLocalReuFilename() { + String filename = widget.getFileLoca(); + if (StringUtils.isEmpty(filename) || !filename.endsWith(".reu")) { + filename = widget.getName() + "." + widget.getUuid() + ".reu"; + } + return filename; + } + + private String fetchRemoteReuFile2TempDir() { + try { + String filename = createLocalReuFilename(); + return DownloadUtils.download(widget.getId(), filename, new Process() { + @Override + public void process(Double value) { + notifyProgress(value); + } + }); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return null; + } + } + + private void installTempReuFile(String tempFilePath) { + File file = new File(tempFilePath); + try { + Group targetGroup = getTargetGroup(); + if (file.exists() && targetGroup.installUniqueIdModule(file)) { + ShareUtils.recordInstallTime(file.getName(), System.currentTimeMillis()); + ComponentCollector.getInstance().collectCmpDownLoad(widget.getUuid()); + } + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + private Group getTargetGroup() { + return DefaultShareGroupManager.getInstance().getGroup(DefaultShareGroup.GROUP_NAME); + } + + @Override + public void cancel() { + if (worker != null) { + worker.cancel(false); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java new file mode 100644 index 000000000..39107a5a1 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/ComponentsPackageInstallation.java @@ -0,0 +1,180 @@ +package com.fr.design.mainframe.share.ui.online.installation; + +import com.fr.design.extra.Process; +import com.fr.design.mainframe.share.ui.base.ImitationProgress; +import com.fr.design.mainframe.share.util.DownloadUtils; +import com.fr.design.mainframe.share.util.InstallUtils; +import com.fr.design.mainframe.share.util.ShareComponentUtils; +import com.fr.form.share.Group; +import com.fr.form.share.bean.OnlineShareWidget; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import org.jetbrains.annotations.Nullable; + +import javax.swing.SwingWorker; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/5 + */ +public class ComponentsPackageInstallation extends AsyncInstallation { + private final OnlineShareWidget packageWidget; + private final int childrenCount; + private ImitationThread imitationThread; + private DownLoadSwingWorker worker; + + public ComponentsPackageInstallation(OnlineShareWidget packageWidget, int childrenCount) { + this.packageWidget = packageWidget; + this.childrenCount = childrenCount; + } + + @Override + public void install() { + + final Process downloadProcess = new Process() { + @Override + public void process(Double value) { + notifyProgress(0.8 * value); + } + }; + final Process installProcess = new Process() { + + @Override + public void process(Double value) { + notifyProgress(0.8 + 0.2 * value); + } + }; + + downloadProcess.process(0.0D); + + //假进度线程 + final ImitationProgress imitationProgress = new ImitationProgress(downloadProcess, childrenCount); + imitationThread = new ImitationThread(imitationProgress); + imitationThread.setName("Component-ImitationProcessThread"); + + //下载线程 + worker = new DownLoadSwingWorker(installProcess, packageWidget); + + imitationThread.start(); + worker.execute(); + } + + @Override + public void cancel() { + if (imitationThread != null) { + imitationThread.interrupt(); + } + if (worker != null) { + worker.cancel(false); + } + } + + /** + * 假进度线程 + */ + private static class ImitationThread extends Thread { + + private final ImitationProgress imitationProgress; + + public ImitationThread(ImitationProgress progress) { + imitationProgress = progress; + } + + @Override + public void run() { + imitationProgress.start(); + } + + public void complete() { + imitationProgress.completed(); + this.interrupt(); + } + + public void stopThread() { + imitationProgress.stop(); + this.interrupt(); + } + } + + private class DownLoadSwingWorker extends SwingWorker { + final Process installProcess; + final OnlineShareWidget onlineShareWidget; + + public DownLoadSwingWorker(Process installProcess, OnlineShareWidget onlineShareWidget) { + this.installProcess = installProcess; + this.onlineShareWidget = onlineShareWidget; + } + + @Override + @Nullable + protected Group doInBackground() { + final String filePath; + List failureList = new ArrayList<>(); + try { + filePath = DownloadUtils.downloadPackage(onlineShareWidget.getId(), onlineShareWidget.getName(), DownLoadSwingWorker.this::isCancelled); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + imitationThread.stopThread(); + return null; + } + if (this.isCancelled()) { + imitationThread.stopThread(); + StableUtils.deleteFile(new File(filePath)); + return null; + } + + //等待假进度线程结束 + imitationThread.complete(); + try { + imitationThread.join(); + } catch (InterruptedException ignore) { + } + + //再判断一次 + if (this.isCancelled()) { + StableUtils.deleteFile(new File(filePath)); + return null; + } + ShareComponentUtils.checkReadMe(); + //安装 + File file = new File(filePath); + installProcess.process(0.0D); + InstallUtils.InstallResult result = null; + try { + if (file.exists()) { + result = InstallUtils.installReusFile(file, System.currentTimeMillis(), failureList, installProcess); + } + } finally { + //删掉下载组件的目录 + StableUtils.deleteFile(file); + } + return result == null ? null : result.group; + } + + @Override + protected void done() { + Group group = null; + try { + group = get(); + } catch (InterruptedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); + } catch (ExecutionException | CancellationException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + notifyProgress(0.0D); + if (group != null) { + notifySuccess(); + } else { + notifyFailed(); + } + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/Installation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/Installation.java new file mode 100644 index 000000000..3fc80a8bf --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/Installation.java @@ -0,0 +1,10 @@ +package com.fr.design.mainframe.share.ui.online.installation; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/5 + */ +public interface Installation { + void install(); +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java new file mode 100644 index 000000000..4de568db7 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/installation/TemplateThemeInstallation.java @@ -0,0 +1,210 @@ +package com.fr.design.mainframe.share.ui.online.installation; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.DesignerEnvManager; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.i18n.Toolkit; +import com.fr.design.login.DesignerLoginHelper; +import com.fr.design.login.DesignerLoginSource; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; +import com.fr.design.mainframe.share.util.DownloadUtils; +import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.transaction.CallBackAdaptor; +import com.fr.workspace.WorkContext; + +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.HashMap; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/5 + */ +public class TemplateThemeInstallation extends AsyncInstallation { + private final Window parentWindow; + private final String themePath; + private SwingWorker worker; + + public TemplateThemeInstallation(Window parentWindow, String themePath) { + this.parentWindow = parentWindow; + this.themePath = themePath; + } + + public TemplateThemeInstallation(String themePath) { + this(DesignerContext.getDesignerFrame(), themePath); + } + + @Override + public void install() { + fetchTheme(); + } + + private void fetchTheme() { + if (!checkAuthority()) { + onThemeFetched(null); + return; + } + + worker = new SwingWorker() { + + @Override + protected FormTheme doInBackground() { + return DownloadUtils.downloadThemeFile(themePath); + } + + @Override + protected void done() { + FormTheme theme = null; + try { + theme = get(); + } catch (InterruptedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); + } catch (ExecutionException | CancellationException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + onThemeFetched(theme); + } + }; + worker.execute(); + } + + private boolean checkAuthority() { + if (!WorkContext.getCurrent().isRoot()) { + FineJOptionPane.showMessageDialog(parentWindow, + Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_No_Authority_Tip_Message"), + Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_No_Authority_Tip_Title"), + JOptionPane.WARNING_MESSAGE); + return false; + } + + String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); + if (StringUtils.isEmpty(userName)) { + DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL, new HashMap<>(), parentWindow); + return false; + } + + return true; + } + + public void onThemeFetched(FormTheme theme) { + if (theme == null) { + notifyFailed(); + return; + } + saveTheme(theme); + } + + private FormTheme ensureThemeHasUniqueName(FormTheme theme, String expectedName) { + if (!FormThemeConfig.getInstance().contains(expectedName)) { + theme.setName(expectedName); + return theme; + } else { + String newName = (String) FineJOptionPane.showInputDialog( + parentWindow, + Toolkit.i18nText("Fine-Design_Share_Rename_Suitable_Theme_Tip"), + Toolkit.i18nText("Fine-Design_Basic_Rename"), + FineJOptionPane.QUESTION_MESSAGE, null, null, + expectedName); + + return StringUtils.isEmpty(newName) ? null : ensureThemeHasUniqueName(theme, newName); + } + } + + private void saveTheme(FormTheme theme) { + final FormTheme uniqueNamedTheme = ensureThemeHasUniqueName(theme, theme.getName()); + if (uniqueNamedTheme != null) { + FormThemeConfig.getInstance().addTheme(theme, true, new CallBackAdaptor() { + @Override + public void afterCommit() { + super.afterCommit(); + onThemeSaved(uniqueNamedTheme); + } + + @Override + public void afterRollback() { + super.afterRollback(); + onThemeSaved(null); + } + }); + } else { + onThemeSaved(null); + } + } + + public void onThemeSaved(FormTheme theme) { + if (theme == null) { + notifyFailed(); + return; + } + + JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (currentTemplate.getUsingTemplateThemeConfig() instanceof FormThemeConfig) { + TemplateThemeUsingDialog dialog = new TemplateThemeUsingDialog(parentWindow); + dialog.addWindowListener(new UsingDialogAdapter(theme, currentTemplate)); + dialog.setVisible(true); + } else { + FineJOptionPane.showConfirmDialog( + MiniComponentShopDialog.getInstance().getWindow(), + Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_Success_Tip"), + "", + FineJOptionPane.YES_NO_OPTION + ); + } + notifySuccess(); + } + + public void applyTheme(JTemplate template, final String name, Window dialog) { + TemplateThemeConfig config = template.getUsingTemplateThemeConfig(); + TemplateTheme theme = config.cachedFetch(name); + template.setTemplateTheme(theme); + dialog.repaint(); + } + + @Override + public void cancel() { + if (worker != null) { + worker.cancel(true); + } + } + + private class UsingDialogAdapter extends WindowAdapter { + private final FormTheme theme; + private final JTemplate currentFormTemplate; + + public UsingDialogAdapter(FormTheme theme, JTemplate currentFormTemplate) { + this.theme = theme; + this.currentFormTemplate = currentFormTemplate; + } + + @Override + public void windowOpened(WindowEvent e) { + super.windowOpened(e); + Window window = e.getWindow(); + int returnVal = FineJOptionPane.showConfirmDialog( + window, + Toolkit.i18nText("Fine-Design_Share_Apply_Suitable_Theme_Tip"), + Toolkit.i18nText("Fine-Design_Basic_Confirm"), + FineJOptionPane.OK_CANCEL_OPTION); + if (returnVal == JOptionPane.YES_OPTION) { + applyTheme(currentFormTemplate, theme.getName(), window); + } + window.removeWindowListener(this); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java new file mode 100644 index 000000000..be2d72466 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java @@ -0,0 +1,139 @@ +package com.fr.design.mainframe.share.ui.online.mini; + +import com.fr.base.ScreenResolution; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.stable.Constants; +import com.fr.stable.unit.FU; +import com.fr.stable.unit.UNIT; + +import javax.swing.JFrame; +import java.awt.Container; +import java.awt.Window; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.HashSet; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/4 + */ +public class MiniComponentShopDialog { + private static class HOLDER { + private static final MiniComponentShopDialog singleton = new MiniComponentShopDialog(); + } + public static MiniComponentShopDialog getInstance() { + return MiniComponentShopDialog.HOLDER.singleton; + } + + private final Set windowListeners = new HashSet<>(); + private JFrame frame; + + private JFrame createFrame() { + final JFrame frame = new JFrame(); + final MiniComponentShopPane shopPane = new MiniComponentShopPane(); + + final UNIT width = FU.getInstance(900 * Constants.FU_PER_OLD_PIX); + final UNIT height = FU.getInstance(600 * Constants.FU_PER_OLD_PIX); + int resolution = ScreenResolution.getScreenResolution(); + frame.setSize(width.toPixI(resolution), height.toPixI(resolution)); + frame.setTitle(Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Window_Title")); + frame.add(shopPane); + frame.setResizable(false); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + frame.addWindowListener(new WindowListener() { + @Override + public void windowOpened(WindowEvent e) { + for (WindowListener listener: windowListeners) { + listener.windowOpened(e); + } + } + + @Override + public void windowClosing(WindowEvent e) { + for (WindowListener listener : windowListeners) { + listener.windowClosing(e); + } + if (MiniShopDisposingChecker.check(frame.getContentPane())) { + e.getWindow().dispose(); + } + } + + @Override + public void windowClosed(WindowEvent e) { + for (WindowListener listener: windowListeners) { + listener.windowClosed(e); + } + shopPane.reload(); + } + + @Override + public void windowIconified(WindowEvent e) { + for (WindowListener listener: windowListeners) { + listener.windowIconified(e); + } + } + + @Override + public void windowDeiconified(WindowEvent e) { + for (WindowListener listener: windowListeners) { + listener.windowDeiconified(e); + } + } + + @Override + public void windowActivated(WindowEvent e) { + for (WindowListener listener: windowListeners) { + listener.windowActivated(e); + } + } + + @Override + public void windowDeactivated(WindowEvent e) { + for (WindowListener listener: windowListeners) { + listener.windowDeactivated(e); + } + } + }); + GUICoreUtils.centerWindow(frame); + return frame; + } + + public void show() { + if (frame == null) { + frame = createFrame(); + } + if (!frame.isVisible()) { + for (WindowListener listener: windowListeners) { + listener.windowOpened(null); + } + } + frame.setVisible(true); + } + + public void showFromOnlineRepoPane() { + show(); + } + + public Container getContentPane() { + if (frame != null) { + return frame.getContentPane(); + } + return null; + } + + public Window getWindow() { + return frame; + } + + public void addWindowAdapter(WindowListener windowListener) { + windowListeners.add(windowListener); + if (frame != null) { + frame.removeWindowListener(windowListener); + frame.addWindowListener(windowListener); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopPane.java new file mode 100644 index 000000000..f9d3849f7 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopPane.java @@ -0,0 +1,85 @@ +package com.fr.design.mainframe.share.ui.online.mini; + +import com.fr.design.mainframe.share.ui.online.mini.bridge.ComposedNativeBridges; +import com.fr.design.mainframe.share.util.OnlineShopUtils; +import com.fr.design.ui.ModernUIPane; +import com.fr.design.ui.compatible.ModernUIPaneFactory; +import com.fr.design.upm.event.CertificateEvent; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.teamdev.jxbrowser.browser.callback.InjectJsCallback; +import com.teamdev.jxbrowser.chromium.JSObject; +import com.teamdev.jxbrowser.chromium.events.ScriptContextAdapter; +import com.teamdev.jxbrowser.chromium.events.ScriptContextEvent; +import com.teamdev.jxbrowser.js.JsObject; +import org.jetbrains.annotations.Nullable; + +import javax.swing.JPanel; +import java.awt.BorderLayout; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/12/20 + */ +public class MiniComponentShopPane extends JPanel { + private final ModernUIPane modernUIPane; + private final Listener loginListener; + private final Listener logoutListener; + + public MiniComponentShopPane() { + setLayout(new BorderLayout()); + modernUIPane = ModernUIPaneFactory.modernUIPaneBuilder() + .withURL(OnlineShopUtils.getWebMiniShopPath()) + .prepareForV6(new ScriptContextAdapter() { + @Override + public void onScriptContextCreated(ScriptContextEvent event) { + super.onScriptContextCreated(event); + JSObject window = event.getBrowser().executeJavaScriptAndReturnValue("window").asObject(); + window.setProperty("ShopHelper", new ComposedNativeBridges(window)); + } + }) + .prepareForV7(new InjectJsCallback() { + @Nullable + @Override + public Response on(Params params) { + // 7.x + JsObject window = params.frame().executeJavaScript("window"); + if (window != null) { + window.putProperty("ShopHelper", new ComposedNativeBridges(window)); + } + return InjectJsCallback.Response.proceed(); + } + }) + .build(); + + add(modernUIPane, BorderLayout.CENTER); + + loginListener = new Listener() { + @Override + public void on(Event event, String param) { + reload(); + } + }; + logoutListener = new Listener() { + @Override + public void on(Event event, String param) { + reload(); + } + }; + + EventDispatcher.listen(CertificateEvent.LOGIN, loginListener); + EventDispatcher.listen(CertificateEvent.LOGOUT, logoutListener); + } + + public void dispose() { + modernUIPane.disposeBrowser(); + EventDispatcher.stopListen(loginListener); + EventDispatcher.stopListen(logoutListener); + } + + public void reload() { + modernUIPane.redirect(OnlineShopUtils.getWebMiniShopPath()); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/ComposedNativeBridges.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/ComposedNativeBridges.java new file mode 100644 index 000000000..3a09774c5 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/ComposedNativeBridges.java @@ -0,0 +1,29 @@ +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.teamdev.jxbrowser.chromium.JSAccessible; +import com.teamdev.jxbrowser.js.JsAccessible; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/12/20 + */ +public class ComposedNativeBridges { + @JSAccessible + @JsAccessible + public final Object Browser; + + @JSAccessible + @JsAccessible + public final Object Auth; + + @JSAccessible + @JsAccessible + public final Object Product; + + public ComposedNativeBridges(Object window) { + this.Browser = new NativeBrowserBridge(); + this.Auth = new NativeAuthBridge(); + this.Product = new NativeProductBridge(window); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeAuthBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeAuthBridge.java new file mode 100644 index 000000000..42f3a6c65 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeAuthBridge.java @@ -0,0 +1,37 @@ +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.bridge.exec.JSBridge; +import com.fr.design.login.DesignerLoginHelper; +import com.fr.design.login.DesignerLoginSource; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; +import com.teamdev.jxbrowser.chromium.JSAccessible; +import com.teamdev.jxbrowser.js.JsAccessible; + +import java.awt.Window; +import java.util.HashMap; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/12/20 + */ +public class NativeAuthBridge { + @JSAccessible + @JsAccessible + @JSBridge + public String getLoginUsername() { + return DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); + } + + @JSAccessible + @JsAccessible + @JSBridge + public void goLogin() { + Window parentWindow = MiniComponentShopDialog.getInstance().getWindow(); + if (parentWindow != null) { + parentWindow.toFront(); + DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL, new HashMap<>(), parentWindow); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeBrowserBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeBrowserBridge.java new file mode 100644 index 000000000..ee77a8b95 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeBrowserBridge.java @@ -0,0 +1,26 @@ +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.fr.design.bridge.exec.JSBridge; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; +import com.teamdev.jxbrowser.chromium.JSAccessible; +import com.teamdev.jxbrowser.js.JsAccessible; + +import java.awt.Window; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/12/20 + */ +public class NativeBrowserBridge { + + @JSAccessible + @JsAccessible + @JSBridge + public void dispose() { + Window nativeWindow = MiniComponentShopDialog.getInstance().getWindow(); + if (nativeWindow != null) { + nativeWindow.dispose(); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java new file mode 100644 index 000000000..e6a4f720c --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java @@ -0,0 +1,512 @@ + +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.fr.design.bridge.exec.JSBridge; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.EastRegionContainerPane; +import com.fr.design.mainframe.FormWidgetDetailPane; +import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; +import com.fr.design.mainframe.share.ui.online.installation.AsyncInstallation; +import com.fr.design.mainframe.share.ui.online.installation.ComponentInstallation; +import com.fr.design.mainframe.share.ui.online.installation.ComponentsPackageInstallation; +import com.fr.design.mainframe.share.ui.online.installation.TemplateThemeInstallation; +import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; +import com.fr.design.mainframe.share.util.OnlineShopUtils; +import com.fr.form.share.Group; +import com.fr.form.share.SharableWidgetProvider; +import com.fr.form.share.bean.OnlineShareWidget; +import com.fr.form.share.group.DefaultShareGroupManager; +import com.fr.json.JSONObject; +import com.fr.stable.StringUtils; +import com.teamdev.jxbrowser.chromium.JSAccessible; +import com.teamdev.jxbrowser.js.JsAccessible; + +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import java.awt.Window; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/12/20 + */ +public class NativeProductBridge { + private static final Map createdComponentInstallationTasks = new HashMap<>(); + private static final Map createdComponentsPackageInstallationTasks = new HashMap<>(); + private static final Map createdTemplateThemeInstallationTasks = new HashMap<>(); + + private static final Map startedComponentInstallationTasks = new HashMap<>(); + private static final Map startedComponentsPackageInstallationTasks = new HashMap<>(); + private static final Map startedTemplateThemeInstallationTasks = new HashMap<>(); + + private final Object window; + + private final Map> componentDownloadTaskStartListeners = new HashMap<>(); + private final Map> componentsPackageDownloadTaskStartListeners = new HashMap<>(); + private final Map> themeDownloadTaskStartListeners = new HashMap<>(); + + public NativeProductBridge(Object window) { + this.window = window; + } + + @JSAccessible + @JsAccessible + @JSBridge + public boolean isProductDownloaded(String uuid) { + for (Group group : DefaultShareGroupManager.getInstance().getAllGroup()) { + SharableWidgetProvider[] widgetProviderList = group.getAllBindInfoList(); + for (SharableWidgetProvider widget: widgetProviderList) { + if (StringUtils.equals(uuid, widget.getId())) { + return true; + } + } + } + return false; + } + + @JSAccessible + @JsAccessible + @JSBridge + public void addProductDownloadTaskStartListener(String json, Object function) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + String uuid = widget.getUuid(); + boolean isPackage = widget.isWidgetPackage(); + + Map> downloadTaskGetters = + isPackage ? componentsPackageDownloadTaskStartListeners : componentDownloadTaskStartListeners; + Set startListeners = downloadTaskGetters.get(widget.getUuid()); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.add(function); + downloadTaskGetters.put(widget.getUuid(), startListeners); + + + } + + @JSAccessible + @JsAccessible + @JSBridge + public void removeProductDownloadTaskStartListener(String json, Object function) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + String uuid = widget.getUuid(); + boolean isPackage = widget.isWidgetPackage(); + + Map> downloadTaskGetters = isPackage ? componentsPackageDownloadTaskStartListeners : componentDownloadTaskStartListeners; + + Set startListeners = downloadTaskGetters.get(uuid); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.remove(function); + downloadTaskGetters.put(uuid, startListeners); + } + + @JSAccessible + @JsAccessible + @JSBridge + public Object getExecutingProductDownloadTask(String json) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + String uuid = widget.getUuid(); + boolean isPackage = widget.isWidgetPackage(); + + Map executingDownloadTask = + isPackage ? startedComponentsPackageInstallationTasks : startedComponentInstallationTasks; + NativeTaskBridge task = executingDownloadTask.get(uuid); + if (task != null) { + task.checkJSEnvChange(this.window); + } + return task; + } + + @JSAccessible + @JsAccessible + @JSBridge + public Object createProductDownloadTask(String json) { + JSONObject object = new JSONObject(json); + OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(object); + int childrenCount = object.optInt("pkgsize", 0); + if (childrenCount > 0) { + if (createdComponentsPackageInstallationTasks.containsKey(widget.getUuid())) { + return createdComponentsPackageInstallationTasks.get(widget.getUuid()); + } else { + ComponentsPackageInstallationTask task = new ComponentsPackageInstallationTask(this, window, widget, childrenCount); + createdComponentsPackageInstallationTasks.put(widget.getUuid(), task); + return task; + } + + } else { + if (createdComponentInstallationTasks.containsKey(widget.getUuid())) { + return createdComponentInstallationTasks.get(widget.getUuid()); + } else { + ComponentInstallationTask task = new ComponentInstallationTask(this, window, widget); + createdComponentInstallationTasks.put(widget.getUuid(), task); + return task; + } + } + } + + @JSAccessible + @JsAccessible + @JSBridge + public void addThemeDownloadTaskStartListener(String themePath, Object function) { + Set startListeners = themeDownloadTaskStartListeners.get(themePath); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.add(function); + themeDownloadTaskStartListeners.put(themePath, startListeners); + } + + @JSAccessible + @JsAccessible + @JSBridge + public void removeThemeDownloadTaskStartListener(String themePath, Object function) { + Set startListeners = themeDownloadTaskStartListeners.get(themePath); + if (startListeners == null) { + startListeners = new HashSet<>(); + } + startListeners.remove(function); + themeDownloadTaskStartListeners.put(themePath, startListeners); + } + + @JSAccessible + @JsAccessible + @JSBridge + public Object getExecutingThemeDownloadTask(String themePath) { + NativeTaskBridge task = startedTemplateThemeInstallationTasks.get(themePath); + if (task != null) { + task.checkJSEnvChange(this.window); + } + return task; + } + + @JSAccessible + @JsAccessible + @JSBridge + public Object createTemplateThemeDownloadTask(String themePath) { + if (createdTemplateThemeInstallationTasks.containsKey(themePath)) { + return createdTemplateThemeInstallationTasks.get(themePath); + } else { + TemplateThemeInstallationTask task = new TemplateThemeInstallationTask(this, window, themePath); + createdTemplateThemeInstallationTasks.put(themePath, task); + return task; + } + } + + public static class ComponentInstallationTask extends NativeTaskBridge { + private final NativeProductBridge env; + private final OnlineShareWidget widget; + private final ComponentInstallation action; + + public ComponentInstallationTask(NativeProductBridge env, Object window, OnlineShareWidget widget) { + super(window); + this.env = env; + this.widget = widget; + action = new ComponentInstallation(widget); + action.setActionListener(new AsyncInstallation.AsyncActionListener() { + @Override + public void onProgress(double value) { + fireProgressEvent(Double.toString(value)); + } + + @Override + public void onSuccess() { + fireSuccessEvent(null); + LocalWidgetRepoPane.getInstance().refreshPane(); + if (!DesignerContext.getDesignerFrame().isActive()) { + FormWidgetDetailPane.getInstance().switch2Local(); + EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB); + } + } + + @Override + public void onFailed() { + fireFailureEvent(null); + } + }); + } + + @JSAccessible + @JsAccessible + @JSBridge + @Override + public void execute() { + if (isExecuting) { + return; + } + super.execute(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + boolean allowedDownload = true; + if (!widget.isCompatibleWithCurrentEnv()) { + int result = FineJOptionPane.showConfirmDialog( + MiniComponentShopDialog.getInstance().getContentPane(), + Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Component_Tip"), + "", + FineJOptionPane.YES_NO_OPTION + ); + allowedDownload = result == JOptionPane.YES_OPTION; + } + if (allowedDownload) { + fireStartEvent(null); + action.install(); + } else { + fireFailureEvent(null); + } + } + }); + } + + @JSAccessible + @JsAccessible + @JSBridge + @Override + public void cancel() { + super.cancel(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + action.cancel(); + } + }); + } + + @Override + protected void fireStartEvent(String event) { + startedComponentInstallationTasks.put(widget.getUuid(), this); + Set startListeners = env.componentDownloadTaskStartListeners.get(widget.getUuid()); + SafeJSFunctionInvoker.invoke(startListeners, env.window); + super.fireStartEvent(event); + } + + @Override + protected void fireFailureEvent(String event) { + startedComponentInstallationTasks.remove(widget.getUuid()); + createdComponentInstallationTasks.remove(widget.getUuid()); + super.fireFailureEvent(event); + } + + @Override + protected void fireSuccessEvent(String event) { + startedComponentInstallationTasks.remove(widget.getUuid()); + createdComponentInstallationTasks.remove(widget.getUuid()); + super.fireSuccessEvent(event); + } + } + + public static class ComponentsPackageInstallationTask extends NativeTaskBridge { + + private final NativeProductBridge env; + private final ComponentsPackageInstallation action; + private final OnlineShareWidget widget; + private final int childrenCount; + + public ComponentsPackageInstallationTask(NativeProductBridge env, Object window, OnlineShareWidget widget, int childrenCount) { + super(window); + this.env = env; + this.widget = widget; + this.childrenCount = childrenCount; + action = new ComponentsPackageInstallation(widget, childrenCount); + action.setActionListener(new AsyncInstallation.AsyncActionListener() { + @Override + public void onProgress(double value) { + fireProgressEvent(Double.toString(value)); + } + + @Override + public void onSuccess() { + fireSuccessEvent(null); + LocalWidgetRepoPane.getInstance().refreshPane(); + if (!DesignerContext.getDesignerFrame().isActive()) { + FormWidgetDetailPane.getInstance().switch2Local(); + EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB); + } + } + + @Override + public void onFailed() { + fireFailureEvent(null); + } + }); + } + + @JSAccessible + @JsAccessible + @JSBridge + @Override + public void execute() { + if (isExecuting) { + return; + } + super.execute(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + boolean allowedDownload; + OnlineShareWidget[] childrenWidgets = OnlineShopUtils.getPackageWidgets(widget, false); + boolean isCompatibleWithCurrentEnv = true; + for (OnlineShareWidget children: childrenWidgets) { + if (!children.isCompatibleWithCurrentEnv()) { + isCompatibleWithCurrentEnv = false; + break; + } + } + int result; + if (!isCompatibleWithCurrentEnv) { + result = FineJOptionPane.showConfirmDialog( + MiniComponentShopDialog.getInstance().getContentPane(), + Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Components_Package_Tip", childrenCount), + "", + FineJOptionPane.YES_NO_OPTION + ); + } else { + result = FineJOptionPane.showConfirmDialog( + MiniComponentShopDialog.getInstance().getContentPane(), + Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Components_Package_Tip", childrenCount), + "", + FineJOptionPane.YES_NO_OPTION + ); + } + allowedDownload = result == JOptionPane.YES_OPTION; + if (allowedDownload) { + fireStartEvent(null); + action.install(); + } else { + fireFailureEvent(null); + } + } + }); + } + + @JSAccessible + @JsAccessible + @JSBridge + @Override + public void cancel() { + super.cancel(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + action.cancel(); + } + }); + } + + @Override + protected void fireStartEvent(String event) { + startedComponentsPackageInstallationTasks.put(widget.getUuid(), this); + super.fireStartEvent(event); + + Set startListeners = env.componentsPackageDownloadTaskStartListeners.get(widget.getUuid()); + SafeJSFunctionInvoker.invoke(startListeners, env.window); + } + + @Override + protected void fireFailureEvent(String event) { + startedComponentsPackageInstallationTasks.remove(widget.getUuid()); + createdComponentsPackageInstallationTasks.remove(widget.getUuid()); + super.fireFailureEvent(event); + } + + @Override + protected void fireSuccessEvent(String event) { + startedComponentsPackageInstallationTasks.remove(widget.getUuid()); + createdComponentsPackageInstallationTasks.remove(widget.getUuid()); + super.fireSuccessEvent(event); + } + } + + public static class TemplateThemeInstallationTask extends NativeTaskBridge { + private final NativeProductBridge env; + private final String themePath; + private final TemplateThemeInstallation action; + public TemplateThemeInstallationTask(NativeProductBridge env, Object window, String themePath) { + super(window); + this.env = env; + this.themePath = themePath; + Window miniShopWindow = MiniComponentShopDialog.getInstance().getWindow(); + action = new TemplateThemeInstallation(miniShopWindow, themePath); + action.setActionListener(new AsyncInstallation.AsyncActionListener() { + @Override + public void onProgress(double value) { + fireProgressEvent(Double.toString(value)); + } + + @Override + public void onSuccess() { + fireSuccessEvent(null); + } + + @Override + public void onFailed() { + fireFailureEvent(null); + } + }); + } + + @JSAccessible + @JsAccessible + @JSBridge + @Override + public void execute() { + if (isExecuting) { + return; + } + super.execute(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + fireStartEvent(null); + action.install(); + } + }); + } + + @JSAccessible + @JsAccessible + @JSBridge + @Override + public void cancel() { + super.cancel(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + action.cancel(); + } + }); + } + + @Override + protected void fireStartEvent(String event) { + startedTemplateThemeInstallationTasks.put(themePath, this); + Set startListeners = env.themeDownloadTaskStartListeners.get(themePath); + SafeJSFunctionInvoker.invoke(startListeners, env.window); + super.fireStartEvent(event); + } + + @Override + protected void fireFailureEvent(String event) { + startedTemplateThemeInstallationTasks.remove(themePath); + createdTemplateThemeInstallationTasks.remove(themePath); + super.fireFailureEvent(event); + } + + @Override + protected void fireSuccessEvent(String event) { + startedTemplateThemeInstallationTasks.remove(themePath); + createdTemplateThemeInstallationTasks.remove(themePath); + super.fireSuccessEvent(event); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java new file mode 100644 index 000000000..2929a3540 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeTaskBridge.java @@ -0,0 +1,84 @@ +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.fr.design.bridge.exec.JSBridge; +import com.fr.design.mainframe.share.mini.MiniShopNativeTask; +import com.fr.design.mainframe.share.mini.MiniShopNativeTaskManager; +import com.teamdev.jxbrowser.chromium.JSAccessible; +import com.teamdev.jxbrowser.js.JsAccessible; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/12/20 + */ +public class NativeTaskBridge implements MiniShopNativeTask { + + private Object window; + protected final Set statusCbs = new HashSet<>(); + protected boolean isExecuting = false; + + public NativeTaskBridge(Object window) { + this.window = window; + } + + public void checkJSEnvChange(Object window) { + if (this.window != window) { + this.window = window; + this.statusCbs.clear(); + } + } + + @JSBridge + @JSAccessible + @JsAccessible + public void addStatusCallback(Object cb) { + this.statusCbs.add(cb); + } + + @JSBridge + @JSAccessible + @JsAccessible + public void removeStatusCallback(Object cb) { + this.statusCbs.remove(cb); + } + + @JSBridge + @JSAccessible + @JsAccessible + @Override + public void execute() { + if (!isExecuting) { + isExecuting = true; + } + } + + @JSBridge + @JSAccessible + @JsAccessible + @Override + public void cancel() { + MiniShopNativeTaskManager.getInstance().removeCompletedTask(this); + fireFailureEvent(null); + } + + protected void fireStartEvent(String event) { + MiniShopNativeTaskManager.getInstance().addStartedTask(this); + SafeJSFunctionInvoker.invoke(statusCbs, window, "START", event); + } + protected void fireProgressEvent(String event) { + SafeJSFunctionInvoker.invoke(statusCbs, window, "PROGRESS", event); + } + protected void fireSuccessEvent(String event) { + isExecuting = false; + MiniShopNativeTaskManager.getInstance().removeCompletedTask(this); + SafeJSFunctionInvoker.invoke(statusCbs, window, "SUCCESS", event); + } + protected void fireFailureEvent(String event) { + isExecuting = false; + MiniShopNativeTaskManager.getInstance().removeCompletedTask(this); + SafeJSFunctionInvoker.invoke(statusCbs, window, "FAILURE", event); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java new file mode 100644 index 000000000..e5bf71da8 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/SafeJSFunctionInvoker.java @@ -0,0 +1,44 @@ +package com.fr.design.mainframe.share.ui.online.mini.bridge; + +import com.teamdev.jxbrowser.chromium.JSFunction; +import com.teamdev.jxbrowser.chromium.JSObject; +import com.teamdev.jxbrowser.js.JsFunction; +import com.teamdev.jxbrowser.js.JsObject; + +import java.util.Collection; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/17 + */ +public class SafeJSFunctionInvoker { + + public static void invoke(Collection functions, Object instance, Object... args) { + if (functions != null) { + for (Object function: functions) { + invoke(function, instance, args); + } + } + } + + public static void invoke(Object function, Object instance, Object... args) { + if (function != null) { + if (function instanceof JSFunction && instance instanceof JSObject) { + invokeV6((JSFunction) function, (JSObject) instance, args); + } else if (function instanceof JsFunction && instance instanceof JsObject) { + invokeV7((JsFunction) function, (JsObject) instance, args); + } + } + } + + private static void invokeV6(JSFunction function, JSObject instance, Object... args) { + if (!function.getContext().isDisposed()) { + function.invoke(instance, args); + } + } + + private static void invokeV7(JsFunction function, JsObject instance, Object... args) { + function.invoke(instance, args); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java index 169759362..d133cd058 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java @@ -48,6 +48,7 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane { private JPanel detailPane; private String currentPackageId; private OnlineWidgetSelectPane onlineWidgetSelectPane; + private OnlineDownloadPackagePane onlineDownloadPackagePane; private UILabel downloadLabel; private final Map cachePanelMap = new HashMap<>(); @@ -109,15 +110,15 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane { private void downLoadPackage() { downloadLabel.setVisible(false); detailPane.removeAll(); - OnlineDownloadPackagePane widgetSelectPane = new OnlineDownloadPackagePane(this, onlineWidgetSelectPane.getSharableWidgetProviders(), 50); - detailPane.add(widgetSelectPane, BorderLayout.CENTER); + onlineDownloadPackagePane = new OnlineDownloadPackagePane(this, onlineWidgetSelectPane.getSharableWidgetProviders(), 50); + detailPane.add(onlineDownloadPackagePane, BorderLayout.CENTER); cardLayout.show(centerPane, WIDGET_DETAIL); - cachePanelMap.put(currentPackageId, widgetSelectPane); + cachePanelMap.put(currentPackageId, onlineDownloadPackagePane); for (OnlineShareWidget onlineShareWidget : getSharableWidgetProviders()) { if (StringUtils.equals(onlineShareWidget.getId(), currentPackageId)) { - widgetSelectPane.downloadWidget(onlineShareWidget); + onlineDownloadPackagePane.downloadWidget(onlineShareWidget); break; } } @@ -193,4 +194,10 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane { protected FilterPane createFilterPane() { return FilterPane.createOnlinePackageFilterPane(); } + + public void refreshShowPaneUI() { + if (onlineDownloadPackagePane != null && onlineDownloadPackagePane.isShowing()) { + onlineDownloadPackagePane.refreshShowPaneUI(); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java index 7341d7cbb..fef0caed2 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java @@ -42,6 +42,10 @@ public class OnlineShopUtils { } + public static String getWebMiniShopPath() { + return ComponentReuseConfigManager.getInstance().getWebMiniShopUrl(); + } + public static String getReuInfoPath() { return ComponentReuseConfigManager.getInstance().getMiniShopUrl(); } @@ -252,7 +256,12 @@ public class OnlineShopUtils { } public static OnlineShareWidget[] getPackageWidgets(OnlineShareWidget widgetPackage) { - String plistUrl = getPackageChildrenPath() + widgetPackage.getId() + "?designerVersion="+ ProductConstants.RELEASE_VERSION; + return getPackageWidgets(widgetPackage, true); + } + + public static OnlineShareWidget[] getPackageWidgets(OnlineShareWidget widgetPackage, boolean requireCompatible) { + String targetDesignerVersion = requireCompatible ? ProductConstants.RELEASE_VERSION : "0"; + String plistUrl = getPackageChildrenPath() + widgetPackage.getId() + "?designerVersion="+ targetDesignerVersion; OnlineShareWidget[] widgets = getOnlineShareWidgets(plistUrl); for (OnlineShareWidget widget : widgets) { widget.setParentPackage(widgetPackage); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleBodyBackgroundEditor.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleBodyBackgroundEditor.java deleted file mode 100644 index fd3430a8c..000000000 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleBodyBackgroundEditor.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.fr.design.mainframe.widget.accessibles; - -import com.fr.design.Exception.ValidationException; -import com.fr.design.designer.properties.Decoder; -import com.fr.design.designer.properties.Encoder; -import com.fr.design.dialog.BasicDialog; -import com.fr.design.dialog.DialogActionAdapter; -import com.fr.design.gui.xpane.FormPredefinedBackgroundPane; -import com.fr.design.mainframe.widget.editors.ITextComponent; -import com.fr.design.mainframe.widget.renderer.EncoderCellRenderer; -import com.fr.form.ui.NameComponentBackground; - -import javax.swing.SwingUtilities; -import java.awt.Dimension; - -/** - * Created by kerry on 2020-09-02 - */ -public class AccessibleBodyBackgroundEditor extends UneditableAccessibleEditor { - private FormPredefinedBackgroundPane backgroundPane; - - public AccessibleBodyBackgroundEditor() { - super(new BackgroundStyleWrapper()); - } - - @Override - protected ITextComponent createTextField() { - return new RendererField(new BackgroundStyleRender()); - } - - @Override - protected void showEditorPane() { - if (backgroundPane == null) { - backgroundPane = new FormPredefinedBackgroundPane(); - backgroundPane.setPreferredSize(new Dimension(600, 400)); - } - BasicDialog dlg = backgroundPane.showWindow(SwingUtilities.getWindowAncestor(this)); - dlg.addDialogActionListener(new DialogActionAdapter() { - - @Override - public void doOk() { - setValue(backgroundPane.updateBean()); - fireStateChanged(); - } - }); - backgroundPane.populateBean((NameComponentBackground) getValue()); - dlg.setVisible(true); - } - - private static class BackgroundStyleWrapper implements Encoder, Decoder { - public BackgroundStyleWrapper() { - - } - - /** - * 将属性转化成字符串 - * - * @param v 属性对象 - * @return 字符串 - */ - public String encode(Object v) { - if (v == null) { - return null; - } - NameComponentBackground style = (NameComponentBackground) v; - return style.usePredefinedStyle() ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Predefined") - : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Custom"); - } - - /** - * 将字符串转化成属性 - * - * @param txt 字符串 - * @return 属性对象 - */ - public Object decode(String txt) { - return null; - } - - /** - * 符合规则 - * - * @param txt 字符串 - * @throws ValidationException 抛错 - */ - public void validate(String txt) throws ValidationException { - - } - - } - - private static class BackgroundStyleRender extends EncoderCellRenderer { - - public BackgroundStyleRender() { - super(new BackgroundStyleWrapper()); - } - - } -} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleBorderStyleEditor.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleBorderStyleEditor.java deleted file mode 100644 index f723474f0..000000000 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleBorderStyleEditor.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.fr.design.mainframe.widget.accessibles; - -import com.fr.design.Exception.ValidationException; -import com.fr.design.designer.properties.Decoder; -import com.fr.design.designer.properties.Encoder; -import com.fr.design.dialog.BasicDialog; -import com.fr.design.dialog.DialogActionAdapter; -import com.fr.design.gui.xpane.PredefinedComponentStyleSettingPane; -import com.fr.design.mainframe.widget.editors.ITextComponent; -import com.fr.design.mainframe.widget.renderer.EncoderCellRenderer; -import com.fr.form.ui.NameLayoutBorderStyle; - -import javax.swing.SwingUtilities; -import java.awt.Dimension; - -/** - * Created by kerry on 2020-09-07 - */ -public class AccessibleBorderStyleEditor extends UneditableAccessibleEditor { - private PredefinedComponentStyleSettingPane borderPane; - - public AccessibleBorderStyleEditor() { - super(new ComponentStyleWrapper()); - } - - @Override - protected ITextComponent createTextField() { - return new RendererField(new ComponentStyleRenderer()); - } - - @Override - protected void showEditorPane() { - if (borderPane == null) { - borderPane = new PredefinedComponentStyleSettingPane(); - borderPane.setPreferredSize(new Dimension(600, 400)); - } - BasicDialog dlg = borderPane.showWindow(SwingUtilities.getWindowAncestor(this)); - dlg.addDialogActionListener(new DialogActionAdapter() { - - @Override - public void doOk() { - setValue(borderPane.updateBean()); - fireStateChanged(); - } - }); - borderPane.populateBean((NameLayoutBorderStyle) getValue()); - dlg.setVisible(true); - } - - - private static class ComponentStyleWrapper implements Encoder, Decoder { - public ComponentStyleWrapper() { - - } - - /** - * 将属性转化成字符串 - * - * @param v 属性对象 - * @return 字符串 - */ - public String encode(Object v) { - if (v == null) { - return null; - } - NameLayoutBorderStyle style = (NameLayoutBorderStyle) v; - return style.usePredefinedStyle() ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Predefined") : - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Custom"); - } - - /** - * 将字符串转化成属性 - * - * @param txt 字符串 - * @return 属性对象 - */ - public Object decode(String txt) { - return null; - } - - /** - * 符合规则 - * - * @param txt 字符串 - * @throws ValidationException 抛错 - */ - public void validate(String txt) throws ValidationException { - - } - - } - - private static class ComponentStyleRenderer extends EncoderCellRenderer { - - public ComponentStyleRenderer() { - super(new ComponentStyleWrapper()); - } - - } -} diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java index 3eb947488..8f1e1c994 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java @@ -7,22 +7,28 @@ import com.fr.design.designer.IntervalConstants; import com.fr.design.designer.creator.*; import com.fr.design.fit.common.TemplateTool; import com.fr.design.fit.attrpane.PcFitExpandablePane; +import com.fr.design.gui.ilable.UIAutoChangeLineLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.style.FollowingThemePane; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.mainframe.widget.accessibles.AccessibleElementCaseToolBarEditor; import com.fr.design.widget.ui.designer.component.PaddingBoundPane; import com.fr.form.ui.ElementCaseEditor; import com.fr.form.ui.PaddingMargin; import com.fr.form.web.FormToolBarManager; import com.fr.general.ComparatorUtils; +import com.fr.report.fit.FitProvider; import com.fr.report.fit.ReportFitAttr; +import com.fr.report.fit.ReportFitConfig; import javax.swing.BorderFactory; import javax.swing.JPanel; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.util.ArrayList; import java.util.List; @@ -78,11 +84,23 @@ public class ElementEditorDefinePane extends WTitleLayoutDefinePane { - protected UIComboBox comboBox; public FRAbsoluteLayoutDefinePane(XCreator xCreator) { super(xCreator); @@ -34,40 +19,8 @@ public class FRAbsoluteLayoutDefinePane extends AbstractFRLayoutDefinePane { - private static final int ADAPT_LABEL_MAX_WIDTH = 80; private XWFitLayout xWFitLayout; private WFitLayout wFitLayout; - private UIComboBox layoutComboBox; - private UIComboBox adaptComboBox; private UISpinner componentIntervel; private PaddingBoundPane paddingBound; private FollowingThemePane themePane; @@ -125,11 +113,7 @@ public class FRFitLayoutDefinePane extends AbstractFRLayoutDefinePane 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator()) { - Component component = xCreator.getComponent(0); - component.setBounds(xCreator.getBounds()); - } - } - if (!xCreator.acceptType(XOccupiedLayout.class)){ - xwAbsoluteBodyLayout.add(xCreator); - } - - } - copyLayoutAttr(wFitLayout, xwAbsoluteBodyLayout.toData()); - xWFitLayout.setBackupParent(xwAbsoluteBodyLayout); - FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); - formDesigner.getSelectionModel().setSelectedCreators( - FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{wAbsoluteBodyLayout})); - if (xwAbsoluteBodyLayout.toData() != null) { - xwAbsoluteBodyLayout.toData().setBorderStyleFollowingTheme(wAbsoluteBodyLayout.isBorderStyleFollowingTheme()); - xwAbsoluteBodyLayout.toData().setBorderStyle(wAbsoluteBodyLayout.getBorderStyle()); - } - xwAbsoluteBodyLayout.refreshStylePreviewEffect(); - if (xWFitLayout.toData() != null) { - xWFitLayout.toData().resetStyle(); - } - xWFitLayout.refreshStylePreviewEffect(); - formDesigner.switchBodyLayout(xwAbsoluteBodyLayout); - return layout; - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - - } - int intervelValue = (int) componentIntervel.getValue(); if (xWFitLayout.canAddInterval(intervelValue)) { // 设置完间隔后,要同步处理界面组件,容器刷新后显示出对应效果 @@ -309,14 +218,6 @@ public class FRFitLayoutDefinePane extends AbstractFRLayoutDefinePane params) { + return OperatingSystem.isMacos() && StringUtils.isEmpty(host) && StringUtils.isEmpty(path) && params.isEmpty(); + } + + @Override + public void run(String url, String host, String path, Map params) { + File file = new File(url); + if (file.exists()) { + DesignerContext.getDesignerFrame().openTemplate(new FileFILE(file)); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/deeplink/TemplateThemeInstallationDeepLink.java b/designer-realize/src/main/java/com/fr/design/deeplink/TemplateThemeInstallationDeepLink.java new file mode 100644 index 000000000..9c9d14669 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/deeplink/TemplateThemeInstallationDeepLink.java @@ -0,0 +1,53 @@ +package com.fr.design.deeplink; + +import com.fr.design.mainframe.share.ui.online.installation.Installation; +import com.fr.design.mainframe.share.ui.online.installation.TemplateThemeInstallation; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StringUtils; +import com.fr.third.springframework.web.util.UriUtils; + +import java.io.UnsupportedEncodingException; +import java.util.Map; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/1/10 + */ +public class TemplateThemeInstallationDeepLink extends DeepLink { + public TemplateThemeInstallationDeepLink() { + } + private static class Holder { + public static TemplateThemeInstallationDeepLink INSTANCE = new TemplateThemeInstallationDeepLink(); + } + public static TemplateThemeInstallationDeepLink getInstance() { + return TemplateThemeInstallationDeepLink.Holder.INSTANCE; + } + + public static final String HOST = "template_theme"; + public static final String PATH = "/add"; + public static final String FILE_KEY = "file"; + + @Override + public boolean accept(String url, String host, String path, Map params) { + return host != null && StringUtils.equals(HOST, host) + && path != null && StringUtils.equals(PATH, path) + && params != null && params.containsKey(FILE_KEY) + ; + } + + @Override + public void run(String url, String host, String path, Map params) { + String remoteFileAddress = (String) params.get(FILE_KEY); + try { + remoteFileAddress = UriUtils.decode(remoteFileAddress, EncodeConstants.ENCODING_UTF_8); + FineLoggerFactory.getLogger().info("TemplateThemeInstallationDeepLink: " + remoteFileAddress); + + Installation installation = new TemplateThemeInstallation(remoteFileAddress); + installation.install(); + } catch (UnsupportedEncodingException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java b/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java index b943778bf..32818de9f 100644 --- a/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java +++ b/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java @@ -3,6 +3,7 @@ package com.fr.design.dscolumn; import com.fr.base.BaseFormula; import com.fr.data.util.SortOrder; import com.fr.design.border.UITitledBorder; +import com.fr.design.constants.LayoutConstants; import com.fr.design.data.DesignTableDataManager; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; @@ -10,10 +11,10 @@ import com.fr.design.formula.CustomVariableResolver; import com.fr.design.formula.FormulaFactory; import com.fr.design.formula.SortFormulaPane; import com.fr.design.formula.UIFormula; -import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ispinner.UISpinner; import com.fr.design.gui.itextfield.UITextField; @@ -21,6 +22,7 @@ import com.fr.design.gui.style.TextFormatPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.sort.celldscolumn.CellDSColumnSortPane; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.report.cell.CellElement; import com.fr.report.cell.TemplateCellElement; @@ -28,19 +30,11 @@ import com.fr.report.cell.cellattr.CellExpandAttr; import com.fr.report.cell.cellattr.core.group.DSColumn; import com.fr.report.cell.cellattr.core.group.SelectCount; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; +import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Arrays; import static com.fr.report.cell.cellattr.core.group.FilterTypeEnum.BOTTOM; import static com.fr.report.cell.cellattr.core.group.FilterTypeEnum.SPECIFY; @@ -64,8 +58,19 @@ public class DSColumnAdvancedPane extends BasicPane { } public DSColumnAdvancedPane(int setting) { - this.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); - this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initContentPane(setting); + initScrollPane(); + } + + private void initScrollPane() { + ScrollPane scrollPane = new ScrollPane(contentPane); + this.add(scrollPane); + } + + private void initContentPane(int setting) { + contentPane = new JPanel(); + contentPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); + contentPane.setLayout(FRGUIPaneFactory.createBorderLayout()); sortPane = new SortPane(); sortPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Sort_Sort_Order"))); @@ -135,7 +140,7 @@ public class DSColumnAdvancedPane extends BasicPane { TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}; double[] columnSize = {TableLayout.FILL}; - this.add(TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize), BorderLayout.CENTER); + contentPane.add(TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize), BorderLayout.CENTER); } @Override @@ -148,7 +153,7 @@ public class DSColumnAdvancedPane extends BasicPane { return; } - sortPane.populate(cellElement); + sortPane.populateBean(cellElement); valuePane.populate(cellElement); formatAttrPane.populate(cellElement); @@ -198,7 +203,7 @@ public class DSColumnAdvancedPane extends BasicPane { return; } - sortPane.update(cellElement); + sortPane.updateBean(cellElement); valuePane.update(cellElement); formatAttrPane.update(cellElement); @@ -234,66 +239,25 @@ public class DSColumnAdvancedPane extends BasicPane { } } - private static class SortPane extends SortFormulaPane { - private CellElement cellElement; + private static class ScrollPane extends UIScrollPane { + ScrollPane(Component component) { + super(component); + this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + } @Override - public void formulaAction() { - if (cellElement == null) { - return; - } - Object value = cellElement.getValue(); - if (value == null || !(value instanceof DSColumn)) { - return; - } - - String[] displayNames = DesignTableDataManager.getSelectedColumnNames( - DesignTableDataManager.getEditingTableDataSource(), ((DSColumn) value).getDSName()); - - showFormulaDialog(displayNames); + public Dimension getPreferredSize() { + return new Dimension(DSColumnPane.DEFAULT_DIMENSION.width - 20, DSColumnPane.DEFAULT_DIMENSION.height - 100); } + } - void populate(CellElement cellElement) { - if (cellElement == null) { - return; - } - this.cellElement = cellElement; - - Object value = cellElement.getValue(); - if (value == null || !(value instanceof DSColumn)) { - return; - } - DSColumn dSColumn = (DSColumn) value; - - int sort = dSColumn.getOrder(); - this.sortOrderComboBox.setSortOrder(new SortOrder(sort)); - - String sortFormula = dSColumn.getSortFormula(); - sortFormulaTextField.setText(sortFormula); + private static class SortPane extends CellDSColumnSortPane { + SortPane() { + this.setLayout(new FlowLayout(FlowLayout.LEFT)); } - public void update(CellElement cellElement) { - if (cellElement == null) { - return; - } - Object value = cellElement.getValue(); - if (value == null || !(value instanceof DSColumn)) { - return; - } - DSColumn dSColumn = (DSColumn) (cellElement.getValue()); - - dSColumn.setOrder(this.sortOrderComboBox.getSortOrder().getOrder()); - //lance:sort formula - - String sText = null; - if (!(sortFormulaTextField.getText() == null || sortFormulaTextField.getText().trim().equals("") || sortFormulaTextField.getText().trim().equals("$$$"))) { - sText = new String(sortFormulaTextField.getText()); - } - if (!(sText == null || sText.length() < 1)) { - dSColumn.setSortFormula(sText); - } else { - dSColumn.setSortFormula(null); - } + protected boolean needSortHeaderPane() { + return false; } } @@ -548,11 +512,11 @@ public class DSColumnAdvancedPane extends BasicPane { } } - public static class ReLayoutTextFormatPane extends TextFormatPane { + public static class FormatAttrPane extends TextFormatPane { protected void initLayout() { - JComponent[][] components = new JComponent[][] { {typeComboBox, textField, roundingBox} }; - double[] rowSize = new double[] { TableLayout.FILL }; + JComponent[][] components = new JComponent[][]{{typeComboBox, textField, roundingBox}}; + double[] rowSize = new double[]{TableLayout.FILL}; double[] columnSize = {TableLayout.PREFERRED, 200, TableLayout.PREFERRED}; JPanel settingPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 4, 0); @@ -578,45 +542,6 @@ public class DSColumnAdvancedPane extends BasicPane { } } - - public static class FormatAttrPane extends AbstractAttrNoScrollPane { - private TextFormatPane formatPane; - - @Override - protected JPanel createContentPane() { - this.formatPane = new ReLayoutTextFormatPane(); - return this.formatPane; - } - - @Override - public Dimension getPreferredSize() { - if (formatPane == null) { - return super.getPreferredSize(); - } - return formatPane.getPreferredSize(); - } - - protected void initContentPane() { - leftContentPane = createContentPane(); - if (leftContentPane != null) { - leftContentPane.setBorder(BorderFactory.createEmptyBorder()); - this.add(leftContentPane, BorderLayout.CENTER); - } - } - - public void populate(CellElement cellElement) { - if (cellElement != null && formatPane != null) { - formatPane.populateBean(cellElement.getStyle()); - } - } - - public void update(CellElement cellElement) { - if (cellElement != null && formatPane != null) { - cellElement.setStyle(formatPane.update(cellElement.getStyle())); - } - } - } - private void checkButtonEnabled() { if (useMultiplyNumCheckBox.isSelected()) { multiNumSpinner.setEnabled(true); diff --git a/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java b/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java index 095d011f7..056707896 100644 --- a/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java +++ b/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java @@ -89,7 +89,7 @@ public class ListenerEditPane extends BasicBeanPane { card = new CardLayout(); hyperlinkPane = FRGUIPaneFactory.createCardLayout_S_Pane(); hyperlinkPane.setLayout(card); - JavaScriptImplPane javaScriptPane = new JavaScriptImplPane(defaultArgs); + JavaScriptImplPane javaScriptPane = new JavaScriptImplPane(defaultArgs,true); hyperlinkPane.add(JS, javaScriptPane); // 提交入库 List dbManiList = new ArrayList(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java index 638254226..20b674a48 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java @@ -4,13 +4,13 @@ import com.fr.base.BaseUtils; import com.fr.base.DynamicUnitList; import com.fr.base.Parameter; import com.fr.base.ScreenResolution; +import com.fr.base.TRL; import com.fr.base.extension.FileExtension; -import com.fr.base.theme.TemplateThemeCompatible; -import com.fr.base.vcs.DesignerMode; import com.fr.base.theme.ReportTheme; -import com.fr.base.theme.ReportThemeConfig; import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.vcs.DesignerMode; import com.fr.design.DesignModelAdapter; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.AllowAuthorityEditAction; @@ -717,10 +717,10 @@ public class JWorkBook extends JTemplate { } protected void addShortCut(MenuDef exportMenuDef, MenuDef excelExportMenuDef) { - if (CptAndCptxCompatibilityUtil.isEngineXEnable(this.getTarget(), getEditingFILE().getPath())){ + if (CptAndCptxCompatibilityUtil.isEngineXEnable(this.getTarget(), getEditingFILE().getPath())) { exportMenuDef.addShortCut(excelExportMenuDef, new PDFExportAction(this), new WordExportAction(this), new SVGExportAction(this), new CSVExportAction(this), new TextExportAction(this)); - }else { + } else { exportMenuDef.addShortCut(excelExportMenuDef, new PDFExportAction(this), new WordExportAction(this), new SVGExportAction(this), new CSVExportAction(this), new TextExportAction(this), new EmbeddedExportExportAction(this)); } @@ -758,15 +758,14 @@ public class JWorkBook extends JTemplate { new ReportWatermarkAction(this), new NameSeparator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_Current_Sheet")), }, this.reportComposite.getEditingReportComponent().shortcut4TemplateMenu()); - if (enableNewEngine){ + if (enableNewEngine) { return ArraysUtil.insert(commonShortCut, new CalculateAttrAction(this), 5); - }else { + } else { return commonShortCut; } } - /** * 模板的工具 * @@ -1243,6 +1242,7 @@ public class JWorkBook extends JTemplate { return ViewRequestConstants.REPORT_VIEW_PATH; } + @Override protected void addChooseFILEFilter(FILEChooserPane fileChooser) { String appName = ProductConstants.APP_NAME; fileChooser.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); @@ -1304,7 +1304,7 @@ public class JWorkBook extends JTemplate { @Override public void setTemplateTheme(TemplateTheme newTheme, TemplateThemeCompatible compatible) { - ReportTheme oldTheme = getTarget().getTemplateTheme(); + ReportTheme oldTheme = getTarget().getTemplateTheme(); boolean shouldCreateUndoState = compatible == TemplateThemeCompatible.NONE && !StringUtils.equals(oldTheme.getName(), newTheme.getName()); getTarget().setTemplateTheme(newTheme, compatible); @@ -1318,4 +1318,9 @@ public class JWorkBook extends JTemplate { super.setTemplateTheme(newTheme, compatible); } + + @Override + public void navigate(TRL trl) { + reportComposite.selectCell(trl); + } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/ReportComponentComposite.java b/designer-realize/src/main/java/com/fr/design/mainframe/ReportComponentComposite.java index 5fe561829..d0f6a114d 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/ReportComponentComposite.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/ReportComponentComposite.java @@ -1,7 +1,7 @@ package com.fr.design.mainframe; import com.fr.base.ScreenResolution; -import com.fr.common.inputevent.InputEventBaseOnOS; +import com.fr.base.TRL; import com.fr.design.base.mode.DesignModeContext; import com.fr.design.designer.EditingState; import com.fr.design.event.RemoveListener; @@ -13,14 +13,13 @@ import com.fr.grid.Grid; import com.fr.log.FineLoggerFactory; import com.fr.main.impl.WorkBook; import com.fr.report.report.TemplateReport; +import com.fr.stable.StringUtils; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.BorderLayout; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; import java.util.ArrayList; /** @@ -80,6 +79,22 @@ public class ReportComponentComposite extends JComponent implements RemoveListen } }; + /** + * 选中格子 + * + * @param trl 模板资源路径 + */ + public void selectCell(TRL trl) { + String sheetIndexStr = trl.next(); + if(StringUtils.isEmpty(sheetIndexStr)) { + return; + } + int sheetIndex = Integer.parseInt(sheetIndexStr); + if (sheetIndex >= 0) { + sheetNameTab.setSelectedIndex(sheetIndex); + centerCardPane.editingComponet.navigate(trl); + } + } protected void doBeforeChange(int oldIndex) { if (oldIndex >= 0) { @@ -131,7 +146,7 @@ public class ReportComponentComposite extends JComponent implements RemoveListen } } - private void updateJSlider(){ + private void updateJSlider() { centerCardPane.editingComponet.updateJSliderValue(); } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/WorkSheetDesigner.java b/designer-realize/src/main/java/com/fr/design/mainframe/WorkSheetDesigner.java index da7548013..0529cf82a 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/WorkSheetDesigner.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/WorkSheetDesigner.java @@ -1,6 +1,7 @@ package com.fr.design.mainframe; import com.fr.base.ScreenResolution; +import com.fr.base.TRL; import com.fr.design.DesignState; import com.fr.design.actions.report.ReportColumnsAction; import com.fr.design.actions.report.ReportEngineAttrAction; @@ -19,11 +20,14 @@ import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; import com.fr.design.selection.SelectionListener; import com.fr.grid.selection.CellSelection; +import com.fr.grid.selection.FloatSelection; import com.fr.grid.selection.Selection; import com.fr.report.cell.CellElement; import com.fr.report.elementcase.TemplateElementCase; import com.fr.report.worksheet.WorkSheet; import com.fr.stable.ArrayUtils; +import com.fr.stable.ColumnRow; +import com.fr.stable.StringUtils; import javax.swing.JComponent; import javax.swing.JPanel; @@ -196,4 +200,27 @@ public class WorkSheetDesigner extends ReportComponent 10000) { + setSelection(new FloatSelection(TRL.unescape(cellName))); + return; + } + CellSelection cellSelection = new CellSelection(columnRow.getColumn(), columnRow.getRow(), columnRow.getColumnSpan(), columnRow.getRowSpan()); + // 滚动到位 + JScrollBar verticalBar = getVerticalScrollBar(), + horizontalBar = getHorizontalScrollBar(); + int m = columnRow.getColumn(), n = columnRow.getRow(); + verticalBar.setMaximum(n); + verticalBar.setValue(n < 21 ? verticalBar.getValue() : n - 20); + horizontalBar.setMaximum(m); + horizontalBar.setValue(m < 13 ? horizontalBar.getValue() : m - 12); + // 选中 + setSelection(cellSelection); + } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/AbstractDSCellEditorPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/AbstractDSCellEditorPane.java index 8a3b2ded4..dd7d3608c 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/AbstractDSCellEditorPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/AbstractDSCellEditorPane.java @@ -1,17 +1,7 @@ package com.fr.design.mainframe.cell; -import com.fr.design.gui.iscrollbar.UIScrollBar; -import com.fr.design.mainframe.CellElementPropertyPane; -import com.fr.quickeditor.cellquick.layout.CellElementBarLayout; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; +import com.fr.design.gui.frpane.AttributeChangeListener; +import com.fr.design.mainframe.AbstractAttrPane; /** * 右侧单元格元素面板抽象类 @@ -20,26 +10,9 @@ import java.awt.event.MouseWheelListener; * @version 2017年7月25日 * @since 9.0 */ -public abstract class AbstractDSCellEditorPane extends JPanel { - - /** - * 滚动条相关配置 - */ - private static final int MAXVALUE = 100; - private static final int TITLE_HEIGHT = 95; - private static final int CONTENT_PANE_WIDTH_GAP = 3; - private static final int SCROLLBAR_WIDTH = 7; - private static final int MOUSE_WHEEL_SPEED = 5; - private int maxHeight = 280; - - private JPanel leftContentPane; - private UIScrollBar scrollBar; - - protected abstract JPanel createContentPane(); +public abstract class AbstractDSCellEditorPane extends AbstractAttrPane { - public abstract String getIconPath(); - - public abstract String title4PopupWindow(); + private static final int FIXED_HEIGHT = 40; /** * 从面板拿数据保存 @@ -51,78 +24,19 @@ public abstract class AbstractDSCellEditorPane extends JPanel { */ public abstract void populate(); - protected void createScrollPane() { - leftContentPane = this.createContentPane(); - this.prepareScrollBar(); - leftContentPane.setBorder(BorderFactory.createMatteBorder(10, 10, 0, 0, this.getBackground())); - - this.setLayout(new CellElementBarLayout(leftContentPane) { - @Override - public void layoutContainer(Container parent) { - maxHeight = CellElementPropertyPane.getInstance().getHeight() - TITLE_HEIGHT; - int beginY; - if ((MAXVALUE - scrollBar.getVisibleAmount()) == 0) { - beginY = 0; - } else { - int preferredHeight = leftContentPane.getPreferredSize().height; - int value = scrollBar.getValue(); - beginY = value * (preferredHeight - maxHeight) / (MAXVALUE - scrollBar.getVisibleAmount()); - } - int width = parent.getWidth(); - int height = parent.getHeight(); - if (leftContentPane.getPreferredSize().height > maxHeight) { - leftContentPane.setBounds(0, -beginY, width - SCROLLBAR_WIDTH - CONTENT_PANE_WIDTH_GAP, height + beginY); - scrollBar.setBounds(width - SCROLLBAR_WIDTH - CONTENT_PANE_WIDTH_GAP, 0, SCROLLBAR_WIDTH + CONTENT_PANE_WIDTH_GAP, height); - } else { - leftContentPane.setBounds(0, 0, width - SCROLLBAR_WIDTH - CONTENT_PANE_WIDTH_GAP, height); - } - } - }); - this.add(scrollBar); - this.add(leftContentPane); - } - - - private void prepareScrollBar() { - scrollBar = new UIScrollBar(UIScrollBar.VERTICAL) { - @Override - public int getVisibleAmount() { - int preferredHeight = leftContentPane.getPreferredSize().height; - int e = MAXVALUE * (maxHeight) / preferredHeight; - setVisibleAmount(e); - return e; - } - - @Override - public int getMaximum() { - return MAXVALUE; - } - }; - - scrollBar.addAdjustmentListener(new AdjustmentListener() { - - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - doLayout(); - } - }); - this.addMouseWheelListener(new MouseWheelListener() { - - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - int value = scrollBar.getValue(); - value += MOUSE_WHEEL_SPEED * e.getWheelRotation(); - scrollBar.setValue(value); - doLayout(); - } - }); - scrollBar.setPreferredSize(new Dimension(SCROLLBAR_WIDTH + CONTENT_PANE_WIDTH_GAP, this.getHeight())); - scrollBar.setBlockIncrement(SCROLLBAR_WIDTH + CONTENT_PANE_WIDTH_GAP); - scrollBar.setBorder(BorderFactory.createMatteBorder(0, CONTENT_PANE_WIDTH_GAP, 0, 0, this.getBackground())); - } /** * 释放tc */ protected abstract void release(); + + protected abstract AttributeChangeListener getAttributeChangeListener(); + + public void addAttributeChangeListener() { + this.addAttributeChangeListener(getAttributeChangeListener()); + } + + protected int getMaxHeight() { + return Math.max(super.getMaxHeight() - FIXED_HEIGHT, 0); + } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java index cd454660d..9549a3a7e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java @@ -4,7 +4,6 @@ import com.fr.design.constants.LayoutConstants; import com.fr.design.constants.UIConstants; import com.fr.design.expand.ExpandLeftFatherPane; import com.fr.design.expand.ExpandUpFatherPane; -import com.fr.design.expand.SortExpandAttrPane; import com.fr.design.foldablepane.UIExpandablePane; import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.icheckbox.UICheckBox; @@ -13,6 +12,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; +import com.fr.design.sort.cellexpand.CellExpandSortPane; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; import com.fr.report.cell.TemplateCellElement; @@ -38,11 +38,11 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { private ExpandUpFatherPane rightFatherPane; private UICheckBox horizontalExpandableCheckBox; private UICheckBox verticalExpandableCheckBox; - private SortExpandAttrPane sortAfterExpand; private JPanel layoutPane; private JPanel basicPane; private JPanel seniorPane; private CellExpandExtraAttrPane extraPane; + private CellExpandSortPane cellExpandSortPane; /** @@ -62,7 +62,6 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { rightFatherPane = new ExpandUpFatherPane(); horizontalExpandableCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_ExpandD_Horizontal_Extendable")); verticalExpandableCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_ExpandD_Vertical_Extendable")); - sortAfterExpand = new SortExpandAttrPane(); initAllNames(); return layoutPane(); } @@ -81,8 +80,11 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { seniorPane = new JPanel(); basicPane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Basic"), 223, 24, basicPane()); seniorPane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Advanced"), 223, 24, seniorPane()); + JPanel sortUIExpandablePane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Expend_Sort"), + 223, 24, cellExpandSortPane = new CellExpandSortPane(this)); layoutPane.add(basicPane, BorderLayout.NORTH); layoutPane.add(seniorPane, BorderLayout.CENTER); + layoutPane.add(sortUIExpandablePane, BorderLayout.SOUTH); extraPane = CellExpandExtraAttrPane.getInstance(); @@ -119,16 +121,12 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { private JPanel seniorPane() { double f = TableLayout.FILL; double p = TableLayout.PREFERRED; - UILabel expendSort = new UILabel(Toolkit.i18nText("Fine-Design_Report_Expend_Sort"), SwingConstants.LEFT); - JPanel expendSortPane = new JPanel(new BorderLayout()); - expendSortPane.add(expendSort, BorderLayout.NORTH); horizontalExpandableCheckBox.setBorder(UIConstants.CELL_ATTR_ZEROBORDER); verticalExpandableCheckBox.setBorder(UIConstants.CELL_ATTR_ZEROBORDER); Component[][] components = new Component[][]{ new Component[]{null, null}, new Component[]{horizontalExpandableCheckBox, null}, new Component[]{verticalExpandableCheckBox, null}, - new Component[]{expendSortPane, sortAfterExpand}, }; double[] rowSize = {p, p, p, p, p}; double[] columnSize = {p, f}; @@ -169,9 +167,8 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { } } - sortAfterExpand.populate(cellExpandAttr); - extraPane.populate(cellElement); + cellExpandSortPane.populateBean(cellElement); } @@ -217,11 +214,8 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { } } - if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_ExpandD_Sort_After_Expand"))) { - sortAfterExpand.update(cellExpandAttr); - } - extraPane.update(cellElement); + cellExpandSortPane.updateBean(cellElement); } /** diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java index 0ea7713ca..efab3fc66 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java @@ -13,6 +13,7 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.layout.VerticalFlowLayout; @@ -30,8 +31,7 @@ import com.fr.report.cell.cellattr.CellPageAttr; import com.fr.report.elementcase.TemplateElementCase; import com.fr.stable.Constants; import com.fr.stable.StringUtils; -import com.fr.design.i18n.Toolkit; -import java.awt.Color; + import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JPanel; @@ -40,6 +40,7 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.CardLayout; +import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Insets; diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/CellPredefinedStyleSettingPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/CellPredefinedStyleSettingPane.java deleted file mode 100644 index bc246da8c..000000000 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/CellPredefinedStyleSettingPane.java +++ /dev/null @@ -1,246 +0,0 @@ -package com.fr.design.mainframe.cell.settingpane.style; - -import com.fr.base.CellBorderStyle; -import com.fr.base.NameStyle; -import com.fr.base.Style; -import com.fr.design.actions.utils.ReportActionUtils; -import com.fr.design.constants.UIConstants; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.dialog.BasicPane; -import com.fr.design.dialog.MultiTabPane; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.style.AbstractBasicStylePane; -import com.fr.design.gui.style.AlignmentPane; -import com.fr.design.gui.style.BorderPane; -import com.fr.design.gui.style.FormatPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.mainframe.ElementCasePane; -import com.fr.design.mainframe.predefined.ui.PredefinedStyleSettingPane; -import com.fr.design.mainframe.predefined.ui.preview.StyleSettingPreviewPane; -import com.fr.design.style.BorderUtils; -//import com.fr.predefined.PredefinedPatternStyleManager; -import com.fr.third.javax.annotation.Nonnull; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.List; - -/** - * Created by kerry on 2020-09-02 - */ -public class CellPredefinedStyleSettingPane extends PredefinedStyleSettingPane { - - private CustomStylePane customPredefinedStylePane; - - private UIComboBox applicationFormat; - - - @Override - protected StyleSettingPreviewPane createPreviewPane() { - return null; - } - - @Override - protected JPanel createCustomDetailPane() { - JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - customPredefinedStylePane = new CustomStylePane(); - jPanel.add(customPredefinedStylePane, BorderLayout.CENTER); - return jPanel; - } - - protected JPanel createPredefinedSettingPane() { - - applicationFormat = new UIComboBox(); - applicationFormat.setPreferredSize(new Dimension(140, 20)); - JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Predefined_Applicate_Format")), applicationFormat} - }, TableLayoutHelper.FILL_NONE, IntervalConstants.INTERVAL_W4, IntervalConstants.INTERVAL_L1); - - return centerPane; - } - - - @Override - public String title4PopupWindow() { - return null; - } - - @Override - public void populateBean(NameStyle ob) { - this.setPopulating(true); -// super.populate(ob); -// PredefinedStyle currentStyle = PredefinedPatternStyleManager.INSTANCE.getStyleFromName(getPredefinedStyleName()); -// PredefinedCellStyleConfig config = currentStyle.getCellStyleConfig(); -// Map allStyle = config.getAllStyles(); -// this.applicationFormat.clearBoxItems(); -// for (String name : allStyle.keySet()) { -// this.applicationFormat.addItem(name); -// } -// if (allStyle.containsKey(ob.getName())) { -// this.applicationFormat.setSelectedItem(ob.getName()); -// }else { -// this.applicationFormat.setSelectedItem(config.getDefaultStyleName()); -// } -// this.customPredefinedStylePane.populateBean(ob); -// this.setPopulating(false); - } - - - protected void populateCustomPane(){ - this.customPredefinedStylePane.populateBean(updatePredefinedStyle()); - } - - - - public void dealWithBorder(ElementCasePane ePane) { - - this.customPredefinedStylePane.dealWithBorder(ePane); - } - - public void updateBorder() { - this.customPredefinedStylePane.updateBorder(); - } - - @Override - @Nonnull - public NameStyle updateBean() { - Style style = updateStyle(); - if (!(style instanceof NameStyle)) { -// return NameStyle.createCustomStyle(style); - } - return (NameStyle) style; - } - - @Nonnull - public Style updateStyle() { - if (this.predefinedRadioBtn.isSelected()) { - return updatePredefinedStyle(); - } else { - return this.customPredefinedStylePane.updateBean(); - } - } - - private NameStyle updatePredefinedStyle() { - Object selectItem = this.applicationFormat.getSelectedItem(); -// return NameStyle.createPredefinedStyle(getPredefinedStyleName(), selectItem == null ? StringUtils.EMPTY : selectItem.toString(), Style.getInstance()); - return null; - } - - class CustomStylePane extends MultiTabPane