diff --git a/build.gradle b/build.gradle index bf1616759c..a3892da963 100644 --- a/build.gradle +++ b/build.gradle @@ -36,7 +36,7 @@ allprojects { group 'com.fr.design' version frDevVersion sourceCompatibility = languageLevelSetting - targetCompatibility = languageLevelSetting + targetCompatibility = languageLevelSetting tasks.withType(JavaCompile) { options.encoding = "UTF-8" @@ -49,8 +49,8 @@ allprojects { idea { module { inheritOutputDirs = false - outputDir = file(outputPath +"/classes") - testOutputDir = file(outputPath +"/test-classes") + outputDir = file(outputPath + "/classes") + testOutputDir = file(outputPath + "/test-classes") languageLevel = new IdeaLanguageLevel(sourceCompatibility) targetBytecodeVersion = targetCompatibility } @@ -69,6 +69,7 @@ allprojects { implementation 'org.swingexplorer:swag:1.0' implementation 'net.java.dev.jna:jna:5.4.0' implementation 'org.apache.tomcat:tomcat-catalina:8.5.72' + implementation 'org.apache.tomcat:tomcat-websocket:8.5.72' implementation 'io.socket:socket.io-client:0.7.0' implementation 'com.fr.third:fine-third:' + frVersion implementation 'com.fr.core:fine-core:' + frDevVersion @@ -77,6 +78,7 @@ allprojects { implementation 'com.fr.decision:fine-decision:' + frVersion implementation 'com.fr.schedule:fine-schedule:' + frVersion implementation 'com.fr.report:engine-report:' + frDevVersion + implementation 'com.fr.report:engine-x:' + frDevVersion implementation 'com.fr.report:engine-chart:' + frDevVersion implementation 'com.fr.report:engine-i18n:' + frDevVersion implementation 'com.fr.design:design-i18n:' + frDevVersion diff --git a/designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java b/designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java new file mode 100644 index 0000000000..14d2dcc811 --- /dev/null +++ b/designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java @@ -0,0 +1,12 @@ +package com.fr.common.exception; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/12/7 + */ +public interface ThrowableHandler { + + boolean process(Throwable e); + +} diff --git a/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java b/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java index ed8f2208ef..3eb3b78579 100644 --- a/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java +++ b/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java @@ -302,7 +302,7 @@ public abstract class DesignModelAdapter urlMap = new HashMap<>(); + + public static DesignerCloudURLManager getInstance() { + return DesignerCloudURLManager.HOLDER.singleton; + } + + private final ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("TestCloudConnectThread")); + + private volatile boolean testResult; + + + private static class HOLDER { + private static final DesignerCloudURLManager singleton = new DesignerCloudURLManager(); + } + + private DesignerCloudURLManager() { + loadURLXMLFile(); + } + + public String acquireUrlByKind(String key) { + String url = urlMap.getOrDefault(key, StringUtils.EMPTY); + if (StringUtils.isEmpty(url)) { + //本地缓存中为空时,直接从云中心获取,获取完成后异步更新本地缓存文件 + String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY); + executorService.submit(() -> { + updateURLXMLFile(key, latestUrl); + }); + return latestUrl; + } + //本地缓存不为空时,直接返回对应 url,同时异步更新 + executorService.submit(() -> { + String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY); + updateURLXMLFile(key, latestUrl); + }); + return url; + } + + private synchronized void updateURLXMLFile(String key, String url) { + if (StringUtils.isNotEmpty(url) && (!urlMap.containsKey(key) || !url.equals(urlMap.get(key)))) { + urlMap.put(key, url); + saveURLXMLFile(); + } + } + + + public void testConnect() { + executorService.submit(() -> { + testResult = isOnline(); + }); + } + + public boolean isConnected() { + return testResult; + } + + public boolean isOnline() { + if (CloudCenterConfig.getInstance().isOnline()) { + String ping = acquireUrlByKind("ping"); + if (StringUtils.isNotEmpty(ping)) { + try { + return StringUtils.isEmpty(HttpToolbox.get(ping)); + } catch (Exception ignore) { + } + } + } + return false; + } + + + /** + * 加载本地 url 管理文件 + */ + private void loadURLXMLFile() { + if (!getInfoFile().exists()) { + return; + } + XMLableReader reader = null; + try (InputStream in = new FileInputStream(getInfoFile())) { + // XMLableReader 还是应该考虑实现 Closable 接口的,这样就能使用 try-with 语句了 + reader = XMLReaderHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER); + if (reader == null) { + return; + } + reader.readXMLObject(this); + } catch (FileNotFoundException e) { + // do nothing + } catch (XMLStreamException | IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (XMLStreamException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + private File getInfoFile() { + + File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), CLOUD_URL_INFO)); + try { + if (!file.exists()) { + file.createNewFile(); + } + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return file; + } + + /** + * 保存到本地 URL 管理文件中,存放在 .Finereport110 中 + */ + void saveURLXMLFile() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLTools.writeOutputStreamXML(this, out); + out.flush(); + out.close(); + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8); + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage()); + } + } + + + @Override + public void readXML(XMLableReader reader) { + String tagName = reader.getTagName(); + if (tagName.equals(CHILD_XML_TAG)) { + String key = reader.getAttrAsString("key", StringUtils.EMPTY); + String value = reader.getAttrAsString("url", StringUtils.EMPTY); + this.urlMap.put(key, value); + } + } + + @Override + public void writeXML(XMLPrintWriter xmlPrintWriter) { + xmlPrintWriter.startTAG(ROOT_XML_TAG); + Iterator> iterable = urlMap.entrySet().iterator(); + while (iterable.hasNext()) { + Map.Entry entry = iterable.next(); + xmlPrintWriter.startTAG(CHILD_XML_TAG).attr("key", entry.getKey()).attr("url", entry.getValue()).end(); + } + xmlPrintWriter.end(); + } + + @Override + public Object clone() throws CloneNotSupportedException { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index 85b4e4e78f..b57ad6c7af 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -17,9 +17,10 @@ import com.fr.design.env.RemoteDesignerWorkspaceInfo; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.i18n.Toolkit; import com.fr.design.locale.impl.ProductImproveMark; -import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo; import com.fr.design.login.DesignerLoginType; import com.fr.design.login.config.DesignerLoginConfigManager; +import com.fr.design.mainframe.ComponentReuseNotifyUtil; +import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo; import com.fr.design.mainframe.vcs.VcsConfigManager; import com.fr.design.notification.SnapChatConfig; import com.fr.design.os.impl.SupportOSImpl; @@ -53,7 +54,8 @@ import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLTools; import com.fr.stable.xml.XMLWriter; import com.fr.stable.xml.XMLableReader; -import com.fr.third.apache.log4j.FileAppender; +import com.fr.third.apache.logging.log4j.core.appender.FileAppender; +import com.fr.third.apache.logging.log4j.core.layout.PatternLayout; import com.fr.third.org.apache.commons.io.FilenameUtils; import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContextCallback; @@ -88,8 +90,12 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private static final int MAX_SHOW_NUM = 10; private static final String VERSION_80 = "80"; + private static final String VERSION_90 = "90"; + private static final String VERSION100 = "100"; private static final int CACHINGTEMPLATE_LIMIT = 5; private static final String WEB_NAME = "webapps"; + public static final int LAYOUT_TEMPLATE_SIMPLE_STYLE = 0; + public static final int LAYOUT_TEMPLATE_REAL_STYLE = 1; /** * 指定默认工作空间 */ @@ -158,7 +164,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { //记录当前激活码的在线激活状态. private int activeKeyStatus = -1; private boolean joinProductImprove = true; - + private boolean startWithEmptyFile = false; private boolean embedServerLazyStartup = false; //最近使用的颜色 private ColorSelectConfigManager configManager = new ColorSelectConfigManager(); @@ -194,6 +200,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private static List mapWorkerList = new ArrayList(); private boolean imageCompress = false;//图片压缩 private boolean showImageCompressMoveTip = true; + private boolean showServerDatasetAuthTip = true; // 开启内嵌web页面的调试窗口 private boolean openDebug = false; @@ -203,6 +210,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private boolean showTemplateMissingPlugin = true; + private int layoutTemplateStyle = LAYOUT_TEMPLATE_SIMPLE_STYLE; + private boolean useOptimizedUPM4Adapter; /** @@ -319,18 +328,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if (!new File(fileName).exists()) { StableUtils.makesureFileExist(new File(fileName)); } - LogHandler handler = new LogHandler() { - final FileAppender appender = new FileAppender( - new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"), - fileName - ); + LogHandler handler = new LogHandler() { + final FileAppender appender = FileAppender.newBuilder(). + setName(FileAppender.class.getSimpleName()). + setLayout(PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n").build()). + withFileName(fileName).build(); @Override public FileAppender getHandler() { return appender; } }; - + handler.getHandler().start(); FineLoggerFactory.getLogger().addLogAppender(handler); } catch (SecurityException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); @@ -357,14 +366,21 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { try { fileWriter = new FileWriter(envFile); File oldEnvFile = new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "6-1" + "Env.xml"); - File envFile80 = new File(getEnvHome(VERSION_80) + File.separator + getEnvFile().getName()); - if (oldEnvFile.exists()) { + File envFile80 = getOldEnvFile(VERSION_80); + File envFile90 = getOldEnvFile(VERSION_90); + File envFile100 = getOldEnvFile(VERSION100); + // 从10.0往前递进是否存在更老版本的配置文件 + if (envFile100.exists()) { + compatibilityPrevVersion(envFile100); + } else if (envFile90.exists()) { + compatibilityPrevVersion(envFile90); + } else if (envFile80.exists()) { + compatibilityPrevVersion(envFile80); + } else if (oldEnvFile.exists()) { // marks:兼容DesignerEnv6-1.xml FileReader fileReader = new FileReader(oldEnvFile); Utils.copyCharTo(fileReader, fileWriter); fileReader.close(); - } else if (envFile80.exists()) { - compatibilityPrevVersion(envFile80); } else { // marks:生成一个新的xml文件 StringReader stringReader = new StringReader(""); @@ -386,6 +402,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } } + private File getOldEnvFile(String version) { + return new File(getEnvHome(version) + File.separator + getEnvFile().getName()); + } + private static String getEnvHome(String version) { String userHome = System.getProperty("user.home"); if (userHome == null) { @@ -400,6 +420,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private void compatibilityPrevVersion(File prevEnvFile) { try { XMLTools.readFileXML(designerEnvManager, prevEnvFile); + clearOldVersionDesignerEnvProperties(); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } @@ -409,6 +430,11 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { designerEnvManager.saveXMLFile(); } + private void clearOldVersionDesignerEnvProperties() { + SnapChatConfig snapChatConfig = designerEnvManager.getSnapChatConfig(); + snapChatConfig.resetRead(ComponentReuseNotifyUtil.COMPONENT_SNAP_CHAT_KEY); + } + public static void setEnvFile(File envFile) { DesignerEnvManager.envFile = envFile; } @@ -1368,6 +1394,24 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.maxNumberOrPreviewRow = maxNumberOrPreviewRow; } + /** + * 启动时是否打开空报表 + * + * @return 是否打开空报表 + */ + public boolean isStartWithEmptyFile() { + return startWithEmptyFile; + } + + /** + * 设置启动时是否打开空报表 + * + * @param startWithEmptyFile 是否打开空报表 + */ + public void setStartWithEmptyFile(boolean startWithEmptyFile) { + this.startWithEmptyFile = startWithEmptyFile; + } + /** * 是否展示工程界面 * @@ -1662,6 +1706,13 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.showImageCompressMoveTip = showImageCompressMoveTip; } + public boolean isShowServerDatasetAuthTip() { + return showServerDatasetAuthTip; + } + + public void setShowServerDatasetAuthTip(boolean showServerDatasetAuthTip) { + this.showServerDatasetAuthTip = showServerDatasetAuthTip; + } public boolean isOpenDebug() { return openDebug; @@ -1671,6 +1722,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.openDebug = openDebug; } + public int getLayoutTemplateStyle() { + return layoutTemplateStyle; + } + + public void setLayoutTemplateStyle(int layoutTemplateStyle) { + this.layoutTemplateStyle = layoutTemplateStyle; + } + /** * Read XML.
* The method will be invoked when read data from XML file.
@@ -1841,6 +1900,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.setEmbedServerLazyStartup(reader.getAttrAsBoolean("embedServerLazyStartup", false)); this.setShowTemplateMissingPlugin(reader.getAttrAsBoolean("showTemplateMissingPlugin", true)); this.setUseOptimizedUPM4Adapter(reader.getAttrAsBoolean("useOptimizedUPM4Adapter", SupportOSImpl.MACOS_12_VERSION_ADAPTER.support())); + this.setShowServerDatasetAuthTip(reader.getAttrAsBoolean("showServerDatasetAuthTip", true)); + this.setLayoutTemplateStyle(reader.getAttrAsInt("layoutTemplateStyle", LAYOUT_TEMPLATE_SIMPLE_STYLE)); } private void readReportPaneAttributions(XMLableReader reader) { @@ -1856,6 +1917,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.setSupportCellEditorDef(reader.getAttrAsBoolean("supportCellEditorDef", false)); this.setDragPermited(reader.getAttrAsBoolean("isDragPermited", false)); this.setUndoLimit(reader.getAttrAsInt("undoLimit", 5)); + this.setStartWithEmptyFile(reader.getAttrAsBoolean("startWithEmptyFile", false)); this.setDefaultStringToFormula(reader.getAttrAsBoolean("defaultStringToFormula", false)); if ((tmpVal = reader.getAttrAsString("gridLineColor", null)) != null) { this.setGridLineColor(new Color(Integer.parseInt(tmpVal))); @@ -2113,6 +2175,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if (!this.isShowTemplateMissingPlugin()) { writer.attr("showTemplateMissingPlugin", this.isShowTemplateMissingPlugin()); } + writer.attr("layoutTemplateStyle", this.getLayoutTemplateStyle()); + writer.attr("showServerDatasetAuthTip", this.isShowServerDatasetAuthTip()); writer.attr("useOptimizedUPM4Adapter", this.isUseOptimizedUPM4Adapter()); writer.end(); } @@ -2232,6 +2296,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { .attr("gridLineColor", this.getGridLineColor().getRGB()) .attr("paginationLineColor", this.getPaginationLineColor().getRGB()) .attr("undoLimit", this.getUndoLimit()) + .attr("startWithEmptyFile", this.isStartWithEmptyFile()) .end(); } @@ -2288,4 +2353,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { DesignerExiter.getInstance().execute(); } } + + public SnapChatConfig getSnapChatConfig() { + return snapChatConfig; + } } diff --git a/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java b/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java index 4aa48591fd..4d1493e01b 100644 --- a/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java +++ b/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java @@ -18,6 +18,7 @@ import com.fr.design.fun.TableDataDefineProvider; import com.fr.design.fun.ToolbarItemProvider; import com.fr.design.gui.core.WidgetOption; import com.fr.design.gui.core.WidgetOptionFactory; +import com.fr.design.mainframe.mobile.utils.MobileStyleProviderManager; import com.fr.design.menu.ShortCut; import com.fr.design.widget.Appearance; import com.fr.design.widget.mobile.WidgetMobilePane; @@ -269,11 +270,10 @@ public class ExtraDesignClassManager extends AbstractExtraClassManager implement public MobileWidgetStyleProvider[] getMobileStyleOfWidget(String xType) { Set set = getArray(MobileWidgetStyleProvider.XML_TAG); - if (set.isEmpty()) { - return new MobileWidgetStyleProvider[0]; - } + Set allSet = MobileStyleProviderManager.getArray(MobileWidgetStyleProvider.XML_TAG); + allSet.addAll(set); List providers = new ArrayList<>(); - for (MobileWidgetStyleProvider provider : set) { + for (MobileWidgetStyleProvider provider : allSet) { if (ComparatorUtils.equalsIgnoreCase(provider.xTypeForWidget(), xType)) { providers.add(provider); } diff --git a/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java b/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java index 5c12ff29c3..048f233373 100644 --- a/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java @@ -345,6 +345,17 @@ public abstract class UpdateAction extends ShortCut implements Action { return (JComponent) object; } + public JComponent createToolBarComponentByName(String componentName) { + Object object = this.getValue(componentName); + if (!(object instanceof AbstractButton)) { + UIButton button = null; + button = new UIButton(); + object = initButton(button, componentName); + } + + return (JComponent) object; + } + protected JComponent initButton(UIButton button, String name) { // 添加一个名字作为自动化测试用 button.setName(getName()); diff --git a/designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java b/designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java new file mode 100644 index 0000000000..812d89e5f8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java @@ -0,0 +1,47 @@ +package com.fr.design.actions.file; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.transform.ui.BatchTransformPane; + +import javax.swing.KeyStroke; +import java.awt.Dialog; +import java.awt.event.ActionEvent; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchCompileAction extends UpdateAction { + public BatchCompileAction() { + this.setMenuKeySet(COMPILE); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/batch_transform.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + BatchTransformPane batchTransformPane = new BatchTransformPane(); + Dialog dialog = batchTransformPane.showDialog(); + dialog.setVisible(true); + } + + private static final MenuKeySet COMPILE = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} 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 db94ace66f..5a777b895d 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 @@ -12,6 +12,7 @@ import com.fr.design.editor.editor.IntegerEditor; import com.fr.design.gui.frpane.UITabbedPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UINoThemeColorButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIDictionaryComboBox; @@ -44,7 +45,7 @@ import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import com.fr.stable.Constants; import com.fr.stable.os.OperatingSystem; -import com.fr.third.apache.log4j.Level; +import com.fr.third.apache.logging.log4j.Level; import com.fr.transaction.Configurations; import com.fr.transaction.Worker; import com.fr.workspace.WorkContext; @@ -164,6 +165,7 @@ public class PreferencePane extends BasicPane { private UICheckBox oracleSpace; private UISpinner cachingTemplateSpinner; private UICheckBox useOptimizedUPMCheckbox; + private UICheckBox useNewVersionLoginCheckbox; private UICheckBox useUniverseDBMCheckbox; private UICheckBox joinProductImproveCheckBox; private UICheckBox autoPushUpdateCheckBox; @@ -177,7 +179,7 @@ public class PreferencePane extends BasicPane { private UICheckBox gcEnableCheckBox; private UIButton gcButton; private UILabel remindVcsLabel; - + private UICheckBox startWithEmptyFile; private JDialog gcDialog; private UILabel gcMessage = new UILabel(); private JPanel gcDialogDownPane = new JPanel(); @@ -230,6 +232,13 @@ public class PreferencePane extends BasicPane { advancePane.add(upmSelectorPane); } + if (SupportOSImpl.DESIGNER_LOGIN.support()) { + JPanel loginSelectorPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Login_Manager")); + useNewVersionLoginCheckbox = new UICheckBox(i18nText("Fine-Design_Basic_Use_New_Login_Manager")); + loginSelectorPane.add(useNewVersionLoginCheckbox); + advancePane.add(loginSelectorPane); + } + JPanel dbmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Database_Manager")); useUniverseDBMCheckbox = new UICheckBox(i18nText("Fine-Design_Basic_Use_Universe_Database_Manager")); //dbmSelectorPane.add(useUniverseDBMCheckbox); @@ -344,18 +353,23 @@ public class PreferencePane extends BasicPane { } private void createFunctionPane(JPanel generalPane) { - JPanel functionPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Function")); - generalPane.add(functionPane); + JPanel topVerticalTitledBorderPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Function")); + JPanel upper = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + JPanel lower = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + topVerticalTitledBorderPane.add(upper); + topVerticalTitledBorderPane.add(lower); + generalPane.add(topVerticalTitledBorderPane); + //添加supportUndo选择项 supportUndoCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Support_Undo")); - functionPane.add(supportUndoCheckBox); + upper.add(supportUndoCheckBox); //添加maxUndoLimit //String[] undoTimes = {"最大撤销次数","5次","10次","15次","20次","50次"}; String[] undoTimes = {i18nText("Fine-Design_Basic_Max_Undo_Limit"), MAX_UNDO_LIMIT_5 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_10 + i18nText("Fine-Design_Basic_Time(s)") , MAX_UNDO_LIMIT_15 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_20 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_50 + i18nText("Fine-Design_Basic_Time(s)")}; maxUndoLimit = new UIComboBox(undoTimes); - functionPane.add(maxUndoLimit); + upper.add(maxUndoLimit); //不支持撤销则不能选择撤销可缓存,也不能设置最大撤销次数 supportUndoCheckBox.addActionListener(new ActionListener() { @@ -369,12 +383,14 @@ public class PreferencePane extends BasicPane { //添加supportDefaultParentCalculate选择项 supportDefaultParentCalculateCheckBox = new UICheckBox( i18nText("Fine-Design_Basic_Preference_Support_Default_Parent_Calculate")); - functionPane.add(supportDefaultParentCalculateCheckBox); + upper.add(supportDefaultParentCalculateCheckBox); //添加是否展示打开模板提示缺少插件选择项 showTemplateMissingPlugin = new UICheckBox( i18nText("Fine-Design_Basic_Preference_Show-Template-Missing-Plugin")); - functionPane.add(showTemplateMissingPlugin); + upper.add(showTemplateMissingPlugin); + startWithEmptyFile = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Start_Empty_File")); + lower.add(startWithEmptyFile); } private void createEditPane(JPanel generalPane) { @@ -465,10 +481,10 @@ public class PreferencePane extends BasicPane { JPanel colorSettingPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Setting_Colors")); generalPane.add(colorSettingPane); - gridLineColorTBButton = new UIColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); + gridLineColorTBButton = new UINoThemeColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); gridLineColorTBButton.setEnabled(this.isEnabled()); - paginationLineColorTBButton = new UIColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); + paginationLineColorTBButton = new UINoThemeColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); paginationLineColorTBButton.setEnabled(this.isEnabled()); JPanel leftPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); @@ -716,6 +732,10 @@ public class PreferencePane extends BasicPane { || DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter()); } + if (useNewVersionLoginCheckbox != null) { + useNewVersionLoginCheckbox.setSelected(!DesignerEnvManager.getEnvManager().isUseOldVersionLogin()); + } + useUniverseDBMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseUniverseDBM()); this.oracleSpace.setSelected(designerEnvManager.isOracleSystemSpace()); @@ -727,6 +747,7 @@ public class PreferencePane extends BasicPane { } this.embedServerLazyStartupCheckBox.setSelected(designerEnvManager.isEmbedServerLazyStartup()); + this.startWithEmptyFile.setSelected(designerEnvManager.isStartWithEmptyFile()); this.imageCompressPanelCheckBox.setSelected(designerEnvManager.isImageCompress()); } @@ -810,11 +831,15 @@ public class PreferencePane extends BasicPane { designerEnvManager.setAutoPushUpdateEnabled(this.autoPushUpdateCheckBox.isSelected()); } + if (useNewVersionLoginCheckbox != null) { + designerEnvManager.setUseOldVersionLogin(!this.useNewVersionLoginCheckbox.isSelected()); + } + designerEnvManager.setUndoLimit(maxUndoLimit.getSelectedIndex() * SELECTED_INDEX_5); if (maxUndoLimit.getSelectedIndex() == SELECTED_INDEX_5) { designerEnvManager.setUndoLimit(MAX_UNDO_LIMIT_50); } - + designerEnvManager.setStartWithEmptyFile(startWithEmptyFile.isSelected()); if (WorkContext.getCurrent().isLocal()) { Configurations.update(new Worker() { @Override diff --git a/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java b/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java index eaff26ba5a..6158540888 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java @@ -14,7 +14,6 @@ import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; import com.fr.general.GeneralUtils; -import com.fr.i18n.UrlI18nManager; import com.fr.locale.InterProviderFactory; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; @@ -83,7 +82,7 @@ public class AboutPane extends JPanel { addPhoneAndQQPane(contentPane); // 官网 - JPanel urlActionPane = getURLActionPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Official_Website"), UrlI18nManager.getInstance().getI18nUrl("website")); + JPanel urlActionPane = getURLActionPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Official_Website"), CloudCenter.getInstance().acquireConf("website." + GeneralContext.getLocale(), ProductConstants.WEBSITE_URL)); // 支持邮箱 String defaultEmail = CloudCenter.getInstance().acquireConf("support.email", ProductConstants.SUPPORT_EMAIL); diff --git a/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java b/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java index 4f06b1c56b..51a390c82d 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java @@ -3,9 +3,9 @@ package com.fr.design.actions.help; import com.fr.design.i18n.Toolkit; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; +import com.fr.general.CloudCenter; import com.fr.general.GeneralContext; import com.fr.general.http.HttpToolbox; -import com.fr.i18n.UrlI18nManager; import com.fr.stable.CommonUtils; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; @@ -28,11 +28,7 @@ public class TutorialAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return UrlI18nManager.getInstance().getI18nUrl("help"); - } - - public String getOffLineWarnMessage() { - return Toolkit.i18nText("Fine-Design_Offline_Helptutorial_Msg"); + return CloudCenter.getInstance().acquireUrlByKind(createDocKey(), "http://help.finereport.com"); } // 生成帮助文档 sitecenter key, help.zh_CN.10 @@ -57,6 +53,10 @@ public class TutorialAction extends AbstractDesignerSSO { } } + public String getOffLineWarnMessage() { + return Toolkit.i18nText("Fine-Design_Offline_Helptutorial_Msg"); + } + public static final MenuKeySet HELP_TUTORIAL = new MenuKeySet() { @Override public char getMnemonic() { diff --git a/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java b/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java index ab85a14dc1..1457f0d111 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java @@ -20,11 +20,11 @@ import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrame; import com.fr.design.menu.MenuKeySet; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; import com.fr.file.TableDataConfig; -import com.fr.transaction.CallBackAdaptor; -import com.fr.transaction.Configurations; -import com.fr.transaction.WorkerFacade; import com.fr.report.LockItem; import javax.swing.KeyStroke; @@ -88,7 +88,7 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS } protected void renameConnection(final String oldName, final String newName) { - tableDataConfig.renameTableData(oldName, newName); + StrategyEventsNotifier.modifyDataSet(DSMapping.ofServerDS(new DsNameTarget(oldName))); } }; final BasicDialog globalTableDataDialog = globalTableDataPane.showWindowWithCustomSize(designerFrame, null, DEFAULT_DIMENSION); @@ -102,33 +102,17 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS globalTableDataDialog.setDoOKSucceed(false); return; } + globalTableDataPane.update(tableDataConfig); DesignTableDataManager.clearGlobalDs(); // 保存时 移除服务器数据集列名缓存 for (String name : tableDataConfig.getTableDatas().keySet()) { DesignTableDataManager.removeSelectedColumnNames(name); } - - Configurations.modify(new WorkerFacade(TableDataConfig.class) { - @Override - public void run() { - globalTableDataPane.update(tableDataConfig); - } - }.addCallBack(new CallBackAdaptor() { - @Override - public boolean beforeCommit() { - //如果更新失败,则不关闭对话框,也不写xml文件,并且将对话框定位在请重命名的那个对象页面 - return doWithDatasourceManager(tableDataConfig, globalTableDataPane, globalTableDataDialog); - } - - @Override - public void afterCommit() { - // 刷新共有数据集 - TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); - fireDSChanged(globalTableDataPane.getDsChangedNameMap()); - // 关闭服务器数据集页面,为其解锁 - EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA); - } - })); + // 刷新共有数据集 + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + fireDSChanged(globalTableDataPane.getDsChangedNameMap()); + // 关闭服务器数据集页面,为其解锁 + EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA); } @Override diff --git a/designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java b/designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java new file mode 100644 index 0000000000..2db6e6aef0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java @@ -0,0 +1,49 @@ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.utils.DesignUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.web.URLConstants; +import com.fr.stable.StableUtils; + +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +/** + * @author Maksim + * Created in 2020/11/5 11:44 上午 + */ +public class LocalAnalyzerAction extends UpdateAction { + + public LocalAnalyzerAction() { + this.setMenuKeySet(ANALYZER); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/analyzer.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + String path = StableUtils.pathJoin("/nx", URLConstants.ANALYZE_VIEW); + DesignUtils.visitEnvServerByParameters(path, new String[]{}, new String[]{}); + } + + private static final MenuKeySet ANALYZER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'R'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Analyzer_Menu_Name"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/border/UITitledBorder.java b/designer-base/src/main/java/com/fr/design/border/UITitledBorder.java index 3987844cf8..875ef00833 100644 --- a/designer-base/src/main/java/com/fr/design/border/UITitledBorder.java +++ b/designer-base/src/main/java/com/fr/design/border/UITitledBorder.java @@ -22,24 +22,7 @@ public class UITitledBorder extends TitledBorder { } private UITitledBorder(String title) { - super( - BorderFactory.createCompoundBorder( - BorderFactory.createEmptyBorder( - 0, - 0, - 5, - 0), - new UIRoundedBorder( - UIConstants.TITLED_BORDER_COLOR, - 1, - 10) - ), - title, - TitledBorder.LEADING, - TitledBorder.TOP, - null, - new Color(1, 159, 222) - ); + this(title, 10); } /** diff --git a/designer-base/src/main/java/com/fr/design/border/UITitledMatteBorder.java b/designer-base/src/main/java/com/fr/design/border/UITitledMatteBorder.java new file mode 100644 index 0000000000..c46143e1e5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/border/UITitledMatteBorder.java @@ -0,0 +1,32 @@ +package com.fr.design.border; + +import com.fr.design.constants.UIConstants; + +import javax.swing.BorderFactory; +import javax.swing.border.TitledBorder; +import java.awt.Color; + +public class UITitledMatteBorder extends TitledBorder { + public static UITitledMatteBorder createTitledTopBorder(String title, Color color) { + return new UITitledMatteBorder(title, 1, 0, 0, 0, color); + } + + public static UITitledMatteBorder createTitledBorder(String title, Color color) { + return new UITitledMatteBorder(title, 1, 1, 1, 1, color); + } + + public static UITitledMatteBorder createTitledBorder(String title, int top, int left, int bottom, int right, Color color) { + return new UITitledMatteBorder(title, top, left, bottom, right, color); + } + + private UITitledMatteBorder(String title, int top, int left, int bottom, int right, Color color) { + super( + BorderFactory.createMatteBorder(top, left, bottom, right, UIConstants.TITLED_BORDER_COLOR), + title, + TitledBorder.LEADING, + TitledBorder.TOP, + null, + color + ); + } +} diff --git a/designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java b/designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java new file mode 100644 index 0000000000..c0b6a0bc85 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java @@ -0,0 +1,180 @@ +package com.fr.design.cell; + +import com.fr.base.CellBorderSourceFlag; +import com.fr.base.CellBorderStyle; +import com.fr.base.Style; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; +import com.fr.general.IOUtils; +import com.fr.report.cell.TemplateCellElement; + +import javax.swing.JPanel; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/3 + */ +public class CellRectangleStylePreviewPane extends JPanel { + + private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); + private final float transparentBackgroundWidth; + private final float transparentBackgroundHeight; + + private static final int ROW_COUNT = 2; + private static final int COLUMN_COUNT = 2; + + private final TemplateCellElement[][] cellElementGrid = new TemplateCellElement[ROW_COUNT][COLUMN_COUNT]; + private final int[][] borderSourceFlags = new int[ROW_COUNT][COLUMN_COUNT]; + private final CellStylePreviewPane[][] cellStylePreviewPaneGrid = new CellStylePreviewPane[ROW_COUNT][COLUMN_COUNT]; + + public CellRectangleStylePreviewPane(boolean supportInnerBorder) { + transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); + transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); + + setLayout(new GridLayout(2, 2)); + setOpaque(false); + setBackground(null); + + for (int r = 0; r < ROW_COUNT; r++) { + for (int c = 0; c < COLUMN_COUNT; c++) { + CellStylePreviewPane pane = new CellStylePreviewPane(c, r, COLUMN_COUNT, ROW_COUNT, false, false); + TemplateCellElement cellElement = DefaultThemedTemplateCellElementCase.createInstance(c, r); + int flags = CellBorderSourceFlag.INVALID_BORDER_SOURCE; + if (supportInnerBorder) { + flags = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r != 0) { + flags |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r != ROW_COUNT - 1) { + flags |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + if (c != 0) { + flags |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c != COLUMN_COUNT - 1) { + flags |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + } + + + pane.setStyle(cellElement.getStyle()); + add(pane); + + cellElementGrid[r][c] = cellElement; + borderSourceFlags[r][c] = flags; + cellStylePreviewPaneGrid[r][c] = pane; + } + } + } + + public void setPlainText(String text) { + cellStylePreviewPaneGrid[0][1].setPaintText(text); + cellStylePreviewPaneGrid[1][1].setPaintText(text); + repaint(); + } + + public void setStyle(Style style, CellBorderStyle borderStyle) { + for (int i = 0; i < ROW_COUNT; i++) { + for (int j = 0; j < COLUMN_COUNT; j++) { + CellStylePreviewPane pane = cellStylePreviewPaneGrid[i][j]; + TemplateCellElement cellElement = cellElementGrid[i][j]; + int flag = borderSourceFlags[i][j]; + cellElement.setStyle(CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, flag)); + + pane.setStyle(cellElement.getStyle()); + } + } + repaint(); + } + + @Override + public void setPreferredSize(Dimension preferredSize) { + super.setPreferredSize(preferredSize); + int hw = preferredSize.width / 2; + int hh = preferredSize.height / 2; + cellStylePreviewPaneGrid[0][0].setPreferredSize(new Dimension(hw, hh)); + cellStylePreviewPaneGrid[0][1].setPreferredSize(new Dimension(hw, hh)); + cellStylePreviewPaneGrid[1][0].setPreferredSize(new Dimension(hw, hh)); + cellStylePreviewPaneGrid[1][1].setPreferredSize(new Dimension(hw, hh)); + } + + @Override + public Dimension getPreferredSize() { + Dimension d00 = cellStylePreviewPaneGrid[0][0].getPreferredSize(); + Dimension d01 = cellStylePreviewPaneGrid[0][1].getPreferredSize(); + Dimension d10 = cellStylePreviewPaneGrid[1][0].getPreferredSize(); + Dimension d11 = cellStylePreviewPaneGrid[1][1].getPreferredSize(); + + int width = Math.max(d00.width + d01.width, d10.width + d11.width); + int height = Math.max(d00.height + d10.height, d01.height + d11.height); + + return new Dimension(width, height); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.clearRect(0, 0, getWidth(), getHeight()); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + paintTransparentBackground((Graphics2D) g, cellElementGrid[0][0].getStyle()); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + + super.paint(g); + } + + @Override + public Rectangle getBounds() { + return super.getBounds(); + } + + private void paintTransparentBackground(Graphics2D g2d, Style style) { + float alpha = computeTransparentBackgroundAlpha(style); + + float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; + float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; + float maxScale = Math.max(scaleWidth, scaleHeight); + + if (maxScale <= 1) { + scaleWidth = scaleHeight = 1; + } else { + scaleHeight = scaleWidth = maxScale; + } + + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); + g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); + g2d.setComposite(oldComposite); + } + + private float computeTextColorBrightness(Style style) { + Color fontColor = style.getFRFont().getForeground(); + return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F; + } + + private float computeTransparentBackgroundAlpha(Style style) { + float textBrightness = computeTextColorBrightness(style); + + float alpha = 1.0F; + if (textBrightness < 50) { + alpha = 0.2F; + } else if (textBrightness < 160){ + alpha = 0.5F; + } + return alpha; + } +} diff --git a/designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java b/designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java new file mode 100644 index 0000000000..eb3c2cd7b5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java @@ -0,0 +1,220 @@ +package com.fr.design.cell; + +import com.fr.base.BaseUtils; +import com.fr.base.GraphHelper; +import com.fr.base.NameStyle; +import com.fr.base.ScreenResolution; +import com.fr.base.Style; +import com.fr.general.FRFont; +import com.fr.general.IOUtils; +import com.fr.stable.Constants; +import com.fr.stable.unit.PT; + +import javax.swing.JPanel; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/3 + */ +public class CellStylePreviewPane extends JPanel { + + public static final int MINIMUM_HEIGHT = 40; + private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); + private final float transparentBackgroundWidth; + private final float transparentBackgroundHeight; + private String paintText = "Report"; + private Style style = Style.DEFAULT_STYLE; + + private final int column; + private final int row; + private final int columnSpan; + private final int rowSpan; + + private final boolean autoClearCanvas; + private final boolean paintingMosaic; + + public CellStylePreviewPane(int column, int row, int columnSpan, int rowSpan, boolean autoClearCanvas, boolean paintingMosaic) { + this.column = column; + this.row = row; + this.columnSpan = columnSpan; + this.rowSpan = rowSpan; + this.autoClearCanvas = autoClearCanvas; + this.paintingMosaic = paintingMosaic; + transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); + transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); + setPreferredSize(new Dimension(0, 0)); + } + + public void setPaintText(String paintText) { + this.paintText = paintText; + repaint(); + } + + public void setStyle(Style style) { + this.style = style; + repaint(); + } + + public void setStyle(NameStyle style) { + paintText = style.getName(); + setStyle(style.getRealStyle()); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + if (autoClearCanvas) { + g2d.clearRect(0, 0, getWidth(), getHeight()); + } + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + if (paintingMosaic) { + paintTransparentBackground(g2d, style); + } + + paintCellStyle(g2d, style); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + } + + private void paintTransparentBackground(Graphics2D g2d, Style style) { + float alpha = computeTransparentBackgroundAlpha(style); + + float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; + float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; + float maxScale = Math.max(scaleWidth, scaleHeight); + + if (maxScale <= 1) { + scaleWidth = scaleHeight = 1; + } else { + scaleHeight = scaleWidth = maxScale; + } + + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); + g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); + g2d.setComposite(oldComposite); + } + + private float computeTextColorBrightness(Style style) { + Color fontColor = style.getFRFont().getForeground(); + return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F; + } + + private float computeTransparentBackgroundAlpha(Style style) { + float textBrightness = computeTextColorBrightness(style); + + float alpha = 1.0F; + if (textBrightness < 50) { + alpha = 0.2F; + } else if (textBrightness < 160){ + alpha = 0.5F; + } + return alpha; + } + + private void paintCellStyle(Graphics2D g2d, Style style) { + int resolution = ScreenResolution.getScreenResolution(); + + int width = getWidth(); + int height = getHeight(); + + if (style == Style.DEFAULT_STYLE) { + // 如果是默认的style,就只写"Report"上去 + Style.paintContent(g2d, paintText, style, width, height, resolution); + return; + } + + Style.paintBackground(g2d, style, width, height); + + Style.paintContent(g2d, paintText, style, width, height, resolution); + + paintCellBorder(g2d, style); + } + + protected void paintCellBorder(Graphics2D g2d, Style style) { + float adjustLeft = 0; + float adjustTop = 0; + float adjustRight = 0; + float adjustBottom = 0; + if (column == 0) { + adjustLeft = computeHalfSize4StyledBorder(style.getBorderLeft()); + } + if (row == 0) { + adjustTop = computeHalfSize4StyledBorder(style.getBorderTop()); + } + if (column == columnSpan - 1) { + adjustRight = -computeHalfSize4StyledBorder(style.getBorderRight()); + } + if (row == rowSpan - 1) { + adjustBottom = -computeHalfSize4StyledBorder(style.getBorderBottom()); + } + + g2d.translate(adjustLeft, adjustTop); + Style.paintBorder(g2d, style, getWidth() - adjustLeft + adjustRight, getHeight() - adjustTop + adjustBottom); + g2d.translate(-adjustLeft, -adjustTop); + } + + private float computeHalfSize4StyledBorder(int border) { + float size = GraphHelper.getLineStyleSize(border) / 2.0F; + + if (border == Constants.LINE_DOUBLE) { + size += GraphHelper.getLineStyleSize(Constants.LINE_THIN) / 2.0F; + } else if (border == Constants.LINE_DOUBLE_DOT) { + size += GraphHelper.getLineStyleSize(Constants.LINE_DOT) / 2.0F; + } + + return size; + } + + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + int width = size.width; + int height = size.height; + + if (height != 0) { + // 使用者设置了一个高度 + return size; + } else if (width == 0) { + // 使用者未设置任何尺寸 + return new Dimension(width, MINIMUM_HEIGHT); + } else { + // 使用者设置了宽度,但未设置高度 + return getAutoWrapContentPreferredSize(width, height); + } + } + + private Dimension getAutoWrapContentPreferredSize(int width, int height) { + int resolution = ScreenResolution.getScreenResolution(); + + // 计算文本区域高度 + final FRFont frFont = style.getFRFont(); + final Font rfont = frFont.applyResolutionNP(resolution); + final FontMetrics metrics = GraphHelper.getFontMetrics(rfont); + final int textLineHeight = metrics.getHeight(); + final double textLineSpacing = PT.pt2pix(style.getLineSpacing(), resolution); + + List textLineList = BaseUtils.getLineTextList(paintText, style, rfont, height, width, resolution); + + double textLinesHeight = textLineList.size() * textLineHeight + Math.max(0, textLineList.size() - 1) * textLineSpacing; + + height = (int) Math.max(MINIMUM_HEIGHT, textLinesHeight); + + return new Dimension(width, height); + } +} diff --git a/designer-base/src/main/java/com/fr/design/config/DesignerProperties.java b/designer-base/src/main/java/com/fr/design/config/DesignerProperties.java new file mode 100644 index 0000000000..d14c7938a9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/config/DesignerProperties.java @@ -0,0 +1,52 @@ +package com.fr.design.config; + +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.Properties; + +public class DesignerProperties { + private static DesignerProperties holder = null; + private boolean supportLoginEntry = true; + + public DesignerProperties() { + String filePath = StableUtils.pathJoin(StableUtils.getInstallHome(), "/config/config.properties"); + InputStream is = null; + try { + is = new BufferedInputStream(new FileInputStream(filePath)); + Properties ps = new Properties(); + ps.load(is); + this.initProperties(ps); + } catch (FileNotFoundException e) { + // ignore + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } finally { + IOUtils.close(is); + } + } + + public static DesignerProperties getInstance() { + if (holder == null) { + holder = new DesignerProperties(); + } + return holder; + } + + private void initProperties(Properties ps) { + String supportLoginEntry = ps.getProperty("supportLoginEntry"); + if (StringUtils.isNotEmpty(supportLoginEntry)) { + this.supportLoginEntry = Boolean.valueOf(supportLoginEntry); + } + } + + public boolean isSupportLoginEntry() { + return supportLoginEntry; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java index b0997b7f6c..530b466930 100644 --- a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java @@ -36,8 +36,6 @@ import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; import com.fr.workspace.WorkContext; -import java.util.HashSet; -import java.util.Set; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.DefaultCellEditor; @@ -55,8 +53,10 @@ import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.EventObject; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.Set; /** * Coder: zack @@ -83,6 +83,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp protected String[] allDSNames; protected ConnectionTableAction connectionTableAction; protected ToolBarDef toolbarDef; + protected TableDataTreePaneListener listener = null; private String type = ""; @@ -142,6 +143,17 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp public abstract void dgEdit(final AbstractTableDataPane uPanel, String originalName, boolean isUpdate); + public void showEditPane(final AbstractTableDataPane tableDataPane, String originalName, TableDataTreePaneListener listener) { + this.listener = listener; + dgEdit(tableDataPane, originalName); + } + + public interface TableDataTreePaneListener { + void doOk(); + + void doCancel(); + } + protected void doPropertyChange(BasicDialog dg, BasicPane.NamePane nPanel, final String oldName) { type = dg.getTitle(); nPanel.setShowText(StringUtils.BLANK); diff --git a/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java b/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java index f1758f0689..f7eb9bacc4 100644 --- a/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java +++ b/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java @@ -47,9 +47,11 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -71,8 +73,8 @@ public abstract class DesignTableDataManager { * 其实globalDsCache没有绝对的必要,只是为了操作方便。如果没有它,那么每次清空服务器数据集或者存储过程的时候,还要去遍历找一下, * 这个操作可能比较复杂 。 从减少代码复杂度的角度看,还是很有必要的 */ - private static java.util.Map globalDsCache = new java.util.HashMap(); - private static java.util.Map dsNameChangedMap = new HashMap(); + private static Map globalDsCache = new java.util.HashMap(); + private static Set dsNameChangedSet = new LinkedHashSet<>(); private static List globalDsListeners = new ArrayList<>(); private static Map> dsListenersMap = new ConcurrentHashMap<>(); @@ -123,7 +125,7 @@ public abstract class DesignTableDataManager { public static void envChange() { columnCache.clear(); dsListenersMap.clear(); - dsNameChangedMap.clear(); + dsNameChangedSet.clear(); clearGlobalDs(); } @@ -136,17 +138,17 @@ public abstract class DesignTableDataManager { public static void fireDSChanged(Map dsNameChangedMap) { clearGlobalDs(); if (!dsNameChangedMap.isEmpty()) { - setDsNameChangedMap(dsNameChangedMap); + setDsNameChangedSet(dsNameChangedMap); } fireDsChanged(); dsNameChangedMap.clear(); } - private static void setDsNameChangedMap(Map map) { + private static void setDsNameChangedSet(Map map) { Iterator iterator = map.keySet().iterator(); while (iterator.hasNext()) { String key = (String) iterator.next(); - dsNameChangedMap.put(key, map.get(key)); + dsNameChangedSet.add(new NameChangeBean(key, map.get(key))); } } @@ -157,15 +159,21 @@ public abstract class DesignTableDataManager { * @return 是则返回true */ public static boolean isDsNameChanged(String oldDsName) { - return dsNameChangedMap.containsKey(oldDsName); + for (NameChangeBean bean : dsNameChangedSet) { + if (ComparatorUtils.equals(oldDsName, bean.getOldName())) { + return true; + } + } + return false; } - public static String getChangedDsNameByOldDsName(String oldDsName) { - if (isDsNameChanged(oldDsName)) { - return dsNameChangedMap.get(oldDsName); - } else { - return StringUtils.EMPTY; + public static String getChangedDsNameByOldDsName(String dsName) { + for (NameChangeBean bean : dsNameChangedSet) { + if (ComparatorUtils.equals(dsName, bean.getOldName())) { + dsName = bean.getChangedName(); + } } + return dsName; } public static void addGlobalDsChangeListener(ChangeListener l) { diff --git a/designer-base/src/main/java/com/fr/design/data/NameChangeBean.java b/designer-base/src/main/java/com/fr/design/data/NameChangeBean.java new file mode 100644 index 0000000000..2d4caf44e3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/NameChangeBean.java @@ -0,0 +1,27 @@ +package com.fr.design.data; + +public class NameChangeBean { + private String oldName; + private String changedName; + + public NameChangeBean(String oldName, String changedName) { + this.oldName = oldName; + this.changedName = changedName; + } + + public String getOldName() { + return oldName; + } + + public void setOldName(String oldName) { + this.oldName = oldName; + } + + public String getChangedName() { + return changedName; + } + + public void setChangedName(String changedName) { + this.changedName = changedName; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java b/designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java new file mode 100644 index 0000000000..e2a75fc11b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java @@ -0,0 +1,136 @@ +package com.fr.design.data; + +import com.fr.base.io.IOFile; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.core.strategy.config.service.StrategyConfigService; +import com.fr.esd.core.strategy.persistence.StrategyConfigsAttr; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.event.xml.XMLSavedHook; +import com.fr.file.FILE; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2020/10/28 + */ +public class StrategyConfigAttrUtils { + + /** + * 获取当前编辑模版的数据集缓存配置属性 + * + * @return + */ + private static StrategyConfigsAttr getStrategyConfigsAttr() { + StrategyConfigsAttr attr; + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (jTemplate != null) { + IOFile ioFile = (IOFile) jTemplate.getTarget(); + + attr = ioFile.getAttrMark(StrategyConfigsAttr.ATTR_MARK); + if (attr == null) { + attr = new StrategyConfigsAttr(); + ioFile.addAttrMark(attr); + } + + //新建模版此时不存在,不需要注册钩子 + if (attr.getXmlSavedHook() == null && WorkContext.getWorkResource().exist(jTemplate.getPath())) { + attr.setXmlSavedHook(new StrategyConfigsAttrSavedHook(jTemplate.getPath(), attr)); + } + return attr; + } else { + throw new IllegalStateException("[ESD]No editing template found."); + } + } + + + /** + * 获取模版数据集配置 + * + * @param dsName + * @return + */ + public static StrategyConfig getStrategyConfig(String dsName) { + + return getStrategyConfigsAttr().getStrategyConfig(dsName); + } + + /** + * 移除模版数据集配置 + * + * @param dsName + * @return + */ + public static StrategyConfig removeStrategyConfig(String dsName) { + + return getStrategyConfigsAttr().removeStrategyConfig(dsName); + } + + /** + * 添加模版数据集配置 + * + * @param strategyConfig + */ + public static void addStrategyConfig(StrategyConfig strategyConfig) { + + getStrategyConfigsAttr().addStrategyConfig(strategyConfig); + } + + + private static class StrategyConfigsAttrSavedHook implements XMLSavedHook { + + private static final long serialVersionUID = -8843201977112289321L; + + private final String tplPath; + private final Map origStrategyConfigs; + + public StrategyConfigsAttrSavedHook(String tplPath, StrategyConfigsAttr raw) { + this.tplPath = tplPath; + this.origStrategyConfigs = new HashMap<>(); + this.initOrigStrategyConfigs(raw); + } + + + private void initOrigStrategyConfigs(StrategyConfigsAttr raw) { + origStrategyConfigs.clear(); + raw.getStrategyConfigs().forEach((k, v) -> { + try { + origStrategyConfigs.put(k, v.clone()); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + }); + } + + @Override + public void doAfterSaved(StrategyConfigsAttr saved) { + + FineLoggerFactory.getLogger().info("[ESD]Write StrategyConfigsAttr done, now check change."); + Set dsNames = new HashSet<>(); + dsNames.addAll(origStrategyConfigs.keySet()); + dsNames.addAll(saved.getStrategyConfigs().keySet()); + + if (StringUtils.isNotEmpty(tplPath)) { + dsNames.forEach(dsName -> { + if (StringUtils.isNotEmpty(dsName)) { + StrategyEventsNotifier.compareAndFireConfigEvents(origStrategyConfigs.get(dsName), saved.getStrategyConfig(dsName), new DSMapping(tplPath, new DsNameTarget(dsName))); + } + }); + } + + initOrigStrategyConfigs(saved); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java index f656105265..99a294fdde 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java @@ -1,12 +1,12 @@ package com.fr.design.data.datapane; import com.fr.base.TableData; -import com.fr.concurrent.NamedThreadFactory; import com.fr.data.core.DataCoreUtils; import com.fr.data.core.db.DBUtils; import com.fr.data.core.db.TableProcedure; import com.fr.data.core.db.dialect.Dialect; import com.fr.data.core.db.dialect.DialectFactory; +import com.fr.data.impl.Connection; import com.fr.data.impl.DBTableData; import com.fr.data.operator.DataOperator; import com.fr.design.DesignerEnvManager; @@ -19,7 +19,7 @@ import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.tabledata.Prepare4DataSourceChange; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.icombobox.FilterableComboBoxModel; -import com.fr.design.gui.icombobox.SearchPreTaskTreeComboBox; +import com.fr.design.gui.icombobox.TableSearchTreeComboBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIComboBoxEditor; import com.fr.design.gui.icombobox.UIComboBoxRenderer; @@ -40,11 +40,6 @@ import com.fr.stable.StringUtils; import com.fr.workspace.WorkContext; import com.fr.workspace.server.connection.DBConnectAuth; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Collections; -import java.util.concurrent.CancellationException; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -58,21 +53,20 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeCellRenderer; -import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; +import java.util.Collections; import java.util.List; import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; +import java.util.concurrent.CancellationException; /** * @author zhou @@ -97,41 +91,12 @@ public class ChoosePane extends BasicBeanPane implements Refresha /** * 表名 */ - protected SearchPreTaskTreeComboBox tableNameComboBox; - - private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("ChoosePane")); + protected TableSearchTreeComboBox tableNameComboBox; private SwingWorker populateWorker; private SwingWorker, Void> initWorker; - private PopupMenuListener popupMenuListener = new PopupMenuListener() { - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - FutureTask task = new FutureTask(new Callable() { - @Override - public Void call() throws Exception { - calculateTableDataNames(); - return null; - } - }); - tableNameComboBox.setPreSearchTask(task); - SERVICE.submit(task); - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - // Do nothing - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - // Do nothing - } - }; - - private PopupMenuListener listener = new PopupMenuListener() { @Override public void popupMenuCanceled(PopupMenuEvent e) { @@ -181,7 +146,7 @@ public class ChoosePane extends BasicBeanPane implements Refresha schemaBox = new StringUIComboBox(); schemaBox.setEditor(new ComboBoxEditor()); - tableNameComboBox = new SearchPreTaskTreeComboBox(new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer, false); + tableNameComboBox = new TableSearchTreeComboBox(this, new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer); tableNameComboBox.setEditable(true); tableNameComboBox.setRenderer(listCellRenderer); registerDSChangeListener(); @@ -198,7 +163,6 @@ public class ChoosePane extends BasicBeanPane implements Refresha }); schemaBox.addPopupMenuListener(listener); addFocusListener(); - this.tableNameComboBox.addPopupMenuListener(popupMenuListener); } protected void addDSBoxListener() { @@ -355,7 +319,7 @@ public class ChoosePane extends BasicBeanPane implements Refresha GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1); } - protected com.fr.data.impl.Connection getConnection() { + public Connection getConnection() { String selectedDSName = this.getDSName(); if (StringUtils.isEmpty(selectedDSName)) { return null; // peter:选中了当前的零长度的节点,直接返回. @@ -455,56 +419,6 @@ public class ChoosePane extends BasicBeanPane implements Refresha return "choosepane"; } - protected void calculateTableDataNames() { - JTree tree = tableNameComboBox.getTree(); - if (tree == null) { - return; - } - DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); - rootTreeNode.removeAllChildren(); - - String selectedDSName = this.getDSName(); - com.fr.data.impl.Connection selectedDatabase = this.getConnection(); - if (selectedDatabase == null) { - return; - } - try { - String schema = StringUtils.isEmpty(this.schemaBox.getSelectedItem()) ? null : this.schemaBox.getSelectedItem(); - TableProcedure[] sqlTableArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); - if (sqlTableArray.length > 0) { - ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); - rootTreeNode.add(tableTreeNode); - for (int i = 0; i < sqlTableArray.length; i++) { - ExpandMutableTreeNode tableChildTreeNode = new ExpandMutableTreeNode(sqlTableArray[i]); - tableTreeNode.add(tableChildTreeNode); - } - } - TableProcedure[] sqlViewArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); - if (sqlViewArray.length > 0) { - ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); - rootTreeNode.add(viewTreeNode); - for (int i = 0; i < sqlViewArray.length; i++) { - ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(sqlViewArray[i]); - viewTreeNode.add(viewChildTreeNode); - } - } - ((DefaultTreeModel) tree.getModel()).reload(); - // daniel 展开所有tree - TreeNode root = (TreeNode) tree.getModel().getRoot(); - TreePath parent = new TreePath(root); - TreeNode node = (TreeNode) parent.getLastPathComponent(); - for (Enumeration e = node.children(); e.hasMoreElements(); ) { - TreeNode n = (TreeNode) e.nextElement(); - TreePath path = parent.pathByAddingChild(n); - tree.expandPath(path); - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); - } - } - /** * 创建选中的数据集数据 * @@ -558,22 +472,23 @@ public class ChoosePane extends BasicBeanPane implements Refresha return tableData; } - protected String getDSName() { + public String getDSName() { return this.dsNameComboBox.getSelectedItem(); } + public String getSchema() { + return this.schemaBox.getSelectedItem(); + } + protected void failedToFindTable() { // Do nothing } protected String getTableName() { String tableName = ""; - Object obj = this.tableNameComboBox.getSelectedItemObject(); + Object obj = this.tableNameComboBox.getSelectedItem(); if (obj == null) { - obj = this.tableNameComboBox.getSelectedItem(); - if (obj == null) { - obj = this.tableNameComboBox.getEditor().getItem(); - } + obj = this.tableNameComboBox.getEditor().getItem(); } if (obj instanceof TreePath) { Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject(); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java index 14d0431e25..8fc62cd77a 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java @@ -83,7 +83,7 @@ public class ChoosePaneSupportFormula extends ChoosePane { * * @return */ - protected String getDSName() { + public String getDSName() { String selectedDSName = null; String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem()); // 没有选中的列表项 那么看看是不是手输值 diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java new file mode 100644 index 0000000000..1fd840ac78 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java @@ -0,0 +1,226 @@ +package com.fr.design.data.datapane; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.esd.common.CacheConstants; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.util.ESDUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; + +import javax.swing.AbstractAction; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2020/7/22 + */ +public class ESDStrategyConfigPane extends BasicBeanPane { + private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html"; + + private UIRadioButton selectAutoUpdate; + private UIRadioButton selectBySchema; + private UICheckBox shouldEvolve; + private UILabel updateIntervalCheckTips; + private UITextField updateInterval; + private UITextField schemaTime; + private ActionLabel actionLabel; + private UILabel schemaTimeCheckTips; + private final boolean global; + private StrategyConfig strategyConfig; + + + public ESDStrategyConfigPane(boolean global) { + this.global = global; + init(); + } + + private void init() { + setLayout(FRGUIPaneFactory.createM_BorderLayout()); + + this.selectAutoUpdate = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Every_Interval")); + + this.updateInterval = new UITextField(4); + this.shouldEvolve = new UICheckBox(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Auto_Evolved_Strategy"), false); + this.shouldEvolve.setEnabled(false); + this.updateIntervalCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Interval_Format")); + this.updateIntervalCheckTips.setForeground(Color.RED); + this.updateIntervalCheckTips.setVisible(false); + + this.selectBySchema = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron")); + this.schemaTime = new UITextField(10); + this.schemaTimeCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format")); + this.schemaTimeCheckTips.setVisible(false); + this.schemaTimeCheckTips.setForeground(Color.RED); + + + this.selectAutoUpdate.addActionListener(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + ESDStrategyConfigPane.this.selectBySchema.setSelected(!ESDStrategyConfigPane.this.selectAutoUpdate.isSelected()); + ESDStrategyConfigPane.this.schemaTime.setEnabled(false); + ESDStrategyConfigPane.this.updateInterval.setEnabled(true); + ESDStrategyConfigPane.this.shouldEvolve.setEnabled(true); + } + }); + + this.selectBySchema.addActionListener(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + ESDStrategyConfigPane.this.selectAutoUpdate.setSelected(!ESDStrategyConfigPane.this.selectBySchema.isSelected()); + ESDStrategyConfigPane.this.schemaTime.setEnabled(true); + ESDStrategyConfigPane.this.updateInterval.setEnabled(false); + ESDStrategyConfigPane.this.shouldEvolve.setEnabled(false); + } + }); + + JPanel pane = FRGUIPaneFactory.createVerticalTitledBorderPane(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Update_Strategy")); + add(pane, BorderLayout.NORTH); + + JPanel row1 = GUICoreUtils.createFlowPane(new Component[]{ + this.selectAutoUpdate, + this.updateInterval, + new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Minute_Update_Cache")), + this.shouldEvolve, + this.updateIntervalCheckTips + }, 0, 5); + pane.add(row1); + + ActionLabel actionLabel = new ActionLabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron_Help")); + actionLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + Desktop.getDesktop().browse(new URI(CRON_HELP_URL)); + } catch (Exception exp) { + FineLoggerFactory.getLogger().error(exp.getMessage(), e); + } + } + }); + + JPanel row2 = GUICoreUtils.createFlowPane(new Component[]{ + this.selectBySchema, + this.schemaTime, + actionLabel, + this.schemaTimeCheckTips + }, 0, 5); + pane.add(row2); + } + + + public void populateBean(StrategyConfig ob) { + + if (ob == null && !global) { + ob = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + this.strategyConfig = ob; + + this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.valueOf(ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE)); + this.schemaTime.setText(StringUtils.join(",", ob.getUpdateSchema().toArray(new String[0]))); + this.shouldEvolve.setSelected(ob.shouldEvolve()); + this.selectBySchema.setSelected(ob.isScheduleBySchema()); + this.selectAutoUpdate.setSelected(!ob.isScheduleBySchema()); + + if (global) { + //使用全局配置,禁用面板编辑 + disablePane(); + } else { + setSchemaEnable(!this.selectAutoUpdate.isSelected()); + } + } + + + private void disablePane() { + this.selectAutoUpdate.setEnabled(false); + this.updateInterval.setEnabled(false); + this.shouldEvolve.setEnabled(false); + + this.selectBySchema.setEnabled(false); + this.schemaTime.setEnabled(false); + } + + private void setSchemaEnable(boolean enable) { + this.updateInterval.setEnabled(!enable); + this.shouldEvolve.setEnabled(!enable); + + this.schemaTime.setEnabled(enable); + } + + + public StrategyConfig updateBean() { + StrategyConfig config = null; + if (!this.global) { + try { + //这里是new的config + config = this.strategyConfig.clone(); + + if (this.selectBySchema.isSelected()) { + List schemaTimes = new ArrayList<>(); + String text = this.schemaTime.getText(); + + if (ESDUtils.checkUpdateTimeSchema(text)) { + if (ESDUtils.isCronExpression(text)) { + schemaTimes.add(text); + } else { + Collections.addAll(schemaTimes, text.split(",")); + } + } else { + this.schemaTimeCheckTips.setVisible(true); + throw new IllegalArgumentException("[ESD]Update schema time format error."); + } + config.setScheduleBySchema(true); + config.setUpdateSchema(schemaTimes); + } else { + String interval = this.updateInterval.getText(); + if (checkUpdateInterval(interval)) { + long intervalMillis = StringUtils.isEmpty(interval) ? 0 : (long) (Double.parseDouble(interval) * CacheConstants.MILLIS_OF_MINUTE); + config.setUpdateInterval(intervalMillis); + } else { + this.updateIntervalCheckTips.setVisible(true); + throw new IllegalArgumentException("[ESD]Error update interval format."); + } + + config.setShouldEvolve(this.shouldEvolve.isSelected()); + config.setScheduleBySchema(false); + } + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + return config; + } + + + private boolean checkUpdateInterval(String intervalValue) { + try { + return !StringUtils.isEmpty(intervalValue) && !(Double.parseDouble(intervalValue) <= 0); + } catch (NumberFormatException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + return false; + } + + + protected String title4PopupWindow() { + return InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Strategy_Config_Title"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java index 8972821b43..87e322b266 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java @@ -1,36 +1,44 @@ package com.fr.design.data.datapane; import com.fr.base.TableData; +import com.fr.base.TableDataBean; +import com.fr.config.RemoteConfigEvent; import com.fr.data.TableDataSource; import com.fr.data.api.StoreProcedureAssist; import com.fr.data.impl.storeproc.StoreProcedure; import com.fr.design.data.BasicTableDataUtils; import com.fr.design.data.DesignTableDataManager; 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.NameableCreator; import com.fr.design.gui.ilist.ListModelElement; import com.fr.design.i18n.Toolkit; +import com.fr.event.EventDispatcher; import com.fr.file.ProcedureConfig; import com.fr.file.TableDataConfig; +import com.fr.file.TableDataOperator; +import com.fr.file.TableDataOperatorImpl; import com.fr.general.ComparatorUtils; import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; +import com.fr.rpc.ExceptionHandler; +import com.fr.rpc.RPCInvokerExceptionInfo; import com.fr.stable.ArrayUtils; import com.fr.stable.Nameable; import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.third.org.apache.commons.collections4.MapUtils; +import com.fr.workspace.WorkContext; -import javax.swing.*; +import javax.swing.DefaultListModel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; /** * TableDataList Pane. @@ -46,15 +54,12 @@ public class TableDataPaneListPane extends JListControlPane implements TableData @Override public void propertyChange() { isNamePermitted = true; - String tempName = getEditingName(); - if (ComparatorUtils.equals(tempName, selectedName)) { - //说明双击之后又取消了,啥也不用做 + if (!checkName()) { + isNamePermitted = false; return; } - Set allDSNames = DesignTableDataManager.getGlobalDataSet().keySet(); - String[] allListNames = nameableList.getAllNames(); - allListNames[editingIndex] = StringUtils.EMPTY; + String tempName = getEditingName(); Object editingType = getEditingType(); if (!BasicTableDataUtils.checkName(tempName)) { @@ -64,35 +69,36 @@ public class TableDataPaneListPane extends JListControlPane implements TableData return; } - if (StringUtils.isEmpty(tempName)) { - isNamePermitted = false; - nameableList.stopEditing(); - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), - Toolkit.i18nText("Fine-Design_Basic_Table_Data_Empty_Name_Tips"), - Toolkit.i18nText("Fine-Design_Report_Alert"), - JOptionPane.WARNING_MESSAGE); - setIllegalIndex(editingIndex); - return; - } - boolean isRepeated = isNameRepeated(new Collection[]{allDSNames, Arrays.asList(allListNames)}, tempName); - if (isRepeated) { - isNamePermitted = false; - nameableList.stopEditing(); - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Table_Data_Duplicate_Name_Tips", tempName)); - setIllegalIndex(editingIndex); - } else if (editingType instanceof StoreProcedure && isIncludeUnderline(tempName)) { + if (editingType instanceof StoreProcedure && isIncludeUnderline(tempName)) { isNamePermitted = false; nameableList.stopEditing(); FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Stored_Procedure_Name_Tips")); setIllegalIndex(editingIndex); + return; } + if (nameableList.getSelectedValue() instanceof ListModelElement) { - rename(selectedName, isRepeated ? NameInspector.ILLEGAL_NAME_HOLDER : tempName); + rename(selectedName, tempName); } } }); } + @Override + public String getEmptyNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Table_Data_Empty_Name_Tips"); + } + + @Override + public String getDuplicatedNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Table_Data_Duplicate_Name_Tips", getEditingName()); + } + + @Override + public Collection getExtraItemsToCheckNameRepeat() { + return DesignTableDataManager.getGlobalDataSet().keySet(); + } + @Override public void rename(String oldName, String newName) { //如果a改成了b,b又被改成了c,就认为是a改成了c @@ -231,15 +237,40 @@ public class TableDataPaneListPane extends JListControlPane implements TableData @Override public void update(TableDataConfig tableDataConfig) { - tableDataConfig.removeAllTableData(); - ProcedureConfig.getInstance().removeAllProcedure(); Nameable[] tableDataArray = this.update(); - Map tableDataMap = new LinkedHashMap(); + List tableDataBeans = new ArrayList<>(); + Map map = MapUtils.invertMap(getDsNameChangedMap()); for (int i = 0; i < tableDataArray.length; i++) { NameObject nameObject = (NameObject) tableDataArray[i]; - tableDataMap.put(nameObject.getName(), (TableData) nameObject.getObject()); + String oldName = map.get(nameObject.getName()); + if (oldName == null) { + oldName = StringUtils.EMPTY; + } + tableDataBeans.add(new TableDataBean(nameObject.getName(), oldName, (TableData) nameObject.getObject())); + } + try { + WorkContext.getCurrent().get(TableDataOperator.class, new ExceptionHandler() { + @Override + public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) { + // 走老的方式 + return saveByOldWay(tableDataBeans); + } + }).saveTableData(new ArrayList<>(tableDataConfig.getTableDatas().keySet()), tableDataBeans); + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.fire(RemoteConfigEvent.EDIT, TableDataConfig.getInstance().getNameSpace()); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + private boolean saveByOldWay(List tableDataBean) { + try { + return TableDataOperatorImpl.getInstance().saveTableData(tableDataBean); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; } - tableDataConfig.setTableDatas(tableDataMap); } @Override diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java index 31630b85c0..5a63666023 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java @@ -2,60 +2,89 @@ package com.fr.design.data.datapane; import com.fr.base.TableData; import com.fr.data.TableDataSource; +import com.fr.data.impl.DBTableData; import com.fr.data.impl.TableDataSourceDependent; import com.fr.design.DesignModelAdapter; +import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.constants.UIConstants; import com.fr.design.data.BasicTableDataTreePane; import com.fr.design.data.BasicTableDataUtils; import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.StrategyConfigAttrUtils; import com.fr.design.data.tabledata.StoreProcedureWorkerListener; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; import com.fr.design.dialog.BasicDialog; -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.fun.TableDataPaneProcessor; import com.fr.design.gui.ibutton.UIHeadGroup; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.i18n.Toolkit; import com.fr.design.icon.IconPathConstants; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.LineSeparator; import com.fr.design.menu.MenuDef; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ToolBarDef; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.query.StrategicTableData; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; +import com.fr.general.IOUtils; import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContext; import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; +import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.workspace.WorkContext; +import org.jetbrains.annotations.NotNull; import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.ToolTipManager; +import javax.swing.tree.TreePath; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.GridLayout; import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; public class TableDataTreePane extends BasicTableDataTreePane { - private static TableDataTreePane singleton = new TableDataTreePane(); + private static final TableDataTreePane singleton = new TableDataTreePane(); public static final int PLUGIN_LISTENER_PRIORITY = 1; @@ -77,31 +106,45 @@ public class TableDataTreePane extends BasicTableDataTreePane { } private TableDataSourceOP op; - private TableDataTree dataTree; + private TableDataTree tableDataTree; private EditAction editAction; private RemoveAction removeAction; + private EsdOnAction esdAction; + private EsdOffAction esdOffAction; private PreviewTableDataAction previewTableDataAction; + private JPanel serverDatasetAuthTipJPanel = new JPanel(); private TableDataTreePane() { + initPane(); + } + + private void initPane() { this.setLayout(new BorderLayout(4, 0)); this.setBorder(null); - dataTree = new TableDataTree(); - ToolTipManager.sharedInstance().registerComponent(dataTree); + + //TableDataTree + tableDataTree = new TableDataTree(); + ToolTipManager.sharedInstance().registerComponent(tableDataTree); ToolTipManager.sharedInstance().setDismissDelay(3000); ToolTipManager.sharedInstance().setInitialDelay(0); - addMenuDef = new MenuDef(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Action_Add")); - addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + + addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); + addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); createAddMenuDef(); // 创建插件监听 createPluginListener(); editAction = new EditAction(); removeAction = new RemoveAction(); - previewTableDataAction = new PreviewTableDataAction(dataTree); + previewTableDataAction = new PreviewTableDataAction(tableDataTree); connectionTableAction = new ConnectionTableAction(); + esdAction = new EsdOnAction(); + esdOffAction = new EsdOffAction(); + + toolbarDef = new ToolBarDef(); - toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction); + toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction); UIToolbar toolBar = ToolBarDef.createJToolBar(); toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); toolBar.setBorderPainted(true); @@ -111,33 +154,72 @@ public class TableDataTreePane extends BasicTableDataTreePane { toolbarPane.add(toolBar, BorderLayout.CENTER); this.add(toolbarPane, BorderLayout.NORTH); - UIScrollPane scrollPane = new UIScrollPane(dataTree); + UIScrollPane scrollPane = new UIScrollPane(tableDataTree); scrollPane.setBorder(null); - initbuttonGroup(); + initServerDatasetAuthTipJPanel(); + initButtonGroup(); JPanel jPanel = new JPanel(new BorderLayout(0, 0)); - JPanel buttonPane = new JPanel(new GridLayout()); + JPanel buttonPane = new JPanel(FRGUIPaneFactory.createBorderLayout()); buttonPane.add(buttonGroup, BorderLayout.CENTER); + buttonPane.add(serverDatasetAuthTipJPanel, BorderLayout.SOUTH); jPanel.add(buttonPane, BorderLayout.NORTH); jPanel.add(scrollPane, BorderLayout.CENTER); this.add(jPanel, BorderLayout.CENTER); - dataTree.addMouseListener(new MouseAdapter() { + tableDataTree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { checkButtonEnabled(); } }); - dataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, dataTree)); + tableDataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, tableDataTree)); // TreeCellEditor - dataTree.setEditable(true); - TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), dataTree, this); + tableDataTree.setEditable(true); + TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this); treeCellEditor.addCellEditorListener(treeCellEditor); - dataTree.setCellEditor(treeCellEditor); - new TableDataTreeDragSource(dataTree, DnDConstants.ACTION_COPY); + tableDataTree.setCellEditor(treeCellEditor); + new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY); checkButtonEnabled(); } - private void createPluginListener() { + private void initServerDatasetAuthTipJPanel() { + String datasetAuthTip = Toolkit.i18nText("Fine-Design_Server_Dataset_Auth_Tip"); + List lineTips = new ArrayList(Arrays.asList(datasetAuthTip.split("\n"))); + if (datasetAuthTip.endsWith("\n")) { + lineTips.add(StringUtils.EMPTY); + } + serverDatasetAuthTipJPanel = new JPanel(); + serverDatasetAuthTipJPanel.setLayout(new GridLayout(lineTips.size(), 1)); + for (int i = 0; i < lineTips.size(); i++) { + String lineTip = lineTips.get(i); + List jLabels = new ArrayList<>(); + JLabel lineJLabel = new JLabel(lineTip); + lineJLabel.setForeground(Color.lightGray); + jLabels.add(lineJLabel); + if (i == (lineTips.size() - 1)) { + JLabel jLabel = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Alphafine_No_Remind")); + jLabel.setForeground(Color.blue); + jLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + DesignerEnvManager.getEnvManager().setShowServerDatasetAuthTip(false); + serverDatasetAuthTipJPanel.setVisible(false); + } + }); + jLabels.add(jLabel); + } + serverDatasetAuthTipJPanel.add(getLineTipJPanel(jLabels)); + } + } + + private JPanel getLineTipJPanel(List jLabels) { + JPanel jPanel = new JPanel(FRGUIPaneFactory.createLabelFlowLayout()); + for (JLabel jLabel : jLabels) { + jPanel.add(jLabel); + } + return jPanel; + } + private void createPluginListener() { //菜单栏监听 GeneralContext.listenPluginRunningChanged(new PluginEventListener(PLUGIN_LISTENER_PRIORITY) { @@ -157,69 +239,113 @@ public class TableDataTreePane extends BasicTableDataTreePane { }); } - - protected void checkButtonEnabled() { - super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, dataTree); - } - /** * 刷新 */ + @Override public void refreshDockingView() { populate(new TableDataSourceOP(tc)); this.checkButtonEnabled(); } - protected void initbuttonGroup() { -// Icon[] iconArray = {BaseUtils.readIcon("/com/fr/design/images/data/datasource.png"), BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png")}; - final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA}; - String[] textArray = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")}; - buttonGroup = new UIHeadGroup(textArray) { - public void tabChanged(int index) { - if (op != null) { - op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); - addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA ? true : false); - refreshDockingView(); - } + + @Override + public final void createAddMenuDef() { + TableDataNameObjectCreator[] creators = TableDataCreatorProducer.getInstance().createReportTableDataCreator(); + for (final TableDataNameObjectCreator creator : creators) { + if (creator.shouldInsertSeparator()) { + addMenuDef.addShortCut(new LineSeparator()); } - }; - buttonGroup.setNeedLeftRightOutLine(false); + + addMenuDef.addShortCut(new AddAction() { + @Override + protected String getTDName() { + return creator.menuName(); + } + + @Override + protected Icon getTDIcon() { + return creator.menuIcon(); + } + + @Override + protected String getNamePrefix() { + return creator.getPrefix(); + } + + @Override + protected TemplateTableDataWrapper getTableDataInstance() { + TableData tableData = (TableData) creator.createObject(); + + //11中所有数据集都是StrategicTableData的子类 + if (tableData instanceof StrategicTableData) { + StrategicTableData std = (StrategicTableData) tableData; + tableData = StrategicTableData.Binder + .bind(std) + .setDsName(createDsName(creator.getPrefix())) + .setScope(StrategicTableData.Scope.TEMPLATE) + .done(); + } + return new TemplateTableDataWrapper(tableData); + } + }); + } } /** * 编辑面板 * - * @param uPanel 面板 - * @param originalName 原始名字 + * @param tableDataPane 面板 + * @param originalName 原始名字 */ - public void dgEdit(final AbstractTableDataPane uPanel, String originalName, boolean isUpdate) { - uPanel.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { + @Override + public void dgEdit(final AbstractTableDataPane tableDataPane, String originalName, boolean isUpdate) { + tableDataPane.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { public void fireDoneAction() { - if (dataTree.getSelectionPath() == null) { - dataTree.refresh(); + if (tableDataTree.getSelectionPath() == null) { + tableDataTree.refresh(); } else { - Object object = dataTree.getSelectionPath().getLastPathComponent(); - int[] rows = dataTree.getSelectionRows(); - dataTree.refreshChildByName(object.toString()); - dataTree.setSelectionRows(rows); + Object object = tableDataTree.getSelectionPath().getLastPathComponent(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(object.toString()); + tableDataTree.setSelectionRows(rows); } } }); - final BasicPane.NamePane nPanel = uPanel.asNamePane(); - nPanel.setObjectName(originalName); + final NamePane tdNamePanel = tableDataPane.asNamePane(); + tdNamePanel.setObjectName(originalName); + final String oldName = originalName; - final BasicDialog dg; allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); - dg = nPanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { + + final BasicDialog dg = tdNamePanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { + @Override public void doOk() { DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); - tc.renameTableData(oldName, nPanel.getObjectName(), false); + tc.renameTableData(oldName, tdNamePanel.getObjectName(), false); TableDataSource tds = tc.getBook(); - TableData td = uPanel.updateBean(); + TableData td = tableDataPane.updateBean(); if (td instanceof TableDataSourceDependent) { ((TableDataSourceDependent) td).setTableDataSource(tds); } - String tdName = nPanel.getObjectName(); + String tdName = tdNamePanel.getObjectName(); + + + //模版还没保存的时候不知道后缀,不能设置到策略配置里面 + if (tableDataPane instanceof DBTableDataPane) { + StrategyConfig editingConfig = ((DBTableDataPane) tableDataPane).updateStrategyConfig(); + if (editingConfig != null) { + editingConfig.setDsName(tdName); + if (!ComparatorUtils.equals(oldName, tdName)) { + //重命名 + StrategyConfigAttrUtils.removeStrategyConfig(oldName); + } + + StrategyConfigAttrUtils.addStrategyConfig(editingConfig); + } + ((DBTableData) td).setDsName(tdName); + } + tds.putTableData(tdName, td); Map map = new HashMap(); if (!ComparatorUtils.equals(oldName, tdName)) { @@ -227,83 +353,42 @@ public class TableDataTreePane extends BasicTableDataTreePane { } fireDSChanged(map); tc.fireTargetModified(); - tc.tableDataParametersChanged(oldName, tdName, td); - int[] rows = dataTree.getSelectionRows(); - dataTree.refreshChildByName(tdName); - dataTree.setSelectionRows(rows); + tc.parameterChanged(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + + + //单独编辑数据集关闭,修改缓存配置状态,刷新下一键开启/关闭按钮 + checkButtonEnabled(); + + if (listener != null) { + listener.doOk(); + } + } + + @Override + public void doCancel() { + super.doCancel(); + if (listener != null) { + listener.doCancel(); + } } }); - nPanel.addPropertyChangeListener(new PropertyChangeAdapter() { + tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() { @Override public void propertyChange() { - doPropertyChange(dg, nPanel, oldName); + doPropertyChange(dg, tdNamePanel, oldName); } }); dg.setVisible(true); } - private class EditAction extends UpdateAction { - public EditAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Edit")); - this.setMnemonic('E'); - this.setSmallIcon("/com/fr/design/images/control/edit"); - } - - public void actionPerformed(ActionEvent e) { - final NameObject selectedNO = dataTree.getSelectedNameObject(); - if (selectedNO == null) { - return; - } - DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); - dgEdit(((AbstractTableDataWrapper) selectedNO.getObject()).creatTableDataPane(), selectedNO.getName(), false); - } - } - - private class RemoveAction extends UpdateAction { - - public RemoveAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove")); - this.setMnemonic('R'); - this.setSmallIcon("/com/fr/design/images/control/remove"); - } - - @Override - public void actionPerformed(ActionEvent e) { - NameObject selectedNO = dataTree.getSelectedNameObject(); - - if (selectedNO == null) { - return; - } - - int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + ":" + selectedNO.getName() + "?", - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - if (returnVal == JOptionPane.OK_OPTION) { - // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 - op.removeAction(selectedNO.getName()); - dataTree.refresh(); - // Richie:默认最后一行获得焦点. - dataTree.requestFocus(); - dataTree.setSelectionRow(dataTree.getRowCount() - 1); - fireDSChanged(); - checkButtonEnabled(); - DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); - DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName()); - } - } - } - - private void populate(TableDataSourceOP op) { - this.op = op; - dataTree.populate(op); - checkButtonEnabled(); - } - - - /** - * @return - */ - public TableDataTree getDataTree() { - return dataTree; + @Override + public void removeTableData(String sourceName) { + TableDataSource tds = this.tc.getBook(); + tds.removeTableData(sourceName); + this.tableDataTree.refresh(); } /** @@ -312,6 +397,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { * @param srcName 数据集来源(比如报表块,就是报表块的名称) * @param tableDataSource 数据集 */ + @Override public Map addTableData(String srcName, TableDataSource tableDataSource, boolean isCover) { Map tdNameMap = new HashMap<>(); allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); @@ -322,39 +408,63 @@ public class TableDataTreePane extends BasicTableDataTreePane { String tdName = (String) tdIterator.next(); String oldName = tdName; TableData td = tableDataSource.getTableData(tdName); - boolean isDsNameRepeaded = isDsNameRepeaded(tdName); - tdName = BasicTableDataUtils.getTableDataName(isCover, tds, tdName, srcName, isDsNameRepeaded); + boolean isDsNameRepeated = isDsNameRepeaded(tdName); + tdName = BasicTableDataUtils.getTableDataName(isCover, tds, tdName, srcName, isDsNameRepeated); tds.putTableData(tdName, td); if (!ComparatorUtils.equals(oldName, tdName)) { tdNameMap.put(oldName, tdName); } } tc.parameterChanged(); - dataTree.refresh(); + tableDataTree.refresh(); return Collections.unmodifiableMap(tdNameMap); } + /** + * 合并数据集 + * + * @param srcName 数据集来源(比如报表块,就是报表块的名称) + * @param tableDataSource 数据集 + */ @Override - public void removeTableData(String sourceName) { + public Map addTableData(String srcName, TableDataSource tableDataSource) { + Map tdNameMap = new HashMap<>(); + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); TableDataSource tds = tc.getBook(); - tds.removeTableData(sourceName); - dataTree.refresh(); + Iterator tdIterator = tableDataSource.getTableDataNameIterator(); + while (tdIterator.hasNext()) { + String tdName = tdIterator.next(); + String oldName = tdName; + TableData td = tableDataSource.getTableData(tdName); + if (tds.getTableData(tdName) != null || isDsNameRepeaded(tdName)) { + //如果有同名的就拼上来源名称 + tdName = srcName + tdName; + } + int i = 0; + while (tds.getTableData(tdName) != null) { + i++;//如果拼上名字后依然已经存在就加编号 + tdName += i; + } + tds.putTableData(tdName, td); + if (!ComparatorUtils.equals(oldName, tdName)) { + tdNameMap.put(oldName, tdName); + } + } + tc.parameterChanged(); + tableDataTree.refresh(); + return Collections.unmodifiableMap(tdNameMap); } @Override - public void checkEnable() { - this.checkButtonEnabled(); - } - public void addDataPane(final AbstractTableDataPane uPanel, String paneName) { final NamePane nPanel = uPanel.asNamePane(); nPanel.setObjectName(paneName); - final String oldName = paneName; allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); - tc.renameTableData(oldName, nPanel.getObjectName(), false); + tc.renameTableData(paneName, nPanel.getObjectName(), false); TableDataSource tds = tc.getBook(); TableData td = uPanel.updateBean(); if (td instanceof TableDataSourceDependent) { @@ -363,14 +473,429 @@ public class TableDataTreePane extends BasicTableDataTreePane { String tdName = nPanel.getObjectName(); tds.putTableData(tdName, td); Map map = new HashMap(); - if (!ComparatorUtils.equals(oldName, tdName)) { - map.put(oldName, tdName); + if (!ComparatorUtils.equals(paneName, tdName)) { + map.put(paneName, tdName); } fireDSChanged(map); tc.fireTargetModified(); - tc.tableDataParametersChanged(oldName, tdName, td); - int[] rows = dataTree.getSelectionRows(); - dataTree.refreshChildByName(tdName); - dataTree.setSelectionRows(rows); + tc.parameterChanged(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + } + + @Override + public TableDataTree getDataTree() { + return this.tableDataTree; + } + + private void populate(TableDataSourceOP op) { + this.op = op; + tableDataTree.populate(op); + checkButtonEnabled(); + } + + + private void resetAddMenuDef() { + this.addMenuDef.clearShortCuts(); + this.createAddMenuDef(); + } + + private void checkButtonEnabled() { + super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, tableDataTree); + this.checkESDComponentsEnabled(); + } + + + private void checkESDComponentsEnabled() { + if (buttonGroup.getSelectedIndex() == 1) { + //切换到服务器数据集的tab,禁用 + esdAction.setEnabled(false); + esdOffAction.setEnabled(false); + return; + } + + new SwingWorker() { + @Override + protected ButtonStatus doInBackground() throws Exception { + ButtonStatus btnStatus = new ButtonStatus(); + Map statusMap = checkCanBeEsdBatchEnableStatus(); + if (statusMap.size() == 0) { + //没有db数据集 + return btnStatus; + } else { + int canTurnOnCount = 0; + int canTurnOffCount = 0; + for (ESDStatus status : statusMap.values()) { + switch (status) { + case GLOBAL_ON: + case GLOBAL_OFF: + case SINGLE_OFF: + canTurnOnCount++; + break; + case SINGLE_ON: + canTurnOffCount++; + break; + default: + break; + } + } + btnStatus.setOnStatus(canTurnOnCount > 0); + btnStatus.setOffStatus(canTurnOffCount > 0); + } + return btnStatus; + } + + @Override + protected void done() { + try { + ButtonStatus buttonStatus = get(); + esdAction.setEnabled(buttonStatus.isOnStatus()); + esdOffAction.setEnabled(buttonStatus.isOffStatus()); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error("get esd status of ds error for " + e.getMessage(), e); + } + } + }.execute(); + } + + private static class ButtonStatus { + private boolean onStatus = false; + private boolean offStatus = false; + + public boolean isOnStatus() { + return onStatus; + } + + public void setOnStatus(boolean onStatus) { + this.onStatus = onStatus; + } + + public boolean isOffStatus() { + return offStatus; + } + + public void setOffStatus(boolean offStatus) { + this.offStatus = offStatus; + } + } + + //模版数据集 + private void initButtonGroup() { + final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA}; + String[] textArray = {Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")}; + buttonGroup = new UIHeadGroup(textArray) { + public void tabChanged(int index) { + if (isShowServerDatasetAuthTipJPanel(textArray[index])) { + serverDatasetAuthTipJPanel.setVisible(true); + } else { + serverDatasetAuthTipJPanel.setVisible(false); + } + if (op != null) { + op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); + addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA); + refreshDockingView(); + + } + } + + private boolean isShowServerDatasetAuthTipJPanel(String name) { + if (ComparatorUtils.equals(name, Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")) + && DesignerEnvManager.getEnvManager().isShowServerDatasetAuthTip() + && !WorkContext.getCurrent().isLocal()) { + return true; + } + return false; + } + }; + buttonGroup.setNeedLeftRightOutLine(false); + } + + + private TableDataWrapper findTableDataWrapper(TreePath treePath) { + if (treePath != null) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) treePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + NameObject nameObject = null; + if (selectedUserObject instanceof NameObject) { + nameObject = (NameObject) selectedUserObject; + } else { + selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + nameObject = (NameObject) selectedUserObject; + } + } + if (nameObject != null && nameObject.getObject() instanceof TableDataWrapper) { + return (TableDataWrapper) nameObject.getObject(); + } + } + + return null; + } + + private String getTplPath() { + return HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getPath(); + } + + enum ESDStatus { + GLOBAL_ON, + GLOBAL_OFF, + SINGLE_ON, + SINGLE_OFF; + } + + + private Map checkCanBeEsdBatchEnableStatus() { + //<数据集, 是否可以被单独开启> + Map result = new HashMap<>(); + for (int i = 0; i < tableDataTree.getRowCount(); i++) { + TreePath treePath = tableDataTree.getPathForRow(i); + + TableDataWrapper wrapper = findTableDataWrapper(treePath); + if (wrapper.getTableData() instanceof DBTableData) { + DBTableData td = (DBTableData) wrapper.getTableData(); + + StrategyConfig config = StrategyConfigAttrUtils.getStrategyConfig(wrapper.getTableDataName()); + if (config == null) { + result.put(td, td.isShare() ? ESDStatus.SINGLE_ON : ESDStatus.SINGLE_OFF); + } else { + if (config.isUseGlobal()) { + if (StrategyConfigHelper.recommended(getTplPath())) { + result.put(td, ESDStatus.GLOBAL_ON); + } else { + result.put(td, ESDStatus.GLOBAL_OFF); + } + } else { + if (config.enabled()) { + result.put(td, ESDStatus.SINGLE_ON); + } else { + result.put(td, ESDStatus.SINGLE_OFF); + } + } + } + } + } + + return result; + } + + + private class EsdOnAction extends AbstractESDAction { + + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_ESD_Batch_Enable"); + } + + @Override + public Icon getIcon() { + return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_on.png"); + } + + @Override + public void doWithTableDataWrapper(TableDataWrapper wrapper) { + String dsName = wrapper.getTableDataName(); + if (wrapper.getTableData() instanceof DBTableData) { + StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName); + strategyConfig.setEnable(true); + strategyConfig.setUseGlobal(false); + StrategyConfigAttrUtils.addStrategyConfig(strategyConfig); + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); + } + } + } + + private @NotNull StrategyConfig getOrCreateStrategyConfig(String dsName) { + StrategyConfig config = StrategyConfigAttrUtils.getStrategyConfig(dsName); + + if (config == null) { + config = StrategyConfigHelper.createStrategyConfig(true); + config.setDsName(dsName); + } + + return config; + } + + + private String createDsName(String prefix) { + int count = 1; + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + while (isDsNameRepeaded(prefix + count)) { + count++; + } + return prefix + count; + } + + + private class EsdOffAction extends AbstractESDAction { + + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_ESD_Batch_Disable"); + } + + @Override + public Icon getIcon() { + return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_off.png"); + } + + @Override + public void doWithTableDataWrapper(TableDataWrapper wrapper) { + String dsName = wrapper.getTableDataName(); + if (wrapper.getTableData() instanceof DBTableData) { + ((DBTableData) wrapper.getTableData()).setShare(false); + StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName); + strategyConfig.setEnable(false); + strategyConfig.setUseGlobal(false); + StrategyConfigAttrUtils.addStrategyConfig(strategyConfig); + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); + } + } + } + + private abstract class AbstractESDAction extends UpdateAction { + + public abstract String getName(); + + public abstract Icon getIcon(); + + public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper); + + public AbstractESDAction() { + this.setName(getName()); + this.setMnemonic('R'); + this.setSmallIcon(getIcon()); + } + + @Override + public void actionPerformed(ActionEvent e) { + List tableDataWrapperList = new ArrayList<>(); + + for (int i = 0; i < tableDataTree.getRowCount(); i++) { + TreePath treePath = tableDataTree.getPathForRow(i); + TableDataWrapper wrapper = findTableDataWrapper(treePath); + if (wrapper != null) { + tableDataWrapperList.add(wrapper); + } + } + if (tableDataWrapperList.isEmpty()) { + return; + } + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + for (TableDataWrapper tableDataWrapper : tableDataWrapperList) { + doWithTableDataWrapper(tableDataWrapper); + } + return null; + } + + @Override + protected void done() { + refreshDockingView(); + } + }.execute(); + } + } + + + /** + * 新建数据集 + *

+ * 抽象化,支持不同类型数据集创建 + */ + private abstract class AddAction extends UpdateAction { + + protected abstract String getTDName(); + + protected abstract Icon getTDIcon(); + + protected abstract String getNamePrefix(); + + protected abstract TemplateTableDataWrapper getTableDataInstance(); + + public AddAction() { + this.setName(this.getTDName()); + this.setSmallIcon(this.getTDIcon()); + } + + @Override + public void actionPerformed(ActionEvent e) { + dgEdit(getTableDataInstance().creatTableDataPane(), createDsName(getNamePrefix()), false); + } + } + + + private class EditAction extends UpdateAction { + public EditAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit")); + this.setMnemonic('E'); + this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + final NameObject selectedNO = tableDataTree.getSelectedNameObject(); + if (selectedNO == null) { + return; + } + + String dsName = selectedNO.getName(); + DesignTableDataManager.removeSelectedColumnNames(dsName); + + AbstractTableDataWrapper wrapper = (AbstractTableDataWrapper) selectedNO.getObject(); + + AbstractTableDataPane tableDataPane = wrapper.creatTableDataPane(); + + //下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name + dgEdit(tableDataPane, dsName, false); + } + } + + private class RemoveAction extends UpdateAction { + + public RemoveAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); + this.setMnemonic('R'); + this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject selectedNO = tableDataTree.getSelectedNameObject(); + + if (selectedNO == null) { + return; + } + + int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + ":" + selectedNO.getName() + "?", + Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (returnVal == JOptionPane.OK_OPTION) { + // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 + op.removeAction(selectedNO.getName()); + tableDataTree.refresh(); + // Richie:默认最后一行获得焦点. + tableDataTree.requestFocus(); + tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1); + fireDSChanged(); + checkButtonEnabled(); + + //删掉缓存配置 + StrategyConfigAttrUtils.removeStrategyConfig(selectedNO.getName()); + + // 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样 + // 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效 + // 这里额外发出一次数据集修改事件 + StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName()))); + DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); + DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName()); + } + } + } + + @Override + public void checkEnable() { + this.checkButtonEnabled(); } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java index 8964ff8de0..422a3a49a8 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java @@ -9,6 +9,7 @@ import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIComboBoxRenderer; import com.fr.file.TableDataConfig; +import com.fr.stable.StringUtils; import javax.swing.*; import java.awt.*; @@ -80,12 +81,13 @@ public class TreeTableDataComboBox extends UIComboBox { } public void setSelectedTableDataByName(String name) { + refresh(); TableDataWrapper tableDataWrapper; - if (res_map.get(name) != null) { - tableDataWrapper = res_map.get(name); - } else { - String changeName = DesignTableDataManager.getChangedDsNameByOldDsName(name); + String changeName = DesignTableDataManager.getChangedDsNameByOldDsName(name); + if (StringUtils.isNotEmpty(changeName)) { tableDataWrapper = res_map.get(changeName); + } else { + tableDataWrapper = res_map.get(name); } this.getModel().setSelectedItem(tableDataWrapper); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java index f1f1c6c75e..175ddbfda3 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java @@ -64,7 +64,7 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { tableFlowPane.add(tableDataNameComboBox); tableDataNameComboBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { - tdChange(); + tdChange(true); } }); tableFlowPane.add(new PreviewLabel(this)); @@ -73,19 +73,21 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { this.add(centerPane, BorderLayout.CENTER); parentMarkRadio = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Build_Tree_Accord_Parent_Marked_Filed"), true); lengthMarkRadio = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Build_Tree_Accord_Marked_Filed_Length")); - parentMarkRadio.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { + parentMarkRadio.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { if (isBuildByParentFiled()) { makeParentEnable(); - tdChange(); + tdChange(false); } } }); - lengthMarkRadio.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { + lengthMarkRadio.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { if (!isBuildByParentFiled()) { makeLengthEnable(); - tdChange(); + tdChange(false); } } }); @@ -169,7 +171,7 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { } - private void tdChange() { + private void tdChange(boolean isChangeDS) { TableDataWrapper tableDataWrappe = this.tableDataNameComboBox.getSelectedItem(); if (tableDataWrappe == null) { return; @@ -186,7 +188,9 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { String[] columnNames = new String[len]; namelist.toArray(columnNames); for (int i = 0; i < valueEditorPanes.length; i++) { - valueEditorPanes[i].setEditors(new Editor[]{new ColumnNameEditor(columnNames), new ColumnIndexEditor(len)}, columnNames[0]); + if (isChangeDS || isNoSelectedColumnName(valueEditorPanes[i])) { + valueEditorPanes[i].setEditors(new Editor[]{new ColumnNameEditor(columnNames), new ColumnIndexEditor(len)}, columnNames[0]); + } } } catch (Exception e) { for (int i = 0; i < valueEditorPanes.length; i++) { @@ -197,6 +201,10 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { } } + private boolean isNoSelectedColumnName(ValueEditorPane valueEditorPane) { + return (Integer) valueEditorPane.update() == -1; + } + @Override protected String title4PopupWindow() { return "TreeTableDataDictionay"; 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 new file mode 100644 index 0000000000..2041230957 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java @@ -0,0 +1,147 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.data.impl.JDBCDatabaseConnection; +import com.fr.data.pool.DBCPConnectionPoolAttr; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.editor.IntegerEditor; +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.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.stable.StringUtils; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +/** + * @author xiqiu + * @date 2021/11/22 + * @description + */ +public class AdvancePane extends BasicPane { + private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor(); + private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")}); + private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor(); + private SpecialUITextField DBCP_VALIDATION_QUERY = new SpecialUITextField(); + + + public AdvancePane() { + + DBCP_VALIDATION_QUERY.addFocusListener(new JTextFieldHintListener(DBCP_VALIDATION_QUERY)); + ; + double p = TableLayout.PREFERRED; + DBCP_VALIDATION_QUERY.setColumns(15); + double[] rowSizeDbcp = {p, p, p, p}; + double[] columnDbcp = {p, 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}, + {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW}, + {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT} + }; + + JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSizeDbcp, columnDbcp, 11, 11); + this.add(contextPane); + this.setPreferredSize(new Dimension(630, 120)); + this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + } + + + public void populate(JDBCDatabaseConnection jdbcDatabase) { + DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr(); + if (dbcpAttr == null) { + dbcpAttr = new DBCPConnectionPoolAttr(); + jdbcDatabase.setDbcpAttr(dbcpAttr); + } + this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive()); + this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait()); + this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery()); + this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0); + + } + + public void update(JDBCDatabaseConnection jdbcDatabase) { + DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr(); + if (dbcpAttr == null) { + dbcpAttr = new DBCPConnectionPoolAttr(); + jdbcDatabase.setDbcpAttr(dbcpAttr); + } + dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue()); + dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue()); + dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText()); + dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Advanced_Setup"); + } + + + private class JTextFieldHintListener implements FocusListener { + private SpecialUITextField textField; + + public JTextFieldHintListener(SpecialUITextField jTextField) { + this.textField = jTextField; + } + + @Override + public void focusGained(FocusEvent e) { + //获取焦点时,清空提示内容 + String temp = textField.getText(); + textField.setForeground(Color.BLACK); + textField.setTextOrigin(temp); + + } + + @Override + public void focusLost(FocusEvent e) { + //失去焦点时,没有输入内容,显示提示内容 + String temp = textField.getTextOrigin(); + textField.setText(temp); + } + } + + private class SpecialUITextField extends UITextField { + + @Override + public String getText() { + String text = super.getText(); + if (isUseless(text)) { + return StringUtils.EMPTY; + } + return text; + } + + @Override + public void setText(String text) { + if (isUseless(text)) { + this.setForeground(Color.GRAY); + super.setText(Toolkit.i18nText("Fine-Design_Dbcp_Default_Query")); + } else { + this.setForeground(Color.BLACK); + super.setText(text); + } + } + + public String getTextOrigin() { + return super.getText(); + } + + public void setTextOrigin(String text) { + super.setText(text); + } + + private boolean isUseless(String text) { + return text == null || text.isEmpty() || Toolkit.i18nText("Fine-Design_Dbcp_Default_Query").equals(text); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java index 5ed53cef40..3b5aebed9e 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java @@ -5,20 +5,13 @@ import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.Connection; import com.fr.data.impl.NameDatabaseConnection; import com.fr.design.DesignerEnvManager; -import com.fr.design.actions.server.ConnectionListAction; -import com.fr.design.dialog.BasicDialog; -import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.editlock.ConnectionLockChangeChecker; import com.fr.design.editlock.EditLockUtils; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UILockButton; -import com.fr.design.mainframe.DesignerContext; import com.fr.file.ConnectionConfig; import com.fr.general.ComparatorUtils; import com.fr.stable.StringUtils; -import com.fr.transaction.CallBackAdaptor; -import com.fr.transaction.Configurations; -import com.fr.transaction.WorkerFacade; import com.fr.workspace.WorkContext; import com.fr.workspace.server.connection.DBConnectAuth; import com.fr.report.LockItem; @@ -133,48 +126,7 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { return; } // 锁定成功,执行后续操作 - final ConnectionListPane connectionListPane = new ConnectionListPane(); - final ConnectionConfig connectionConfig = ConnectionConfig.getInstance(); - ConnectionConfig cloned = connectionConfig.mirror(); - connectionListPane.populate(cloned); - final BasicDialog connectionListDialog = connectionListPane.showLargeWindow( - SwingUtilities.getWindowAncestor(ConnectionComboBoxPanel.this), null); - connectionListDialog.addDialogActionListener(new DialogActionAdapter() { - public void doOk() { - if (!connectionListPane.isNamePermitted()) { - connectionListDialog.setDoOKSucceed(false); - return; - } - Configurations.modify(new WorkerFacade(ConnectionConfig.class) { - @Override - public void run() { - connectionListPane.update(connectionConfig); - } - }.addCallBack(new CallBackAdaptor() { - @Override - public boolean beforeCommit() { - //如果更新失败,则不关闭对话框,也不写xml文件,并且将对话框定位在请重命名的那个对象页面 - return ConnectionListAction.doWithDatasourceManager(connectionConfig, connectionListPane, connectionListDialog); - } - - @Override - public void afterCommit() { - DesignerContext.getDesignerBean("databasename").refreshBeanElement(); - // 关闭定义数据连接页面,为其解锁 - EditLockUtils.unlock(LockItem.CONNECTION); - } - })); - - } - - @Override - public void doCancel() { - // 关闭定义数据连接页面,为其解锁 - super.doCancel(); - EditLockUtils.unlock(LockItem.CONNECTION); - } - }); - connectionListDialog.setVisible(true); + ConnectionListPane.showDialog(SwingUtilities.getWindowAncestor(ConnectionComboBoxPanel.this)); refreshItems(); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java new file mode 100644 index 0000000000..2428c9a005 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java @@ -0,0 +1,48 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.editlock.EditLockUtils; +import com.fr.design.mainframe.DesignerContext; +import com.fr.file.ConnectionConfig; +import com.fr.report.LockItem; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/9/8 + */ +public class ConnectionListDialogActionAdapter extends DialogActionAdapter { + + private final ConnectionManagerPane connectionManagerPane; + private final BasicDialog connectionListDialog; + private final ConnectionConfig connectionConfig; + + public ConnectionListDialogActionAdapter(ConnectionManagerPane connectionManagerPane, + BasicDialog connectionListDialog, + ConnectionConfig connectionConfig) { + this.connectionManagerPane = connectionManagerPane; + this.connectionListDialog = connectionListDialog; + this.connectionConfig = connectionConfig; + } + + @Override + public void doOk() { + if (!connectionManagerPane.isNamePermitted()) { + connectionListDialog.setDoOKSucceed(false); + return; + } + connectionManagerPane.update(connectionConfig); + DesignerContext.getDesignerBean("databasename").refreshBeanElement(); + // 关闭定义数据连接页面,为其解锁 + EditLockUtils.unlock(LockItem.CONNECTION); + + } + + @Override + public void doCancel() { + // 关闭定义数据连接页面,为其解锁 + super.doCancel(); + EditLockUtils.unlock(LockItem.CONNECTION); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java index daa408ab6c..1566395edb 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java @@ -1,27 +1,35 @@ package com.fr.design.data.datapane.connect; +import com.fr.config.RemoteConfigEvent; import com.fr.data.impl.Connection; +import com.fr.data.impl.ConnectionBean; import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.impl.JNDIDatabaseConnection; import com.fr.design.ExtraDesignClassManager; -import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.dialog.BasicDialog; import com.fr.design.fun.ConnectionProvider; 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.ilist.ListModelElement; import com.fr.design.i18n.Toolkit; +import com.fr.event.EventDispatcher; import com.fr.file.ConnectionConfig; -import com.fr.general.ComparatorUtils; +import com.fr.file.ConnectionOperator; +import com.fr.file.ConnectionOperatorImpl; import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; +import com.fr.rpc.ExceptionHandler; +import com.fr.rpc.RPCInvokerExceptionInfo; import com.fr.stable.ArrayUtils; import com.fr.stable.Nameable; import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.third.org.apache.commons.collections4.MapUtils; +import com.fr.workspace.WorkContext; -import javax.swing.SwingUtilities; +import java.awt.Window; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,36 +49,39 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh this.addEditingListener(new PropertyChangeAdapter() { public void propertyChange() { isNamePermitted = true; - String[] allListNames = nameableList.getAllNames(); - allListNames[nameableList.getSelectedIndex()] = StringUtils.EMPTY; - String tempName = getEditingName(); - if (StringUtils.isEmpty(tempName)) { - nameableList.stopEditing(); - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ConnectionListPane.this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connection_Empty_Name")); - setIllegalIndex(editingIndex); + if (!checkName()) { isNamePermitted = false; return; } - if (!ComparatorUtils.equals(tempName, selectedName) - && isNameRepeated(new List[]{Arrays.asList(allListNames)}, tempName)) { - isNamePermitted = false; - nameableList.stopEditing(); - String message = Toolkit.i18nText("Fine-Design_Basic_Connection_Duplicate_Name", tempName); - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ConnectionListPane.this), message); - setIllegalIndex(editingIndex); - } - if (isNamePermitted && !ComparatorUtils.equals(tempName, selectedName)) { - rename(selectedName, tempName); - } - + rename(selectedName, getEditingName()); } }); } + @Override + public String getEmptyNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Connection_Empty_Name"); + } + + @Override + public String getDuplicatedNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Connection_Duplicate_Name", getEditingName()); + } protected void rename(String oldName, String newName) { - renameMap.remove(selectedName); - renameMap.put(selectedName, newName); + //如果a改成了b,b又被改成了c,就认为是a改成了c + for (Map.Entry entry : renameMap.entrySet()) { + if (StringUtils.equals(oldName, entry.getValue())) { + oldName = entry.getKey(); + break; + } + } + if (StringUtils.equals(oldName, newName)) { + //a -> b;b -> a,说明没改 + renameMap.remove(oldName); + } else { + renameMap.put(oldName, newName); + } } /** @@ -151,17 +162,54 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh public void update(ConnectionConfig connectionConfig) { // Nameable[]居然不能强转成NameObject[],一定要这么写... Nameable[] res = this.update(); - NameObject[] res_array = new NameObject[res.length]; - java.util.Arrays.asList(res).toArray(res_array); - - connectionConfig.removeAllConnection(); + List connectionBeans = new ArrayList<>(); + Map map = MapUtils.invertMap(getRenameMap()); + for (int i = 0; i < res.length; i++) { + NameObject nameObject = (NameObject) res[i]; + String oldName = map.get(nameObject.getName()); + if (oldName == null) { + oldName = StringUtils.EMPTY; + } + connectionBeans.add(new ConnectionBean(nameObject.getName(), oldName, (Connection) nameObject.getObject())); + } + try { + WorkContext.getCurrent().get(ConnectionOperator.class, new ExceptionHandler() { + @Override + public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) { + return saveByOldWay(connectionBeans); + } + }).saveConnection(new ArrayList<>(connectionConfig.getConnections().keySet()), connectionBeans); + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.fire(RemoteConfigEvent.EDIT, ConnectionConfig.getInstance().getNameSpace()); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } - for (int i = 0; i < res_array.length; i++) { - NameObject nameObject = res_array[i]; - connectionConfig.addConnection(nameObject.getName(), (Connection) nameObject.getObject()); + private boolean saveByOldWay(List connectionBeans) { + try { + return ConnectionOperatorImpl.getInstance().saveConnection(connectionBeans); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; } } + public static void showDialog(Window parent) { + final ConnectionConfig connectionConfig = ConnectionConfig.getInstance(); + final ConnectionManagerPane connectionManagerPane = new ConnectionManagerPane() { + @Override + public void complete() { + ConnectionConfig cloned = connectionConfig.mirror(); + populate(cloned); + } + }; + final BasicDialog connectionListDialog = connectionManagerPane.showLargeWindow(parent, null); + connectionListDialog.addDialogActionListener(new ConnectionListDialogActionAdapter(connectionManagerPane, connectionListDialog, connectionConfig)); + connectionListDialog.setVisible(true); + } + @Override public void onCopyItem() { super.onCopyItem(); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java index f65b6dc128..86e7633be0 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java @@ -20,6 +20,7 @@ import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Window; @@ -45,13 +46,8 @@ public class DBCPAttrPane extends BasicPane { private static final int EMPTY_FETCHSIZE = -2; // carl:DBCP的一些属性 private IntegerEditor DBCP_INITIAL_SIZE = new IntegerEditor(); - private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor(); - private IntegerEditor DBCP_MAX_IDLE = new IntegerEditor(); private IntegerEditor DBCP_MIN_IDLE = new IntegerEditor(); - private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor(); - private UITextField DBCP_VALIDATION_QUERY = new UITextField(); - private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")}); private UIComboBox DBCP_TESTONRETURN = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")}); private UIComboBox DBCP_TESTWHILEIDLE = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")}); @@ -75,25 +71,19 @@ public class DBCPAttrPane extends BasicPane { defaultPane = this; // JPanel northFlowPane - northFlowPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_ConnectionPool_Attr")); - northFlowPane.setPreferredSize(new Dimension(630, 320)); + northFlowPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_ConnectionPool_Attr")); + northFlowPane.setPreferredSize(new Dimension(630, 330)); defaultPane.add(northFlowPane, BorderLayout.NORTH); - DBCP_VALIDATION_QUERY.setColumns(15); // ContextPane double f = TableLayout.FILL; // double p = TableLayout.PREFERRED; - double[] rowSize = {f, f, f, f, f, f, f, f, f, f, f, f}; + double[] rowSize = {f, f, f, f, f, f, f}; double[] columnSize = {f, f}; Component[][] comps = { {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Initial_Size") + ":", SwingConstants.RIGHT), DBCP_INITIAL_SIZE}, - {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE}, - {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Idle") + ":", SwingConstants.RIGHT), DBCP_MAX_IDLE}, {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Min_Idle") + ":", SwingConstants.RIGHT), DBCP_MIN_IDLE}, - {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT}, - {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY}, - {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW}, {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Return") + ":", SwingConstants.RIGHT), DBCP_TESTONRETURN}, {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_While_Idle") + ":", SwingConstants.RIGHT), DBCP_TESTWHILEIDLE}, {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Evictionruns_millis") + ":", SwingConstants.RIGHT), @@ -102,8 +92,13 @@ public class DBCPAttrPane extends BasicPane { {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Mix_Evictable_Idle_Time_Millis") + ":", SwingConstants.RIGHT), DBCP_MINEVICTABLEIDLETIMEMILLIS}}; - JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 4); + JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 10); northFlowPane.add(contextPane); + JPanel boxFlowInnerContainer = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 5, 5); + UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Dbcp_Warning")); + uiLabel.setForeground(Color.RED); + boxFlowInnerContainer.add(uiLabel); + northFlowPane.add(boxFlowInnerContainer); } public void populate(JDBCDatabaseConnection jdbcDatabase) { @@ -113,12 +108,7 @@ public class DBCPAttrPane extends BasicPane { jdbcDatabase.setDbcpAttr(dbcpAttr); } this.DBCP_INITIAL_SIZE.setValue(dbcpAttr.getInitialSize()); - this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive()); - this.DBCP_MAX_IDLE.setValue(dbcpAttr.getMaxIdle()); - this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait()); this.DBCP_MIN_IDLE.setValue(dbcpAttr.getMinIdle()); - this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery()); - this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0); this.DBCP_TESTONRETURN.setSelectedIndex(dbcpAttr.isTestOnReturn() ? 1 : 0); this.DBCP_TESTWHILEIDLE.setSelectedIndex(dbcpAttr.isTestWhileIdle() ? 1 : 0); this.DBCP_MINEVICTABLEIDLETIMEMILLIS.setValue(dbcpAttr.getMinEvictableIdleTimeMillis() / TIME_MULTIPLE); @@ -141,12 +131,7 @@ public class DBCPAttrPane extends BasicPane { jdbcDatabase.setDbcpAttr(dbcpAttr); } dbcpAttr.setInitialSize(this.DBCP_INITIAL_SIZE.getValue().intValue()); - dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue()); - dbcpAttr.setMaxIdle(this.DBCP_MAX_IDLE.getValue().intValue()); - dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue()); dbcpAttr.setMinIdle(this.DBCP_MIN_IDLE.getValue().intValue()); - dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText()); - dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true); dbcpAttr.setTestOnReturn(this.DBCP_TESTONRETURN.getSelectedIndex() == 0 ? false : true); dbcpAttr.setTestWhileIdle(this.DBCP_TESTWHILEIDLE.getSelectedIndex() == 0 ? false : true); dbcpAttr.setMinEvictableIdleTimeMillis(((Number) this.DBCP_MINEVICTABLEIDLETIMEMILLIS.getValue()).intValue() * TIME_MULTIPLE); 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 e55aaa2dd4..91e8006d10 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 @@ -14,11 +14,11 @@ import com.fr.data.solution.processor.SolutionProcessor; import com.fr.design.beans.BasicBeanPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.scrollruler.ModLineBorder; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.log.FineLoggerFactory; import com.fr.rpc.ExceptionHandler; @@ -34,6 +34,7 @@ import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; +import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.UIManager; @@ -60,6 +61,8 @@ 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_WIDTH = 675; private UILabel message; private UIButton okButton; @@ -305,6 +308,10 @@ public abstract class DatabaseConnectionPane MAX_MAIN_PANEL_HEIGHT || mainPanel.getPreferredSize().width > MAX_MAIN_PANEL_WIDTH) { + UIScrollPane jp = new + UIScrollPane(mainPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + jp.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT)); + northPane.add(jp, BorderLayout.CENTER); + } else { + mainPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT)); + northPane.add(mainPanel, BorderLayout.CENTER); + } // ChartSet String[] defaultEncode = new String[]{Toolkit.i18nText("Fine-Design_Encode_Auto")}; charSetComboBox = new UIComboBox(ArrayUtils.addAll(defaultEncode, EncodeConstants.ENCODING_ARRAY)); @@ -406,6 +426,7 @@ public abstract class DatabaseConnectionPane { private static JDBCDefPane jdbcDefPane = new JDBCDefPane(); private static DBCPAttrPane dbcpAttrPane = new DBCPAttrPane(); + private static AdvancePane advancePane = new AdvancePane(); @Override protected JPanel mainPanel() { @@ -425,15 +446,22 @@ public abstract class DatabaseConnectionPane 0) { + driverLoaderBox.setSelectedIndex(0); + } + if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), StringUtils.EMPTY)) { + driverComboBox.setSelectedItem(StringUtils.EMPTY); + return; + } + + DriverURLName[] dus = jdbcMap.get(dbtypeComboBox.getSelectedItem()); + for (int i = 0, len = dus.length; i < len; i++) { + driverComboBox.addItem(dus[i].getDriver()); + if (i == 0) { + driverComboBox.setSelectedItem(dus[i].getDriver()); + urlTextField.setText(dus[i].getURL()); + } + } + // 更改数据库类型后 数据库名称置空和之前逻辑保持一致 + if (needRefresh) { + jdbcDatabase.setDatabase(StringUtils.EMPTY); + } + changePane(dbtypeComboBox.getSelectedItem()); + JDBCConnectionDef.getInstance().setConnection((String) dbtypeComboBox.getSelectedItem(), jdbcDatabase); + DatabaseConnectionPane.JDBC.getAdvancedAttrPane().populate(jdbcDatabase); + } + }; + private HashBiMap nameAndRepresent; public JDBCDefPane() { + initMap(); this.setBorder(UITitledBorder.createBorderWithTitle("JDBC" + ":")); this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); JPanel innerthis = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); @@ -115,7 +170,15 @@ public class JDBCDefPane extends JPanel { } dbtypeComboBox.addActionListener(dbtypeActionListener); dbtypeComboBox.setMaximumRowCount(10); - + driverLoaderBox = new SpecialUIComboBox(); + refreshDriverLoader(); + driverLoaderBox.setPreferredSize(new Dimension(200, driverLoaderBox.getPreferredSize().height)); + driverLoaderBox.setEditable(false); + driverManageBox = new UIComboBox(); + refreshDriverManage(true); + driverManageBox.setEditable(false); + driverManageBox.addActionListener(driverManageListener); + driverLoaderBox.setVisible(isSelfDefine()); driverComboBox = new UIComboBox(); driverComboBox.setEditable(true); driverComboBox.addActionListener(driverListener); @@ -159,13 +222,37 @@ public class JDBCDefPane extends JPanel { odbcTipsLink.setPreferredSize(new Dimension(GraphHelper.getWidth(Toolkit.i18nText("Fine-Design_Basic_Odbc_Tips")), odbcTipsLink.getPreferredSize().height)); odbcTipsLink.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { - String url = UrlI18nManager.getInstance().getI18nUrl("odbc.help"); + String url = CloudCenter.getInstance().acquireUrlByKind("odbc.help"); + BrowseUtils.browser(url); + } + }); + driverManageLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Driver_Manage_Add_Driver")) { + @Override + public void paintComponent(Graphics _gfx) { + super.paintComponent(_gfx); + _gfx.setColor(Color.blue); + _gfx.drawLine(0, this.getHeight() - 1, GraphHelper.getWidth(this.getText()), this.getHeight() - 1); + } + }; + driverManageLabel.setPreferredSize(new Dimension(GraphHelper.getWidth(Toolkit.i18nText("Fine-Design_Driver_Manage_Add_Driver")), driverManageLabel.getPreferredSize().height)); + driverManageLabel.setVisible(isSelfDefine()); + driverManageLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + String url = CloudCenter.getInstance().acquireUrlByKind("driver.add.help"); BrowseUtils.browser(url); } }); + odbcTipsPane.add(driverManageLabel); + odbcTipsPane.add(odbcTipsLink); + JPanel driverComboBoxAndTips = new JPanel(new BorderLayout()); - driverComboBoxAndTips.add(driverComboBox, BorderLayout.WEST); + JPanel normalFlowInnerContainer_s_pane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 5, 0); + normalFlowInnerContainer_s_pane.add(driverManageBox); + normalFlowInnerContainer_s_pane.add(driverComboBox); + normalFlowInnerContainer_s_pane.add(driverLoaderBox); + driverComboBoxAndTips.add(normalFlowInnerContainer_s_pane, BorderLayout.WEST); driverComboBoxAndTips.add(odbcTipsPane, BorderLayout.CENTER); JPanel hostPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); @@ -225,7 +312,71 @@ public class JDBCDefPane extends JPanel { innerthis.add(centerPanel); } + private void refreshDriverLoader() { + Set representSet = nameAndRepresent.values(); + driverLoaderBox.clearBoxItems(); + for (String represent : representSet) { + driverLoaderBox.addItem(represent); + } + } + + private String getRepresent(String driverClass, String driverName) { + return driverClass + "(" + driverName + ")"; + } + + private boolean isSelfDefine() { + return ComparatorUtils.equals(Toolkit.i18nText("Fine-Design_Driver_Manage_Self_Define"), driverManageBox.getSelectedItem()); + } + + private void refreshDriverManage(boolean addSelfDefine) { + driverManageBox.clearBoxItems(); + driverManageBox.addItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Default")); + if (addSelfDefine) { + driverManageBox.addItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Self_Define")); + } + } + + private void initMap() { + Map driverLoaders = DriverLoaderConfig.getInstance().getDriverLoaders(); + nameAndRepresent = getDriverLoaderAndRepresent(driverLoaders); + } + + private HashBiMap getDriverLoaderAndRepresent(Map driverLoaders) { + HashBiMap driverHashBiMap = HashBiMap.create(); + if (WorkContext.getCurrent().isWarDeploy()) { + return driverHashBiMap; + } + // name 是唯一的,name+driver自然也是唯一的 + for (DriverLoader driverLoader : driverLoaders.values()) { + driverHashBiMap.put(driverLoader.getName(), getRepresent(driverLoader.getDriverClass(), driverLoader.getName())); + } + return driverHashBiMap; + } + + + protected JDBCDatabaseConnection getJDBCDatabase() { + return this.jdbcDatabase; + } + + private void changePane(Object dbType) { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {p, f, 22}; + if (ComparatorUtils.equals(dbType, OTHER_DB) || ComparatorUtils.equals(dbType, "Access") || ComparatorUtils.equals(dbType, "SQLite")) { + if (this.centerPanel.getComponentCount() != partComponents.length * 2) { + centerPanel.removeAll(); + TableLayoutHelper.addComponent2ResultPane(partComponents, new double[]{p, p, p, p, p}, columnSize, centerPanel); + } + } else if (this.centerPanel.getComponentCount() != allComponents.length * 2) { + centerPanel.removeAll(); + TableLayoutHelper.addComponent2ResultPane(allComponents, new double[]{p, p, p, p, p, p, p, p}, columnSize, centerPanel); + } + } + public void populate(JDBCDatabaseConnection jdbcDatabase) { + // 单例对象,重新打开的时候并不会新建,但是由于driverloaderbox里面需要是动态内容,因此需要进行刷新动作 + initMap(); + refreshDriverLoader(); needRefresh = false; if (jdbcDatabase == null) { jdbcDatabase = new JDBCDatabaseConnection(); @@ -255,7 +406,24 @@ public class JDBCDefPane extends JPanel { this.dbtypeComboBox.setSelectedItem(OTHER_DB); } } - this.driverComboBox.setSelectedItem(jdbcDatabase.getDriver()); + // jdbcDatabase.getDriverSource() 只会是空或者是有值,但是为了保险起见,还是应该做个处理 + String driverSource = jdbcDatabase.getDriverSource(); + if (driverSource == null) { + driverSource = StringUtils.EMPTY; + } + if (driverSource.isEmpty()) { + refreshDriverManage(!nameAndRepresent.isEmpty()); + this.driverManageBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Default")); + this.driverComboBox.setSelectedItem(jdbcDatabase.getDriver()); + } else { + refreshDriverManage(true); + this.driverManageBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Self_Define")); + String represent = getRepresent(jdbcDatabase.getDriver(), jdbcDatabase.getDriverSource()); + if (!nameAndRepresent.containsValue(represent)) { + this.driverLoaderBox.addItem(represent); + } + this.driverLoaderBox.setSelectedItem(represent); + } this.urlTextField.setText(jdbcDatabase.getURL()); this.userNameTextField.setText(jdbcDatabase.getUser()); this.passwordTextField.setText(jdbcDatabase.getPassword()); @@ -268,31 +436,10 @@ public class JDBCDefPane extends JPanel { needRefresh = false; } - protected JDBCDatabaseConnection getJDBCDatabase() { - return this.jdbcDatabase; - } - - private void changePane(Object dbType) { - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] columnSize = {p, f, 22}; - if (ComparatorUtils.equals(dbType, OTHER_DB) || ComparatorUtils.equals(dbType, "Access") || ComparatorUtils.equals(dbType, "SQLite")) { - if (this.centerPanel.getComponentCount() != partComponents.length * 2) { - centerPanel.removeAll(); - TableLayoutHelper.addComponent2ResultPane(partComponents, new double[]{p, p, p, p, p}, columnSize, centerPanel); - } - } else if (this.centerPanel.getComponentCount() != allComponents.length * 2) { - centerPanel.removeAll(); - TableLayoutHelper.addComponent2ResultPane(allComponents, new double[]{p, p, p, p, p, p, p, p}, columnSize, centerPanel); - } - } - public JDBCDatabaseConnection update() { if (jdbcDatabase == null) { jdbcDatabase = new JDBCDatabaseConnection(); } - Object driveItem = this.driverComboBox.getSelectedItem(); - jdbcDatabase.setDriver(driveItem == null ? null : driveItem.toString().trim()); jdbcDatabase.setURL(this.urlTextField.getText().trim()); jdbcDatabase.setUser(this.userNameTextField.getText().trim()); jdbcDatabase.setPassword(new String(this.passwordTextField.getPassword()).trim()); @@ -304,36 +451,30 @@ public class JDBCDefPane extends JPanel { jdbcDatabase.setNewCharsetName(EncodeConstants.ENCODING_GBK); jdbcDatabase.setOriginalCharsetName(((String) this.charSetComboBox.getSelectedItem())); } - return jdbcDatabase; - } - - ActionListener dbtypeActionListener = new ActionListener() { - public void actionPerformed(ActionEvent evt) { - - urlTextField.setText(StringUtils.EMPTY); - driverComboBox.removeAllItems(); - if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), StringUtils.EMPTY)) { - driverComboBox.setSelectedItem(StringUtils.EMPTY); - return; - } - - DriverURLName[] dus = jdbcMap.get(dbtypeComboBox.getSelectedItem()); - for (int i = 0, len = dus.length; i < len; i++) { - driverComboBox.addItem(dus[i].getDriver()); - if (i == 0) { - driverComboBox.setSelectedItem(dus[i].getDriver()); - urlTextField.setText(dus[i].getURL()); + String driverLoader = (String) this.driverLoaderBox.getSelectedItem(); + if (driverLoader == null) { + driverLoader = StringUtils.EMPTY; + } + if (isSelfDefine()) { + String[] split = driverLoader.split("\\("); + if (split.length > 1) { + String name = split[1]; + if (name.length() > 0) { + jdbcDatabase.setDriverSource(name.substring(0, name.length() - 1)); + } else { + jdbcDatabase.setDriverSource(StringUtils.EMPTY); } + } else { + jdbcDatabase.setDriverSource(StringUtils.EMPTY); } - // 更改数据库类型后 数据库名称置空和之前逻辑保持一致 - if (needRefresh) { - jdbcDatabase.setDatabase(StringUtils.EMPTY); - } - changePane(dbtypeComboBox.getSelectedItem()); - JDBCConnectionDef.getInstance().setConnection((String) dbtypeComboBox.getSelectedItem(), jdbcDatabase); - DatabaseConnectionPane.JDBC.getAdvancedAttrPane().populate(jdbcDatabase); + jdbcDatabase.setDriver(split[0]); + } else { + Object driveItem = this.driverComboBox.getSelectedItem(); + jdbcDatabase.setDriver(driveItem == null ? null : driveItem.toString().trim()); + jdbcDatabase.setDriverSource(StringUtils.EMPTY); } - }; + return jdbcDatabase; + } ActionListener driverListener = new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -579,4 +720,22 @@ public class JDBCDefPane extends JPanel { private String driver; private String url; } + + private static class SpecialUIComboBox extends UIComboBox { + + @Override + public ComboBoxUI getUIComboBoxUI() { + return new SpecialUIComboBoxUI(); + } + } + + private static class SpecialUIComboBoxUI extends UIComboBoxUI { + + @Override + public ComboPopup createPopup() { + return createHorizontalNeverUIComboPopUp(); + } + + } + } diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/strategy/StrategyConfigHandler.java b/designer-base/src/main/java/com/fr/design/data/tabledata/strategy/StrategyConfigHandler.java new file mode 100644 index 0000000000..5b6a744d0d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/strategy/StrategyConfigHandler.java @@ -0,0 +1,37 @@ +package com.fr.design.data.tabledata.strategy; + +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.query.StrategicTableData; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2021/3/19 + */ +public abstract class StrategyConfigHandler { + + private final T tableData; + + public StrategyConfigHandler(T tableData) { + this.tableData = tableData; + } + + protected T getTableData() { + return tableData; + } + + /** + * 查找配置 + * + * @return 缓存配置 + */ + public abstract StrategyConfig find(); + + + /** + * 保存配置 + * + * @param config 缓存配置 + */ + public abstract void save(T saved, StrategyConfig config); +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java index fecf9c079e..1746330f11 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java @@ -1,6 +1,5 @@ package com.fr.design.data.tabledata.tabledatapane; -import com.fr.base.BaseUtils; import com.fr.base.Parameter; import com.fr.base.ParameterHelper; import com.fr.data.core.db.TableProcedure; @@ -13,16 +12,22 @@ import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; +import com.fr.design.data.StrategyConfigAttrUtils; +import com.fr.design.data.datapane.ESDStrategyConfigPane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; -import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener; import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane; import com.fr.design.data.datapane.sqlpane.SQLEditPane; +import com.fr.design.data.tabledata.strategy.StrategyConfigHandler; +import com.fr.design.data.tabledata.tabledatapane.db.StrategyConfigFrom; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.DBTableDataMenuHandler; +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.itableeditorpane.ParameterTableModel; import com.fr.design.gui.itableeditorpane.UITableEditAction; @@ -30,11 +35,20 @@ import com.fr.design.gui.itableeditorpane.UITableEditorPane; import com.fr.design.gui.itoolbar.UIToolbar; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; +import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ToolBarDef; import com.fr.design.utils.ParameterUtils; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.core.strategy.config.service.StrategyConfigService; +import com.fr.esd.data.db.DBTableDataSavedHook; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.query.StrategicTableData; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; import com.fr.general.sql.SqlUtils; @@ -43,6 +57,7 @@ import com.fr.script.Calculator; import com.fr.stable.ArrayUtils; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; import javax.swing.BorderFactory; import javax.swing.Box; @@ -57,6 +72,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; @@ -64,25 +80,45 @@ import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.List; +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2020/7/22 + */ public class DBTableDataPane extends AbstractTableDataPane { + private static final int BOTTOM = 6; - private static final String PREVIEW_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"); - private static final String REFRESH_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh"); + private static final String PREVIEW_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Preview"); + private static final String REFRESH_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Refresh"); private ConnectionTableProcedurePane connectionTableProcedurePane; private UITableEditorPane editorPane; - private DBTableDataMenuHandler dbTableDataMenuHandler; private SQLEditPane sqlTextPane; - private UICheckBox isShareCheckBox; - private MaxMemRowCountPanel maxPanel; - private String pageQuery = null; + private String pageQuery; private DBTableData dbTableData; + //ESD + private UILabel esdSettingsLabel; + private UIComboBox esdConfigOption; + private UICheckBox esdEnabled; + private UIButton esdSettingsBtn; + private UILabel barErrorTips; + //配置 + private StrategyConfig strategyConfig; + + private StrategyConfigHandler configHandler; + + + public DBTableDataPane() { + init(); + initMainSplitPane(); + } + private void init() { - this.setLayout(new BorderLayout(4, 4)); + setLayout(new BorderLayout(4, 4)); - sqlTextPane = new SQLEditPane(); - sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); + this.sqlTextPane = new SQLEditPane(); + this.sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); ParameterTableModel model = new ParameterTableModel() { @Override @@ -90,25 +126,27 @@ public class DBTableDataPane extends AbstractTableDataPane { return ArrayUtils.add(super.createDBTableAction(), new RefreshAction()); } }; - editorPane = new UITableEditorPane(model); + editorPane = new UITableEditorPane<>(model); - // 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table - connectionTableProcedurePane = new ConnectionTableProcedurePane() { + + this.connectionTableProcedurePane = new ConnectionTableProcedurePane() { @Override protected void filter(Connection connection, String conName, List nameList) { - - connection.addConnection(nameList, conName, new Class[]{JDBCDatabaseConnection.class, JNDIDatabaseConnection.class}); + connection.addConnection(nameList, conName, new Class[]{ + JDBCDatabaseConnection.class, + JNDIDatabaseConnection.class + }); } + @Override protected void addKeyMonitor() { - searchField.addKeyListener(new KeyListener() { - + this.searchField.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { - //do nothing } + @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { @@ -117,45 +155,44 @@ public class DBTableDataPane extends AbstractTableDataPane { } } + @Override public void keyReleased(KeyEvent e) { - //do nothing } }); } }; - connectionTableProcedurePane.addDoubleClickListener(new DoubleClickSelectedNodeOnTreeListener() { - + this.connectionTableProcedurePane.addDoubleClickListener(new ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener() { @Override public void actionPerformed(TableProcedure target) { - Document document = sqlTextPane.getDocument(); + Document document = DBTableDataPane.this.sqlTextPane.getDocument(); try { - document.insertString(sqlTextPane.getCaretPosition(), target.toString(), null); + document.insertString(DBTableDataPane.this.sqlTextPane.getCaretPosition(), target.toString(), null); } catch (BadLocationException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } - // 这里开始作色,本来可以给sqlTextPane添加DocumentListener来实现的, - // 后来发现insertString的时候,锁定了JTextPane,不能调用setXXX来作色,先这样了. - // sqlTextPane.syntaxTexts(); - sqlTextPane.requestFocus(); + + + DBTableDataPane.this.sqlTextPane.requestFocus(); } }); - sqlTextPane.addFocusListener(new FocusListener() { + + this.sqlTextPane.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { - // do nothing + barErrorTips.setVisible(false); } + @Override public void focusLost(FocusEvent e) { - if (isPreviewOrRefreshButton(e)) { - checkParameter(); + if (DBTableDataPane.this.isPreviewOrRefreshButton(e)) { + DBTableDataPane.this.checkParameter(); } } }); } - private void initMainSplitPane() { Box box = new Box(BoxLayout.Y_AXIS); @@ -165,106 +202,189 @@ public class DBTableDataPane extends AbstractTableDataPane { northPane.add(editToolBar, BorderLayout.CENTER); northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM, 0)); - RTextScrollPane sqlTextScrollPane = new RTextScrollPane(sqlTextPane); + RTextScrollPane sqlTextScrollPane = new RTextScrollPane(this.sqlTextPane); sqlTextScrollPane.setLineNumbersEnabled(true); sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); sqlTextScrollPane.setPreferredSize(new Dimension(680, 600)); JPanel paraMeanPane = new JPanel(new BorderLayout()); paraMeanPane.setPreferredSize(new Dimension(680, 90)); - UILabel paraMean = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Param_DES")); + UILabel paraMean = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Datasource_Param_DES")); paraMeanPane.add(paraMean, BorderLayout.CENTER); box.add(northPane); box.add(sqlTextScrollPane); box.add(paraMeanPane); - box.add(editorPane); + box.add(this.editorPane); JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4)); sqlSplitPane.add(box, BorderLayout.CENTER); box.setMinimumSize(new Dimension(300, 400)); - // 防止数据连接名过长时影响 split pane 分割效果 - // 本界面中给MaxMemRowCountPanel留的空间太小,造成MaxMemRowCountPanel显示异常,这边减小一点最小宽度,拉长MaxMemRowCountPanel - connectionTableProcedurePane.setMinimumSize(new Dimension(230, 400)); - connectionTableProcedurePane.setMaximumSize(new Dimension(500, 400)); - // 使用SplitPane - JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, connectionTableProcedurePane, sqlSplitPane); + + this.connectionTableProcedurePane.setMinimumSize(new Dimension(230, 400)); + this.connectionTableProcedurePane.setMaximumSize(new Dimension(500, 400)); + + JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.connectionTableProcedurePane, sqlSplitPane); mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor())); mainSplitPane.setOneTouchExpandable(true); - this.add(mainSplitPane, BorderLayout.CENTER); + add(mainSplitPane, BorderLayout.CENTER); } - public DBTableDataPane() { - init(); - initMainSplitPane(); - } - - private boolean isPreviewOrRefreshButton(FocusEvent e) { if (e.getOppositeComponent() != null) { String name = e.getOppositeComponent().getName(); - return ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON); + return (ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON)); } return false; } @Override protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); + return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); } - private void refresh() { + private void refreshParameters() { String[] paramTexts = new String[2]; - paramTexts[0] = SqlUtils.tryPureSqlText(sqlTextPane.getText()); - paramTexts[1] = SqlUtils.tryPureSqlText(pageQuery); - List existParameterList = editorPane.update(); - Parameter[] ps = existParameterList == null ? new Parameter[0] : existParameterList.toArray(new Parameter[0]); - editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps)); + paramTexts[0] = SqlUtils.tryPureSqlText(this.sqlTextPane.getText()); + paramTexts[1] = SqlUtils.tryPureSqlText(this.pageQuery); + List existParameterList = this.editorPane.update(); + Parameter[] ps = (existParameterList == null) ? new Parameter[0] : existParameterList.toArray(new Parameter[0]); + + this.editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps)); } private JToolBar createToolBar() { - // p:工具栏. ToolBarDef toolBarDef = new ToolBarDef(); toolBarDef.addShortCut(new PreviewAction()); toolBarDef.addShortCut(new PreviewPerformedSQLAction()); toolBarDef.addShortCut(SeparatorDef.DEFAULT); toolBarDef.addShortCut(new EditPageQueryAction()); - dbTableDataMenuHandler = ExtraDesignClassManager.getInstance().getSingle(DBTableDataMenuHandler.MARK_STRING); - if (dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler = ExtraDesignClassManager.getInstance().getSingle("DBTableDataMenuHandler"); + if (this.dbTableDataMenuHandler != null) { toolBarDef.addShortCut(SeparatorDef.DEFAULT); - toolBarDef.addShortCut(dbTableDataMenuHandler.createQueryAction()); + toolBarDef.addShortCut(this.dbTableDataMenuHandler.createQueryAction()); } - isShareCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Is_Share_DBTableData")); - isShareCheckBox.setBackground(Color.WHITE); - maxPanel = new MaxMemRowCountPanel(); - maxPanel.setBorder(null); + UIToolbar editToolBar = ToolBarDef.createJToolBar(); toolBarDef.updateToolBar(editToolBar); - editToolBar.add(isShareCheckBox); - editToolBar.add(maxPanel); + + //esd相关组件初始化 + createToolbarEsdComponents(editToolBar); return editToolBar; } + private void createToolbarEsdComponents(final UIToolbar editToolBar) { + this.esdSettingsLabel = new UILabel(Toolkit.i18nText("Fine-Design_ESD_Cache_Settings")); + this.esdConfigOption = new UIComboBox(StrategyConfigFrom.values()); + this.esdEnabled = new UICheckBox(Toolkit.i18nText("Fine-Design_ESD_Enable_Cache")); + this.barErrorTips = new UILabel(); + this.barErrorTips.setForeground(Color.RED); + this.barErrorTips.setVisible(false); + + esdSettingsBtn = new UIButton(Toolkit.i18nText("Fine-Design_ESD_Strategy_Config")); + esdSettingsBtn.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + final boolean global = globalOptionSelected(); + + final ESDStrategyConfigPane strategyConfigPane = new ESDStrategyConfigPane(global); + + StrategyConfig populateStrategyConfig; + if (global) { + populateStrategyConfig = StrategyConfigService.getGlobalConfig(); + } else { + populateStrategyConfig = strategyConfig; + } + + //显示对应的配置 + strategyConfigPane.populateBean(populateStrategyConfig); + + BasicDialog dlg = strategyConfigPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + super.doOk(); + if (!global) { + //点击策略配置面板的确定,重新设置策略配置 + strategyConfig = strategyConfigPane.updateBean(); + // TODO: 2021/3/12 这个直接使用不太好 + } + } + }); + dlg.setAlwaysOnTop(true); + dlg.setVisible(true); + } + }); + + this.esdConfigOption.setSelectedIndex(StrategyConfigFrom.GLOBAL.getIndex()); + this.esdConfigOption.addActionListener(e -> setEsdEnabled()); + + + //工具栏加上esd相关组件 + editToolBar.add(this.esdSettingsLabel); + editToolBar.add(this.esdConfigOption); + editToolBar.add(this.esdEnabled); + editToolBar.add(this.esdSettingsBtn); + editToolBar.add(this.barErrorTips); + } + + private boolean globalOptionSelected() { + return esdConfigOption.getSelectedIndex() == StrategyConfigFrom.GLOBAL.getIndex(); + } + + private void setEsdEnableStatus(boolean selected, boolean enabled) { + this.esdEnabled.setSelected(selected); + this.esdEnabled.setEnabled(enabled); + } + + private void setEsdEnabled() { + boolean useIndividualConfig = !this.globalOptionSelected(); + if (useIndividualConfig) { + if (this.strategyConfig == null) { + //新建的数据集,选择单独时,可用但是不勾选 + setEsdEnableStatus(false, true); + } else { + setEsdEnableStatus(!this.strategyConfig.isUseGlobal() && this.strategyConfig.enabled(), true); + } + } else { + //判断是不是模版数据集 + switch (this.dbTableData.getScope()) { + case TEMPLATE: + String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath(); + setEsdEnableStatus(StrategyConfigService.isTemplateEnabled(tplPath), false); + break; + case SERVER: + //不会走到这里 + default: + break; + } + } + } + + public StrategyConfig updateStrategyConfig() { + return this.strategyConfig; + } + private void checkParameter() { String[] paramTexts = new String[2]; - paramTexts[0] = sqlTextPane.getText(); - paramTexts[1] = pageQuery; + paramTexts[0] = this.sqlTextPane.getText(); + paramTexts[1] = this.pageQuery; Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); - if (parameters.length < 1 && editorPane.update().size() < 1) { + if (parameters.length < 1 && this.editorPane.update().size() < 1) { return; } boolean isIn = true; - List list = editorPane.update(); - List name = new ArrayList(); - for (int i = 0; i < list.size(); i++) { - name.add(list.get(i).getName()); + List list = this.editorPane.update(); + List name = new ArrayList<>(); + for (ParameterProvider parameter : list) { + name.add(parameter.getName()); } - for (int i = 0; i < parameters.length; i++) { - if (!name.contains(parameters[i].getName())) { + for (Parameter parameter : parameters) { + if (!name.contains(parameter.getName())) { isIn = false; break; } @@ -272,101 +392,162 @@ public class DBTableDataPane extends AbstractTableDataPane { if (list.size() == parameters.length && isIn) { return; } - // bug:34175 删了是否刷新对话框, 均直接刷新 - refresh(); + + refreshParameters(); } @Override - public void populateBean(DBTableData dbtabledata) { - this.dbTableData = dbtabledata; - if (dbTableDataMenuHandler != null) { - dbTableDataMenuHandler.populate(dbtabledata); + public void populateBean(DBTableData dbTableData) { + this.dbTableData = dbTableData; + if (this.dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler.populate(dbTableData); } - ParameterProvider[] parameters = null; + Calculator c = Calculator.createCalculator(); - parameters = dbtabledata.getParameters(c); - editorPane.populate(parameters); + ParameterProvider[] parameters = dbTableData.getParameters(c); + this.editorPane.populate(parameters); - com.fr.data.impl.Connection db = null; - String query = null; - boolean isShare = false; - int maxMemeryRow = -1; - db = dbtabledata.getDatabase(); - query = dbtabledata.getQuery(); - isShare = dbtabledata.isShare(); - maxMemeryRow = dbtabledata.getMaxMemRowCount(); - this.pageQuery = dbtabledata.getPageQuerySql(); + Connection db = dbTableData.getDatabase(); + String query = dbTableData.getQuery(); + this.pageQuery = dbTableData.getPageQuerySql(); this.connectionTableProcedurePane.setSelectedDatabaseConnection(db); this.sqlTextPane.setText(query); this.sqlTextPane.requestFocus(); this.sqlTextPane.moveCaretPosition(this.sqlTextPane.getCaretPosition()); - isShareCheckBox.setSelected(isShare); - maxPanel.setValue(maxMemeryRow); + + switch (dbTableData.getScope()) { + + case TEMPLATE: + this.configHandler = new TemplateStrategyConfigHandler(dbTableData); + break; + case SERVER: + //服务器数据集 + default: + //新建服务器数据集 + this.configHandler = new ServerStrategyConfigHandler(dbTableData); + break; + } + //设置esd相关组件显示状态 + populateESDComponents(); + } + + private void populateESDComponents() { + //查找映射的配置 + this.strategyConfig = configHandler.find(); + + boolean shouldEnable = false; + StrategyConfigFrom from = StrategyConfigFrom.GLOBAL; + + if (this.strategyConfig != null) { + if (this.strategyConfig.enabled()) { + shouldEnable = true; + } + if (!this.strategyConfig.isUseGlobal()) { + from = StrategyConfigFrom.INDIVIDUAL; + } + } + + //服务器数据集不允许设置来源,只能单独配置 + if (dbTableData.getScope() != StrategicTableData.Scope.TEMPLATE) { + from = StrategyConfigFrom.INDIVIDUAL; + this.esdConfigOption.setEnabled(false); + } + this.esdEnabled.setSelected(shouldEnable); + this.esdConfigOption.setSelectedIndex(from.getIndex()); } @Override public DBTableData updateBean() { + + updateDBTableData(); + internalUpdateStrategyConfig(); + + return this.dbTableData; + } + + private void internalUpdateStrategyConfig() { + //这边只修改enable和useGlobal + boolean global = globalOptionSelected(); + boolean enable = this.esdEnabled.isSelected(); + + + //未开启缓存的,如果选择了单独配置,需要创建配置 + if (this.strategyConfig == null && !global) { + this.strategyConfig = StrategyConfig.createDefault(); + } + + //设置配置来源和开启状态 + if (this.strategyConfig != null) { + this.strategyConfig.setEnable(enable); + this.strategyConfig.setUseGlobal(global); + } + + //保存 + this.configHandler.save(this.dbTableData, this.strategyConfig); + } + + private void updateDBTableData() { String dbName = this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); if (StringUtils.isBlank(dbName) || StringUtils.isBlank(this.sqlTextPane.getText())) { try { - throw new Exception(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); - } catch (Exception ignore) { - // JOptionPane.showMessageDialog(DBTableDataPane.this, - // com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); + throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } } + + // 保存前 刷新下参数列表 保证获取到最新的参数 - refresh(); - List parameterList = editorPane.update(); - Parameter[] parameters = parameterList.toArray(new Parameter[parameterList.size()]); + refreshParameters(); + + List parameterList = this.editorPane.update(); + ParameterProvider[] parameters = parameterList.toArray(new ParameterProvider[0]); dbTableData.setDatabase(new NameDatabaseConnection(dbName)); - // p:必须先设置Parameters数组,因为setQuery里面会自动设置的 dbTableData.setParameters(parameters); - dbTableData.setQuery(this.sqlTextPane.getText()); + dbTableData.setQuery(this.sqlTextPane.getText().trim()); - dbTableData.setShare(isShareCheckBox.isSelected()); - dbTableData.setMaxMemRowCount(maxPanel.getValue()); dbTableData.setPageQuerySql(this.pageQuery); - if (dbTableDataMenuHandler != null) { - dbTableDataMenuHandler.update(); + if (this.dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler.update(); } - return dbTableData; } protected class RefreshAction extends UITableEditAction { public RefreshAction() { - this.setName(REFRESH_BUTTON); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + setName(REFRESH_BUTTON); + setSmallIcon(IOUtils.readIcon("/com/fr/design/images/control/refresh.png")); } + @Override public void actionPerformed(ActionEvent e) { - refresh(); + DBTableDataPane.this.refreshParameters(); } + @Override public void checkEnabled() { - // do nothing } } private class PreviewAction extends UpdateAction { public PreviewAction() { - this.setName(PREVIEW_BUTTON); - this.setMnemonic('P'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + setName(PREVIEW_BUTTON); + setMnemonic('P'); + setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_file/preview.png")); } + @Override public void actionPerformed(ActionEvent evt) { - checkParameter(); + DBTableDataPane.this.checkParameter(); PreviewTablePane.previewTableData(DBTableDataPane.this.updateBean()); } } @@ -387,14 +568,14 @@ public class DBTableDataPane extends AbstractTableDataPane { private class EditPageQueryAction extends UpdateAction { public EditPageQueryAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Page_Query")); + this.setName(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Page_Query")); this.setMnemonic('L'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/text.png")); + this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_file/text.png")); } @Override public void actionPerformed(ActionEvent e) { - final QueryPane pane = new QueryPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL")); + final QueryPane pane = new QueryPane(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL")); pane.populate(pageQuery); BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame()); dialog.addDialogActionListener(new DialogActionAdapter() { @@ -408,9 +589,9 @@ public class DBTableDataPane extends AbstractTableDataPane { } } - private class QueryPane extends BasicPane { + private static class QueryPane extends BasicPane { private SQLEditPane pageQueryPane; - private String title; + private final String title; public QueryPane(String title) { this.title = title; @@ -427,21 +608,135 @@ public class DBTableDataPane extends AbstractTableDataPane { if (StringUtils.isBlank(text)) { return; } - pageQueryPane.setText(text); + this.pageQueryPane.setText(text); } public String update() { - String text = pageQueryPane.getText(); + String text = this.pageQueryPane.getText(); if (StringUtils.isBlank(text)) { return null; - } else { - return text; } + return text; } + @Override protected String title4PopupWindow() { - return title; + return this.title; + } + } + + /** + * 服务器数据集配置处理器 + */ + private static class ServerStrategyConfigHandler extends StrategyConfigHandler { + private final String origName; + + private final String origConnection; + + private final String origQuery; + + public ServerStrategyConfigHandler(DBTableData tableData) { + super(tableData); + this.origName = tableData.getDsName(); + this.origConnection = tableData.getDatabase().toString(); + this.origQuery = tableData.getQuery(); + } + + @Override + public StrategyConfig find() { + StrategyConfig strategyConfig = null; + if (getTableData() != null) { + strategyConfig = getTableData().getStrategyConfig(); + if (strategyConfig == null) { + //共享数据集 + if (getTableData().isShare()) { + strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + } + } + + return strategyConfig; + } + + @Override + public void save(DBTableData saved, StrategyConfig strategyConfig) { + String conn = saved.getDatabase().toString(); + String query = saved.getQuery(); + + + //检查数据链接和sql是否修改,如果修改需要触发缓存监听事件 + if (!conn.equals(origConnection) || !query.equals(origQuery)) { + if (StringUtils.isNotEmpty(origName)) { + //新建数据集的origName为null,不用触发 + StrategyEventsNotifier.modifyDataSet(DSMapping.ofServerDS(new DsNameTarget(origName))); + } + } + + + //配置变动事件 + try { + final StrategyConfig orig = getTableData().getStrategyConfig(); + saved.setStrategyConfig(strategyConfig.clone()); + StrategyEventsNotifier.compareAndFireConfigEvents(orig, strategyConfig, DSMapping.ofServerDS(new DsNameTarget(saved.getDsName()))); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + + /** + * 模版数据集配置处理器 + */ + private static class TemplateStrategyConfigHandler extends StrategyConfigHandler { + public TemplateStrategyConfigHandler(DBTableData tableData) { + super(tableData); + } + + @Override + public StrategyConfig find() { + StrategyConfig strategyConfig = null; + String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath(); + if (getTableData() != null && StringUtils.isNotEmpty(tplPath)) { + //设置保存数据集的事件检查钩子 + //新建模版此时不存在,不需要注册钩子 + if (getTableData().getXmlSavedHook() == null && WorkContext.getWorkResource().exist(tplPath)) { + getTableData().setXmlSavedHook(new DBTableDataSavedHook(tplPath, getTableData())); + } + + //获取当前的缓存配置,没有就创建一份 + String dsName = getTableData().getDsName(); + + //这里为了之前兼容插件创建的配置,缓存配置不在DBTableData,而是从模版attr读取 + strategyConfig = StrategyConfigAttrUtils.getStrategyConfig(dsName); + + + if (useGlobal(getTableData(), strategyConfig)) { + //使用全局配置 + strategyConfig = StrategyConfigHelper.createStrategyConfig(true); + } else if (strategyConfig == null && getTableData().isShare()) { + //没有配置时,使用共享数据集兼容配置 + strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + } + + return strategyConfig; + } + + private boolean useGlobal(DBTableData dbTableData, StrategyConfig strategyConfig) { + //非共享且配置为空或者指定使用全局配置时,检查是否全局开启 + if (strategyConfig == null) { + return !dbTableData.isShare(); + } else { + return strategyConfig.isUseGlobal(); + } + } + + @Override + public void save(DBTableData saved, StrategyConfig config) { + + //DBTableDataSavedHook处理了 } } } diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java index f1d2433dbe..d2a1918d4f 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java @@ -8,10 +8,12 @@ import com.fr.data.impl.NameDatabaseConnection; import com.fr.data.impl.storeproc.ProcedureDataModel; import com.fr.data.impl.storeproc.StoreProcedure; import com.fr.data.operator.DataOperator; +import com.fr.design.DesignModelAdapter; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener; import com.fr.design.data.datapane.sqlpane.SQLEditPane; @@ -291,6 +293,7 @@ public class ProcedureDataPane extends AbstractTableDataPane imp sp.setCalculating(false); doAfterProcudureDone(); fireDSChanged(); + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); } }; diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/db/StrategyConfigFrom.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/db/StrategyConfigFrom.java new file mode 100644 index 0000000000..a1a07ee113 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/db/StrategyConfigFrom.java @@ -0,0 +1,33 @@ +package com.fr.design.data.tabledata.tabledatapane.db; + +import com.fr.design.i18n.Toolkit; + +public enum StrategyConfigFrom { + GLOBAL(0, Toolkit.i18nText("Fine-Design_ESD_Use_Global_Settings")), + + INDIVIDUAL(1, Toolkit.i18nText("Fine-Design_ESD_Use_Individual_Settings")); + + int index; + + String displayText; + + StrategyConfigFrom(int index, String displayText) { + this.index = index; + this.displayText = displayText; + } + + + public int getIndex() { + return this.index; + } + + + public String getDisplayText() { + return this.displayText; + } + + + public String toString() { + return getDisplayText(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/TableDataFactory.java b/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/TableDataFactory.java index adce85f3b6..6bc9e21ed6 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/TableDataFactory.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/TableDataFactory.java @@ -26,6 +26,8 @@ import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.authority.user.UserAuthority; import java.lang.reflect.Constructor; import java.util.ArrayList; @@ -175,7 +177,8 @@ public abstract class TableDataFactory { public static String[] getSortOfChineseNameOfServerData(TableDataConfig tableDataConfig) { clearAll(); try { - java.util.Iterator nameIt = tableDataConfig.getTableDatas().keySet().iterator(); + UserAuthority userAuthority = WorkContext.getCurrent().get(UserAuthority.class); + Iterator nameIt = userAuthority.getAuthServerDataSetNames().iterator(); while (nameIt.hasNext()) { String name = nameIt.next(); addName(name, tableDataConfig.getTableData(name)); diff --git a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java index d3c592a4ed..75626441bf 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java +++ b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java @@ -8,9 +8,14 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.core.PropertyChangeAdapter; -import javax.swing.*; +import javax.swing.JPanel; import javax.swing.event.DocumentEvent; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Window; @Open public abstract class BasicPane extends JPanel { @@ -262,6 +267,10 @@ public abstract class BasicPane extends JPanel { public void checkValid() throws Exception { } + public boolean confirmContinueBeforeDoOK() { + return true; + } + public static class NamePane extends BasicPane { private UITextField nameTextField; private UILabel Name; @@ -390,6 +399,10 @@ public abstract class BasicPane extends JPanel { BasicPane.this.checkValid(); } + public boolean confirmContinueBeforeDoOK() { + return BasicPane.this.confirmContinueBeforeDoOK(); + } + } private class UnsizedDialog extends UIDialog { diff --git a/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java b/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java index dd3ddab3b9..458daddab5 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java +++ b/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java @@ -33,6 +33,7 @@ public abstract class UIDialog extends JDialog { private BasicPane pane; private java.util.List listeners = new ArrayList(); private boolean isDoOKSucceed; + private boolean needExceptionCheck = true; public UIDialog(Frame parent) { @@ -151,6 +152,10 @@ public abstract class UIDialog extends JDialog { }); } + public void setNeedExceptionCheck(boolean needExceptionCheck) { + this.needExceptionCheck = needExceptionCheck; + } + /** * 添加监听器 @@ -172,10 +177,21 @@ public abstract class UIDialog extends JDialog { * 确定操作 */ public void doOK() { + //由于checkValid不可以加入自定义的弹窗以及操作,添加一个接口 + if (!confirmContinueBeforeDoOK()) { + return; + } + try { checkValid(); } catch (Exception exp) { - FineJOptionPane.showMessageDialog(this, exp.getMessage()); + if (needExceptionCheck) { + FineJOptionPane.showMessageDialog( + this, + exp.getMessage(), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.WARNING_MESSAGE); + } return; } @@ -249,6 +265,10 @@ public abstract class UIDialog extends JDialog { */ public abstract void checkValid() throws Exception; + public boolean confirmContinueBeforeDoOK() { + return true; + } + public void setButtonEnabled(boolean b) { this.okButton.setEnabled(b); } diff --git a/designer-base/src/main/java/com/fr/design/event/ComponentChangeListener.java b/designer-base/src/main/java/com/fr/design/event/ComponentChangeListener.java new file mode 100644 index 0000000000..d16d49b6a4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/event/ComponentChangeListener.java @@ -0,0 +1,7 @@ +package com.fr.design.event; + +import java.awt.*; + +public interface ComponentChangeListener { + void initListener(Container changedComponent); +} diff --git a/designer-base/src/main/java/com/fr/design/event/ComponentChangeObserver.java b/designer-base/src/main/java/com/fr/design/event/ComponentChangeObserver.java new file mode 100644 index 0000000000..9ef75d514a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/event/ComponentChangeObserver.java @@ -0,0 +1,6 @@ +package com.fr.design.event; + + +public interface ComponentChangeObserver { + void registerChangeListener(ComponentChangeListener uiChangeableListener); +} diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginInstalledPane.java b/designer-base/src/main/java/com/fr/design/extra/PluginInstalledPane.java index 2fa1ea1102..1923a22876 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginInstalledPane.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginInstalledPane.java @@ -60,11 +60,14 @@ public class PluginInstalledPane extends PluginAbstractViewPane { public void actionPerformed(ActionEvent e) { PluginView plugin = controlPane.getSelectedPlugin(); if (plugin != null) { - boolean isActive = plugin.isActive(); - PluginMarker pluginMarker = PluginMarker.create(plugin.getID(), plugin.getVersion()); - final String modifyMessage = isActive ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Actived") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Disabled"); - if (isActive) { - PluginManager.getController().forbid(pluginMarker, new PluginTaskCallback() { + PluginContext pluginContext = getPluginContextByView(plugin); + if (pluginContext == null) { + return; + } + boolean running = pluginContext.isRunning(); + final String modifyMessage = running ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Actived") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Disabled"); + if (running) { + PluginManager.getController().forbidPersistently(pluginContext.getMarker(), new PluginTaskCallback() { @Override public void done(PluginTaskResult result) { if (result.isSuccess()) { @@ -75,7 +78,7 @@ public class PluginInstalledPane extends PluginAbstractViewPane { } }); } else { - PluginManager.getController().enable(pluginMarker, new PluginTaskCallback() { + PluginManager.getController().enablePersistently(pluginContext.getMarker(), new PluginTaskCallback() { @Override public void done(PluginTaskResult result) { if (result.isSuccess()) { @@ -145,13 +148,25 @@ public class PluginInstalledPane extends PluginAbstractViewPane { } private void changeTextForButton(PluginView plugin) { - if (plugin.isActive()) { + PluginContext pluginContext = getPluginContextByView(plugin); + if (pluginContext == null) { + return; + } + if (pluginContext.isRunning()) { disableButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Disable")); } else { disableButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Active")); } } + private PluginContext getPluginContextByView(PluginView pluginView) { + if (pluginView != null) { + PluginMarker pluginMarker = PluginMarker.create(pluginView.getID(), pluginView.getVersion()); + return PluginManager.getContext(pluginMarker); + } + return null; + } + @Override protected String title4PopupWindow() { return "Installed"; diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java b/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java index d7260f84ee..379daab28e 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java @@ -25,6 +25,8 @@ import com.fr.plugin.manage.control.PluginTask; import com.fr.plugin.manage.control.PluginTaskCallback; import com.fr.plugin.manage.control.PluginTaskResult; import com.fr.plugin.view.PluginView; +import com.fr.plugin.xml.PluginElementName; +import com.fr.plugin.xml.PluginXmlElement; import com.fr.stable.StringUtils; import javax.swing.JOptionPane; @@ -91,15 +93,37 @@ public class PluginOperateUtils { public static void setPluginActive(String pluginInfo, JSCallback jsCallback) { - PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); - PluginContext plugin = PluginManager.getContext(pluginMarker); - boolean active = plugin.isActive(); - PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(active, jsCallback); - if (active) { - PluginManager.getController().forbid(pluginMarker, modifyStatusCallback); - } else { - PluginManager.getController().enable(pluginMarker, modifyStatusCallback); - } + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); + PluginContext plugin = PluginManager.getContext(pluginMarker); + boolean isRunning = plugin.isRunning(); + PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(isRunning, jsCallback); + if (isRunning) { + PluginXmlElement forbidReminder = plugin.getXml().getElement(PluginElementName.ForbidReminder); + if (forbidReminder != null && forbidReminder.getContent() != null) { + // 禁用前提示 + int rv = FineJOptionPane.showConfirmDialog( + null, + forbidReminder.getContent(), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.WARNING_MESSAGE + ); + if (rv == JOptionPane.OK_OPTION) { + PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback); + } + } else { + // 正常禁用 + PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback); + } + } else { + PluginManager.getController().enablePersistently(pluginMarker, modifyStatusCallback); + } + } + }); } public static void uninstallPlugin(final String pluginInfo, final boolean isForce, final JSCallback jsCallback) { diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java b/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java index ed7253bad2..521821eadf 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java @@ -80,10 +80,12 @@ public class PluginUtils { public static String transPluginsToString(List plugins) throws Exception { JSONArray jsonArray = new JSONArray(); for (PluginContext plugin : plugins) { - JSONObject jo = new JSONObject(); - jo.put("id", plugin.getID()); - jo.put("version", plugin.getVersion()); - jsonArray.put(jo); + if (VersionIntervalType.isSupported(plugin.supportCurrentFRVersion())) { + JSONObject jo = new JSONObject(); + jo.put("id", plugin.getID()); + jo.put("version", plugin.getVersion()); + jsonArray.put(jo); + } } return jsonArray.toString(); } @@ -267,7 +269,8 @@ public class PluginUtils { jo.put("vendor", pluginContext.getVendor()); jo.put("price", pluginContext.getPrice()); jo.put("requiredJarTime", pluginContext.getRequiredJarTime()); - jo.put("active", pluginContext.isActive()); + // 前端需求的active实际上是插件的运行状态,通过isRunning()获取 + jo.put("active", pluginContext.isRunning()); jo.put("hidden", pluginContext.isHidden()); jo.put("free", pluginContext.isFree()); jo.put("licDamaged", pluginContext.isLicDamaged()); diff --git a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java index c00f8bb44f..443a55671d 100644 --- a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java +++ b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java @@ -251,7 +251,11 @@ public class HistoryTemplateListCache implements CallbackEvent { for (int i = 0; i < vCount; i++) { JTemplate overTemplate = historyList.get(i); - if (overTemplate.getEditingFILE().exists() && overTemplate.isALLSaved() && overTemplate != editingTemplate) { + boolean replaceWithJVirtualTemplate = overTemplate.getEditingFILE().exists() + && overTemplate.isALLSaved() + && overTemplate != editingTemplate + && overTemplate.checkEnable(); + if (replaceWithJVirtualTemplate) { closeVirtualSelectedReport(overTemplate); historyList.set(i, new JVirtualTemplate(overTemplate.getEditingFILE())); } diff --git a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java index 047420294a..1920212f4a 100644 --- a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java @@ -4,7 +4,6 @@ package com.fr.design.file; import com.fr.base.BaseUtils; import com.fr.base.GraphHelper; import com.fr.base.vcs.DesignerMode; -import com.fr.design.base.mode.DesignModeContext; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.imenu.UIMenuItem; @@ -17,6 +16,7 @@ import com.fr.design.utils.DesignUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUIPaintUtils; import com.fr.design.worker.WorkerManager; +import com.fr.design.utils.TemplateUtils; import com.fr.design.worker.save.CallbackSaveWorker; import com.fr.file.FILE; import com.fr.general.ComparatorUtils; @@ -269,7 +269,7 @@ public class MutilTempalteTabPane extends JComponent { private String tempalteShowName(JTemplate template) { - String name = template.getTemplateName(); + String name = TemplateUtils.createLockeTemplatedName(template, template.getTemplateName()); if (!template.isSaved() && !name.endsWith(" *")) { name += " *"; } @@ -732,6 +732,16 @@ public class MutilTempalteTabPane extends JComponent { } } + /** + * 后台关闭当前编辑模板 + */ + public void closeCurrentTpl(){ + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + this.setIsCloseCurrent(true); + this.closeFormat(jTemplate); + this.closeSpecifiedTemplate(jTemplate); + } + /** * 关闭模板 * @@ -766,8 +776,8 @@ public class MutilTempalteTabPane extends JComponent { // 如果关闭的模板是当前选中的模板,则重新激活当前 selectIndex 的模板; // selectIndex 没有变化,但是对应的模板已经变成了前一张模板 if (closeIconIndex == selectedIndex || isCloseCurrent) { - // 如果 closeIconIndex 是最后一个被渲染画出的,那么预览上一个,防止数组越界 - if (closeIconIndex >= maxPaintIndex) { + // 如果当前关闭的模板在最右侧,那么预览上一个,防止数组越界 + if (selectedIndex >= maxPaintIndex) { // selectIndex 不会 <0 因为如果关闭的是打开的最后一个模板,那么关闭之后 openedTemplate.isEmpty() = true selectedIndex--; } diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java index 2c0d860fb4..bc5e0da6bd 100644 --- a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java +++ b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java @@ -12,20 +12,28 @@ import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.lock.LockInfoUtils; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.lock.LockInfoDialog; +import com.fr.design.mainframe.JTemplate; import com.fr.file.FILE; import com.fr.file.FileNodeFILE; import com.fr.file.filetree.FileNode; import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.form.fit.web.editpreview.FileLockStateObservable; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; +import com.fr.workspace.base.UserInfo; import com.fr.stable.ArrayUtils; import com.fr.stable.CoreConstants; import com.fr.stable.StableUtils; import com.fr.stable.project.ProjectConstants; import com.fr.workspace.WorkContext; +import com.fr.report.lock.LockInfoOperator; +import java.util.UUID; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; @@ -47,6 +55,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.Objects; +import java.util.Observable; +import java.util.Observer; +import org.jetbrains.annotations.Nullable; + import static javax.swing.JOptionPane.WARNING_MESSAGE; import static javax.swing.JOptionPane.YES_NO_OPTION; @@ -76,6 +88,13 @@ public class TemplateTreePane extends JPanel implements FileOperations { scrollPane.setBorder(null); contentPane.add(scrollPane, BorderLayout.CENTER); + FileLockStateObservable.getInstance().addObserver(new Observer() { + @Override + public void update(Observable o, Object arg) { + TemplateTreePane.this.refresh(); + } + }); + /* * Tree.MouseAdapter */ @@ -103,6 +122,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { if (toolBarStateChangeListener != null) { toolBarStateChangeListener.stateChange(); } + DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(reportletsTree.getSelectedFileNode()); } }; // lx: add mouse listener @@ -202,21 +222,48 @@ public class TemplateTreePane extends JPanel implements FileOperations { @Override public void openFile() { // 判断是否是远程设计的锁定文件 - if (!WorkContext.getCurrent().isLocal()) { - FileNode node = reportletsTree.getSelectedFileNode(); - if (node == null) { - return; - } - String lock = node.getLock(); - if (lock != null && !lock.equals(node.getUserID())) { - return; - } + FileNode node = reportletsTree.getSelectedFileNode(); + if (node == null) { + return; } String reportPath = reportletsTree.getSelectedTemplatePath(); final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, reportPath); + String lock = node.getLock(); + boolean showLockInfo = LockInfoUtils.isCompatibleOperator() + || LockInfoUtils.unableGetLockInfo() + || WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(selectedFilePath) + ? (lock != null && !lock.equals(node.getUserID())) + : WorkContext.getCurrent().get(LockInfoOperator.class).isTplLocked(selectedFilePath); + if (showLockInfo) { + UserInfo userInfo = WorkContext.getCurrent().get(LockInfoOperator.class).getUserInfo(selectedFilePath); + node.setLock(UUID.randomUUID().toString()); + // 对于开发者预览占位锁定 定位到tab中 + checkDevelopForBiddenTemplate(selectedFilePath); + LockInfoDialog.show(userInfo); + return; + } else { + node.setLock(null); + } DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false))); } + private void checkDevelopForBiddenTemplate(String selectedFilePath) { + JTemplate template = getOpenedTemplate(selectedFilePath); + if (template != null && template.isForbidden()) { + DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false))); + } + } + + @Nullable + private JTemplate getOpenedTemplate(String path) { + for (JTemplate template : HistoryTemplateListCache.getInstance().getHistoryList()) { + if (ComparatorUtils.equals(template.getEditingFILE().getPath(), path)) { + return template; + } + } + return null; + } + /** * 打开文件夹 */ @@ -240,6 +287,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { // 刷新远程文件夹权限 NodeAuthProcessor.getInstance().refresh(); reportletsTree.refresh(); + DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(null); FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Template_File_Tree_Refresh_Successfully") + "!"); } diff --git a/designer-base/src/main/java/com/fr/design/formula/FRFormulaLexer.java b/designer-base/src/main/java/com/fr/design/formula/FRFormulaLexer.java new file mode 100644 index 0000000000..23c15d98ac --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/FRFormulaLexer.java @@ -0,0 +1,1689 @@ +package com.fr.design.formula; + +import com.fr.parser.FRParserTokenTypes; +import com.fr.third.antlr.ByteBuffer; +import com.fr.third.antlr.CharBuffer; +import com.fr.third.antlr.CharStreamException; +import com.fr.third.antlr.CharStreamIOException; +import com.fr.third.antlr.InputBuffer; +import com.fr.third.antlr.LexerSharedInputState; +import com.fr.third.antlr.NoViableAltForCharException; +import com.fr.third.antlr.RecognitionException; +import com.fr.third.antlr.Token; +import com.fr.third.antlr.TokenStream; +import com.fr.third.antlr.TokenStreamException; +import com.fr.third.antlr.TokenStreamIOException; +import com.fr.third.antlr.TokenStreamRecognitionException; +import com.fr.third.antlr.collections.impl.BitSet; + +import java.io.InputStream; +import java.io.Reader; +import java.util.Hashtable; + +/** + * @author Hoky + * @date 2021/11/22 + */ + +public class FRFormulaLexer extends com.fr.third.antlr.CharScanner implements FRParserTokenTypes, TokenStream { + public FRFormulaLexer(InputStream in) { + this(new ByteBuffer(in)); + } + + public FRFormulaLexer(Reader in) { + this(new CharBuffer(in)); + } + + public FRFormulaLexer(InputBuffer ib) { + this(new LexerSharedInputState(ib)); + } + + public FRFormulaLexer(LexerSharedInputState state) { + super(state); + caseSensitiveLiterals = true; + setCaseSensitive(true); + literals = new Hashtable(); + } + + public Token nextToken() throws TokenStreamException { + Token theRetToken = null; + tryAgain: + for (; ; ) { + Token _token = null; + int _ttype = Token.INVALID_TYPE; + resetText(); + try { // for char stream error handling + try { // for lexical error handling + switch (LA(1)) { + case '?': { + mQUESTION(true); + theRetToken = _returnToken; + break; + } + case '(': { + mLPAREN(true); + theRetToken = _returnToken; + break; + } + case ')': { + mRPAREN(true); + theRetToken = _returnToken; + break; + } + case '[': { + mLBRACK(true); + theRetToken = _returnToken; + break; + } + case ']': { + mRBRACK(true); + theRetToken = _returnToken; + break; + } + case '{': { + mLCURLY(true); + theRetToken = _returnToken; + break; + } + case '}': { + mRCURLY(true); + theRetToken = _returnToken; + break; + } + case ',': { + mCOMMA(true); + theRetToken = _returnToken; + break; + } + case '/': { + mDIV(true); + theRetToken = _returnToken; + break; + } + case '+': { + mPLUS(true); + theRetToken = _returnToken; + break; + } + case '-': { + mMINUS(true); + theRetToken = _returnToken; + break; + } + case '*': { + mSTAR(true); + theRetToken = _returnToken; + break; + } + case '%': { + mMOD(true); + theRetToken = _returnToken; + break; + } + case '^': { + mPOWER(true); + theRetToken = _returnToken; + break; + } + case ';': { + mSEMI(true); + theRetToken = _returnToken; + break; + } + case '#': { + mSHARP(true); + theRetToken = _returnToken; + break; + } + case '@': { + mAT(true); + theRetToken = _returnToken; + break; + } + case '~': { + mWAVE(true); + theRetToken = _returnToken; + break; + } + case '`': { + mALLL2(true); + theRetToken = _returnToken; + break; + } + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + mINT_NUM(true); + theRetToken = _returnToken; + break; + } + case '"': { + mSTRING_LITERAL_DSQ(true); + theRetToken = _returnToken; + break; + } + case '\'': { + mSTRING_LITERAL_SSQ(true); + theRetToken = _returnToken; + break; + } + case '\t': + case '\n': + case '\u000c': + case '\r': + case ' ': { + mWS(true); + theRetToken = _returnToken; + break; + } + default: + if ((LA(1) == ':') && (LA(2) == ':')) { + mDCOLON(true); + theRetToken = _returnToken; + } else if ((LA(1) == '=') && (LA(2) == '=')) { + mEQUAL(true); + theRetToken = _returnToken; + } else if ((LA(1) == '!') && (LA(2) == '=')) { + mNOT_EQUAL(true); + theRetToken = _returnToken; + } else if ((LA(1) == '<') && (LA(2) == '>')) { + mNOT_EQUAL2(true); + theRetToken = _returnToken; + } else if ((LA(1) == '>') && (LA(2) == '=')) { + mGE(true); + theRetToken = _returnToken; + } else if ((LA(1) == '<') && (LA(2) == '=')) { + mLE(true); + theRetToken = _returnToken; + } else if ((LA(1) == '|') && (LA(2) == '|')) { + mLOR(true); + theRetToken = _returnToken; + } else if ((LA(1) == '&') && (LA(2) == '&')) { + mLAND(true); + theRetToken = _returnToken; + } else if ((LA(1) == '!') && (LA(2) == '0')) { + mALLL(true); + theRetToken = _returnToken; + } else if ((LA(1) == '&') && (_tokenSet_0.member(LA(2)))) { + mCR_ADRESS(true); + theRetToken = _returnToken; + } else if ((LA(1) == ':') && (true)) { + mCOLON(true); + theRetToken = _returnToken; + } else if ((LA(1) == '=') && (true)) { + mEQUAL2(true); + theRetToken = _returnToken; + } else if ((LA(1) == '!') && (true)) { + mLNOT(true); + theRetToken = _returnToken; + } else if ((LA(1) == '>') && (true)) { + mGT(true); + theRetToken = _returnToken; + } else if ((LA(1) == '<') && (true)) { + mLT(true); + theRetToken = _returnToken; + } else if ((LA(1) == '|') && (true)) { + mBOR(true); + theRetToken = _returnToken; + } else if ((LA(1) == '&') && (true)) { + mBAND(true); + theRetToken = _returnToken; + } else if ((_tokenSet_1.member(LA(1)))) { + mIDENT(true); + theRetToken = _returnToken; + } else { + if (LA(1) == EOF_CHAR) { + uponEOF(); + _returnToken = makeToken(Token.EOF_TYPE); + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + } + if (_returnToken == null) continue tryAgain; // found SKIP token + _ttype = _returnToken.getType(); + _ttype = testLiteralsTable(_ttype); + _returnToken.setType(_ttype); + return _returnToken; + } catch (RecognitionException e) { + throw new TokenStreamRecognitionException(e); + } + } catch (CharStreamException cse) { + if (cse instanceof CharStreamIOException) { + throw new TokenStreamIOException(((CharStreamIOException) cse).io); + } else { + throw new TokenStreamException(cse.getMessage()); + } + } + } + } + + public final void mQUESTION(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = QUESTION; + int _saveIndex; + + match('?'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LPAREN; + int _saveIndex; + + match('('); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mRPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = RPAREN; + int _saveIndex; + + match(')'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLBRACK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LBRACK; + int _saveIndex; + + match('['); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mRBRACK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = RBRACK; + int _saveIndex; + + match(']'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLCURLY(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LCURLY; + int _saveIndex; + + match('{'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mRCURLY(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = RCURLY; + int _saveIndex; + + match('}'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mCOLON(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = COLON; + int _saveIndex; + + match(':'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mDCOLON(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = DCOLON; + int _saveIndex; + + match("::"); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mCOMMA(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = COMMA; + int _saveIndex; + + match(','); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mEQUAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = EQUAL; + int _saveIndex; + + match("=="); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mEQUAL2(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = EQUAL2; + int _saveIndex; + + match('='); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLNOT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LNOT; + int _saveIndex; + + match('!'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mNOT_EQUAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = NOT_EQUAL; + int _saveIndex; + + match("!="); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mNOT_EQUAL2(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = NOT_EQUAL2; + int _saveIndex; + + match("<>"); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mDIV(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = DIV; + int _saveIndex; + + match('/'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mPLUS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = PLUS; + int _saveIndex; + + match('+'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mMINUS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = MINUS; + int _saveIndex; + + match('-'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mSTAR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = STAR; + int _saveIndex; + + match('*'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mMOD(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = MOD; + int _saveIndex; + + match('%'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mPOWER(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = POWER; + int _saveIndex; + + match('^'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mGE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = GE; + int _saveIndex; + + match(">="); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mGT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = GT; + int _saveIndex; + + match('>'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LE; + int _saveIndex; + + match("<="); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LT; + int _saveIndex; + + match('<'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mBOR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = BOR; + int _saveIndex; + + match('|'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mBAND(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = BAND; + int _saveIndex; + + match('&'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLOR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LOR; + int _saveIndex; + + match("||"); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mLAND(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LAND; + int _saveIndex; + + match("&&"); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mSEMI(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = SEMI; + int _saveIndex; + + match(';'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mSHARP(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = SHARP; + int _saveIndex; + + match('#'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mAT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = AT; + int _saveIndex; + + match('@'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mWAVE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = WAVE; + int _saveIndex; + + match('~'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mALLL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = ALLL; + int _saveIndex; + + match('!'); + match('0'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mALLL2(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = ALLL2; + int _saveIndex; + + match('`'); + match('0'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mIDENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = IDENT; + int _saveIndex; + + mChar(false); + { + _loop109: + do { + if ((_tokenSet_1.member(LA(1)))) { + mChar(false); + } else if (((LA(1) >= '0' && LA(1) <= '9'))) { + { + mDIGIT(false); + } + } else { + break _loop109; + } + + } while (true); + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + /** + * 'a'..'z', '_', 'A'..'Z' and others without number + */ + protected final void mChar(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = Char; + int _saveIndex; + + switch (LA(1)) { + case '$': { + match('\u0024'); + break; + } + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': { + matchRange('\u0041', '\u005a'); + break; + } + case '_': { + match('\u005f'); + break; + } + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': { + matchRange('\u0061', '\u007a'); + break; + } + case '\u00c0': + case '\u00c1': + case '\u00c2': + case '\u00c3': + case '\u00c4': + case '\u00c5': + case '\u00c6': + case '\u00c7': + case '\u00c8': + case '\u00c9': + case '\u00ca': + case '\u00cb': + case '\u00cc': + case '\u00cd': + case '\u00ce': + case '\u00cf': + case '\u00d0': + case '\u00d1': + case '\u00d2': + case '\u00d3': + case '\u00d4': + case '\u00d5': + case '\u00d6': { + matchRange('\u00c0', '\u00d6'); + break; + } + case '\u00d8': + case '\u00d9': + case '\u00da': + case '\u00db': + case '\u00dc': + case '\u00dd': + case '\u00de': + case '\u00df': + case '\u00e0': + case '\u00e1': + case '\u00e2': + case '\u00e3': + case '\u00e4': + case '\u00e5': + case '\u00e6': + case '\u00e7': + case '\u00e8': + case '\u00e9': + case '\u00ea': + case '\u00eb': + case '\u00ec': + case '\u00ed': + case '\u00ee': + case '\u00ef': + case '\u00f0': + case '\u00f1': + case '\u00f2': + case '\u00f3': + case '\u00f4': + case '\u00f5': + case '\u00f6': { + matchRange('\u00d8', '\u00f6'); + break; + } + case '\u00f8': + case '\u00f9': + case '\u00fa': + case '\u00fb': + case '\u00fc': + case '\u00fd': + case '\u00fe': + case '\u00ff': { + matchRange('\u00f8', '\u00ff'); + break; + } + default: + if (((LA(1) >= '\u0100' && LA(1) <= '\u1fff'))) { + matchRange('\u0100', '\u1fff'); + } else if (((LA(1) >= '\u3040' && LA(1) <= '\u318f'))) { + matchRange('\u3040', '\u318f'); + } else if (((LA(1) >= '\u3300' && LA(1) <= '\u337f'))) { + matchRange('\u3300', '\u337f'); + } else if (((LA(1) >= '\u3400' && LA(1) <= '\u3d2d'))) { + matchRange('\u3400', '\u3d2d'); + } else if (((LA(1) >= '\u4e00' && LA(1) <= '\u9fff'))) { + matchRange('\u4e00', '\u9fff'); + } else if (((LA(1) >= '\uf900' && LA(1) <= '\ufaff'))) { + matchRange('\uf900', '\ufaff'); + } else if (((LA(1) >= '\uac00' && LA(1) <= '\ud7af'))) { + matchRange('\uac00', '\ud7af'); + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + protected final void mDIGIT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = DIGIT; + int _saveIndex; + + matchRange('0', '9'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mCR_ADRESS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = CR_ADRESS; + int _saveIndex; + + mBAND(false); + { + int _cnt112 = 0; + _loop112: + do { + if ((_tokenSet_0.member(LA(1)))) { + mLETTER(false); + } else { + if (_cnt112 >= 1) { + break _loop112; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + + _cnt112++; + } while (true); + } + { + int _cnt114 = 0; + _loop114: + do { + if (((LA(1) >= '0' && LA(1) <= '9'))) { + mDIGIT(false); + } else { + if (_cnt114 >= 1) { + break _loop114; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + + _cnt114++; + } while (true); + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + protected final void mLETTER(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = LETTER; + int _saveIndex; + + switch (LA(1)) { + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': { + matchRange('A', 'Z'); + break; + } + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': { + matchRange('a', 'z'); + break; + } + default: { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mINT_NUM(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = INT_NUM; + int _saveIndex; + + switch (LA(1)) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + { + int _cnt117 = 0; + _loop117: + do { + if (((LA(1) >= '0' && LA(1) <= '9'))) { + mDIGIT(false); + } else { + if (_cnt117 >= 1) { + break _loop117; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + + _cnt117++; + } while (true); + } + { + if ((LA(1) == '.')) { + match('.'); + { + _loop120: + do { + if (((LA(1) >= '0' && LA(1) <= '9'))) { + mDIGIT(false); + } else { + break _loop120; + } + + } while (true); + } + _ttype = FLOT_NUM; + } else { + } + + } + { + if ((LA(1) == 'E' || LA(1) == 'e')) { + mExponent(false); + _ttype = FLOT_NUM; + } else { + } + + } + + //System.out.println("number like 1.2e+12"); + + break; + } + case '.': { + match('.'); + _ttype = DOT; + { + if (((LA(1) >= '0' && LA(1) <= '9'))) { + { + int _cnt124 = 0; + _loop124: + do { + if (((LA(1) >= '0' && LA(1) <= '9'))) { + mDIGIT(false); + } else { + if (_cnt124 >= 1) { + break _loop124; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + + _cnt124++; + } while (true); + } + { + if ((LA(1) == 'E' || LA(1) == 'e')) { + mExponent(false); + } else { + } + + } + _ttype = FLOT_NUM; + } else { + } + + } + + //System.out.println("number like .3e-2"); + + break; + } + default: { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + protected final void mExponent(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = Exponent; + int _saveIndex; + + { + switch (LA(1)) { + case 'e': { + match('e'); + break; + } + case 'E': { + match('E'); + break; + } + default: { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + } + { + switch (LA(1)) { + case '+': { + match('+'); + break; + } + case '-': { + match('-'); + break; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + break; + } + default: { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + } + { + int _cnt144 = 0; + _loop144: + do { + if (((LA(1) >= '0' && LA(1) <= '9'))) { + mDIGIT(false); + } else { + if (_cnt144 >= 1) { + break _loop144; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + + _cnt144++; + } while (true); + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mSTRING_LITERAL_DSQ(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = STRING_LITERAL_DSQ; + int _saveIndex; + + match('"'); + { + _loop128: + do { + if ((LA(1) == '\\')) { + mESC(false); + } else if ((_tokenSet_2.member(LA(1)))) { + matchNot('"'); + } else { + break _loop128; + } + + } while (true); + } + match('"'); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + protected final void mESC(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = ESC; + int _saveIndex; + + match('\\'); + { + switch (LA(1)) { + case 'n': { + match('n'); + break; + } + case 'r': { + match('r'); + break; + } + case 't': { + match('t'); + break; + } + case 'b': { + match('b'); + break; + } + case 'f': { + match('f'); + break; + } + case '"': { + match('"'); + break; + } + case '\'': { + match('\''); + break; + } + case '\\': { + match('\\'); + break; + } + case 'u': { + { + int _cnt136 = 0; + _loop136: + do { + if ((LA(1) == 'u')) { + match('u'); + } else { + if (_cnt136 >= 1) { + break _loop136; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + + _cnt136++; + } while (true); + } + mXDIGIT(false); + mXDIGIT(false); + mXDIGIT(false); + mXDIGIT(false); + break; + } + case '0': + case '1': + case '2': + case '3': { + matchRange('0', '3'); + { + if (((LA(1) >= '0' && LA(1) <= '7')) && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) { + matchRange('0', '7'); + { + if (((LA(1) >= '0' && LA(1) <= '7')) && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) { + matchRange('0', '7'); + } else if (((LA(1) >= '\u0003' && LA(1) <= '\ufffe')) && (true)) { + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + + } + } else if (((LA(1) >= '\u0003' && LA(1) <= '\ufffe')) && (true)) { + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + + } + break; + } + case '4': + case '5': + case '6': + case '7': { + matchRange('4', '7'); + { + if (((LA(1) >= '0' && LA(1) <= '7')) && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) { + matchRange('0', '7'); + } else if (((LA(1) >= '\u0003' && LA(1) <= '\ufffe')) && (true)) { + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + + } + break; + } + default: { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mSTRING_LITERAL_SSQ(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = STRING_LITERAL_SSQ; + int _saveIndex; + + match('\''); + { + _loop131: + do { + if ((LA(1) == '\\')) { + mESC(false); + } else if ((_tokenSet_3.member(LA(1)))) { + matchNot('\''); + } else { + break _loop131; + } + + } while (true); + } + match('\''); + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + protected final void mXDIGIT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = XDIGIT; + int _saveIndex; + + switch (LA(1)) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + matchRange('0', '9'); + break; + } + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': { + matchRange('a', 'f'); + break; + } + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': { + matchRange('A', 'F'); + break; + } + default: { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + public final void mWS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException { + int _ttype; + Token _token = null; + int _begin = text.length(); + _ttype = WS; + int _saveIndex; + + { + int _cnt151 = 0; + _loop151: + do { + switch (LA(1)) { + case ' ': { + match(' '); + break; + } + case '\t': { + match('\t'); + break; + } + case '\u000c': { + match('\f'); + break; + } + case '\n': + case '\r': { + { + if ((LA(1) == '\r') && (LA(2) == '\n')) { + match("\r\n"); + } else if ((LA(1) == '\r') && (true)) { + match('\r'); + } else if ((LA(1) == '\n')) { + match('\n'); + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + + } + //new line 不生效情况居多,此line对于公式语法的检测没有什么作用,还不如直接用column定位,表示第xx个字符 + //newline(); + break; + } + default: { + if (_cnt151 >= 1) { + break _loop151; + } else { + throw new NoViableAltForCharException((char) LA(1), getFilename(), getLine(), getColumn()); + } + } + } + _cnt151++; + } while (true); + } + _ttype = Token.SKIP; + if (_createToken && _token == null && _ttype != Token.SKIP) { + _token = makeToken(_ttype); + _token.setText(new String(text.getBuffer(), _begin, text.length() - _begin)); + } + _returnToken = _token; + } + + + private static final long[] mk_tokenSet_0() { + long[] data = new long[1025]; + data[1] = 576460743847706622L; + return data; + } + + public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0()); + + private static final long[] mk_tokenSet_1() { + long[] data = new long[3988]; + data[0] = 68719476736L; + data[1] = 576460745995190270L; + data[3] = -36028797027352577L; + for (int i = 4; i <= 127; i++) { + data[i] = -1L; + } + for (int i = 193; i <= 197; i++) { + data[i] = -1L; + } + data[198] = 65535L; + for (int i = 204; i <= 205; i++) { + data[i] = -1L; + } + for (int i = 208; i <= 243; i++) { + data[i] = -1L; + } + data[244] = 70368744177663L; + for (int i = 312; i <= 639; i++) { + data[i] = -1L; + } + for (int i = 688; i <= 861; i++) { + data[i] = -1L; + } + data[862] = 281474976710655L; + for (int i = 996; i <= 1003; i++) { + data[i] = -1L; + } + return data; + } + + public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1()); + + private static final long[] mk_tokenSet_2() { + long[] data = new long[2048]; + data[0] = -17179869192L; + data[1] = -268435457L; + for (int i = 2; i <= 1022; i++) { + data[i] = -1L; + } + data[1023] = 9223372036854775807L; + return data; + } + + public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2()); + + private static final long[] mk_tokenSet_3() { + long[] data = new long[2048]; + data[0] = -549755813896L; + data[1] = -268435457L; + for (int i = 2; i <= 1022; i++) { + data[i] = -1L; + } + data[1023] = 9223372036854775807L; + return data; + } + + public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3()); + +} + diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java b/designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java new file mode 100644 index 0000000000..302be0b08d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java @@ -0,0 +1,48 @@ +package com.fr.design.formula; + +import com.fr.design.formula.exception.FormulaExceptionTipsProcessor; +import com.fr.design.i18n.Toolkit; +import com.fr.parser.FRParser; +import com.fr.script.checker.FunctionCheckerDispatcher; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.stable.StringUtils; +import com.fr.stable.script.Expression; +import com.fr.stable.script.Node; +import com.fr.third.antlr.TokenStreamRecognitionException; + +import java.io.StringReader; + +/** + * @author Hoky + * @date 2021/9/28 + */ +public class FormulaChecker { + public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula"); + public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"); + private static FormulaExceptionTipsProcessor processor = FormulaExceptionTipsProcessor.getProcessor(); + + public static FormulaCheckResult check(String formulaText) { + if (StringUtils.isEmpty(formulaText) || formulaText.equals(Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Tips"))) { + return new FormulaCheckResult(true, VALID_FORMULA, FormulaCoordinates.INVALID, true); + } + //过滤一些空格等符号 + StringReader in = new StringReader(formulaText); + //此lexer为公式校验定制 + FRFormulaLexer lexer = new FRFormulaLexer(in); + FRParser parser = new FRParser(lexer); + + try { + Expression expression = parser.parse(); + Node node = expression.getConditionalExpression(); + boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(formulaText, node); + return new FormulaCheckResult(valid, valid ? Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula") : + Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"), FormulaCoordinates.INVALID, true); + } catch (Exception e) { + if (e instanceof TokenStreamRecognitionException) { + return processor.getExceptionTips(((TokenStreamRecognitionException) e).recog); + } + return processor.getExceptionTips(e); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaCheckerException.java b/designer-base/src/main/java/com/fr/design/formula/FormulaCheckerException.java new file mode 100644 index 0000000000..42fc585cbb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaCheckerException.java @@ -0,0 +1,11 @@ +package com.fr.design.formula; + +public class FormulaCheckerException extends Exception { + public FormulaCheckerException() { + + } + + public FormulaCheckerException(String message) { + super(message); + } +} 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 8b68dcdbe4..a4354ee9d1 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 @@ -2,32 +2,79 @@ package com.fr.design.formula; import com.fr.base.BaseFormula; import com.fr.base.BaseUtils; +import com.fr.base.Parameter; +import com.fr.base.ParameterMapNameSpace; +import com.fr.base.TableDataNameSpace; +import com.fr.base.Utils; +import com.fr.base.io.IOFile; +import com.fr.data.TableDataSource; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; 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.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListCache; +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.FormulaCompletion; +import com.fr.design.gui.autocomplete.FormulaPaneAutoCompletion; import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilist.QuickList; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; import com.fr.design.gui.itextarea.UITextArea; import com.fr.design.gui.itextfield.UITextField; 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.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.parameter.ParameterInputPane; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.ComparatorUtils; +import com.fr.general.FArray; import com.fr.log.FineLoggerFactory; -import com.fr.parser.FRLexer; -import com.fr.parser.FRParser; +import com.fr.parser.ArrayExpression; +import com.fr.parser.BlockIntervalLiteral; +import com.fr.parser.ColumnRowRangeInPage; +import com.fr.parser.NumberLiteral; +import com.fr.parser.SheetIntervalLiteral; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.report.core.namespace.SimpleCellValueNameSpace; +import com.fr.script.Calculator; +import com.fr.script.ScriptConstants; +import com.fr.script.checker.result.FormulaCheckResult; import com.fr.stable.EncodeConstants; +import com.fr.stable.EssentialUtils; +import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; +import com.fr.stable.script.CRAddress; +import com.fr.stable.script.ColumnRowRange; import com.fr.stable.script.Expression; - -import javax.swing.*; +import com.fr.stable.script.Node; +import com.fr.stable.script.Tiny; +import com.fr.stable.script.TinyHunter; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeSelectionEvent; @@ -37,9 +84,15 @@ import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +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.FocusEvent; +import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; @@ -52,10 +105,16 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; +import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; /** * 公式编辑面板 @@ -63,21 +122,35 @@ import java.util.List; * @editor zhou * @since 2012-3-29下午1:50:53 */ +@EnableMetrics public class FormulaPane extends BasicPane implements KeyListener, UIFormula { - + public static final int DEFUAL_FOMULA_LENGTH = 103; + public static final String ELLIPSIS = "..."; + public static final char KEY_CODE_A = 'A'; + public static final char KEY_CODE_Z = 'z'; + public static final String NEWLINE = "\n"; + public static final String FORMULA_ICON = "/com/fr/design/images/m_file/formula.png"; + public static final String PARAM_ICON = "/com/fr/design/images/m_file/param.png"; private VariableTreeAndDescriptionArea variableTreeAndDescriptionArea; private RSyntaxTextArea formulaTextArea; private UITextField keyWordTextField = new UITextField(18); private int currentPosition = 0; private int beginPosition = 0; private int insertPosition = 0; + protected static UICheckBox autoCompletionCheck; + protected static UICheckBox checkBeforeColse; private JList tipsList; + private JPopupMenu popupMenu; protected DefaultListModel listModel = new DefaultListModel(); private int ifHasBeenWriten = 0; private DefaultListModel functionTypeListModel = new DefaultListModel(); private QuickList functionTypeList; private DefaultListModel functionNameModel; private JList functionNameList; + private UITableEditorPane editor4CalPane; + private FormulaPaneAutoCompletion autoCompletion; + private DefaultCompletionProvider completionProvider; + private static final Map PARAM_PREFIX_MAP = new HashMap<>(); public FormulaPane() { initComponents(); @@ -86,6 +159,20 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initFormulaTextAreaKeyListener() { formulaTextArea.addKeyListener(this); formulaTextArea.addKeyListener(new KeyAdapter() { + //用来判断一下是不是组合键 + + @Override + public void keyTyped(KeyEvent e) { + if (inKeyCodeRange(e) && autoCompletionCheck.isSelected()) { + autoCompletion.doCompletion(); + } + } + + private boolean inKeyCodeRange(KeyEvent e) { + return (e.getKeyChar() >= KEY_CODE_A && e.getKeyChar() <= KEY_CODE_Z); + } + + @Override public void keyReleased(KeyEvent e) { formulaTextArea.setForeground(Color.black); String text = formulaTextArea.getText(); @@ -121,7 +208,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { beginPosition = getBeginPosition(); insertPosition = beginPosition; firstStepToFindTips(beginPosition); - fixFunctionNameList(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); + } } } }); @@ -151,7 +240,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { if (e.getKeyCode() == KeyEvent.VK_ENTER) { String toFind = keyWordTextField.getText(); search(toFind, false); - fixFunctionNameList(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); + } e.consume(); } } @@ -160,28 +251,35 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initTipsPane() { // tipsPane - JPanel tipsPane = new JPanel(new BorderLayout(4, 4)); - this.add(tipsPane, BorderLayout.EAST); + JPanel containerSPane = new JPanel(new BorderLayout(4, 1)); + JPanel labelPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0), true); + JPanel searchPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0), true); + containerSPane.setPreferredSize(new Dimension(892, 23)); + this.add(containerSPane, BorderLayout.NORTH); - JPanel searchPane = new JPanel(new BorderLayout(4, 4)); - searchPane.add(keyWordTextField, BorderLayout.CENTER); UIButton searchButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Search")); + UILabel formulaLabel = new UILabel( + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Input_Formula_In_The_Text_Area_Below") + ":"); + formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + + labelPane.add(formulaLabel, BorderLayout.WEST); + keyWordTextField.setPreferredSize(new Dimension(240, 23)); + searchPane.add(keyWordTextField, BorderLayout.EAST); searchPane.add(searchButton, BorderLayout.EAST); - tipsPane.add(searchPane, BorderLayout.NORTH); + + containerSPane.add(labelPane, BorderLayout.WEST); + containerSPane.add(searchPane, BorderLayout.EAST); + initKeyWordTextFieldKeyListener(); tipsList = new JList(listModel); tipsList.addMouseListener(new DoubleClick()); - UIScrollPane tipsScrollPane = new UIScrollPane(tipsList); - tipsScrollPane.setPreferredSize(new Dimension(170, 75)); - tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); - tipsPane.add(tipsScrollPane, BorderLayout.CENTER); - searchButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - String toFind = keyWordTextField.getText(); - search(toFind, false); - formulaTextArea.requestFocusInWindow(); - fixFunctionNameList(); + searchButton.addActionListener(e -> { + String toFind = keyWordTextField.getText(); + search(toFind, false); + popTips(); + formulaTextArea.requestFocusInWindow(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); } }); } @@ -192,6 +290,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { initTextPane(); initTipsPane(); initVariableTreeAndDescriptionArea(); + refocusInWindow(); + } + + public void refocusInWindow() { + SwingUtilities.invokeLater(() -> formulaTextArea.requestFocusInWindow()); } private void initVariableTreeAndDescriptionArea() { @@ -203,31 +306,122 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { // text JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); this.add(textPane, BorderLayout.CENTER); - JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - UILabel formulaLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Input_Formula_In_The_Text_Area_Below") + ":" - + " "); - formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); initFormulaTextArea(); UIScrollPane formulaTextAreaScrollPane = new UIScrollPane(formulaTextArea); formulaTextAreaScrollPane.setBorder(null); - textPane.add(formulaLabel, BorderLayout.NORTH); textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER); textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH); UIButton checkValidButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Check_Valid")); + UIButton calButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Button")); checkValidButton.addActionListener(checkValidActionListener); + calButton.addActionListener(calculateActionListener); + //靠左流式布局 JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - checkBoxPane.setPreferredSize(new Dimension(450, 30)); checkBoxandbuttonPane.add(checkBoxPane, BorderLayout.WEST); - checkBoxandbuttonPane.add(checkValidButton, BorderLayout.EAST); + //靠右流式布局 + JPanel buttonPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPane.add(checkValidButton, BorderLayout.EAST); + buttonPane.add(calButton, BorderLayout.EAST); + checkBoxandbuttonPane.add(buttonPane, BorderLayout.EAST); + if (autoCompletionCheck == null) { + autoCompletionCheck = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_AutoCompletion")); + autoCompletionCheck.setSelected(true); + } + if (checkBeforeColse == null) { + checkBeforeColse = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Before_Closed")); + checkBeforeColse.setSelected(true); + } + checkBoxPane.add(autoCompletionCheck, BorderLayout.WEST); + checkBoxPane.add(checkBeforeColse, BorderLayout.WEST); extendCheckBoxPane(checkBoxPane); + + ParameterTableModel model = new ParameterTableModel(0); + editor4CalPane = new UITableEditorPane<>(model); + formulaTextArea.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + // 获得焦点时 安装 + if (autoCompletion == null && autoCompletionCheck.isSelected()) { + installAutoCompletion(); + } + } + + @Override + public void focusLost(FocusEvent e) { + // 失去焦点时 卸载 + uninstallAutoCompletion(); + } + }); + } + + private CompletionProvider createCompletionProvider() { + if (completionProvider == null) { + completionProvider = new DefaultCompletionProvider(); + NameAndDescription[] nameAndDescriptions = FunctionConstants.ALL.getDescriptions(); + for (NameAndDescription nameAndDescription : nameAndDescriptions) { + completionProvider.addCompletion(new FormulaCompletion(completionProvider, nameAndDescription.getName(), BaseUtils.readIcon(FORMULA_ICON))); + } + + VariableResolver variableResolver = VariableResolver.DEFAULT; + List allParameters = new ArrayList<>(); + allParameters.addAll(Arrays.asList(variableResolver.resolveCurReportVariables())); + allParameters.addAll(Arrays.asList(variableResolver.resolveColumnNames())); + allParameters.addAll(Arrays.asList(variableResolver.resolveGlobalParameterVariables())); + allParameters.addAll(Arrays.asList(variableResolver.resolveReportParameterVariables())); + allParameters.addAll(Arrays.asList(variableResolver.resolveTableDataParameterVariables())); + + //先把参数前缀拿出来 + for (String parameter : allParameters) { + String paramWithoutPre; + if (parameter.startsWith("$$")) { + paramWithoutPre = parameter.substring(2); + PARAM_PREFIX_MAP.put(paramWithoutPre, "$$"); + } else if (parameter.startsWith("$")) { + paramWithoutPre = parameter.substring(1); + PARAM_PREFIX_MAP.put(paramWithoutPre, "$"); + } else { + paramWithoutPre = parameter; + PARAM_PREFIX_MAP.put(paramWithoutPre, StringUtils.EMPTY); + } + completionProvider.addCompletion(new FormulaCompletion(completionProvider, paramWithoutPre, BaseUtils.readIcon(PARAM_ICON))); + } + + return completionProvider; + } + return completionProvider; + } + + public static boolean containsParam(String param) { + return PARAM_PREFIX_MAP.containsKey(param); + } + + public static String getParamPrefix(String param) { + return PARAM_PREFIX_MAP.getOrDefault(param, StringUtils.EMPTY); + } + + private void uninstallAutoCompletion() { + if (autoCompletion != null) { + autoCompletion.uninstall(); + autoCompletion = null; + } + } + + private void installAutoCompletion() { + CompletionProvider provider = createCompletionProvider(); + autoCompletion = new FormulaPaneAutoCompletion(provider); + autoCompletion.setListCellRenderer(new CompletionCellRenderer()); + autoCompletion.install(formulaTextArea); + autoCompletion.installVariableTree(variableTreeAndDescriptionArea); } protected void extendCheckBoxPane(JPanel checkBoxPane) { + // do nothing } @@ -274,6 +468,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { if (ComparatorUtils.equals((String) listModel.getElementAt(index), doublePressContent)) { doubleClickActuator(doublePressContent); } + if (popupMenu != null) { + popupMenu.setVisible(false); + } } } } @@ -281,7 +478,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void singleClickActuator(String currentLineContent) { refreshDescriptionTextArea(currentLineContent); formulaTextArea.requestFocusInWindow(); - fixFunctionNameList(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); + } } private void doubleClickActuator(String currentLineContent) { @@ -345,43 +544,47 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { beginPosition = getBeginPosition(); insertPosition = beginPosition; firstStepToFindTips(beginPosition); - fixFunctionNameList(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); + } ifHasBeenWriten = 1; } } } - private void fixFunctionNameList() { - if (tipsList.getSelectedValue() != null) { - int signOfContinue = 1; - int indexOfFunction = 0; - for (int i = 0; i < functionTypeListModel.size(); i++) { - int signOfType = 0; - FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i); - NameAndDescription[] nads = functionType.getDescriptions(); - if (signOfContinue == 1) { - functionNameModel.removeAllElements(); - String functionName = ((String) tipsList.getSelectedValue()); - for (int k = 0; k < nads.length; k++) { - functionNameModel.addElement(nads[k]); - if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex() - { - signOfType = 1; - signOfContinue = 0; - indexOfFunction = k; - } + private void fixFunctionNameList(String functionName) { + int signOfContinue = 1; + int indexOfFunction = 0; + boolean found = false; + for (int i = 0; i < functionTypeListModel.size(); i++) { + int signOfType = 0; + FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i); + NameAndDescription[] nads = functionType.getDescriptions(); + if (signOfContinue == 1) { + functionNameModel.removeAllElements(); + for (int k = 0; k < nads.length; k++) { + functionNameModel.addElement(nads[k]); + if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex() + { + signOfType = 1; + signOfContinue = 0; + indexOfFunction = k; + found = true; } + } - if (signOfType == 1) { - functionTypeList.setSelectedIndex(i); - signOfType = 0; - } + if (signOfType == 1) { + functionTypeList.setSelectedIndex(i); + signOfType = 0; } } + } + if (found) { functionNameList.setSelectedIndex(indexOfFunction); functionNameList.ensureIndexIsVisible(indexOfFunction); + } else { + functionTypeList.setSelectedIndex(0); } - } private int getBeginPosition() { @@ -432,9 +635,17 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { // do nothing } + private void popTips() { + popupMenu = new JPopupMenu(); + JScrollPane tipsScrollPane = new JScrollPane(tipsList); + popupMenu.add(tipsScrollPane); + tipsScrollPane.setPreferredSize(new Dimension(240, 146)); + tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + popupMenu.show(keyWordTextField, 0, 23); + } + protected void search(String keyWord, boolean findDescription) { listModel.removeAllElements(); - keyWord = removeAllSpace(keyWord); if (keyWord.length() != 0) { NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions(); @@ -550,7 +761,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { beginPosition = getBeginPosition(); insertPosition = beginPosition; firstStepToFindTips(beginPosition); - fixFunctionNameList(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); + } ifHasBeenWriten = 1; } else { this.formulaTextArea.setText(content); @@ -558,7 +771,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { beginPosition = getBeginPosition(); insertPosition = beginPosition; firstStepToFindTips(beginPosition); - fixFunctionNameList(); + if (tipsList.getSelectedValue() != null) { + fixFunctionNameList(tipsList.getSelectedValue().toString()); + } ifHasBeenWriten = 1; } } @@ -585,39 +800,247 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { } // check valid - private ActionListener checkValidActionListener = new ActionListener() { + private final ActionListener checkValidActionListener = new ActionListener() { public void actionPerformed(ActionEvent evt) { // Execute Formula default cell element. String formulaText = formulaTextArea.getText().trim(); + FormulaCheckResult checkResult = FormulaChecker.check(formulaText); + confirmCheckResult(checkResult, checkResult.getTips()); + } + }; + + private void calculateFormula() { + String formulaText = formulaTextArea.getText().trim(); + String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText); + if (unSupportFormula != null) { + showMessageDialog(Toolkit.i18nText("Fine-Design_Basic_Formula_Unsupported_Formulas") + ":" + unSupportFormula, false); + return; + } + + String messageTips; + FormulaCheckResult checkResult = FormulaChecker.check(formulaText); + if (checkResult.grammarValid()) { + messageTips = checkResult.getTips() + NEWLINE; + Map paramsMap = setParamsIfExist(formulaText); + Calculator calculator = Calculator.createCalculator(); + ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap); + calculator.pushNameSpace(parameterMapNameSpace); + + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (currentEditingTemplate != null) { + IOFile file = (IOFile) currentEditingTemplate.getTarget(); + calculator.setAttribute(TableDataSource.KEY, file); + calculator.pushNameSpace(TableDataNameSpace.getInstance()); + calculator.pushNameSpace(SimpleCellValueNameSpace.getInstance()); + } + + BaseFormula baseFormula = BaseFormula.createFormulaBuilder().build(formulaText); + Object calResult; + try { + calResult = calculator.evalValue(baseFormula); + String objectToString = EssentialUtils.objectToString(calResult); + String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ? + objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString; + messageTips = messageTips + Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result; + } catch (Exception ce) { + //模拟计算如果出现错误,则抛出错误 + calResult = ce.getMessage(); + FineLoggerFactory.getLogger().error(ce.getMessage(), ce); + messageTips = messageTips + Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Error") + ":" + calResult; + } + FineLoggerFactory.getLogger().info("value:{}", calResult); + } else { + messageTips = checkResult.getTips(); + } + if (checkResult.isValid()) { + showMessageDialog(messageTips, checkResult.isValid()); + } else { + confirmCheckResult(checkResult, messageTips); + } + } + + + private final ActionListener calculateActionListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + calculateFormula(); + } + }; + + private boolean confirmCheckResult(FormulaCheckResult checkResult, String messageTips) { + if (checkResult.isValid()) { + showMessageDialog(checkResult.getTips(), checkResult.isValid()); + } else { + int columns = checkResult.getFormulaCoordinates().getColumns(); + String position = StringUtils.EMPTY; + if (columns >= 0) { + position = Toolkit.i18nText("Fine-Design_Basic_Formula_The") + columns + + Toolkit.i18nText("Fine-Design_Basic_Formula_Error_Position") + " "; + } + int confirmDialog = FineJOptionPane.showConfirmDialog( + FormulaPane.this, + position + messageTips, + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Result"), Toolkit.i18nText("Fine-Design_Basic_Formula_Continue")}, + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Result")); + if (confirmDialog == 0) { + formulaTextArea.setCaretPosition(Math.max(columns, 0)); + formulaTextArea.requestFocus(); + return false; + } + } + return true; + } + + private void showMessageDialog(String message, boolean formulaValid) { + if (formulaValid) { + FineJOptionPane.showMessageDialog( + FormulaPane.this, + message); + } else { + FineJOptionPane.showMessageDialog( + FormulaPane.this, + message, + Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.WARNING_MESSAGE); + } + } + + private String containsUnsupportedSimulationFormulas(String formulaText) { + try { + Expression expression = Calculator.createCalculator().parse(formulaText); + UnsupportedFormulaScanner scanner = new UnsupportedFormulaScanner(); + if (!scanner.travelFormula(expression.getConditionalExpression())) { + return scanner.getUnSupportFormula(); + } + + UnsupportedSimulationNodeHunter unsupportedSimulationFormulaHunter = new UnsupportedSimulationNodeHunter(); + expression.traversal4Tiny(unsupportedSimulationFormulaHunter); + return unsupportedSimulationFormulaHunter.isSupported() ? null : unsupportedSimulationFormulaHunter.getUnSupportedNode(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("", e); + } + return null; + } + + @Override + public boolean confirmContinueBeforeDoOK() { + if (checkBeforeColse.isSelected()) { + String formula = formulaTextArea.getText().trim(); + FormulaCheckResult checkResult = FormulaChecker.check(formula); + if (!checkResult.isValid()) { + return confirmCheckResult(checkResult, checkResult.getTips()); + } + } + return true; + } + + private Map setParamsIfExist(String formulaText) { + Map parameterMap = new HashMap<>(); + try { + Calculator calculator = Calculator.createCalculator(); + Expression expression = calculator.parse(formulaText); + ParameterCellHunter parameterCellHunter = new ParameterCellHunter(); + expression.traversal4Tiny(parameterCellHunter); + Parameter[] parameters = parameterCellHunter.getParameterBooty(); + + if (parameters.length < 1 && editor4CalPane.update().size() < 1) { + return parameterMap; + } + ParameterInputPane pPane = new ParameterInputPane(parameters); + pPane.showSmallWindow(new JFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + parameterMap.putAll(pPane.update()); + } + }).setVisible(true); + //过滤出数组参数,如:[1,2] + for (Map.Entry entry : parameterMap.entrySet()) { + if (entry.getValue().toString().startsWith("[") && entry.getValue().toString().endsWith("]")) { + Expression parse = calculator.parse(entry.getValue()); + ArrayExpression arrayExpression = (ArrayExpression) parse.getConditionalExpression(); + Node[] arrays = arrayExpression.getArrays(); + List arrayList = new ArrayList<>(); + for (Node array : arrays) { + if (array instanceof NumberLiteral) { + arrayList.add(NumberFormat.getInstance().parse(array.toString())); + } else { + arrayList.add(array); + } + } + FArray fArray = new FArray<>(arrayList); + parameterMap.put(entry.getKey(), fArray); + } else if (Utils.isNumeric(entry.getValue().toString())) { + try { + Number number = NumberFormat.getInstance().parse(entry.getValue().toString()); + parameterMap.put(entry.getKey(), number); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn("", e); + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("", e); + } + return parameterMap; + } - if (formulaText != null && formulaText.length() > 0) { - StringReader in = new StringReader(formulaText); + private static class ParameterCellHunter extends TinyHunter { - FRLexer lexer = new FRLexer(in); - FRParser parser = new FRParser(lexer); + private final Set parameterList = new HashSet<>(); + + Parameter[] getParameterBooty() { + return parameterList.toArray(new Parameter[0]); + } - Expression expression = null; - try { - expression = parser.parse(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - // alex:继续往下面走,expression为null时告知不合法公式 + public void hunter4Tiny(Tiny tiny) { + String statement = tiny.getStatement(); + if (StringUtils.isNotBlank(statement) && statement.startsWith(ScriptConstants.DETAIL_TAG)) { + if (statement.startsWith(ScriptConstants.SUMMARY_TAG)) { + parameterList.add(new Parameter(statement)); + } else { + parameterList.add(new Parameter(statement.substring(1))); } + } else if (tiny.getClass() == ColumnRowRange.class || + tiny.getClass() == SheetIntervalLiteral.class || tiny.getClass() == BlockIntervalLiteral.class) { + parameterList.add(new Parameter(tiny.toString())); + } + } + } + + private static class UnsupportedSimulationNodeHunter extends TinyHunter { + + private boolean supported = true; + + private String unSupportedNode; + + private String[] curReportVariables; + + public UnsupportedSimulationNodeHunter() { + curReportVariables = VariableResolver.DEFAULT.resolveCurReportVariables(); + } - FineJOptionPane.showMessageDialog( - FormulaPane.this, - /* - * alex:仅仅只需要根据expression是否为null作合法性判断 - * 不需要eval - * TODO 但有个问题,有些函数的参数个数是有规定的,何以判别之 - */ - (expression != null ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula")) + ".", - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), - JOptionPane.INFORMATION_MESSAGE); + public boolean isSupported() { + return supported; + } + + public String getUnSupportedNode() { + return unSupportedNode; + } + + public void hunter4Tiny(Tiny tiny) { + if (tiny.getClass() == ColumnRowRangeInPage.class || tiny.getClass() == CRAddress.class + || Arrays.asList(curReportVariables).contains(tiny.toString())) { + supported = false; + unSupportedNode = tiny.toString(); } } - }; + } public class VariableTreeAndDescriptionArea extends JPanel { @@ -757,7 +1180,8 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initDescriptionTextArea() { // Description - descriptionTextArea = new UITextArea(16, 27); + descriptionTextArea = new UITextArea(); + descriptionTextArea.setPreferredSize(new Dimension(350, 200)); UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea); desScrollPane.setBorder(null); @@ -805,13 +1229,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) variablesTree.getLastSelectedPathComponent(); Object selectedValue = selectedTreeNode.getUserObject(); - Object selectedParentValue = ((DefaultMutableTreeNode)selectedTreeNode.getParent()).getUserObject(); + Object selectedParentValue = ((DefaultMutableTreeNode) selectedTreeNode.getParent()).getUserObject(); if (selectedValue == null) { return; } - if (selectedValue instanceof TextUserObject) { + if (selectedValue instanceof TextUserObject) { //有公式说明的条件:1.属于TextUserObject 2.parent是系统参数 if (ComparatorUtils.equals(((TextFolderUserObject) selectedParentValue).getText(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables"))) { @@ -885,7 +1309,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { }; basicPane.setLayout(FRGUIPaneFactory.createBorderLayout()); UITextArea desArea = new UITextArea(); -// desArea。setEnabled(false); desArea.setText(this.getTextAreaText()); basicPane.add(new UIScrollPane(desArea), BorderLayout.CENTER); BasicDialog dialog = basicPane.showWindow(DesignerContext.getDesignerFrame()); @@ -958,6 +1381,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { } }; + public void refreshText(String line) { + fixFunctionNameList(line); + refreshDescriptionTextArea(line); + } + public void populate(VariableResolver variableResolver) { // varibale tree. DefaultTreeModel variableModel = (DefaultTreeModel) variablesTree.getModel(); @@ -1010,6 +1438,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { /** * 把以关键词开头的和不以关键词开头的分别按照字母表顺序排序 + * * @param o1 待比较对象1 * @param o2 待比较对象2 * @return 比较结果,1表示 o1 > o2, -1表示 o1 < o2, 0表示 o1 = o2 @@ -1092,12 +1521,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { buffer.append(name.toUpperCase()); buffer.append("\""); buffer.append("|"); - buffer.append("\n"); + buffer.append(NEWLINE); buffer.append("\""); buffer.append(name.toLowerCase()); buffer.append("\""); buffer.append("|"); - buffer.append("\n"); + buffer.append(NEWLINE); } FineLoggerFactory.getLogger().debug(buffer.toString()); } diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java b/designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java index e08f7e3b40..ab49b605d4 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java @@ -3,11 +3,10 @@ package com.fr.design.formula; import com.fr.base.BaseFormula; import com.fr.design.gui.icheckbox.UICheckBox; - -import javax.swing.*; +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.*; +import java.awt.BorderLayout; /** * @author richie @@ -41,8 +40,8 @@ public class FormulaPaneWhenReserveFormula extends FormulaPane { reserveCheckBox4Write = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Save_Formula")); reserveCheckBox4Write.setSelected(false); - checkBoxPane.add(reserveCheckBox4Result, BorderLayout.CENTER); - checkBoxPane.add(reserveCheckBox4Write, BorderLayout.SOUTH); + checkBoxPane.add(reserveCheckBox4Result, BorderLayout.WEST); + checkBoxPane.add(reserveCheckBox4Write, BorderLayout.WEST); } @Override diff --git a/designer-base/src/main/java/com/fr/design/formula/UnsupportedFormulaScanner.java b/designer-base/src/main/java/com/fr/design/formula/UnsupportedFormulaScanner.java new file mode 100644 index 0000000000..88f7a24b3a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/UnsupportedFormulaScanner.java @@ -0,0 +1,54 @@ +package com.fr.design.formula; + +import com.fr.parser.BinaryExpression; +import com.fr.parser.DatasetFunctionCall; +import com.fr.parser.FunctionCall; +import com.fr.stable.script.Node; + +import java.util.Arrays; + +/** + * @author Hoky + * @date 2021/8/30 + */ +public class UnsupportedFormulaScanner { + public final static String[] UNSUPPORTED_FORMULAS = new String[]{"PROPORTION", "TOIMAGE", + "WEBIMAGE", "SORT", "CROSSLAYERTOTAL", "CIRCULAR", "LAYERTOTAL", "MOM", "HIERARCHY", + "FILENAME", "FILESIZE", "FILETYPE", "TREELAYER", "GETUSERDEPARTMENTS", "GETUSERJOBTITLES"}; + + private String unSupportFormula = ""; + + public boolean travelFormula(Node node) { + if (node instanceof FunctionCall) { + if (isUnsupportedFomula(((FunctionCall) node).getName())) { + unSupportFormula = ((FunctionCall) node).getName(); + return false; + } else { + for (Node argument : ((FunctionCall) node).getArguments()) { + if (!travelFormula(argument)) { + return false; + } + } + } + } else if (node instanceof BinaryExpression) { + for (Node array : ((BinaryExpression) node).getNodes()) { + if (!travelFormula(array)) { + return false; + } + } + } else if (node instanceof DatasetFunctionCall) { + DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) node; + unSupportFormula = datasetFunctionCall.getSourceName() + "." + datasetFunctionCall.getFnName() + "()"; + return false; + } + return true; + } + + public String getUnSupportFormula() { + return unSupportFormula; + } + + private static boolean isUnsupportedFomula(String formula) { + return Arrays.asList(UNSUPPORTED_FORMULAS).contains(formula.toUpperCase()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java b/designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java new file mode 100644 index 0000000000..53fa9aaf89 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java @@ -0,0 +1,48 @@ +package com.fr.design.formula.exception; + +import com.fr.design.formula.FormulaChecker; +import com.fr.design.formula.exception.function.FormulaCheckWrongFunction; +import com.fr.design.formula.exception.function.MismatchedCharFunction; +import com.fr.design.formula.exception.function.MismatchedTokenFunction; +import com.fr.design.formula.exception.function.NoViableAltForCharFunction; +import com.fr.design.formula.exception.function.NoViableAltFunction; +import com.fr.script.checker.exception.FunctionCheckWrongException; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.third.antlr.MismatchedCharException; +import com.fr.third.antlr.MismatchedTokenException; +import com.fr.third.antlr.NoViableAltException; +import com.fr.third.antlr.NoViableAltForCharException; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +/** + * @author Hoky + * @date 2021/10/26 + */ +public class FormulaExceptionTipsProcessor { + private static final Map> EXCEPTION_TIPS = new ConcurrentHashMap<>(); + + private static final FormulaExceptionTipsProcessor PROCESSOR = new FormulaExceptionTipsProcessor(); + + static { + EXCEPTION_TIPS.put(FunctionCheckWrongException.class, FormulaCheckWrongFunction.getFunction()); + EXCEPTION_TIPS.put(MismatchedCharException.class, MismatchedCharFunction.getFunction()); + EXCEPTION_TIPS.put(MismatchedTokenException.class, MismatchedTokenFunction.getFunction()); + EXCEPTION_TIPS.put(NoViableAltException.class, NoViableAltFunction.getFunction()); + EXCEPTION_TIPS.put(NoViableAltForCharException.class, NoViableAltForCharFunction.getFunction()); + + } + + public FormulaCheckResult getExceptionTips(Exception e) { + return EXCEPTION_TIPS.getOrDefault(e.getClass(), + e1 -> new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false)) + .apply(e); + } + + public static FormulaExceptionTipsProcessor getProcessor() { + return PROCESSOR; + } +} diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java new file mode 100644 index 0000000000..20ad72156b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java @@ -0,0 +1,14 @@ +package com.fr.design.formula.exception.function; + +/** + * @author Hoky + * @date 2021/10/28 + */ +public class FormulaCheckConstants { + public static final String COLON = ":"; + public static final String LEFT = "("; + public static final String COMMON = ","; + public static final String RIGHT = ")"; + public static final String BLANK = " "; + public static final String SINGLE_QUOTES = "'"; +} diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java new file mode 100644 index 0000000000..417e9b37a6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java @@ -0,0 +1,80 @@ +package com.fr.design.formula.exception.function; + +import com.fr.design.i18n.Toolkit; +import com.fr.script.checker.exception.FunctionCheckWrongException; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.script.rules.FunctionParameterType; +import com.fr.script.rules.FunctionRule; +import com.fr.stable.StringUtils; + +import java.util.List; +import java.util.function.Function; + +/** + * @author Hoky + * @date 2021/10/26 + */ +public class FormulaCheckWrongFunction implements Function { + private final static FormulaCheckWrongFunction FUNCTION = new FormulaCheckWrongFunction(); + + @Override + public FormulaCheckResult apply(Exception e) { + if (e instanceof FunctionCheckWrongException) { + FunctionCheckWrongException ce = (FunctionCheckWrongException) e; + List rules = ce.getRules(); + String functionName = ce.getFunctionName(); + StringBuilder errorMsg = new StringBuilder(functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + FormulaCheckConstants.COLON); + for (int i = 0; i < rules.size(); i++) { + errorMsg.append(FormulaCheckConstants.LEFT); + if (rules.get(i).getParameterList().isEmpty()) { + errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param")); + } + for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) { + errorMsg.append(getTypeString(functionParameterType)).append(FormulaCheckConstants.COMMON); + } + if (FormulaCheckConstants.COMMON.equals(errorMsg.charAt(errorMsg.length() - 1) + StringUtils.EMPTY)) { + errorMsg.deleteCharAt(errorMsg.length() - 1); + } + errorMsg.append(FormulaCheckConstants.RIGHT); + if (i != rules.size() - 1) { + errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or")); + } + } + return new FormulaCheckResult(false, errorMsg.toString(), new FormulaCoordinates(1, indexPosition(ce.getFormulaText(), ce.getNode().toString())), true); + } + return new FormulaCheckResult(false, StringUtils.EMPTY, new FormulaCoordinates(-1, -1), true); + } + + private static String getTypeString(FunctionParameterType type) { + switch (type) { + case NUMBER: + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number"); + case STRING: + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String"); + case ANY: + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any"); + case DATE: + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date"); + case BOOLEAN: + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean"); + case ARRAY: + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array"); + } + return StringUtils.EMPTY; + } + + public static Function getFunction() { + return FUNCTION; + } + + private int indexPosition(String formulaText, String invalidFormula) { + //处理一下自己FunctionCall自己拼的逗号逻辑 + if (invalidFormula.contains(",")) { + invalidFormula = invalidFormula.substring(0, invalidFormula.indexOf(",")); + } + int index = formulaText.indexOf(invalidFormula); + return index; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java new file mode 100644 index 0000000000..69ea0c81a9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java @@ -0,0 +1,95 @@ +package com.fr.design.formula.exception.function; + +import com.fr.design.formula.FormulaChecker; +import com.fr.design.i18n.Toolkit; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.third.antlr.MismatchedCharException; + +import java.util.function.Function; + +/** + * @author Hoky + * @date 2021/10/28 + */ +public class MismatchedCharFunction implements Function { + private final static MismatchedCharFunction FUNCTION = new MismatchedCharFunction(); + + @Override + public FormulaCheckResult apply(Exception e) { + if (e instanceof MismatchedCharException) { + MismatchedCharException charException = (MismatchedCharException) e; + FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1); + return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false); + } + return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); + } + + public static Function getFunction() { + return FUNCTION; + } + + private String getMessage(MismatchedCharException charException) { + StringBuffer sb = new StringBuffer(); + switch (charException.mismatchType) { + case 1: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": "); + appendCharName(sb, charException.expecting); + break; + case 2: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ") + .append(FormulaCheckConstants.BLANK) + .append(FormulaCheckConstants.SINGLE_QUOTES); + appendCharName(sb, charException.expecting); + sb.append("';").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway")); + break; + case 3: + case 4: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token")); + if (charException.mismatchType == 4) { + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not")); + } + + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")).append(": "); + appendCharName(sb, charException.expecting); + sb.append(".."); + appendCharName(sb, charException.upper); + break; + case 5: + case 6: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") + .append(charException.mismatchType == 6 ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not") : FormulaCheckConstants.BLANK) + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF")).append(" ("); + int[] elems = charException.set.toArray(); + + for (int i = 0; i < elems.length; ++i) { + appendCharName(sb, elems[i]); + } + break; + default: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Char")); + } + + return sb.toString(); + } + + private void appendCharName(StringBuffer sb, int c) { + switch (c) { + case 9: + sb.append("'\\t'"); + break; + case 10: + sb.append("'\\n'"); + break; + case 13: + sb.append("'\\r'"); + break; + case 65535: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF")); + break; + default: + sb.append((char) c); + } + + } +} 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 new file mode 100644 index 0000000000..dd830ed572 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java @@ -0,0 +1,110 @@ +package com.fr.design.formula.exception.function; + +import com.fr.design.formula.FormulaChecker; +import com.fr.design.i18n.Toolkit; +import com.fr.log.FineLoggerFactory; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.stable.StringUtils; +import com.fr.third.antlr.MismatchedTokenException; + +import java.lang.reflect.Field; +import java.util.function.Function; + +/** + * @author Hoky + * @date 2021/10/28 + */ +public class MismatchedTokenFunction implements Function { + private final static MismatchedTokenFunction FUNCTION = new MismatchedTokenFunction(); + public static final String NULL_STRING = "null"; + + @Override + public FormulaCheckResult apply(Exception e) { + if (e instanceof MismatchedTokenException) { + MismatchedTokenException charException = (MismatchedTokenException) e; + FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1); + return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false); + } + return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); + } + + public static Function getFunction() { + return FUNCTION; + } + + public String getMessage(MismatchedTokenException exception) { + StringBuilder sb = new StringBuilder(); + Object fieldValue = getFieldValue(exception, "tokenText"); + String tokenText = fieldValue == null ? NULL_STRING : fieldValue.toString(); + switch (exception.mismatchType) { + case 1: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") + .append(tokenName(exception.expecting, exception)); + break; + case 2: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ") + .append(tokenName(exception.expecting, exception)) + .append("; ") + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway")); + break; + case 3: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token")) + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")) + .append(": ") + .append(tokenName(exception.expecting, exception)) + .append("..") + .append(tokenName(exception.upper, exception)); + break; + case 4: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token")) + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not")) + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")) + .append(": ") + .append(tokenName(exception.expecting, exception)) + .append("..") + .append(tokenName(exception.upper, exception)); + break; + case 5: + case 6: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") + .append(exception.mismatchType == 6 ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not") : FormulaCheckConstants.BLANK) + .append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF")).append("("); + int[] elms = exception.set.toArray(); + + for (int i = 0; i < elms.length; ++i) { + sb.append(' '); + sb.append(tokenName(elms[i], exception)); + } + + break; + default: + sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Token")); + } + + return sb.toString(); + } + + private String tokenName(int tokenType, MismatchedTokenException exception) { + if (tokenType == 0) { + return ""; + } else { + String[] tokenNames = (String[]) getFieldValue(exception, "tokenNames"); + return tokenType >= 0 && tokenType < tokenNames.length ? TranslateTokenUtils.translateToken(tokenNames[tokenType]) : "<" + tokenType + ">"; + } + } + + + private Object getFieldValue(Object object, String fieldName) { + try { + Field field = object.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(object); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + return StringUtils.EMPTY; + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java new file mode 100644 index 0000000000..1f0bdf8735 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java @@ -0,0 +1,44 @@ +package com.fr.design.formula.exception.function; + +import com.fr.design.formula.FormulaChecker; +import com.fr.design.i18n.Toolkit; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.third.antlr.NoViableAltForCharException; + +import java.util.function.Function; + +/** + * @author Hoky + * @date 2021/10/28 + */ +public class NoViableAltForCharFunction implements Function { + private final static NoViableAltForCharFunction FUNCTION = new NoViableAltForCharFunction(); + + @Override + public FormulaCheckResult apply(Exception e) { + if (e instanceof NoViableAltForCharException) { + NoViableAltForCharException charException = (NoViableAltForCharException) e; + FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1); + return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false); + } + return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); + } + + public static Function getFunction() { + return FUNCTION; + } + + public String getMessage(NoViableAltForCharException exception) { + String mesg = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Char") + ": "; + if (exception.foundChar >= ' ' && exception.foundChar <= '~') { + mesg = mesg + '\''; + mesg = mesg + exception.foundChar; + mesg = mesg + '\''; + } else { + mesg = mesg + exception.foundChar; + } + + return mesg; + } +} diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java new file mode 100644 index 0000000000..85cc0ecc64 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java @@ -0,0 +1,41 @@ +package com.fr.design.formula.exception.function; + +import com.fr.design.formula.FormulaChecker; +import com.fr.design.i18n.Toolkit; +import com.fr.script.checker.result.FormulaCheckResult; +import com.fr.script.checker.result.FormulaCoordinates; +import com.fr.third.antlr.NoViableAltException; +import com.fr.third.antlr.TreeParser; + +import java.util.function.Function; + +/** + * @author Hoky + * @date 2021/10/28 + */ +public class NoViableAltFunction implements Function { + private final static NoViableAltFunction FUNCTION = new NoViableAltFunction(); + + @Override + public FormulaCheckResult apply(Exception e) { + if (e instanceof NoViableAltException) { + NoViableAltException altException = (NoViableAltException) e; + FormulaCoordinates formulaCoordinates = new FormulaCoordinates(altException.line, altException.column - 1); + return new FormulaCheckResult(false, getMessage(altException), formulaCoordinates, false); + } + return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); + } + + public static Function getFunction() { + return FUNCTION; + } + + public String getMessage(NoViableAltException exception) { + if (exception.token != null) { + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Token") + ": " + exception.token.getText(); + } else { + return exception.node == TreeParser.ASTNULL ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_End_Of_Subtree") : + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_AST_Node") + ": " + exception.node.toString(); + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/formula/exception/function/TranslateTokenUtils.java b/designer-base/src/main/java/com/fr/design/formula/exception/function/TranslateTokenUtils.java new file mode 100644 index 0000000000..1df697d071 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/exception/function/TranslateTokenUtils.java @@ -0,0 +1,96 @@ +package com.fr.design.formula.exception.function; + +import com.fr.design.i18n.Toolkit; + +/** + * @author Hoky + * @date 2021/11/30 + */ +public class TranslateTokenUtils { + public static String translateToken(String token) { + switch (token) { + case ("RPAREN"): + return ")"; + case ("LPAREN"): + return "("; + case ("COMMA"): + return ","; + case ("COLON"): + return ":"; + case ("EOF"): + return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF"); + case ("DOT"): + return "."; + case ("FLOT_NUM"): + return Toolkit.i18nText("Fine-Design_Basic_Formula_Float_Number"); + case ("LOR"): + return "||"; + case ("LAND"): + return "&&"; + case ("EQUAL"): + return "="; + case ("EQUAL2"): + return "="; + case ("NOT_EQUAL"): + return "!="; + case ("NOT_EQUAL2"): + return "!="; + case ("GE"): + return ">="; + case ("LE"): + return "<="; + case ("LT"): + return "<"; + case ("PLUS"): + return "+"; + case ("MINUS"): + return "-"; + case ("STAR"): + return "*"; + case ("DIV"): + return "/"; + case ("MOD"): + return "%"; + case ("POWER"): + return "^"; + case ("LNOT"): + return "!"; + case ("WAVE"): + return "~"; + case ("LBRACK"): + return "["; + case ("SEMI"): + return ";"; + case ("RBRACK"): + return "]"; + case ("LCURLY"): + return "{"; + case ("RCURLY"): + return "}"; + case ("DCOLON"): + return ";"; + case ("INT_NUM"): + return Toolkit.i18nText("Fine-Design_Basic_Formula_Integer"); + case ("CR_ADRESS"): + return "\n"; + case ("SHARP"): + return "#"; + case ("AT"): + return "@"; + case ("QUESTION"): + return "?"; + case ("BOR"): + return "||"; + case ("BAND"): + return "&&"; + case ("Char"): + return Toolkit.i18nText("Fine-Design_Basic_Formula_Character"); + case ("DIGIT"): + return Toolkit.i18nText("Fine-Design_Basic_Formula_Digital"); + case ("XDIGIT"): + return Toolkit.i18nText("Fine-Design_Basic_Formula_Hexadecimal_Digital"); + default: + return token; + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/fun/PcFitProvider.java b/designer-base/src/main/java/com/fr/design/fun/PcFitProvider.java new file mode 100644 index 0000000000..46437917e9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/PcFitProvider.java @@ -0,0 +1,19 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.mark.Mutable; + + +public interface PcFitProvider extends Mutable { + String XML_TAG = "PcFitProvider"; + int CURRENT_LEVEL = 1; + + //设计器上看到的选项 + String getContentDisplayValue(); + + //返回给前端的值 + int getContentDisplayKey(); + + //设计器上的提示信息 + String getContentDisplayTip(); + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java b/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java index c07a4efe03..76b5037ef5 100644 --- a/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java +++ b/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java @@ -2,6 +2,7 @@ package com.fr.design.fun; import com.fr.design.mainframe.JTemplate; import com.fr.stable.Filter; +import com.fr.stable.StringUtils; import com.fr.stable.fun.mark.Mutable; import java.util.Map; @@ -62,5 +63,13 @@ public interface PreviewProvider extends Mutable, Filter { */ String getActionType(); + /** + * 下拉弹出菜单的提示 + * @return 弹出菜单的提示 + */ + default String tooltipForPopItem() { + return StringUtils.EMPTY; + } + } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPcFitProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPcFitProvider.java new file mode 100644 index 0000000000..b3a43754ef --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPcFitProvider.java @@ -0,0 +1,19 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.PcFitProvider; +import com.fr.stable.fun.mark.API; + + +@API(level = PcFitProvider.CURRENT_LEVEL) +public abstract class AbstractPcFitProvider implements PcFitProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/DesignerStartWithEmptyFile.java b/designer-base/src/main/java/com/fr/design/fun/impl/DesignerStartWithEmptyFile.java new file mode 100644 index 0000000000..12ad01dccd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/DesignerStartWithEmptyFile.java @@ -0,0 +1,28 @@ +package com.fr.design.fun.impl; + +import com.fr.file.FILE; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.record.analyzer.EnableMetrics; + +/** + * Created by rinoux on 2016/12/16. + */ +@EnableMetrics +public class DesignerStartWithEmptyFile extends AbstractDesignerStartOpenFileProcessor { + + private static final DesignerStartWithEmptyFile INSTANCE = new DesignerStartWithEmptyFile(); + + private DesignerStartWithEmptyFile() { + } + + public static DesignerStartWithEmptyFile getInstance() { + return INSTANCE; + } + + @Override + @Focus(id = "com.fr.dzstartemptyfile", text = "Fine_Design_Start_Empty_File", source = Original.REPORT) + public FILE fileToShow() { + return null; + } +} 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 new file mode 100644 index 0000000000..0e1c7c6ac2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java @@ -0,0 +1,1003 @@ +/* + * 12/21/2008 + * + * AutoCompletePopupWindow.java - A window containing a list of auto-complete + * choices. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +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 + * certain keystrokes in the parent text component and uses them to navigate + * the completion choices instead. If Enter or Escape is pressed, the window + * hides itself and notifies the {@link AutoCompletion} to insert the selected + * text. + * + * @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"; + + + /** + * 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(); + } + } + + } + + + 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/FormulaCompletion.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaCompletion.java new file mode 100644 index 0000000000..3b344dc358 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaCompletion.java @@ -0,0 +1,22 @@ +package com.fr.design.gui.autocomplete; + +import javax.swing.Icon; + +/** + * @author Hoky + * @date 2021/11/5 + */ +public class FormulaCompletion extends BasicCompletion { + private Icon icon; + + public FormulaCompletion(CompletionProvider provider, String replacementText, Icon icon) { + super(provider, replacementText); + this.icon = icon; + } + + @Override + public Icon getIcon() { + return icon; + } + +} 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 new file mode 100644 index 0000000000..8168c767d5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java @@ -0,0 +1,1311 @@ +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(); + + + /** + * Constructor. + * + * @param provider The completion provider. This cannot be + * null. + */ + 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); + // 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 (preferredChoicesWindowSize != null) { + popupWindow.setSize(preferredChoicesWindowSize); + } + if (preferredDescWindowSize != null) { + popupWindow.setDescriptionWindowSize( + preferredDescWindowSize); + } + 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. + * + * @param c A completion to insert. This cannot be null. + * @param typedParamListStartChar Whether the parameterized completion + * start character was typed (typically '('). + */ + protected void insertCompletion(Completion c, + boolean typedParamListStartChar) { + + JTextComponent textComp = getTextComponent(); + String alreadyEntered = c.getAlreadyEntered(textComp); + hidePopupWindow(); + Caret caret = textComp.getCaret(); + + int dot = caret.getDot(); + int len = alreadyEntered.length(); + int start = dot - len; + String replacement = getReplacementText(c, textComp.getDocument(), + start, len); + + caret.setDot(start); + caret.moveDot(dot); + if (FormulaPane.containsParam(replacement)) { + textComp.replaceSelection(FormulaPane.getParamPrefix(replacement) + replacement); + int caretPosition = textComp.getCaretPosition(); + textComp.setCaretPosition(caretPosition); + } else { + textComp.replaceSelection(replacement + "()"); + int caretPosition = textComp.getCaretPosition(); + textComp.setCaretPosition(caretPosition - 1); + } + + + if (isParameterAssistanceEnabled() && + (c instanceof ParameterizedCompletion)) { + ParameterizedCompletion pc = (ParameterizedCompletion) c; + startParameterizedCompletionAssistance(pc, typedParamListStartChar); + } + + } + + /** + * 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/ParameterizedCompletionContext.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java index 78d5e74a48..238fa496b8 100644 --- a/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java @@ -16,16 +16,34 @@ import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; import com.fr.design.gui.syntax.ui.rtextarea.ChangeableHighlightPainter; import com.fr.log.FineLoggerFactory; -import javax.swing.*; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +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.*; +import javax.swing.text.AbstractDocument; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Document; +import javax.swing.text.Highlighter; import javax.swing.text.Highlighter.Highlight; import javax.swing.text.Highlighter.HighlightPainter; -import java.awt.*; -import java.awt.event.*; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; @@ -41,7 +59,7 @@ import java.util.List; * @author Robert Futrell * @version 1.0 */ -class ParameterizedCompletionContext { +public class ParameterizedCompletionContext { /** * The parent window. diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java index 82cba758b7..ee05422caa 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java @@ -1,10 +1,12 @@ package com.fr.design.gui.controlpane; import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilist.JNameEdList; import com.fr.design.gui.ilist.ListModelElement; import com.fr.design.gui.ilist.ModNameActionListener; +import com.fr.design.i18n.Toolkit; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.form.event.Listener; import com.fr.general.ComparatorUtils; @@ -12,6 +14,7 @@ import com.fr.general.IOUtils; import com.fr.invoke.Reflect; import com.fr.stable.ArrayUtils; import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; import javax.swing.DefaultListCellRenderer; @@ -23,12 +26,16 @@ import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import java.util.Collection; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +import static javax.swing.JOptionPane.WARNING_MESSAGE; public abstract class JListControlPane extends JControlPane implements ListControlPaneProvider { private static final String LIST_NAME = "JControl_List"; @@ -424,4 +431,47 @@ public abstract class JListControlPane extends JControlPane implements ListContr } + public boolean checkName() { + String tempName = getEditingName(); + if (ComparatorUtils.equals(tempName, selectedName)) { + return false; + } + + if (StringUtils.isEmpty(tempName)) { + nameableList.stopEditing(); + showWarningDialog(getEmptyNameTip()); + setIllegalIndex(editingIndex); + return false; + } + + String[] allListNames = nameableList.getAllNames(); + allListNames[editingIndex] = StringUtils.EMPTY; + if (isNameRepeated(new Collection[]{getExtraItemsToCheckNameRepeat(), Arrays.asList(allListNames)}, tempName)) { + nameableList.stopEditing(); + showWarningDialog(getDuplicatedNameTip()); + setIllegalIndex(editingIndex); + return false; + } + return true; + } + + public String getEmptyNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Not_Null_Des"); + } + + public String getDuplicatedNameTip() { + return StringUtils.EMPTY; + } + + public Collection getExtraItemsToCheckNameRepeat() { + return new ArrayList(); + } + + private void showWarningDialog(String tip) { + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(JListControlPane.this), + tip, + Toolkit.i18nText("Fine-Design_Basic_Alert"), + WARNING_MESSAGE); + } + } diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java index 063491f884..ed07ecc2d5 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java @@ -331,7 +331,7 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li width = Math.max(width, calculateUIListMaxCellWidth(uiList.getModel(), uiList.getFontMetrics(uiList.getFont()))); } iterator = nameEdListMap.entrySet().iterator(); - width += 40; + width += 30; while (iterator.hasNext()) { Map.Entry entry = iterator.next(); ListWrapperPane wrapperPane = entry.getValue(); @@ -351,7 +351,8 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li } else { text = element.toString(); } - width = Math.max(width, fontMetrics.stringWidth(text)); + //增加 10px 的左右间隔 + width = Math.max(width, fontMetrics.stringWidth(text) + 10); } } return width; @@ -541,7 +542,8 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li label.setBackground(Color.WHITE); label.setForeground(Color.decode("#333334")); label.setFont(label.getFont().deriveFont(11F)); - label.setPreferredSize(new Dimension(224, 26)); + //预留 10px 的纵向滚动条的宽度 + label.setPreferredSize(new Dimension(214, 26)); this.nameEdList = nameEdList; this.add(label, BorderLayout.NORTH); this.add(this.nameEdList, BorderLayout.CENTER); diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java index 381a9cd761..15d50d00cb 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java @@ -3,6 +3,8 @@ package com.fr.design.gui.frpane; import com.fr.design.dialog.BasicPane; import com.fr.design.event.GlobalNameListener; import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.ComponentChangeListener; +import com.fr.design.event.ComponentChangeObserver; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import com.fr.stable.StringUtils; @@ -24,6 +26,16 @@ public abstract class AbstractAttrNoScrollPane extends BasicPane { private AttributeChangeListener listener; private String globalName = ""; + private boolean autoFireAttributesChanged = true; + + public boolean isAutoFireAttributesChanged() { + return this.autoFireAttributesChanged; + } + + public void setAutoFireAttributesChanged(boolean autoFireAttributesChanged) { + this.autoFireAttributesChanged = autoFireAttributesChanged; + } + protected AbstractAttrNoScrollPane() { initAll(); } @@ -93,6 +105,15 @@ public abstract class AbstractAttrNoScrollPane extends BasicPane { } }); } + if(tmpComp instanceof ComponentChangeObserver){ + ComponentChangeObserver uiChangeableObserver = ((ComponentChangeObserver)tmpComp); + uiChangeableObserver.registerChangeListener(new ComponentChangeListener() { + @Override + public void initListener(Container changedComponent) { + AbstractAttrNoScrollPane.this.initListener(changedComponent); + } + }); + } } } @@ -127,7 +148,9 @@ public abstract class AbstractAttrNoScrollPane extends BasicPane { public void attributeChanged() { synchronized (this) { if (listener != null) { - listener.attributeChange(); + if (autoFireAttributesChanged) { + listener.attributeChange(); + } } } } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/AttributeChangeUtils.java b/designer-base/src/main/java/com/fr/design/gui/frpane/AttributeChangeUtils.java new file mode 100644 index 0000000000..bfc1ff9d45 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/AttributeChangeUtils.java @@ -0,0 +1,47 @@ +package com.fr.design.gui.frpane; + +import java.awt.Component; +import java.awt.Container; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/17 + */ +public class AttributeChangeUtils { + private static AbstractAttrNoScrollPane findNearestAttrNoScrollPaneAncestor(Component c) { + for(Container p = c.getParent(); p != null; p = p.getParent()) { + if (p instanceof AbstractAttrNoScrollPane) { + return (AbstractAttrNoScrollPane) p; + } + } + return null; + } + + public static void changeComposedUI(Component composedComponent, boolean fireMiddleStateChanged, UIChangeAction action) { + AbstractAttrNoScrollPane attrPane = findNearestAttrNoScrollPaneAncestor(composedComponent); + boolean oldAutoFire = true; + + if (!fireMiddleStateChanged) { + // 禁止属性面板自动处理属性更新 + if (attrPane != null) { + oldAutoFire = attrPane.isAutoFireAttributesChanged(); + attrPane.setAutoFireAttributesChanged(false); + } + } + + // 更新UI + action.changeComposedUI(); + + if (!fireMiddleStateChanged) { + // 恢复属性面板自动处理属性更新 + if (attrPane != null) { + attrPane.setAutoFireAttributesChanged(oldAutoFire); + } + } + } + + public interface UIChangeAction { + void changeComposedUI(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java index 6103e68002..a47b0021f2 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java @@ -27,13 +27,16 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.stable.StringUtils; -import java.awt.*; + +import javax.swing.JPanel; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.List; -import javax.swing.*; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; public class JTreeAutoBuildPane extends BasicPane implements PreviewLabel.Previewable, EditOrNewLabel.Editable { private TreeTableDataComboBox treeTableDataComboBox; @@ -239,12 +242,22 @@ public class JTreeAutoBuildPane extends BasicPane implements PreviewLabel.Previe rtd = treeTableDataComboBox.getSelcetedTableData(); name = treeTableDataComboBox.getSelectedItem().getTableDataName(); } + final String tableDataName = name; AbstractTableDataWrapper atdw = new TemplateTableDataWrapper(rtd, ""); - tdtp.dgEdit(atdw.creatTableDataPane(), name); - treeTableDataComboBox.refresh(); - treeTableDataComboBox.setSelectedTableDataByName(name); - textPane.populate(1); - valuePane.populate(1); + tdtp.showEditPane(atdw.creatTableDataPane(), name, new BasicTableDataTreePane.TableDataTreePaneListener() { + @Override + public void doOk() { + // 去除缓存列,后面刷新会重新选中 + DesignTableDataManager.removeSelectedColumnNames(tableDataName); + treeTableDataComboBox.refresh(); + treeTableDataComboBox.setSelectedTableDataByName(tableDataName); + } + + @Override + public void doCancel() { + + } + }); } } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java index ba75cce9df..db453c99f4 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java @@ -127,7 +127,7 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { buildBox.setSelectedIndex(1); TableDataDictionary dictionary = treeEditor.getDictionary(); autoBuildPane.populate(dictionary); - } else if (treeEditor.isLayerBuild()) { + } else if (treeEditor.isFastLayerBuild()) { buildBox.setSelectedIndex(0); java.util.List layerConfigList = treeEditor.getLayerConfigs(); LayerConfig[] layerConfigs = new LayerConfig[layerConfigList.size()]; @@ -156,12 +156,12 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { if (buildBox.getSelectedIndex() == 1) { TableDataDictionary dictionary = this.autoBuildPane.update(); te.setAutoBuild(true); - te.setLayerBuild(false); + te.setFastLayerBuild(false); te.setDictionary(dictionary); te.setNodeOrDict(dictionary); } else if (buildBox.getSelectedIndex() == 2) { te.setAutoBuild(false); - te.setLayerBuild(false); + te.setFastLayerBuild(false); NameObject no = this.controlPane.update(); if (no != null) { TreeEditor editor = (TreeEditor) no.getObject(); @@ -181,7 +181,7 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { } else { LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject(); te.setAutoBuild(false); - te.setLayerBuild(true); + te.setFastLayerBuild(true); te.setLayerConfigs(Arrays.asList(configs)); } return te; @@ -215,12 +215,12 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { if (buildBox.getSelectedIndex() == 1) { TableDataDictionary dictionary = this.autoBuildPane.update(); tcb.setAutoBuild(true); - tcb.setLayerBuild(false); + tcb.setFastLayerBuild(false); tcb.setDictionary(dictionary); tcb.setNodeOrDict(dictionary); } else if (buildBox.getSelectedIndex() == 2) { tcb.setAutoBuild(false); - tcb.setLayerBuild(false); + tcb.setFastLayerBuild(false); NameObject no = this.controlPane.update(); if (no != null) { if (no.getObject() instanceof TreeComboBoxEditor) { @@ -244,7 +244,7 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { }else { LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject(); tcb.setAutoBuild(false); - tcb.setLayerBuild(true); + tcb.setFastLayerBuild(true); tcb.setLayerConfigs(Arrays.asList(configs)); } return tcb; diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPane.java index c1021321b9..fd2fcc3755 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPane.java @@ -21,6 +21,8 @@ public class UITabbedPane extends JTabbedPane{ private String classPath; //panel对象的类名 private String tabName; //Tab名称 private int tabSize = 0; + private Color tabBorderColor; + public UITabbedPane() { super(); } @@ -93,6 +95,16 @@ public class UITabbedPane extends JTabbedPane{ public int getTabSize(){ return tabSize; } + + public Color getTabBorderColor() { + return tabBorderColor; + } + + public void setTabBorderColor(Color tabBorderColor) { + this.tabBorderColor = tabBorderColor; + repaint(); + } + @Override /** * 获取UI对象 diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPaneUI.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPaneUI.java index 5798a864b0..d31107c2ce 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPaneUI.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPaneUI.java @@ -31,9 +31,20 @@ public class UITabbedPaneUI extends BasicTabbedPaneUI { private int addX = -1; private int addY = -1; private int rollover = -1; - private Color tabBorderColor = new Color(143, 160, 183); + private final Color DEFAULT_TAB_BORDER_COLOR = new Color(143, 160, 183); private Color[] tabSelectedColor = {UIConstants.NORMAL_BLUE, UIConstants.NORMAL_BLUE, UIConstants.NORMAL_BLUE}; + public Color getTabBorderColor() { + Color color = null; + if (tabPane instanceof UITabbedPane) { + color = ((UITabbedPane) tabPane).getTabBorderColor(); + } + if (color == null) { + color = DEFAULT_TAB_BORDER_COLOR; + } + return color; + } + /** * 创建UI对象 * @@ -252,9 +263,9 @@ public class UITabbedPaneUI extends BasicTabbedPaneUI { private void drawUITabBorder(Graphics g, int tabPlacement, int x, int y, int w, int h, boolean isSelected, boolean isEnabled, boolean isRollover) { if (!isEnabled) { - drawUITabBorder(g, tabBorderColor, x, y, w, h, tabPlacement); + drawUITabBorder(g, getTabBorderColor(), x, y, w, h, tabPlacement); } else if (isSelected || isRollover) { - drawSelectedUITabBorder(g, tabBorderColor, x, y, w, h, tabPlacement); + drawSelectedUITabBorder(g, getTabBorderColor(), x, y, w, h, tabPlacement); if (isRollover && canClose()) { closeX = x + w - closeIcon.getIconWidth() - 3; closeY = 0; @@ -269,7 +280,7 @@ public class UITabbedPaneUI extends BasicTabbedPaneUI { closeIcon.paintIcon(tabPane, g, closeX, closeY); } } else { - drawUITabBorder(g, tabBorderColor, x, y, w, h, tabPlacement); + drawUITabBorder(g, getTabBorderColor(), x, y, w, h, tabPlacement); } } @@ -322,7 +333,7 @@ public class UITabbedPaneUI extends BasicTabbedPaneUI { } private void drawUIContentBorder(Graphics g, int x, int y, int w, int h) { - g.setColor(tabBorderColor); + g.setColor(getTabBorderColor()); g.drawRect(x, y, w - 3, h - 3); // Shadow g.setColor(new Color(204, 204, 204)); diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java index bab3e8851c..5769fdacfe 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java @@ -10,6 +10,7 @@ import com.fr.design.gui.ispinner.UIBasicSpinner; import com.fr.design.gui.itextfield.UINumberField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.GeneralUtils; import com.fr.stable.AssistUtils; import com.fr.stable.StringUtils; @@ -27,7 +28,8 @@ import java.math.BigDecimal; * For input Number. */ public abstract class UnitInputPane extends BasicPane { - private static final double NUM_POINT = 0.000001; + private static final double MAX_NUM = 3000.0D; + private static final double NUM_POINT = 0.000001; private int scale = -1; String title; @@ -46,7 +48,7 @@ public abstract class UnitInputPane extends BasicPane { centerPane.add(titleLabel); // Denny:在对话框中加入JSpinner对象 - numberFieldSpinner = new UIBasicSpinner(new SpinnerNumberModel(0, 0, 999, 1)); + numberFieldSpinner = new UIBasicSpinner(new SpinnerNumberModel(0, 0, MAX_NUM, 1)); GUICoreUtils.setColumnForSpinner(numberFieldSpinner, 24); numberFieldSpinner.setPreferredSize(new Dimension(60, 20)); numberFieldSpinner.setMinimumSize(new Dimension(60, 20)); @@ -71,17 +73,17 @@ public abstract class UnitInputPane extends BasicPane { public void populate(float floatValue) { popValue = floatValue; - numberFieldSpinner.setModel(new SpinnerNumberModel(0.00, 0.00, 999.00, 0.01)); + numberFieldSpinner.setModel(new SpinnerNumberModel(0.00, 0.00, MAX_NUM, 0.01)); JFormattedTextField temp = GUICoreUtils.getSpinnerTextField(numberFieldSpinner); addChangeListener(temp); - BigDecimal de = new BigDecimal(floatValue + ""); + BigDecimal de = new BigDecimal(GeneralUtils.objectToString(floatValue)); if (scale > 0) { floatValue = de.setScale(scale, BigDecimal.ROUND_DOWN).floatValue(); } else { floatValue = de.floatValue(); } - //选中多列, 并且列宽不完全一致的话, 就不显示值了. + //选中多列, 并且列宽不完全一致的话, 就不显示值了. temp.setText(AssistUtils.equals(floatValue, 0) ? StringUtils.EMPTY : Utils.convertNumberStringToString(new Float(floatValue))); // denny:默认应该为选中,方便用户修改 @@ -99,8 +101,8 @@ public abstract class UnitInputPane extends BasicPane { public double update() throws ValueNotChangeException { // 值没变就不改 if (!changed) { - throw vncExp; - } + throw vncExp; + } // Denny: get numberFieldSpinner 的 TextField JFormattedTextField temp = GUICoreUtils.getSpinnerTextField(numberFieldSpinner); @@ -108,7 +110,8 @@ public abstract class UnitInputPane extends BasicPane { if (temp.getText().length() == 0) { return 0; } - BigDecimal de = new BigDecimal(temp.getText()); + + BigDecimal de = new BigDecimal(GeneralUtils.objectToString(temp.getValue())); if (scale > 0) { return de.setScale(scale, BigDecimal.ROUND_DOWN).floatValue(); } else { @@ -176,4 +179,4 @@ public abstract class UnitInputPane extends BasicPane { // 鼠标按键在组件上单击时 } }; -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java index 5ca303fd57..a9b97d2698 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java @@ -3,6 +3,8 @@ package com.fr.design.gui.ibutton; import com.fr.design.constants.UIConstants; import com.fr.design.event.GlobalNameListener; import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.stable.ArrayUtils; import com.fr.stable.StringUtils; @@ -24,7 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class UIButtonGroup extends JPanel implements GlobalNameObserver { +public class UIButtonGroup extends JPanel implements GlobalNameObserver, UIObserver { private static final long serialVersionUID = 1L; private static final int TEXT_LENGTH = 3; private static final int BUTTON_SIZE = 2; @@ -37,6 +39,9 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { private boolean isToolBarComponent = false; private boolean isClick; + private UIObserverListener uiObserverListener; + private boolean autoFireStateChanged = true; + public UIButtonGroup(String[] textArray) { this(textArray, null); } @@ -72,7 +77,7 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { if (globalNameListener != null) { globalNameListener.setGlobalName(buttonGroupName); } - setSelectedWithFireChanged(index); + setSelectedIndex(index, autoFireStateChanged); } }; } @@ -108,7 +113,7 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { if (globalNameListener != null) { globalNameListener.setGlobalName(buttonGroupName); } - setSelectedWithFireChanged(index); + setSelectedIndex(index, autoFireStateChanged); } }; } @@ -175,7 +180,7 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { if (globalNameListener != null) { globalNameListener.setGlobalName(buttonGroupName); } - setSelectedWithFireChanged(index); + setSelectedIndex(index, autoFireStateChanged); } }; } @@ -253,6 +258,10 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { g2d.setClip(oldClip); } + public void setAutoFireStateChanged(boolean autoFireStateChanged) { + this.autoFireStateChanged = autoFireStateChanged; + } + /** * setSelectedItem * @@ -287,13 +296,14 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { return selectedIndex; } - protected void setSelectedWithFireChanged(int newSelectedIndex) { - selectedIndex = newSelectedIndex; - for (int i = 0; i < labelButtonList.size(); i++) { - if (i == selectedIndex) { - labelButtonList.get(i).setSelectedWithFireListener(true); - } else { - labelButtonList.get(i).setSelected(false); + protected void setSelectedIndex(int newSelectedIndex, boolean fireChanged) { + if (selectedIndex != newSelectedIndex) { + selectedIndex = newSelectedIndex; + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).setSelected(i == selectedIndex, false); + } + if (fireChanged) { + fireStateChanged(); } } } @@ -304,10 +314,7 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { * @param newSelectedIndex */ public void setSelectedIndex(int newSelectedIndex) { - selectedIndex = newSelectedIndex; - for (int i = 0; i < labelButtonList.size(); i++) { - labelButtonList.get(i).setSelected(i == selectedIndex); - } + setSelectedIndex(newSelectedIndex, false); } private void fireStateChanged() { @@ -322,6 +329,9 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { ((ChangeListener) listeners[i + 1]).stateChanged(e); } } + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } } /** @@ -364,14 +374,24 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { return true; } + @Override + public void registerChangeListener(UIObserverListener listener) { + this.uiObserverListener = listener; + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + /** * @param l */ public void addChangeListener(ChangeListener l) { + listenerList.add(ChangeListener.class, l); for (int i = 0; i < labelButtonList.size(); i++) { labelButtonList.get(i).addChangeListener(l); - listenerList.add(ChangeListener.class, l); } } @@ -379,9 +399,9 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { * @param l */ public void removeChangeListener(ChangeListener l) { + listenerList.remove(ChangeListener.class, l); for (int i = 0; i < labelButtonList.size(); i++) { labelButtonList.get(i).removeChangeListener(l); - listenerList.remove(ChangeListener.class, l); } } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java index 28f5830619..31a6d963d9 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java @@ -136,6 +136,7 @@ public class UIColorButton extends UIButton implements PopupHider, UIObserver, G } popupWin = this.getColorControlWindow(); + popupWin.setColor(color); GUICoreUtils.showPopupMenu(popupWin, this, POPUP_MENU_SHIFT, this.getSize().height); } @@ -154,18 +155,22 @@ public class UIColorButton extends UIButton implements PopupHider, UIObserver, G protected ColorControlWindow getColorControlWindow() { //find parant. if (this.popupWin == null) { - this.popupWin = new ColorControlWindow(UIColorButton.this) { - @Override - protected void colorChanged() { - UIColorButton.this.setColor(this.getColor()); - } - - }; + this.popupWin = initColorControlWindow(); } return popupWin; } + protected ColorControlWindow initColorControlWindow(){ + return new ColorControlWindow(UIColorButton.this) { + @Override + protected void colorChanged() { + UIColorButton.this.setColor(this.getColor()); + } + + }; + } + /** * 添加监听 * diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UINoThemeColorButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UINoThemeColorButton.java new file mode 100644 index 0000000000..da071458a1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UINoThemeColorButton.java @@ -0,0 +1,36 @@ +package com.fr.design.gui.ibutton; + +import com.fr.design.gui.ipoppane.PopupHider; +import com.fr.design.style.color.ColorControlWindow; + +import javax.swing.Icon; + + +public class UINoThemeColorButton extends UIColorButton{ + + public UINoThemeColorButton(Icon icon) { + super(icon); + } + + protected ColorControlWindow initColorControlWindow(){ + return new NoThemeColorControlWindow(this); + } + + private class NoThemeColorControlWindow extends ColorControlWindow{ + + + public NoThemeColorControlWindow(PopupHider popupHider) { + super(popupHider); + } + + protected boolean supportThemeColor(){ + return false; + } + + + @Override + protected void colorChanged() { + UINoThemeColorButton.this.setColor(this.getColor()); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java index 69f5845f1d..d772591047 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java @@ -63,13 +63,8 @@ public class UITabGroup extends UIButtonGroup { } @Override - protected void setSelectedWithFireChanged(int newSelectedIndex) { - if (selectedIndex != newSelectedIndex) { - selectedIndex = newSelectedIndex; - for (int i = 0; i < labelButtonList.size(); i++) { - labelButtonList.get(i).setSelected(i == selectedIndex); - } - } + protected void setSelectedIndex(int newSelectedIndex, boolean fireChanged) { + super.setSelectedIndex(newSelectedIndex, false); tabChanged(newSelectedIndex); } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java index dc380c0c94..18764e9119 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java @@ -142,10 +142,12 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ } } - public void setSelectedWithFireListener(boolean isSelected) { + public void setSelected(boolean isSelected, boolean fireChanged) { if (this.isSelected != isSelected) { this.isSelected = isSelected; - fireSelectedChanged(); + if (fireChanged) { + fireSelectedChanged(); + } refresh(isSelected); } } @@ -175,7 +177,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ @Override public void mouseClicked(MouseEvent e) { if (isEnabled() && !isEventBannded) { - setSelectedWithFireListener(!isSelected()); + setSelected(!isSelected(), true); } } }; diff --git a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java index e294d80220..0ddd3e22d2 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java @@ -58,7 +58,7 @@ public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObser super(locText, b); setUI(new UICheckBoxUI()); initListener(); - this.markMnemonic=markMnemonic; + this.markMnemonic = markMnemonic; } public UICheckBox(String text, Icon icon) { @@ -100,6 +100,10 @@ public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObser } + public void removeChangeListener() { + uiObserverListener = null; + } + @Override public void setGlobalName(String name) { checkboxName = name; diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java index 044bb65188..9f9a3f13c0 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java @@ -2,19 +2,18 @@ package com.fr.design.gui.icombobox; import com.fr.base.ChartColorMatching; import com.fr.base.ChartPreStyleConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.chart.ThemedChartSeriesColor; import com.fr.cert.token.lang.Collections; import com.fr.chart.base.ChartConstants; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.general.GeneralUtils; import javax.swing.DefaultComboBoxModel; import javax.swing.JLabel; import javax.swing.JList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; @@ -23,6 +22,12 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LinearGradientPaint; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author Bjorn @@ -65,7 +70,22 @@ public class ColorSchemeComboBox extends UIComboBox { Iterator names = config.names(); if (preDefined) { - colorSchemes.put(Toolkit.i18nText("Fine-Design_Chart_Predefined"), null); + if (ChartEditContext.supportTheme()) { + ColorInfo colorInfo = new ColorInfo(); + List list = new ArrayList<>(); + colorInfo.setColors(list); + TemplateTheme templateTheme = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme(); + ThemedChartSeriesColor themedChartSeriesColor = templateTheme.getChartStyle().getThemedChartSeriesColor(); + if (themedChartSeriesColor.isCombineColor()) { + colorInfo.setGradient(false); + list.addAll(templateTheme.getColorScheme().getColors()); + } else { + colorInfo.setGradient(true); + list.add(themedChartSeriesColor.getBeginColor()); + list.add(themedChartSeriesColor.getEndColor()); + } + colorSchemes.put(Toolkit.i18nText("Fine-Design_Chart_Follow_Theme"), colorInfo); + } } else { //添加默认的方案和第一个方案 String defaultName = config.getCurrentStyle(); @@ -133,7 +153,7 @@ public class ColorSchemeComboBox extends UIComboBox { if (selectedIndex == itemCount - 2) { return SelectType.COMBINATION_COLOR; } - if (selectedIndex == 0) { + if (selectedIndex == 0 && ChartEditContext.supportTheme()) { return SelectType.DEFAULT; } return SelectType.NORMAL; diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java index 8fe79d41ed..c122394476 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java @@ -248,7 +248,7 @@ public class FRTreeComboBox extends UIComboBox { private static TreePopup treePopup; - private static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{ + protected static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{ private boolean isRollover = false; public FRTreeComboBoxUI() { @@ -535,7 +535,7 @@ public class FRTreeComboBox extends UIComboBox { public class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener { private volatile boolean setting = false; private FRTreeComboBox comboBox; - private Object item; + protected Object item; public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) { super(); diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java deleted file mode 100644 index 2d936d8964..0000000000 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fr.design.gui.icombobox; - -import com.fr.log.FineLoggerFactory; - -import javax.swing.JTree; -import javax.swing.SwingWorker; -import javax.swing.tree.TreeCellRenderer; -import java.util.concurrent.FutureTask; - -/** - * 模糊搜索前需执行完前置任务的TreeComboBox - * @author Lucian.Chen - * @version 10.0 - * Created by Lucian.Chen on 2021/4/14 - */ -public class SearchPreTaskTreeComboBox extends FRTreeComboBox { - - /** - * 模糊搜索前任务 - */ - private FutureTask preSearchTask; - - public SearchPreTaskTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) { - super(tree, renderer, editable); - } - - public FutureTask getPreSearchTask() { - return preSearchTask; - } - - public void setPreSearchTask(FutureTask preSearchTask) { - this.preSearchTask = preSearchTask; - } - - protected UIComboBoxEditor createEditor() { - return new SearchPreTaskComboBoxEditor(this); - } - - private class SearchPreTaskComboBoxEditor extends FrTreeSearchComboBoxEditor { - - public SearchPreTaskComboBoxEditor(FRTreeComboBox comboBox) { - super(comboBox); - } - - protected void changeHandler() { - if (isSetting()) { - return; - } - setPopupVisible(true); - new SwingWorker() { - @Override - protected Void doInBackground() { - FutureTask task = getPreSearchTask(); - try { - // 确保模糊搜索前任务执行完成后,再进行模糊搜索 - if (task != null) { - task.get(); - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - if (task != null) { - // 任务执行后置空,否则会被别的操作重复触发 - setPreSearchTask(null); - } - return null; - } - - @Override - protected void done() { - // 模糊搜索 - search(); - } - }.execute(); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java new file mode 100644 index 0000000000..6b41986939 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java @@ -0,0 +1,217 @@ +package com.fr.design.gui.icombobox; + +import com.fr.data.core.DataCoreUtils; +import com.fr.data.core.db.TableProcedure; +import com.fr.data.impl.Connection; +import com.fr.design.DesignerEnvManager; +import com.fr.design.data.datapane.ChoosePane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.mainframe.DesignerContext; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Filter; +import com.fr.stable.StringUtils; + +import javax.swing.JOptionPane; +import javax.swing.JTree; +import javax.swing.SwingWorker; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.awt.event.MouseEvent; +import java.util.Enumeration; + +/** + * 实现模糊搜索表名的FRTreeComboBox + * FRTreeComboBox:搜索后滚动到首个匹配节点 + * SearchFRTreeComboBox:显示所有匹配的节点 + * + * @author Lucian.Chen + * @version 10.0 + * Created by Lucian.Chen on 2021/4/14 + */ +public class TableSearchTreeComboBox extends FRTreeComboBox { + // 持有父容器,需要实时获取其他组件值 + private final ChoosePane parent; + + public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) { + super(tree, renderer); + this.parent = parent; + setUI(new TableSearchTreeComboBoxUI()); + } + + protected UIComboBoxEditor createEditor() { + return new TableSearchComboBoxEditor(this); + } + + @Override + protected String pathToString(TreePath path) { + Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); + if (obj instanceof TableProcedure) { + return ((TableProcedure) obj).getName(); + } + return super.pathToString(path); + } + + @Override + public void setSelectedItemString(String _name) { + super.setSelectedItemString(_name); + // 会因为连续两次选中的值一致,导致未触发编辑框联动 + this.getEditor().setItem(_name); + } + + /** + * 执行模糊搜索 + */ + private void searchExecute() { + UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor(); + new SwingWorker() { + @Override + protected Void doInBackground() { + processTableDataNames( + parent.getDSName(), + parent.getConnection(), + parent.getSchema(), + createFilter((String) searchEditor.getItem())); + return null; + } + + @Override + protected void done() { + expandTree(); + // 输入框获取焦点 + searchEditor.getEditorComponent().requestFocus(); + } + }.execute(); + } + + private TableNameFilter createFilter(String text) { + return StringUtils.isEmpty(text) ? EMPTY_FILTER : new TableNameFilter(text); + } + + /** + * 查询数据库表,并构建节点目录 + * + * @param databaseName 数据库名 + * @param connection 数据连接 + * @param schema 模式 + * @param filter 模糊搜索过滤器 + */ + private void processTableDataNames(String databaseName, Connection connection, String schema, TableNameFilter filter) { + if (tree == null) { + return; + } + DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); + rootTreeNode.removeAllChildren(); + + if (connection == null) { + return; + } + try { + schema = StringUtils.isEmpty(schema) ? null : schema; + TableProcedure[] sqlTableArray = DataCoreUtils.getTables(connection, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); + if (ArrayUtils.isNotEmpty(sqlTableArray)) { + ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); + rootTreeNode.add(tableTreeNode); + addArrayNode(tableTreeNode, sqlTableArray, filter); + } + TableProcedure[] sqlViewArray = DataCoreUtils.getTables(connection, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); + if (ArrayUtils.isNotEmpty(sqlViewArray)) { + ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); + rootTreeNode.add(viewTreeNode); + addArrayNode(viewTreeNode, sqlViewArray, filter); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); + } + } + + private void addArrayNode(ExpandMutableTreeNode rootNode, TableProcedure[] sqlArray, TableNameFilter filter) { + if (sqlArray != null) { + for (TableProcedure procedure : sqlArray) { + if (filter.accept(procedure)) { + ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(procedure); + rootNode.add(viewChildTreeNode); + } + } + } + } + + /** + * 展开节点 + */ + private void expandTree() { + ((DefaultTreeModel) tree.getModel()).reload(); + // daniel 展开所有tree + TreeNode root = (TreeNode) tree.getModel().getRoot(); + TreePath parent = new TreePath(root); + TreeNode node = (TreeNode) parent.getLastPathComponent(); + for (Enumeration e = node.children(); e.hasMoreElements(); ) { + TreeNode n = (TreeNode) e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + tree.expandPath(path); + } + } + + private static final TableNameFilter EMPTY_FILTER = new TableNameFilter() { + public boolean accept(TableProcedure procedure) { + return true; + } + }; + + /** + * 表名模糊搜索实现 + */ + private static class TableNameFilter implements Filter { + private String searchFilter; + + public TableNameFilter() { + } + + public TableNameFilter(String searchFilter) { + this.searchFilter = searchFilter.toLowerCase().trim(); + } + + // 表名匹配 + @Override + public boolean accept(TableProcedure procedure) { + return procedure.getName().toLowerCase().contains(searchFilter); + } + } + + /** + * 重写FRTreeComboBoxUI,实现点击下拉时触发模糊搜索 + */ + private class TableSearchTreeComboBoxUI extends FRTreeComboBoxUI { + + @Override + public void mouseClicked(MouseEvent e) { + searchExecute(); + } + } + + /** + * 重写输入框编辑器,实现输入框模糊搜索逻辑 + */ + private class TableSearchComboBoxEditor extends FrTreeSearchComboBoxEditor { + + public TableSearchComboBoxEditor(FRTreeComboBox comboBox) { + super(comboBox); + } + + @Override + protected void changeHandler() { + if (isSetting()) { + return; + } + setPopupVisible(true); + this.item = textField.getText(); + searchExecute(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/imenu/UIPopupMenu.java b/designer-base/src/main/java/com/fr/design/gui/imenu/UIPopupMenu.java index cdad63bff2..3aeaa186be 100644 --- a/designer-base/src/main/java/com/fr/design/gui/imenu/UIPopupMenu.java +++ b/designer-base/src/main/java/com/fr/design/gui/imenu/UIPopupMenu.java @@ -8,8 +8,10 @@ import javax.swing.*; import com.fr.design.constants.UIConstants; public class UIPopupMenu extends JPopupMenu{ - private static final float REC = 8f; + private static final float DEFAULT_REC = 8f; private boolean onlyText = false; + private float rec = DEFAULT_REC; + public static UIPopupMenu EMPTY = new UIPopupMenu(); public UIPopupMenu() { super(); @@ -19,8 +21,7 @@ public class UIPopupMenu extends JPopupMenu{ @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; - Shape shape = null; - shape = new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), REC, REC); + Shape shape = new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), rec, rec); g2d.setClip(shape); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); super.paintComponent(g2d); @@ -29,10 +30,9 @@ public class UIPopupMenu extends JPopupMenu{ @Override protected void paintBorder(Graphics g) { Graphics2D g2d = (Graphics2D) g; - int rec = (int) REC; g2d.setColor(UIConstants.UIPOPUPMENU_LINE_COLOR); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, rec, rec); + g2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, (int) rec, (int) rec); } @Override @@ -46,4 +46,8 @@ public class UIPopupMenu extends JPopupMenu{ public void setOnlyText(boolean onlyText) { this.onlyText = onlyText; } + + public void setRadius(float radius) { + this.rec = radius; + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/iprogressbar/ProgressDialog.java b/designer-base/src/main/java/com/fr/design/gui/iprogressbar/ProgressDialog.java index d1847545ce..3106ebff70 100644 --- a/designer-base/src/main/java/com/fr/design/gui/iprogressbar/ProgressDialog.java +++ b/designer-base/src/main/java/com/fr/design/gui/iprogressbar/ProgressDialog.java @@ -31,22 +31,22 @@ public class ProgressDialog extends UIDialog { super(parent); setUndecorated(true); setSize(parent.getSize()); - setLocationRelativeTo(null); + setLocation(parent.getLocation()); OSSupportCenter.buildAction(new OSBasedAction() { @Override public void execute(Object... objects) { setOpacity(0.5f); } }, SupportOSImpl.OPACITY); - initComponent(); + initComponent(parent); } - private void initComponent() { + private void initComponent(Frame parent) { centerDialog = new JDialog(this); centerDialog.setSize(new Dimension(482, 124)); centerDialog.setUndecorated(true); - GUICoreUtils.centerWindow(centerDialog); + centerDialog.setLocationRelativeTo(parent); JPanel panel = new JPanel(); panel.setBorder(new UIProgressBorder(3, UIConstants.DEFAULT_BG_RULER, 14, 46, 47, 37, 47)); panel.setLayout(new BorderLayout(4, 15)); diff --git a/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java b/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java index 22f6cb246e..4a722fc50d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java +++ b/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java @@ -73,6 +73,12 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver textField.setValue(defaultValue); } + public UISpinner(double minValue, double maxValue, double dierta, double defaultValue, boolean fillNegativeNumber) { + init(minValue, maxValue, dierta); + textField.setValue(defaultValue); + textField.canFillNegativeNumber(fillNegativeNumber); + } + protected void init(double minValue, double maxValue, double dierta) { this.minValue = minValue; this.maxValue = maxValue; diff --git a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java index d6973f6bb4..07756a56b7 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableEditorPane.java @@ -153,4 +153,12 @@ public class UITableEditorPane extends BasicPane { tableModel.stopCellEditing(); } + + /** + * 设置表头是否可以改变大小 + */ + public void setHeaderResizing(boolean resizingAllowed){ + editTable.getTableHeader().setResizingAllowed(resizingAllowed); + } + } diff --git a/designer-base/src/main/java/com/fr/design/gui/itextfield/UIAutoCompletionField.java b/designer-base/src/main/java/com/fr/design/gui/itextfield/UIAutoCompletionField.java index 967aeddbb9..f976f3471c 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itextfield/UIAutoCompletionField.java +++ b/designer-base/src/main/java/com/fr/design/gui/itextfield/UIAutoCompletionField.java @@ -256,10 +256,9 @@ public class UIAutoCompletionField extends UITextField implements DocumentListen * */ public void setText(String t) { - if (this.isOpen == true) { - if (!UIAutoCompletionField.this.isShowing()) { - return; - } + boolean unavailable = !this.isEnabled() && !this.isEditable(); + if (unavailable) { + return; } try { Document doc = getDocument(); diff --git a/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java b/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java index 347dd768f5..709fdece73 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java +++ b/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java @@ -2,9 +2,12 @@ package com.fr.design.gui.itoolbar; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.mainframe.JTemplate; + import java.awt.Component; import java.awt.FlowLayout; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import javax.swing.JToolBar; public class UIToolbar extends JToolBar { @@ -35,13 +38,18 @@ public class UIToolbar extends JToolBar { } } - public void refreshUIToolBar() { - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (template != null) { - for (int i = 0; i < getComponentCount(); i++) { - Component component = getComponents()[i]; - component.setEnabled(template.checkEnable()); - } + public Map getComponentState() { + Map componentState = new HashMap<>(); + for (int i = 0; i < getComponentCount(); i++) { + Component component = getComponent(i); + componentState.put(component, component.isEnabled()); + } + return componentState; + } + + public static void resetComponentState(Map componentState) { + for (Component component : componentState.keySet()) { + component.setEnabled(componentState.get(component)); } } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java index f3771a0f90..a748fa3201 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java @@ -67,7 +67,7 @@ public class EnvFileTree extends RefreshableJTree { String lock = node.getLock(); String name = node.getName(); if (treeNode.hasFullAuthority()) { - if (lock != null && !node.getUserID().equals(lock)) { + if (lock != null && !lock.equals(node.getUserID())) { name = name + Toolkit.i18nText("Fine-Design_Basic_Template_Status_Locked", "(", ")"); } this.setIcon(FileTreeIcon.getIcon(node)); diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java index b418c1db4c..b2956b70f8 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java @@ -2,6 +2,7 @@ package com.fr.design.gui.itree.filetree; import com.fr.base.BaseUtils; import com.fr.design.ExtraDesignClassManager; +import com.fr.design.icon.LocalFileIcon; import com.fr.design.icon.LockIcon; import com.fr.design.fun.ReportSupportedFileUIProvider; import com.fr.file.filetree.FileNode; @@ -19,6 +20,8 @@ public class FileTreeIcon { private FileTreeIcon() { } + public static final String FILE_LOCKED_ICON_PATH = "/com/fr/design/images/gui/file_lock.png"; + public static final Icon BLANK_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/blank.gif"); public static final Icon FOLDER_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/folder.png"); @@ -48,6 +51,9 @@ public class FileTreeIcon { public static final Icon MODERN_CHT_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/modern_style_cht_file_icon_16x16.png"); + public static final Icon CPTX_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon.png"); + public static final Icon CPTX_LOCKED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon_locked.png"); + public static final LockIcon FOLDER_LOCK_ICON = new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/fold.png")); public static final LockIcon FILE_LOCK_ICON = @@ -108,6 +114,7 @@ public class FileTreeIcon { public final static int CPT_FILE = 11; //.cpt public final static int FRM_FILE = 12; //.form .frm public final static int CHT_FILE = 13; //.chart .cht + public final static int CPTX_FILE = 14; //.cptx public static Icon getIcon(File file) { return FileTreeIcon.getIcon(file, false); @@ -149,7 +156,7 @@ public class FileTreeIcon { if (node.isDirectory()) { return FileTreeIcon.FOLDER_IMAGE_ICON; } - return getLocalFileIcon(path); + return getLocalFileIcon(path, isShowLock); } } if (node.isDirectory()) { @@ -159,12 +166,12 @@ public class FileTreeIcon { } } - private static Icon getLocalFileIcon(String path) { - Icon icon = getExtraIcon(path, false); + private static Icon getLocalFileIcon(String path, boolean isShowLock) { + Icon icon = getExtraIcon(path, isShowLock); if (icon != null) { return icon; } - return FileSystemView.getFileSystemView().getSystemIcon(new File(path)); + return new LocalFileIcon(FileSystemView.getFileSystemView().getSystemIcon(new File(path)), isShowLock); } private static Icon getRemoteFileIcon(FileNode node, boolean isShowLock) { @@ -252,6 +259,12 @@ public class FileTreeIcon { } else { return FileTreeIcon.MODERN_CPT_FILE_IMAGE_ICON; } + } else if (fileType == CPTX_FILE) { + if (isLocked) { + return FileTreeIcon.CPTX_LOCKED_ICON; + } else { + return FileTreeIcon.CPTX_ICON; + } } else if (fileType == FRM_FILE) { //form frm if (isLocked) { return FileTreeIcon.FRM_FILE_LOCK_ICON; @@ -314,6 +327,8 @@ public class FileTreeIcon { return BMP_FILE; } else if (fileName.endsWith(".cpt")) { return CPT_FILE; + } else if (fileName.endsWith(".cptx")) { + return CPTX_FILE; } else if (fileName.endsWith(".frm") || fileName.endsWith(".form")) { return FRM_FILE; } else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")) { diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java index 3f5fff689b..69e5a2c8ae 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java @@ -53,7 +53,7 @@ public class ReportletPane extends BasicPane { centerPane.add(cardPane, BorderLayout.CENTER); cardPane.setLayout(card = new CardLayout()); templateReportletTree = new TemplateFileTree(); - IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class", ".frm", ".form"}); + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class", ".frm", ".form", ".cptx"}); templateReportletTree.setFileNodeFilter(filter); cardPane.add(t_panel = new JScrollPane(templateReportletTree), "TEMPLATE"); classReportletTree = new ClassFileTree(); diff --git a/designer-base/src/main/java/com/fr/design/gui/style/AbstractBorderPackerPane.java b/designer-base/src/main/java/com/fr/design/gui/style/AbstractBorderPackerPane.java new file mode 100644 index 0000000000..4356f133ad --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/AbstractBorderPackerPane.java @@ -0,0 +1,20 @@ +package com.fr.design.gui.style; + +import com.fr.design.dialog.BasicPane; +import com.fr.general.act.BorderPacker; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public abstract class AbstractBorderPackerPane extends BasicPane { + + public abstract void populateBean(BorderPacker style); + public abstract void updateBean(BorderPacker style); + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/AbstractTranslucentBackgroundSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/AbstractTranslucentBackgroundSpecialPane.java new file mode 100644 index 0000000000..0b814f284a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/AbstractTranslucentBackgroundSpecialPane.java @@ -0,0 +1,99 @@ +package com.fr.design.gui.style; + +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.frpane.UIPercentDragPane; +import com.fr.design.gui.ilable.UILabel; +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.widget.FRWidgetFactory; +import com.fr.general.Background; +import com.fr.general.act.BackgroundPacker; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public abstract class AbstractTranslucentBackgroundSpecialPane extends BasicPane { + + private final int uiLabelWidth; + private final int uiSettingWidth; + // 背景名称:如主题背景 或 标题背景 + private final String backgroundName; + // 背景 + protected BackgroundSpecialPane backgroundPane = new LayoutBackgroundSpecialPane(); + // 背景透明度 + protected UIPercentDragPane opacityPane = new UIPercentDragPane(); + + public AbstractTranslucentBackgroundSpecialPane(int uiLabelWidth, int uiSettingWidth, String backgroundName) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + this.backgroundName = backgroundName; + this.initializePane(); + } + + private void initializePane() { + setLayout(new BorderLayout(0, 0)); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + // 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐 + JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(7, 0, 0, 0)); + backgroundLabelPane.add(FRWidgetFactory.createLineWrapLabel(backgroundName), BorderLayout.NORTH); + + JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( + new JComponent[][]{ + {backgroundLabelPane, backgroundPane} + }, + new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); + + JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( + new JComponent[][]{ + {new UILabel(""), FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, + {new UILabel(""), opacityPane} + }, + new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); + opacityComposedPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + opacityComposedPane.setVisible(false); + + backgroundPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + Background background = backgroundPane.update(); + opacityComposedPane.setVisible(background != null); + } + }); + + add(backgroundComposedPane, BorderLayout.NORTH, 0); + add(opacityComposedPane, BorderLayout.CENTER, 1); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + public abstract void populateBean(T style); + + public abstract void updateBean(T style); + + protected static class LayoutBackgroundSpecialPane extends BackgroundSpecialPane { + @Override + protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { + return new GradientBackgroundQuickPane(140); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java b/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java index b188cb5aa8..eb72db81cc 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java @@ -17,6 +17,7 @@ import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.icombobox.UIComboBox; 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.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; @@ -56,11 +57,11 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO private static final int GAP = 23; private static final int VERGAP = 3; private static final Dimension SPINNER_DIMENSION = new Dimension(75, 20); - private static final String[] TEXT = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Wrap_Text"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Single_Line"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Single_Line(Adjust_Font)"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Multi_Line(Adjust_Font)")}; + private static final String[] TEXT = {Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Wrap_Text"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Single_Line"), + Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Single_Line(Adjust_Font)"), Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Multi_Line(Adjust_Font)")}; - private static final String[] LAYOUT = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Default"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Titled"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Extend"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Adjust")}; + private static final String[] LAYOUT = {Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Default"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Titled"), + Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Extend"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Adjust")}; private JPanel hPaneContainer; private JPanel vPaneContainer; @@ -103,8 +104,8 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/defaultAlignment.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/defaultAlignment_white.png")}}; Integer[] hAlignment = new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT, Integer.valueOf(Constants.DISTRIBUTED), Constants.NULL}; hAlignmentPane = new UIButtonGroup<>(hAlignmentIconArray, hAlignment); - hAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Left"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Right"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Distributed"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_DEFAULT")}); + hAlignmentPane.setAllToolTips(new String[]{Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Left"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Center"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Right"), + Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Distributed"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_DEFAULT")}); hPaneContainer = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); vPaneContainer = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); @@ -113,7 +114,7 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_down_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_down_normal_white.png")}}; Integer[] vAlignment = new Integer[]{Constants.TOP, Constants.CENTER, Constants.BOTTOM}; vAlignmentPane = new UIButtonGroup<>(vAlignmentIconArray, vAlignment); - vAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Top"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Bottom")}); + vAlignmentPane.setAllToolTips(new String[]{Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Top"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Center"), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Bottom")}); initOtherComponent(); initAllNames(); @@ -175,7 +176,7 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO private void initTextRotationCombox() { ArrayList selectOption = new ArrayList<>(); - selectOption.add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Custom_Angle")); + selectOption.add(Toolkit.i18nText("Fine-Design_Basic_Custom_Angle")); VerticalTextProcessor processor = ExtraClassManager.getInstance().getSingle(VerticalTextProcessor.XML_TAG, DefaultVerticalTextProcessor.class); selectOption.addAll(Arrays.asList(processor.getComboxOption())); @@ -183,25 +184,25 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO } private void initAllNames() { - hAlignmentPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal")); - vAlignmentPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical")); - imageLayoutComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Layout")); - textComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Text_Style")); - textRotationComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation")); - rotationPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation")); - leftIndentSpinner.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Left_Indent")); - rightIndentSpinner.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Right_Indent")); - spaceBeforeSpinner.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_Before")); - spaceAfterSpinner.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_After")); - lineSpaceSpinner.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Line_Spacing")); + hAlignmentPane.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal")); + vAlignmentPane.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical")); + imageLayoutComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Image_Layout")); + textComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Text_Style")); + textRotationComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation")); + rotationPane.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation")); + leftIndentSpinner.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Left_Indent")); + rightIndentSpinner.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Right_Indent")); + spaceBeforeSpinner.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_Before")); + spaceAfterSpinner.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_After")); + lineSpaceSpinner.setGlobalName(Toolkit.i18nText("Fine-Design_Basic_Style_Line_Spacing")); } private JPanel createPane() { JPanel jp1 = new JPanel(new BorderLayout()); basicPane = new JPanel(); seniorPane = new JPanel(); - basicPane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Basic"), 290, 24, basicPane()); - seniorPane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Advanced"), 290, 24, seniorPane()); + basicPane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Report_Basic"), 290, 24, basicPane()); + seniorPane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Basic_Advanced"), 290, 24, seniorPane()); jp1.add(basicPane, BorderLayout.NORTH); jp1.add(seniorPane, BorderLayout.CENTER); @@ -212,13 +213,13 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO private JPanel basicPane() { double f = TableLayout.FILL; double p = TableLayout.PREFERRED; - UILabel horizontalLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal") + " ", SwingConstants.LEFT); + UILabel horizontalLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal") + " ", SwingConstants.LEFT); UIComponentUtils.setLineWrap(horizontalLabel); Component[][] components = new Component[][]{ new Component[]{null, null}, new Component[]{horizontalLabel, hPaneContainer}, new Component[]{null, null}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical") + " ", SwingConstants.RIGHT), vPaneContainer}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical") + " ", SwingConstants.RIGHT), vPaneContainer}, new Component[]{null, null} }; double[] rowSize = {p, p, p, p, p, p}; @@ -233,11 +234,11 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO double p = TableLayout.PREFERRED; Component[][] components = new Component[][]{ new Component[]{null, null}, - new Component[]{new UILabel((com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Layout")) + " ", SwingConstants.LEFT), imageLayoutComboBox}, + new Component[]{new UILabel((Toolkit.i18nText("Fine-Design_Basic_Image_Layout")) + " ", SwingConstants.LEFT), imageLayoutComboBox}, new Component[]{null, null}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Text_Style") + " ", SwingConstants.LEFT), textComboBox}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Text_Style") + " ", SwingConstants.LEFT), textComboBox}, new Component[]{null, null}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation") + " ", SwingConstants.LEFT), textRotationComboBox}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation") + " ", SwingConstants.LEFT), textRotationComboBox}, new Component[]{null, rotationBarCC}, new Component[]{null, null}, }; @@ -261,23 +262,23 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO lineSpaceSpinner.setPreferredSize(SPINNER_DIMENSION); JPanel indentationPane = new JPanel(new BorderLayout()); - indentationPane.add(new UILabel((com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Indentation")), SwingConstants.LEFT)); + indentationPane.add(new UILabel((Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Indentation")), SwingConstants.LEFT)); indentationPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, GAP)); JPanel partSpacingPane = new JPanel(new BorderLayout()); - partSpacingPane.add(new UILabel((com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Part_Spacing")), SwingConstants.LEFT)); + partSpacingPane.add(new UILabel((Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Part_Spacing")), SwingConstants.LEFT)); partSpacingPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, GAP)); JPanel spacingPane = new JPanel(new BorderLayout()); - spacingPane.add(new UILabel((com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Spacing")), SwingConstants.LEFT)); + spacingPane.add(new UILabel((Toolkit.i18nText("Fine-Design_Basic_Style_Line_Spacing")), SwingConstants.LEFT)); spacingPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, GAP)); Component[][] components = new Component[][]{ new Component[]{null, null, null}, new Component[]{indentationPane, creatSpinnerPane(leftIndentSpinner), creatSpinnerPane(rightIndentSpinner)}, - new Component[]{null, 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)}, + new Component[]{null, new UILabel((Toolkit.i18nText("Fine-Design_Report_Left")), SwingConstants.CENTER), new UILabel((Toolkit.i18nText("Fine-Design_Basic_Right")), SwingConstants.CENTER)}, new Component[]{null, null, null}, new Component[]{null, null, null}, new Component[]{partSpacingPane, creatSpinnerPane(spaceBeforeSpinner), creatSpinnerPane(spaceAfterSpinner)}, - new Component[]{null, new UILabel((com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Front")), SwingConstants.CENTER), new UILabel((com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Behind")), SwingConstants.CENTER)}, + new Component[]{null, new UILabel((Toolkit.i18nText("Fine-Design_Basic_Front")), SwingConstants.CENTER), new UILabel((Toolkit.i18nText("Fine-Design_Basic_Behind")), SwingConstants.CENTER)}, new Component[]{null, null, null}, new Component[]{null, null, null}, new Component[]{spacingPane, creatSpinnerPane(lineSpaceSpinner), null}, @@ -300,7 +301,7 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO * @return 标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Alignment"); + return Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Style_Alignment"); } /** @@ -363,18 +364,18 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO return null; } - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal"))) { Integer h = this.hAlignmentPane.getSelectedItem(); style = style.deriveHorizontalAlignment(h == null ? -1 : h); } - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical"))) { Integer vAlign = this.vAlignmentPane.getSelectedItem(); if (vAlign != null) { style = style.deriveVerticalAlignment(vAlign); } } - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Text_Style"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Text_Style"))) { if (ComparatorUtils.equals(this.textComboBox.getSelectedItem(), TEXT[0])) { style = style.deriveTextStyle(Style.TEXTSTYLE_WRAPTEXT); } else if (ComparatorUtils.equals(this.textComboBox.getSelectedItem(), TEXT[1])) { @@ -394,7 +395,7 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO private Style updateImageLayout(Style style) { - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Layout"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Image_Layout"))) { if (ComparatorUtils.equals(this.imageLayoutComboBox.getSelectedItem(), LAYOUT[1])) { style = style.deriveImageLayout(Constants.IMAGE_TILED); } else if (ComparatorUtils.equals(this.imageLayoutComboBox.getSelectedItem(), LAYOUT[2])) { @@ -410,7 +411,7 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO private Style updateTextRotation(Style style) { - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation"))) { if (this.textRotationComboBox.getSelectedIndex() != 0) { style = style.deriveVerticalText(Style.VERTICALTEXT); style = style.deriveRotation(0); @@ -424,21 +425,21 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO } private Style updateOther(Style style) { - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Left_Indent"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Left_Indent"))) { style = style.derivePaddingLeft(indentationUnitProcessor.paddingUnitGainFromSpinner((int) (this.leftIndentSpinner.getValue()))); } - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Right_Indent"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Right_Indent"))) { style = style.derivePaddingRight(indentationUnitProcessor.paddingUnitGainFromSpinner((int) (this.rightIndentSpinner.getValue()))); } //间距 - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_Before"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_Before"))) { style = style.deriveSpacingBefore((int) (this.spaceBeforeSpinner.getValue())); } - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_After"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Spacing_After"))) { style = style.deriveSpacingAfter((int) (this.spaceAfterSpinner.getValue())); } - if (ComparatorUtils.equals(globalNameListener.getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Line_Spacing"))) { + if (ComparatorUtils.equals(globalNameListener.getGlobalName(), Toolkit.i18nText("Fine-Design_Basic_Style_Line_Spacing"))) { style = style.deriveLineSpacing((int) (this.lineSpaceSpinner.getValue())); } return style; diff --git a/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java b/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java index a3151b2e71..3c917ea456 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java @@ -4,7 +4,6 @@ package com.fr.design.gui.style; * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. */ -import com.fr.base.BaseUtils; import com.fr.base.CellBorderStyle; import com.fr.base.Style; import com.fr.design.constants.LayoutConstants; @@ -18,6 +17,7 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.style.color.NewColorSelectBox; import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; +import com.fr.general.IOUtils; import com.fr.stable.Constants; import com.fr.stable.CoreConstants; @@ -29,6 +29,7 @@ import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.GridLayout; import java.util.Arrays; import java.util.HashSet; @@ -43,7 +44,6 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse private static final String[] BORDERARRAY = {"currentLineCombo", "currentLineColorPane", "outerToggleButton", "topToggleButton", "leftToggleButton", "bottomToggleButton", "rightToggleButton", "innerToggleButton", "horizontalToggleButton", "verticalToggleButton"}; private static final Set BORDER_SET = new HashSet<>(Arrays.asList(BORDERARRAY)); - private boolean insideMode = false; private UIToggleButton topToggleButton; private UIToggleButton horizontalToggleButton; @@ -55,11 +55,8 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse private UIToggleButton innerToggleButton; private UIToggleButton outerToggleButton; - private LineComboBox currentLineCombo; - private NewColorSelectBox currentLineColorPane; - private JPanel panel; - private JPanel borderPanel; - private JPanel backgroundPanel; + protected LineComboBox currentLineCombo; + protected NewColorSelectBox currentLineColorPane; private BackgroundPane backgroundPane; private GlobalNameListener globalNameListener = null; @@ -86,22 +83,28 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse new Component[]{null, null}, new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Color") + " ", SwingConstants.LEFT), currentLineColorPane}, new Component[]{null, null}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Out_Border") + " ", SwingConstants.LEFT), outerToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("com/fr/design/images/m_format/out.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/out_white.png")}, false)}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Out_Border") + " ", SwingConstants.LEFT), outerToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("com/fr/design/images/m_format/out.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/out_white.png")}, false)}, new Component[]{null, externalPane}, new Component[]{null, null}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_In_Border") + " ", SwingConstants.LEFT), innerToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("com/fr/design/images/m_format/in.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/in_white.png")}, false)}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_In_Border") + " ", SwingConstants.LEFT), innerToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("com/fr/design/images/m_format/in.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/in_white.png")}, false)}, new Component[]{null, insidePane}, new Component[]{null, null} }; double[] rowSize = {p, p, p, p, p, p, p, p, p, p, p}; double[] columnSize = {p, f}; int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; - panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM); - borderPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Border"), 280, 24, panel); + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM); + JPanel borderPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Border"), 280, 24, panel); this.add(borderPanel, BorderLayout.NORTH); + UILabel backgroundFillLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Background_Fill")); + backgroundFillLabel.setPreferredSize(new Dimension(60, 20)); + backgroundPane = new BackgroundPane(); - backgroundPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), 280, 24, backgroundPane); + JPanel backgroundContainPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{backgroundFillLabel, backgroundPane}}, + TableLayoutHelper.FILL_LASTCOLUMN, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM); + + JPanel backgroundPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), 280, 24, backgroundContainPane); this.add(backgroundPanel, BorderLayout.CENTER); initAllNames(); outerToggleButton.addChangeListener(outerToggleButtonChangeListener); @@ -129,12 +132,12 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse }; private void initButtonsWithIcon() { - topToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/top.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/top_white.png")}, false); - leftToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/left.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/left_white.png")}, false); - bottomToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/bottom.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bottom_white.png")}, false); - rightToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/right.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/right_white.png")}, false); - horizontalToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/horizontal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/horizontal_white.png")}, false); - verticalToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/vertical.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/vertical_white.png")}, false); + topToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/top.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/top_white.png")}, false); + leftToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/left.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/left_white.png")}, false); + bottomToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/bottom.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bottom_white.png")}, false); + rightToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/right.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/right_white.png")}, false); + horizontalToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/horizontal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/horizontal_white.png")}, false); + verticalToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/vertical.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/vertical_white.png")}, false); this.currentLineCombo = new LineComboBox(CoreConstants.UNDERLINE_STYLE_ARRAY); this.currentLineColorPane = new NewColorSelectBox(100); } @@ -173,15 +176,15 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse cellBorderStyle.setRightStyle(style.getBorderRight()); cellBorderStyle.setRightColor(style.getBorderRightColor()); this.backgroundPane.populateBean(style.getBackground()); - this.populateBean(cellBorderStyle, false, style.getBorderTop(), style.getBorderTopColor()); + this.populateBean(cellBorderStyle, false); } - public void populateBean(CellBorderStyle cellBorderStyle, boolean insideMode, int currentStyle, Color currentColor) { - this.insideMode = insideMode; + public void populateBean(CellBorderStyle cellBorderStyle, boolean insideMode) { + populateBean(cellBorderStyle, insideMode, true); + } - this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getTopStyle() == Constants.LINE_NONE ? Constants.LINE_THIN : cellBorderStyle.getTopStyle()); - this.currentLineColorPane.setSelectObject(cellBorderStyle.getTopColor()); + public void populateBean(CellBorderStyle cellBorderStyle, boolean insideMode, boolean onlyInspectTop) { this.topToggleButton.setSelected(cellBorderStyle.getTopStyle() != Constants.LINE_NONE); this.bottomToggleButton.setSelected(cellBorderStyle.getBottomStyle() != Constants.LINE_NONE); @@ -194,9 +197,46 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse this.innerToggleButton.setSelected(cellBorderStyle.getInnerBorder() != Constants.LINE_NONE); this.outerToggleButton.setSelected(cellBorderStyle.getOuterBorderStyle() != Constants.LINE_NONE); - this.innerToggleButton.setEnabled(this.insideMode); - this.horizontalToggleButton.setEnabled(this.insideMode); - this.verticalToggleButton.setEnabled(this.insideMode); + this.innerToggleButton.setEnabled(insideMode); + this.horizontalToggleButton.setEnabled(insideMode); + this.verticalToggleButton.setEnabled(insideMode); + + populateLineStyleAndColor(cellBorderStyle, onlyInspectTop); + } + + public void populateLineStyleAndColor(CellBorderStyle cellBorderStyle, boolean onlyInspectTop) { + resetLineStyleAndColorSetting(); + + if (cellBorderStyle.getTopStyle() != Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getTopStyle()); + this.currentLineColorPane.setSelectObject(cellBorderStyle.getTopColor()); + } else if (!onlyInspectTop) { + if (cellBorderStyle.getBottomStyle() != Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getBottomStyle()); + this.currentLineColorPane.setSelectObject(cellBorderStyle.getBottomColor()); + } else if (cellBorderStyle.getLeftStyle() != Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getLeftStyle()); + this.currentLineColorPane.setSelectObject(cellBorderStyle.getLeftColor()); + } else if (cellBorderStyle.getRightStyle() != Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getRightStyle()); + this.currentLineColorPane.setSelectObject(cellBorderStyle.getRightColor()); + } else if (cellBorderStyle.getVerticalStyle() != Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getVerticalStyle()); + this.currentLineColorPane.setSelectObject(cellBorderStyle.getVerticalColor()); + } else if (cellBorderStyle.getHorizontalStyle() != Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getHorizontalStyle()); + this.currentLineColorPane.setSelectObject(cellBorderStyle.getHorizontalColor()); + } + } + + if (this.currentLineCombo.getSelectedLineStyle() == Constants.LINE_NONE) { + this.currentLineCombo.setSelectedLineStyle(Constants.LINE_THIN); + } + } + + private void resetLineStyleAndColorSetting() { + this.currentLineCombo.setSelectedLineStyle(Constants.LINE_NONE); + this.currentLineColorPane.setSelectObject(null); } @Override @@ -212,7 +252,7 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse if (BORDER_SET.contains(globalNameListener.getGlobalName())) { CellBorderStyle cellBorderStyle = this.update(); style = style.deriveBorder(cellBorderStyle.getTopStyle(), cellBorderStyle.getTopColor(), cellBorderStyle.getBottomStyle(), cellBorderStyle.getBottomColor(), - cellBorderStyle.getLeftStyle(), cellBorderStyle.getLeftColor(), cellBorderStyle.getRightStyle(), cellBorderStyle.getRightColor()); + cellBorderStyle.getLeftStyle(), cellBorderStyle.getLeftColor(), cellBorderStyle.getRightStyle(), cellBorderStyle.getRightColor()); } return style; @@ -252,16 +292,8 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse } cellBorderStyle.setHorizontalStyle(horizontalToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); - if (leftToggleButton.isSelected() && bottomToggleButton.isSelected() && rightToggleButton.isSelected() && topToggleButton.isSelected()) { - outerToggleButton.setSelected(true); - } else { - outerToggleButton.setSelected(false); - } - if (verticalToggleButton.isSelected() && horizontalToggleButton.isSelected()) { - innerToggleButton.setSelected(true); - } else { - innerToggleButton.setSelected(false); - } + outerToggleButton.setSelected(leftToggleButton.isSelected() && bottomToggleButton.isSelected() && rightToggleButton.isSelected() && topToggleButton.isSelected()); + innerToggleButton.setSelected(verticalToggleButton.isSelected() && horizontalToggleButton.isSelected()); return cellBorderStyle; } diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ComponentBodyStylePane.java b/designer-base/src/main/java/com/fr/design/gui/style/ComponentBodyStylePane.java new file mode 100644 index 0000000000..8463ed6f54 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ComponentBodyStylePane.java @@ -0,0 +1,33 @@ +package com.fr.design.gui.style; + +import com.fr.general.act.BorderPacker; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class ComponentBodyStylePane extends AbstractTranslucentBackgroundSpecialPane { + + public ComponentBodyStylePane(int uiLabelWidth) { + this(uiLabelWidth, -1); + } + + public ComponentBodyStylePane(int uiLabelWidth, int uiSettingWidth) { + super(uiLabelWidth, uiSettingWidth, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill")); + } + + @Override + public void populateBean(BorderPacker style) { + this.backgroundPane.populateBean(style.getBackground()); + if (this.opacityPane != null) { + this.opacityPane.populateBean(style.getAlpha()); + } + } + + @Override + public void updateBean(BorderPacker style) { + style.setBackground(backgroundPane.update()); + style.setAlpha((float)opacityPane.updateBean()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ComponentIntegralStylePane.java b/designer-base/src/main/java/com/fr/design/gui/style/ComponentIntegralStylePane.java new file mode 100644 index 0000000000..0fe9c14891 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ComponentIntegralStylePane.java @@ -0,0 +1,109 @@ +package com.fr.design.gui.style; + +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.icombobox.UIComboBox; +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 com.fr.design.widget.FRWidgetFactory; +import com.fr.general.act.BorderPacker; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.BorderLayout; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class ComponentIntegralStylePane extends AbstractBorderPackerPane { + public static final 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") + }; + + //渲染风格:有无阴影 + protected UIComboBox borderStyleCombo; + // 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色) + protected TranslucentBorderSpecialPane borderPane; + //边框圆角或圆角裁剪 + protected UISpinner cornerSpinner; + + private final int uiLabelWidth; + private final int uiSettingWidth; + private final boolean supportBorderImage; + private final boolean supportCornerRadius; + + public ComponentIntegralStylePane(int uiLabelWidth, + boolean supportBorderImage, boolean supportCornerRadius) { + this(uiLabelWidth, -1, supportBorderImage, supportCornerRadius); + } + + public ComponentIntegralStylePane(int uiLabelWidth, int uiSettingWidth) { + this(uiLabelWidth, uiSettingWidth, true, true); + } + + public ComponentIntegralStylePane( + int uiLabelWidth, int uiSettingWidth, + boolean supportBorderImage, boolean supportCornerRadius) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + this.supportBorderImage = supportBorderImage; + this.supportCornerRadius = supportCornerRadius; + + this.initializePane(); + } + + private void initializeComponents() { + borderStyleCombo = new UIComboBox(BORDER_STYLE); + borderPane = new TranslucentBorderSpecialPane(this.supportBorderImage); + cornerSpinner = new UISpinner(0,1000,1,0); + } + + protected void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + this.initializeComponents(); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = supportCornerRadius ? new double[] {p, p, p} : new double[]{p, p}; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), FRGUIPaneFactory.createBorderLayoutNorthPaneWithComponent(borderStyleCombo)}, + {this.borderPane, null}, + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, + }, + rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); + + this.add(content, BorderLayout.NORTH); + } + + @Override + public void populateBean(BorderPacker style) { + if (this.borderStyleCombo != null) { + this.borderStyleCombo.setSelectedIndex(style.getBorderStyle()); + } + if (cornerSpinner != null) { + this.cornerSpinner.setValue(style.getBorderRadius()); + } + if (this.borderPane != null) { + this.borderPane.populateBean(style); + } + } + + @Override + public void updateBean(BorderPacker style) { + if (borderStyleCombo != null) { + style.setBorderStyle(borderStyleCombo.getSelectedIndex()); + } + if (cornerSpinner != null) { + style.setBorderRadius((int) cornerSpinner.getValue()); + } + if (borderPane != null) { + borderPane.updateBean(style); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ComponentTitleStylePane.java b/designer-base/src/main/java/com/fr/design/gui/style/ComponentTitleStylePane.java new file mode 100644 index 0000000000..33af029ad6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ComponentTitleStylePane.java @@ -0,0 +1,351 @@ +package com.fr.design.gui.style; + +import com.fr.base.Utils; +import com.fr.base.svg.IconUtils; +import com.fr.design.designer.IntervalConstants; +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.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.WidgetTitle; +import com.fr.general.FRFont; +import com.fr.general.IOUtils; +import com.fr.general.act.BorderPacker; +import com.fr.general.act.TitlePacker; +import com.fr.stable.Constants; + +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.Dimension; +import java.awt.Font; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class ComponentTitleStylePane extends AbstractBorderPackerPane { + private static final Dimension BUTTON_SIZE = new Dimension(20, 20); + public static final TitlePacker DEFAULT_TITLE_PACKER = new WidgetTitle(); + + // 标题可见 + protected UICheckBox visibleCheckbox; + //标题文字内容 + protected TinyFormulaPane textContentPane; + //标题字体格式 + protected UIComboBox fontFamilyComboBox; + //标题字体大小 + protected UIComboBox fontSizeComboBox; + //标题字体颜色 + protected UIColorButton fontColorSelectPane; + //标题字体特殊效果:粗体、斜体、下划线 + private UIToggleButton fontBoldButton; + private UIToggleButton fontItalicButton; + private UIToggleButton fontUnderlineButton; + // 标题图文混排 + protected TextInsetImageBackgroundSpecialPane insetImagePane; + //对齐方式 + protected UIButtonGroup alignPane; + //标题整体背景 + protected TitleTranslucentBackgroundSpecialPane backgroundPane; + + // 是否支持用户编辑这些属性(不支持时: 设置面板总是不可见) + private boolean isSupportTitleVisible = true; + private boolean isSupportTitleContent = true; + private boolean isSupportTitleOtherSetting = true; + + // 用于控制各部分设置的可见性 + private JPanel titleVisiblePane; + private JPanel titleContentPane; + private JPanel titleOtherSettingPane; + + private final int uiLabelWidth; + private final int uiSettingWidth; + + public ComponentTitleStylePane(int uiLabelWidth) { + this(uiLabelWidth, -1); + } + + public ComponentTitleStylePane( + int uiLabelWidth, int uiSettingWidth) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + this.initializePane(); + } + + private void initializeComponents() { + visibleCheckbox = new UICheckBox(); + + textContentPane = new TinyFormulaPane(); + + fontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); + FRFont frFont = DEFAULT_TITLE_PACKER.getFrFont(); + if (frFont != null) { + String fontFamily = frFont.getFamily(); + // 使用style中默认的字体初始化titleFontFamilyComboBox,保证UI和数据的一致性 + this.fontFamilyComboBox.setSelectedItem(fontFamily); + } + fontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); + + fontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); + fontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); + + fontColorSelectPane = new UIColorButton(); + fontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); + fontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); + + fontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); + fontBoldButton.setPreferredSize(BUTTON_SIZE); + fontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); + fontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); + + fontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); + fontItalicButton.setPreferredSize(BUTTON_SIZE); + fontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); + fontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); + + fontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); + fontUnderlineButton.setPreferredSize(BUTTON_SIZE); + fontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); + fontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); + + insetImagePane = new TextInsetImageBackgroundSpecialPane(); + + alignPane = new UIButtonGroup<>( + new Icon[]{ + IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), + IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), + IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png") + }, + new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}); + alignPane.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") + }); + alignPane.setSelectedItem(DEFAULT_TITLE_PACKER.getPosition()); + + backgroundPane = new TitleTranslucentBackgroundSpecialPane(this.uiLabelWidth, this.uiSettingWidth); + } + + private void initializePane() { + this.setLayout(new BorderLayout(0, 0)); + this.initializeComponents(); + + titleVisiblePane = this.createTitleVisiblePane(); + titleContentPane = this.createTitleContentPane(); + titleOtherSettingPane = this.createTitleOtherSettingPane(); + + if (isSupportTitleVisible) { + titleVisiblePane.setVisible(true); + } + if (isSupportTitleVisible) { + titleContentPane.setVisible(false); + } + if (isSupportTitleVisible) { + titleOtherSettingPane.setVisible(false); + } + + addComponents(titleVisiblePane, titleContentPane, titleOtherSettingPane); + } + + private JPanel createTitleVisiblePane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + visibleCheckbox.setSelected(false); + + container.add(visibleCheckbox, BorderLayout.WEST); + container.add(FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER); + + visibleCheckbox.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + boolean visible = visibleCheckbox.isSelected(); + if (titleContentPane != null) { + titleContentPane.setVisible(visible && isSupportTitleContent); + } + if (titleOtherSettingPane != null) { + titleOtherSettingPane.setVisible(visible && isSupportTitleOtherSetting); + } + } + }); + return container; + } + + private JPanel createTitleContentPane() { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p}; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + return TableLayoutHelper.createCommonTableLayoutPane( + new JComponent[][]{{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), textContentPane}}, + rowSize, columnSize, IntervalConstants.INTERVAL_L1); + } + + private JPanel createTitleOtherSettingPane() { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p, p, p, p, p}; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + JComponent[][] components = new JComponent[][]{ + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), FRGUIPaneFactory.createBorderLayoutNorthPaneWithComponent(fontFamilyComboBox)}, + {null, createTitleFontButtonPane()}, + {insetImagePane, null}, + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), alignPane}, + {backgroundPane, null} + }; + + return TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, IntervalConstants.INTERVAL_L1); + } + + protected JPanel createTitleFontButtonPane(){ + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p}; + double[] columnSize = {f, p, p, p, p}; + + JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { + {fontSizeComboBox, fontColorSelectPane, fontItalicButton, fontBoldButton, fontUnderlineButton}, + }, rowSize, columnSize, IntervalConstants.INTERVAL_W0); + + JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + containerPane.add(buttonPane, BorderLayout.NORTH); + + return containerPane; + } + + @Override + public void populateBean(BorderPacker style) { + TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle(); + widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; + boolean titleVisible = style != null && style.getType() != LayoutBorderStyle.STANDARD; + visibleCheckbox.setSelected(isSupportTitleVisible && titleVisible); + titleContentPane.setVisible(isSupportTitleContent && titleVisible); + titleOtherSettingPane.setVisible(isSupportTitleOtherSetting && titleVisible); + + this.textContentPane.populateBean(widgetTitle.getTextObject().toString()); + + FRFont frFont = widgetTitle.getFrFont(); + this.fontSizeComboBox.setSelectedItem(frFont.getSize()); + this.fontFamilyComboBox.setSelectedItem(frFont.getFamily()); + this.fontColorSelectPane.setColor(frFont.getForeground()); + this.fontColorSelectPane.repaint(); + fontBoldButton.setSelected(frFont.isBold()); + fontItalicButton.setSelected(frFont.isItalic()); + + int line = frFont.getUnderline(); + if (line == Constants.LINE_NONE) { + fontUnderlineButton.setSelected(false); + } else { + fontUnderlineButton.setSelected(true); + } + + alignPane.setSelectedItem(widgetTitle.getPosition()); + insetImagePane.populateBean(widgetTitle); + backgroundPane.populateBean(widgetTitle); + } + + @Override + public void updateBean(BorderPacker style) { + style.setType(visibleCheckbox != null && visibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD); + TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); + title.setTextObject(textContentPane.updateBean()); + FRFont frFont = title.getFrFont(); + frFont = frFont.applySize((Integer) fontSizeComboBox.getSelectedItem()); + frFont = frFont.applyName(fontFamilyComboBox.getSelectedItem().toString()); + frFont = frFont.applyForeground(fontColorSelectPane.getColor()); + frFont = updateTitleFontItalicBold(frFont); + int line = fontUnderlineButton.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE; + frFont = frFont.applyUnderline(line); + title.setFrFont(frFont); + title.setPosition((Integer) alignPane.getSelectedItem()); + insetImagePane.updateBean(title); + backgroundPane.updateBean(title); + style.setTitle(title); + } + + private FRFont updateTitleFontItalicBold(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 (fontItalicButton.isSelected() && !isItalic) { + italic_bold += Font.ITALIC; + } else if (!fontItalicButton.isSelected() && isItalic) { + italic_bold -= Font.ITALIC; + } + frFont = frFont.applyStyle(italic_bold); + if (fontBoldButton.isSelected() && !isBold) { + italic_bold += Font.BOLD; + } else if (!fontBoldButton.isSelected() && isBold) { + italic_bold -= Font.BOLD; + } + frFont = frFont.applyStyle(italic_bold); + return frFont; + } + + private void addComponents(JComponent... components) { + if (components == null) { + return; + } + JPanel container = this; + for (int i = 0; i < components.length; i++) { + JComponent component = components[i]; + if (component != null) { + container.add(component, BorderLayout.NORTH); + component.setBorder(BorderFactory.createEmptyBorder(i == 0 ? 0 : IntervalConstants.INTERVAL_L1, 0, 0, 0)); + if (i < components.length - 1) { + JPanel nextContainer = new JPanel(FRGUIPaneFactory.createBorderLayout()); + container.add(nextContainer, BorderLayout.CENTER); + container = nextContainer; + } + } + } + } + + + public void setSupportTitleVisible(boolean supporting) { + isSupportTitleVisible = supporting; + if (titleVisiblePane != null) { + titleVisiblePane.setVisible(supporting); + } + } + + public void setSupportTitleContent(boolean supporting) { + isSupportTitleContent = supporting; + if (titleContentPane != null) { + boolean titleVisible = visibleCheckbox.isSelected(); + if (isSupportTitleContent) { + titleContentPane.setVisible(titleVisible); + } else { + titleContentPane.setVisible(false); + } + } + } + + public void setSupportOtherSetting(boolean supporting) { + isSupportTitleOtherSetting = supporting; + if (titleOtherSettingPane != null) { + boolean titleVisible = visibleCheckbox.isSelected(); + if (isSupportTitleOtherSetting) { + titleOtherSettingPane.setVisible(titleVisible); + } else { + titleOtherSettingPane.setVisible(false); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java b/designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java new file mode 100644 index 0000000000..bf06aa2fd7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java @@ -0,0 +1,140 @@ +package com.fr.design.gui.style; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.AttributeChangeUtils; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ilable.UILabel; +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.JTemplate; +import com.fr.design.widget.FRWidgetFactory; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/19 + */ +public class FollowingThemePane extends BasicPane implements UIObserver { + public static final int SETTING_LABEL_WIDTH = 60; + + public static final String[] FOLLOWING_THEME_STRING_ARRAYS = new String[]{ + Toolkit.i18nText("Fine-Design_Style_Follow_Theme"), + Toolkit.i18nText("Fine-Design_Style_Not_Follow_Theme"), + }; + + private final UIButtonGroup followingThemeButtonGroup; + private final List changeListeners = new ArrayList<>(); + private UIObserverListener uiObserverListener; + + private JPanel container; + + public FollowingThemePane(String name) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + + followingThemeButtonGroup = new UIButtonGroup<>(FOLLOWING_THEME_STRING_ARRAYS); + followingThemeButtonGroup.setAutoFireStateChanged(false); + followingThemeButtonGroup.setSelectedIndex(1); + followingThemeButtonGroup.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + AttributeChangeUtils.changeComposedUI(FollowingThemePane.this, false, new AttributeChangeUtils.UIChangeAction() { + @Override + public void changeComposedUI() { + for (FollowingThemeActionChangeListener changeListener : changeListeners) { + changeListener.onFollowingTheme(isFollowingTheme()); + } + invalidate(); + } + }); + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + } + }); + + UILabel followingThemeLabel = FRWidgetFactory.createLineWrapLabel(name); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + JPanel followingThemePane = + TableLayoutHelper.createGapTableLayoutPane( new Component[][]{new Component[] { followingThemeLabel, FRGUIPaneFactory.createBorderLayoutNorthPaneWithComponent(followingThemeButtonGroup)}}, + new double[] { p }, new double[] { SETTING_LABEL_WIDTH, f }, 10, 0); + followingThemePane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + followingThemePane.setVisible(false); + + add(followingThemePane, BorderLayout.NORTH); + container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + add(container, BorderLayout.CENTER); + } + + public void addFollowThemePane(JPanel content, FollowingThemeActionChangeListener changeListener) { + if (content != null) { + container.add(content, BorderLayout.NORTH); + changeListeners.add(changeListener); + + JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(nextContainer, BorderLayout.CENTER); + container = nextContainer; + } + } + + @Override + protected String title4PopupWindow() { + return null; + } + + @Override + public void registerChangeListener(UIObserverListener uiObserverListener) { + this.uiObserverListener = uiObserverListener; + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + + public interface FollowingThemeActionChangeListener { + void onFollowingTheme(boolean following); + } + + public TemplateTheme getUsingTheme() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + return template.getTemplateTheme(); + } + return null; + } + + public void supportFollowingTheme(boolean supporting) { + getComponent(0).setVisible(supporting); + if (!supporting) { + setFollowingTheme(false); + } + } + + public void setFollowingTheme(boolean following) { + followingThemeButtonGroup.setSelectedIndex(following ? 0 : 1); + for (FollowingThemeActionChangeListener changeListener : changeListeners) { + changeListener.onFollowingTheme(isFollowingTheme()); + } + } + public boolean isFollowingTheme() { + return followingThemeButtonGroup.getSelectedIndex() == 0; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ReportBackgroundSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/ReportBackgroundSpecialPane.java new file mode 100644 index 0000000000..aeb2938a27 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ReportBackgroundSpecialPane.java @@ -0,0 +1,102 @@ +package com.fr.design.gui.style; + +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 com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ImageBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.NullBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.PatternBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.TextureBackgroundQuickPane; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/19 + */ +public class ReportBackgroundSpecialPane extends BackgroundPane { + public ReportBackgroundSpecialPane(){ + super(); + } + + @Override + protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { + NullBackgroundQuickPane nullBackgroundPane = new NullBackgroundQuickPane(); + + ColorBackgroundQuickPane colorBackgroundPane = new ColorBackgroundQuickPane(); + colorBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + ImageBackgroundQuickPane imageBackgroundPane = new ImageBackgroundQuickPane(); + imageBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + GradientBackgroundQuickPane gradientBackgroundPane = createGradientBackgroundQuickPane(); + gradientBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + TextureBackgroundQuickPane textureBackgroundPane = new TextureBackgroundQuickPane(); + textureBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + PatternBackgroundQuickPane patternBackgroundPane = new PatternBackgroundQuickPane(); + patternBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + + + List kinds = new ArrayList(); + + kinds.add(nullBackgroundPane); + kinds.add(colorBackgroundPane); + kinds.add(imageBackgroundPane); + kinds.add(gradientBackgroundPane); + kinds.add(textureBackgroundPane); + kinds.add(patternBackgroundPane); + + Set providers = ExtraDesignClassManager.getInstance().getArray(BackgroundQuickUIProvider.MARK_STRING); + for (BackgroundQuickUIProvider provider : providers) { + BackgroundQuickPane newTypePane = provider.appearanceForBackground(); + newTypePane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + kinds.add(newTypePane); + } + + return kinds.toArray(new BackgroundQuickPane[kinds.size()]); + } + + protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { + // 使用默认的150宽度构建渐变条 + return new GradientBackgroundQuickPane(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/TextFontTippedPane.java b/designer-base/src/main/java/com/fr/design/gui/style/TextFontTippedPane.java new file mode 100644 index 0000000000..7f11b0d4bf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/TextFontTippedPane.java @@ -0,0 +1,86 @@ +package com.fr.design.gui.style; + +import com.fr.base.Style; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.ilable.UILabel; +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.theme.edit.ui.LabelUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; + + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/29 + */ +public class TextFontTippedPane extends AbstractBasicStylePane { + + private FRFontPane fontPane; + + public TextFontTippedPane(boolean showFormatTip) { + this.initializePane(showFormatTip); + } + + private void initializePane(boolean showFormatTip) { + setLayout(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + + fontPane = new FRFontPane(); + this.add(createLabeledPane(Toolkit.i18nText("Fine-Design_Form_FR_Font"), fontPane), BorderLayout.NORTH); + + if (showFormatTip) { + JPanel formatTipPane = createFormatTipPane(); + this.add(formatTipPane, BorderLayout.CENTER); + } + } + + private JPanel createLabeledPane(String text, JPanel panel) { + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = { p }; + double[] columnSize = {p, f}; + + UILabel uiLabel = new UILabel(text); + JPanel uiLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + uiLabelPane.add(uiLabel, BorderLayout.NORTH); + + return TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ + new Component[] { uiLabelPane, panel }, + }, rowSize, columnSize, LayoutConstants.VGAP_LARGE, LayoutConstants.VGAP_MEDIUM); + } + + private JPanel createFormatTipPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + JTextArea formatMigratedTip = LabelUtils.createAutoWrapLabel(Toolkit.i18nText("Fine-Design_Report_Format_Style_Migrated_Tip"), new Color(153, 153, 153)); + + container.add(formatMigratedTip, BorderLayout.NORTH); + return container; + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Report_Text"); + } + + @Override + public void populateBean(Style style) { + this.fontPane.populateBean(style); + } + + @Override + public Style update(Style style) { + return this.fontPane.update(style); + } +} + diff --git a/designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java b/designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java new file mode 100644 index 0000000000..7e0db6051b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java @@ -0,0 +1,464 @@ +package com.fr.design.gui.style; + +import com.fr.base.CoreDecimalFormat; +import com.fr.base.GraphHelper; +import com.fr.base.Style; +import com.fr.base.TextFormat; +import com.fr.data.core.FormatField; +import com.fr.data.core.FormatField.FormatContents; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.TextFontComboBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +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.event.ItemEvent; +import java.awt.event.ItemListener; +import java.math.RoundingMode; +import java.text.Format; +import java.text.SimpleDateFormat; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/29 + * 包含格式相关的设置 + */ +public class TextFormatPane extends AbstractBasicStylePane implements GlobalNameObserver { + private static final long serialVersionUID = 724330854437726751L; + + private static final int LABEL_X = 4; + private static final int LABEL_Y = 18; + private static final int LABEL_DELTA_WIDTH = 8; + private static final int LABEL_HEIGHT = 15; //标签背景的范围 + private static final int CURRENCY_FLAG_POINT = 6; + + private static final Integer[] TYPES = new Integer[]{ + FormatContents.NULL, FormatContents.NUMBER, + FormatContents.CURRENCY, FormatContents.PERCENT, + FormatContents.SCIENTIFIC, FormatContents.DATE, + FormatContents.TIME, FormatContents.TEXT}; + + private static final Integer[] DATE_TYPES = new Integer[]{FormatContents.NULL, FormatContents.DATE, FormatContents.TIME}; + + protected UIComboBox typeComboBox; + protected TextFontComboBox textField; + protected UICheckBox roundingBox; + protected UILabel previewLabel; + + private boolean isRightFormat; + private boolean isDate = false; + private GlobalNameListener globalNameListener = null; + + public TextFormatPane() { + + initFormatTypesComboBox(); + initTextFontComboBox4GeneralFormats(); + initRoundingCheckBox4PercentFormat(); + initPreviewLabel4GeneralFormat(); + + initLayout(); + + setTextFieldVisible(false); + setRoundingBoxVisible(false); + setPreviewLabelVisible(false); + } + + private void initFormatTypesComboBox() { + typeComboBox = new UIComboBox(TextFormatPane.TYPES); + typeComboBox.setRenderer(createComBoxRender()); + typeComboBox.addItemListener(itemListener); + typeComboBox.setGlobalName("typeComboBox"); + typeComboBox.setPreferredSize(new Dimension(155,20)); + } + + private void initTextFontComboBox4GeneralFormats() { + textField = new TextFontComboBox<>(); + textField.addItemListener(textFieldItemListener); + textField.setEditable(true); + textField.setGlobalName("textField"); + } + + private void initRoundingCheckBox4PercentFormat() { + roundingBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Base_Option_Half_Up")); + roundingBox.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); + roundingBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + } + }); + roundingBox.setGlobalName("roundingBox"); + } + + private void initPreviewLabel4GeneralFormat() { + Border interBorder = new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 4); + String title = Toolkit.i18nText("Fine-Design_Report_Base_StyleFormat_Sample"); + Border border = BorderFactory.createTitledBorder(interBorder, title, TitledBorder.LEFT, 0, null, UIConstants.LINE_COLOR); + previewLabel = new UILabel(FormatField.getInstance().getFormatValue()) { + + @Override + public void paint(Graphics g) { + super.paint(g); + int width = getWidth(); + Color original = g.getColor(); + g.setColor(getBackground()); + g.fillRect(LABEL_X, LABEL_Y, width - LABEL_DELTA_WIDTH, LABEL_HEIGHT); + g.setColor(UIConstants.LINE_COLOR); + FontMetrics cellFM = g.getFontMetrics(); + int textWidth = cellFM.stringWidth(getText()); + GraphHelper.drawString(g, getText(), (width - textWidth) / 2F, 26); + g.setColor(original); + } + }; + previewLabel.setHorizontalAlignment(UILabel.CENTER); + previewLabel.setBorder(border); + } + + protected void initLayout() { + JPanel labeledFormatTypeComboBoxPane = new JPanel(new BorderLayout(20, 0)); + labeledFormatTypeComboBoxPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Format")), BorderLayout.WEST); + labeledFormatTypeComboBoxPane.add(typeComboBox, BorderLayout.CENTER); + + JPanel labeledRoundingCheckboxPane = new JPanel(new BorderLayout(0, 0)); + labeledRoundingCheckboxPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Option")), BorderLayout.WEST); + labeledRoundingCheckboxPane.add(roundingBox, BorderLayout.CENTER); + + addComponents(4, new JComponent[] { labeledFormatTypeComboBoxPane, textField, labeledRoundingCheckboxPane, previewLabel}); + } + + protected void setTextFieldVisible(boolean visible) { + textField.setVisible(visible); + } + + protected void setRoundingBoxVisible(boolean visible) { + roundingBox.getParent().setVisible(visible); + } + + protected void setPreviewLabelVisible(boolean visible) { + previewLabel.setVisible(visible); + } + + protected void addComponents(int gap, JComponent[] components) { + JPanel container = this; + container.setLayout(new BorderLayout(0, gap)); + for (JComponent component: components) { + if (component != null) { + container.add(component, BorderLayout.NORTH); + JPanel nextContainer = new JPanel(new BorderLayout(0, gap)); + container.add(nextContainer, BorderLayout.CENTER); + container = nextContainer; + } + } + if (container.getComponentCount() == 0) { + container.getParent().remove(container); + } + } + + protected UIComboBoxRenderer createComBoxRender() { + return new UIComboBoxRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof Integer) { + label.setText(" " + FormatField.getInstance().getName((Integer) value)); + } + return label; + } + }; + } + + + @Override + /** + * 得到合适的大小 + */ + public Dimension getPreferredSize() { + if (this.typeComboBox.getSelectedIndex() == FormatContents.NULL) { + return typeComboBox.getPreferredSize(); + } + return super.getPreferredSize(); + } + + /** + * 弹出框标题 + * + * @return 标题 + */ + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Report_Text"); + } + + /** + * Populate + */ + public void populateBean(Format format) { + if (format == null) { + this.typeComboBox.setSelectedIndex(FormatContents.NULL); + } else { + if (format instanceof CoreDecimalFormat) { + // check all value + String pattern = ((CoreDecimalFormat) format).toPattern(); + if (isCurrencyFormatStyle(pattern)) { + setPatternComboBoxAndList(FormatContents.CURRENCY, pattern); + } else if (pattern.indexOf("%") > 0) { + setPatternComboBoxAndList(FormatContents.PERCENT, pattern); + this.roundingBox.setSelected(((CoreDecimalFormat) format).getRoundingMode().equals(RoundingMode.HALF_UP)); + } else if (pattern.indexOf("E") > 0) { + setPatternComboBoxAndList(FormatContents.SCIENTIFIC, pattern); + } else { + setPatternComboBoxAndList(FormatContents.NUMBER, pattern); + } + } else if (format instanceof SimpleDateFormat) { // date and time + String pattern = ((SimpleDateFormat) format).toPattern(); + if (!isTimeType(pattern)) { + setPatternComboBoxAndList(FormatContents.DATE, pattern); + } else { + setPatternComboBoxAndList(FormatContents.TIME, pattern); + } + } else if (format instanceof TextFormat) { // Text + this.typeComboBox.setSelectedItem(FormatContents.TEXT); + } + } + } + + private boolean isCurrencyFormatStyle(String pattern) { + if (pattern.length() == 0) { + return false; + } + + if (pattern.charAt(0) == '¤' || pattern.charAt(0) == '$') { + return true; + } + + return pattern.length() > CURRENCY_FLAG_POINT && pattern.startsWith("#,##0;"); + } + + /** + * 判断是否是数组有模式 + * + * @param stringArray 字符串数组 + * @param pattern 格式 + * @return 是否是数组有模式 + */ + public static int isArrayContainPattern(String[] stringArray, String pattern) { + for (int i = 0; i < stringArray.length; i++) { + if (ComparatorUtils.equals(stringArray[i], pattern)) { + return i; + } + } + + return -1; + } + + private void setPatternComboBoxAndList(int formatStyle, String pattern) { + this.typeComboBox.setSelectedItem(formatStyle); + this.textField.setSelectedItem(pattern); + } + + private boolean isTimeType(String pattern) { + return pattern.matches(".*[Hhmsa].*"); + } + + /** + * update + */ + public Format update() { + String patternString = String.valueOf(textField.getSelectedItem()); + if (getFormatContents() == FormatContents.TEXT) { + return FormatField.getInstance().getFormat(getFormatContents(), patternString); + } + if (isRightFormat) { + if (StringUtils.isNotEmpty(patternString)) { + RoundingMode roundingMode = roundingBox.isSelected() ? RoundingMode.HALF_UP : RoundingMode.HALF_EVEN; + return FormatField.getInstance().getFormat(getFormatContents(), patternString, roundingMode); + } + } + return null; + } + + private int getFormatContents() { + return (Integer) typeComboBox.getSelectedItem(); + } + + /** + * Refresh preview label. + */ + private void refreshPreviewLabel() { + this.previewLabel.setText(FormatField.getInstance().getFormatValue()); + this.previewLabel.setForeground(UIManager.getColor("Label.foreground")); + try { + isRightFormat = true; + if (StringUtils.isEmpty(String.valueOf(textField.getSelectedItem()))) { + return; + } + this.previewLabel.setText(FormatField.getInstance().getFormatValue(getFormatContents(), String.valueOf(textField.getSelectedItem()))); + } catch (Exception e) { + this.previewLabel.setForeground(Color.red); + this.previewLabel.setText(e.getMessage()); + isRightFormat = false; + } + } + + private boolean isTextOrNull() { + int contents = getFormatContents(); + return contents == FormatContents.TEXT || contents == FormatContents.NULL; + } + + /** + * Radio selection listener. + */ + ItemListener itemListener = new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + int contents = getFormatContents(); + + if (!isTextOrNull()) { + textField.removeAllItems(); + String[] items = FormatField.getInstance().getFormatArray(contents, false); + textField.setItemArray(items); + textField.setSelectedIndex(0); + } + setTextFieldVisible(!isTextOrNull()); + setPreviewLabelVisible(!isTextOrNull()); + setRoundingBoxVisible(getFormatContents() == FormatContents.PERCENT); + } + + } + }; + + ItemListener textFieldItemListener = new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + refreshPreviewLabel(); + } + } + }; + + @Override + /** + * populate + */ + public void populateBean(Style style) { + this.populateBean(style.getFormat()); + } + + @Override + /** + * update + */ + public Style update(Style style) { + return updateByGlobalNamedSetting(style); + } + + private Style updateByGlobalNamedSetting(Style style) { + if (globalNameListener != null) { + String[] alterSettingNames = new String[] {"typeComboBox", "textField", "roundingBox"}; + String globalSettingName = globalNameListener.getGlobalName(); + if (StringUtils.isNotEmpty(globalSettingName)) { + for (String alterSettingName : alterSettingNames) { + if (ComparatorUtils.equals(alterSettingName, globalSettingName)) { + return style.deriveFormat(this.update()); + } + } + } + } + return style; + } + + /** + * 默认只显示百分比的编辑下拉. + */ + public void justUsePercentFormat() { + typeComboBox.setEnabled(false); + this.typeComboBox.setSelectedItem(FormatContents.PERCENT); + } + + public void setForDataSheet() { + Integer[] otherTypes = new Integer[]{FormatContents.NULL, FormatContents.NUMBER, FormatContents.CURRENCY, FormatContents.PERCENT, FormatContents.SCIENTIFIC,}; + this.typeComboBox = new UIComboBox(otherTypes); + UIComboBoxRenderer render = new UIComboBoxRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof Integer) { + label.setText(" " + FormatField.getInstance().getName((Integer) value)); + } + return label; + } + }; + typeComboBox.setRenderer(render); + typeComboBox.addItemListener(itemListener); + setTypeComboBoxPane(typeComboBox); + } + + protected void setTypeComboBoxPane (UIComboBox typeComboBox) { + this.add(typeComboBox, BorderLayout.NORTH); + } + + public void setComboBoxModel(boolean isDate) { + if (this.isDate != isDate) { + this.isDate = isDate; + this.typeComboBox.setSelectedIndex(0); + if (isDate) { + for (int i = 0; i < DATE_TYPES.length; i++) { + this.typeComboBox.addItem(DATE_TYPES[i]); + } + for (int i = 0; i < TYPES.length; i++) { + this.typeComboBox.removeItemAt(1); + } + } else { + for (int i = 0; i < TYPES.length; i++) { + this.typeComboBox.addItem(TYPES[i]); + } + for (int i = 0; i < DATE_TYPES.length; i++) { + this.typeComboBox.removeItemAt(1); + } + } + } + } + + @Override + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + public void registerChangeListener(UIObserverListener listener) { + typeComboBox.registerChangeListener(listener); + textField.registerChangeListener(listener); + } + + @Override + public boolean shouldResponseNameListener() { + return false; + } + + @Override + public void setGlobalName(String name) { + + } +} diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/TitleInsetImagePane.java b/designer-base/src/main/java/com/fr/design/gui/style/TextInsetImageBackgroundSpecialPane.java similarity index 95% rename from designer-form/src/main/java/com/fr/design/gui/xpane/TitleInsetImagePane.java rename to designer-base/src/main/java/com/fr/design/gui/style/TextInsetImageBackgroundSpecialPane.java index 3671259a20..b3556dc6f8 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/TitleInsetImagePane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/TextInsetImageBackgroundSpecialPane.java @@ -1,4 +1,4 @@ -package com.fr.design.gui.xpane; +package com.fr.design.gui.style; import com.fr.base.Style; import com.fr.base.background.ImageBackground; @@ -18,7 +18,6 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.backgroundpane.ImagePreviewPane; import com.fr.design.style.background.image.ImageFileChooser; -import com.fr.design.widget.ui.designer.component.UIBoundSpinner; import com.fr.form.ui.WidgetTitle; import com.fr.general.Background; import com.fr.general.IOUtils; @@ -26,11 +25,20 @@ import com.fr.general.ImageWithSuffix; import com.fr.general.act.TitlePacker; import com.fr.stable.Constants; -import javax.swing.*; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.basic.BasicButtonUI; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -42,8 +50,8 @@ import java.awt.geom.RoundRectangle2D; * @version 10.0.18 * Created by Starryi on 2021/7/3 */ -public class TitleInsetImagePane extends JPanel implements UIObserver { - private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH; +public class TextInsetImageBackgroundSpecialPane extends JPanel implements UIObserver { + private final int SETTING_LABEL_WIDTH = 60; private final int DELETE_BUTTON_SIZE = 24; private final int IMAGE_PREVIEW_SIZE = 145; private final Color IMAGE_PREVIEW_OVERLAY_COLOR = new Color(255, 255, 255, 51); @@ -62,7 +70,7 @@ public class TitleInsetImagePane extends JPanel implements UIObserver { private ImageFileChooser imageFileChooser; - public TitleInsetImagePane() { + public TextInsetImageBackgroundSpecialPane() { this.initComponents(); this.initLayout(); } @@ -198,7 +206,7 @@ public class TitleInsetImagePane extends JPanel implements UIObserver { com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Right_Tooltip"), }); - imagePaddingPane = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, WidgetTitle.DEFAULT_INSET_PADDING); + imagePaddingPane = new UISpinner(0, Integer.MAX_VALUE, 1, WidgetTitle.DEFAULT_INSET_PADDING); imagePaddingPane.setValue(DEFAULT_INSET_PADDING); } diff --git a/designer-base/src/main/java/com/fr/design/gui/style/TitleTranslucentBackgroundSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/TitleTranslucentBackgroundSpecialPane.java new file mode 100644 index 0000000000..db8c64e19c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/TitleTranslucentBackgroundSpecialPane.java @@ -0,0 +1,27 @@ +package com.fr.design.gui.style; + +import com.fr.general.act.TitlePacker; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class TitleTranslucentBackgroundSpecialPane extends AbstractTranslucentBackgroundSpecialPane { + + public TitleTranslucentBackgroundSpecialPane(int uiLabelWidth, int uiSettingWidth) { + super(uiLabelWidth, uiSettingWidth, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background")); + } + + @Override + public void populateBean(TitlePacker style) { + backgroundPane.populateBean(style.getBackground()); + opacityPane.populateBean(style.getBackgroundOpacity()); + } + + @Override + public void updateBean(TitlePacker style) { + style.setBackground(backgroundPane.update()); + style.setBackgroundOpacity((float)opacityPane.updateBean()); + } +} diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java b/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java similarity index 96% rename from designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java rename to designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java index 47ea7fb0de..20e47f556c 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java @@ -1,8 +1,6 @@ -package com.fr.design.gui.xpane; +package com.fr.design.gui.style; -import com.fr.base.GraphHelper; import com.fr.base.Style; -import com.fr.base.Utils; import com.fr.base.background.ImageBackground; import com.fr.base.background.ImageFileBackground; import com.fr.design.border.UIRoundedBorder; @@ -16,8 +14,6 @@ import com.fr.design.event.UIObserverListener; import com.fr.design.gui.frpane.ImgChooseWrapper; import com.fr.design.gui.frpane.UIPercentDragPane; 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.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; @@ -28,10 +24,10 @@ import com.fr.design.mainframe.backgroundpane.ImagePreviewPane; import com.fr.design.style.background.image.ImageFileChooser; import com.fr.design.style.color.NewColorSelectBox; import com.fr.env.utils.DesignerInteractionHistory; -import com.fr.form.ui.LayoutBorderStyle; import com.fr.general.Background; import com.fr.general.IOUtils; import com.fr.i18n.UrlI18nManager; +import com.fr.general.act.BorderPacker; import com.fr.stable.Constants; import com.fr.stable.GraphDrawHelper; import com.fr.stable.ProjectLibrary; @@ -79,8 +75,8 @@ import java.util.Arrays; * * 可配置图片类型边框的样式设置面板 */ -public class BorderLineAndImagePane extends JPanel implements UIObserver { - private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH; +public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane implements UIObserver { + private final int SETTING_LABEL_WIDTH = 60; private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); private final String TWEAK_NINE_POINT_HELP_URL = "https://help.fanruan.com/finereport/doc-view-4135.html"; @@ -99,7 +95,7 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private int[] ninePoint = new int[] {-1, -1, -1, -1}; - public BorderLineAndImagePane(boolean supportBorderImage) { + public TranslucentBorderSpecialPane(boolean supportBorderImage) { this.initComponents(supportBorderImage); this.initLayout(); } @@ -274,7 +270,7 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { if (imagePreviewPane.getImage() != null) { tweakPane.previewPane.setNinePoint(ninePoint); - BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(BorderLineAndImagePane.this)); + BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(TranslucentBorderSpecialPane.this)); dialog.addDialogActionListener(new DialogActionAdapter() { @Override public void doOk() { @@ -288,7 +284,13 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { }); } - public void populateBean(LayoutBorderStyle style) { + @Override + protected String title4PopupWindow() { + return null; + } + + @Override + public void populateBean(BorderPacker style) { int borderLine = style.getBorder(); Color borderColor = style.getColor(); @@ -335,7 +337,8 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { this.borderColorPane.setSelectObject(style.getColor()); } - public void updateBean(LayoutBorderStyle style) { + @Override + public void updateBean(BorderPacker style) { style.setBorder(this.borderLineCombo.getSelectedLineStyle()); style.setColor(this.borderColorPane.getSelectObject()); @@ -368,24 +371,6 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { return true; } - protected UIButtonUI createButtonUI(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); - } - }; - } - protected static class BorderLineAndImageComboBox extends LineComboBox { public static final int LINE_PICTURE = -1; public final static int[] BORDER_LINE_AND_IMAGE_STYLE_ARRAY = new int[] { diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/ContentSettingPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/ContentSettingPane.java new file mode 100644 index 0000000000..848ac9e57c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/ContentSettingPane.java @@ -0,0 +1,328 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.base.BaseFormula; +import com.fr.base.BaseUtils; +import com.fr.base.Parameter; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.TinyFormulaPane; +import com.fr.design.gui.frpane.ReportletParameterViewPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itree.filetree.ReportletPane; +import com.fr.design.hyperlink.AbstractHyperLinkPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.module.DesignModuleFactory; +import com.fr.design.parameter.ParameterReader; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.js.MobilePopupHyperlink; +import com.fr.stable.CommonUtils; +import com.fr.stable.FormulaProvider; +import com.fr.stable.ParameterProvider; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +public class ContentSettingPane extends AbstractHyperLinkPane { + private JPanel popupTargetPane; + private UIRadioButton templatePopupButton; + private UIRadioButton textPopupButton; + private ButtonGroup popupTargetButtons; + + private JPanel templateContentPane; + private UITextField templatePathTextField; + private UICheckBox extendParametersCheckBox; + + private JPanel textSettingPanel; + private TinyFormulaPane textContentPane; + private CustomFontPane fontPane; + + public ContentSettingPane() { + super(); + this.initCompoennt(); + } + + public void addTargetRadioActionListener(ActionListener listener) { + templatePopupButton.addActionListener(listener); + textPopupButton.addActionListener(listener); + } + + public String getTargetType() { + if (templatePopupButton.isSelected()) { + return MobilePopupConstants.Target_Template; + } else { + return MobilePopupConstants.Target_Text; + } + + } + + private void initCompoennt() { + this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); + this.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Content"))); + + popupTargetPane = this.createPopupTargetPane(); + this.add(popupTargetPane, BorderLayout.NORTH); + + templateContentPane= this.createTemplateContentPane(); + textSettingPanel = this.createTextSettingPane(); + } + + private JPanel createPopupTargetPane() { + templatePopupButton = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Template")); + templatePopupButton.addActionListener(radioActionListener); + + textPopupButton = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Text")); + textPopupButton.addActionListener(radioActionListener); + + popupTargetButtons = new ButtonGroup(); + popupTargetButtons.add(templatePopupButton); + popupTargetButtons.add(textPopupButton); + + JPanel popupButtonsPanel = new JPanel(); + popupButtonsPanel.setLayout( new FlowLayout(FlowLayout.LEFT, 10, 0)); + popupButtonsPanel.add(templatePopupButton); + popupButtonsPanel.add(textPopupButton); + return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Target"), popupButtonsPanel); + } + + private ActionListener radioActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if(templatePopupButton.isSelected()) { + ContentSettingPane.this.add(templateContentPane); + ContentSettingPane.this.remove(textSettingPanel); + } else if (textPopupButton.isSelected()) { + ContentSettingPane.this.add(textSettingPanel); + ContentSettingPane.this.remove(templateContentPane); + } + ContentSettingPane.this.revalidate(); + ContentSettingPane.this.repaint(); + } + }; + + private JPanel createTemplateContentPane() { + JPanel templateContentPane = new JPanel(); + templateContentPane.setLayout(new BorderLayout(0,8)); + + templateContentPane.add(this.createTemplateSelectPanel(), BorderLayout.NORTH); + + parameterViewPane = this.createReportletParameterViewPane(); + templateContentPane.add(parameterViewPane, BorderLayout.CENTER); + + extendParametersCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Extends_Report_Parameters")); + templateContentPane.add(GUICoreUtils.createFlowPane(extendParametersCheckBox, FlowLayout.LEFT), BorderLayout.SOUTH); + + return templateContentPane; + } + + private JPanel createTemplateSelectPanel() { + JPanel templatePanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + // 路径输入框 + templatePathTextField = new UITextField(20); + templatePanel.add(templatePathTextField, BorderLayout.CENTER); + + // 选择路径按钮 + UIButton templateSelectButton = new UIButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Select")); + templateSelectButton.setPreferredSize(new Dimension(templateSelectButton.getPreferredSize().width, 20)); + templatePanel.add(templateSelectButton, BorderLayout.EAST); + templateSelectButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + final ReportletPane reportletPane = new ReportletPane(); + reportletPane.setSelectedReportletPath(templatePathTextField.getText()); + BasicDialog reportletDialog = reportletPane.showWindow(SwingUtilities.getWindowAncestor(ContentSettingPane.this)); + + reportletDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + templatePathTextField.setText(reportletPane.getSelectedReportletPath()); + } + }); + reportletDialog.setVisible(true); + } + }); + return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Template"), templatePanel); + } + + private ReportletParameterViewPane createReportletParameterViewPane() { + ReportletParameterViewPane templateParameterViewPane = new ReportletParameterViewPane( + new UITableEditAction[]{ + new HyperlinkParametersAction() + }, + getChartParaType(), + getValueEditorPane(), + getValueEditorPane() + ); + templateParameterViewPane.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Parameter"), null)); + templateParameterViewPane.setPreferredSize(new Dimension(this.getWidth(), 200)); + return templateParameterViewPane; + } + + private JPanel createTextSettingPane() { + JPanel textSettingPanel = new JPanel(); + textSettingPanel.setLayout(new BorderLayout(0,8)); + + textContentPane = new TinyFormulaPane(); + textContentPane.getUITextField().setColumns(20); + textSettingPanel.add( + MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Text"), textContentPane), + BorderLayout.CENTER); + + fontPane = new CustomFontPane(); + textSettingPanel.add( + MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Style"), fontPane), + BorderLayout.SOUTH); + return MobilePopupUIUtils.createTitleSplitLineContentPane("", textSettingPanel); + } + + private String getReportletName() { + String text = this.templatePathTextField.getText(); + return StringUtils.isBlank(text) ? StringUtils.EMPTY : text.substring(1); + } + + @Override + public void populateBean(MobilePopupHyperlink link) { + this.populatePopupTargetBean(link.getPopupTarget()); + this.populateTemplateContentBean(link); + this.populateTextContentBean(link); + + } + + @Override + public MobilePopupHyperlink updateBean() { + return null; + } + + @Override + public void updateBean(MobilePopupHyperlink link) { + this.updatePopupTargetBean(link); + this.updateTemplateContentBean(link); + this.updateTextContentBean(link); + } + + @Override + public String title4PopupWindow() { + return StringUtils.EMPTY; + } + + /** + * 自动添加模板参数的按钮操作 + */ + private class HyperlinkParametersAction extends UITableEditAction { + public HyperlinkParametersAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Template_Parameter")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/p.gif")); + } + + @Override + public void actionPerformed(ActionEvent e) { + String tpl = getReportletName(); + if (StringUtils.isBlank(tpl)) { + JOptionPane.showMessageDialog( + ContentSettingPane.this, + Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Please_Select_Reportlet") + ".", + Toolkit.i18nText("Fine-Design_Basic_Message"), + JOptionPane.WARNING_MESSAGE); + return; + } + + //根据模板路径返回参数 + //与当前模块、当前文件无关 + Parameter[] parameters = new Parameter[0]; + + ParameterReader[] readers = DesignModuleFactory.getParameterReaders(); + for (ParameterReader reader : readers) { + Parameter[] ps = reader.readParameterFromPath(tpl); + if (ps != null) { + parameters = ps; + } + } + parameterViewPane.populate(parameters); + } + + @Override + public void checkEnabled() { + //do nothing + } + } + + private void populatePopupTargetBean(String target) { + if (StringUtils.equals(target, MobilePopupConstants.Target_Text)) { + popupTargetButtons.setSelected(textPopupButton.getModel(), true); + this.remove(templateContentPane); + this.add(textSettingPanel, BorderLayout.CENTER); + } else { + popupTargetButtons.setSelected(templatePopupButton.getModel(), true); + this.remove(textSettingPanel); + this.add(templateContentPane, BorderLayout.CENTER); + } + + } + + private void updatePopupTargetBean(MobilePopupHyperlink mobilePopupHyperlink) { + if (templatePopupButton.isSelected()) { + mobilePopupHyperlink.setPopupTarget(MobilePopupConstants.Target_Template); + } else if (textPopupButton.isSelected()) { + mobilePopupHyperlink.setPopupTarget(MobilePopupConstants.Target_Text); + } + } + + private void populateTemplateContentBean(MobilePopupHyperlink link) { + // 模板路径 + templatePathTextField.setText(link.getReportletPath()); + + // 参数面板 + List parameterList = this.parameterViewPane.update(); + parameterList.clear(); + ParameterProvider[] parameters =link.getParameters(); + parameterViewPane.populate(parameters); + + // 继承参数 + extendParametersCheckBox.setSelected(link.isExtendParameters()); + } + + private void updateTemplateContentBean(MobilePopupHyperlink link) { + link.setReportletPath(templatePathTextField.getText()); + + List parameterList = this.parameterViewPane.update(); + if (!parameterList.isEmpty()) { + Parameter[] parameters = new Parameter[parameterList.size()]; + parameterList.toArray(parameters); + link.setParameters(parameters); + } else { + link.setParameters(null); + } + + link.setExtendParameters(extendParametersCheckBox.isSelected()); + + } + + private void populateTextContentBean(MobilePopupHyperlink link) { + Object text = link.getPopupText(); + if (text instanceof FormulaProvider) { + textContentPane.populateBean(((FormulaProvider) text).getContent()); + } else { + textContentPane.populateBean(text == null ? StringUtils.EMPTY : text.toString()); + } + fontPane.populateBean(link.getFRFont()); + } + private void updateTextContentBean(MobilePopupHyperlink link) { + link.setPopupText(textContentPane.getUITextField().getText()); + String text = textContentPane.updateBean(); + if (CommonUtils.maybeFormula(text)) { + link.setPopupText(BaseFormula.createFormulaBuilder().build(textContentPane.updateBean())); + } else { + link.setPopupText(text); + } + + link.setFRFont(fontPane.updateBean()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/CustomFontPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/CustomFontPane.java new file mode 100644 index 0000000000..aa3e3f8680 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/CustomFontPane.java @@ -0,0 +1,100 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.LayoutConstants; +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.i18n.Toolkit; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.*; +import java.awt.*; +import java.util.Vector; + +public class CustomFontPane extends JPanel { + private static final int MAX_FONT_SIZE = 100; + private static final Dimension BUTTON_SIZE = new Dimension(20, 18); + + public static Vector getFontSizes() { + Vector FONT_SIZES = new Vector(); + for (int i = 1; i < MAX_FONT_SIZE; i++) { + FONT_SIZES.add(i); + } + return FONT_SIZES; + } + + private UIComboBox fontSizeComboBox; + private UIToggleButton bold; + private UIToggleButton italic; + private UIToggleButton underline; + private UIColorButton colorSelectPane; + + public CustomFontPane() { + this.initComponent(); + } + + private void initComponent() { + + fontSizeComboBox = new UIComboBox(getFontSizes()); + fontSizeComboBox.setPreferredSize(new Dimension(60, 20)); + fontSizeComboBox.setEditable(true); + + 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")); + + this.setButtonsTips(); + this.setButtonsSize(BUTTON_SIZE); + + Component[] components_font = new Component[]{ + fontSizeComboBox, colorSelectPane, bold, underline, italic + }; + + JPanel buttonPane = new JPanel(new BorderLayout()); + buttonPane.add(GUICoreUtils.createFlowPane(components_font, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL)); + + this.setLayout(new BorderLayout(0,0)); + this.add(buttonPane, BorderLayout.CENTER); + } + + private void setButtonsTips() { + colorSelectPane.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Foreground")); + italic.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Italic")); + bold.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Bold")); + underline.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Underline")); + } + + private void setButtonsSize(Dimension size) { + colorSelectPane.setPreferredSize(size); + bold.setPreferredSize(size); + italic.setPreferredSize(size); + underline.setPreferredSize(size); + } + + + public void populateBean(FRFont frFont) { + fontSizeComboBox.setSelectedItem(frFont.getSize()); + colorSelectPane.setColor(frFont.getForeground()); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + underline.setSelected(frFont.getUnderline() != Constants.LINE_NONE); + } + + public FRFont updateBean() { + int style = Font.PLAIN; + style += this.bold.isSelected() ? Font.BOLD : Font.PLAIN; + style += this.italic.isSelected() ? Font.ITALIC : Font.PLAIN; + return FRFont.getInstance( + FRFont.DEFAULT_FONTNAME, + style, + Float.parseFloat(fontSizeComboBox.getSelectedItem().toString()), + colorSelectPane.getColor(), + underline.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE + ); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupConstants.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupConstants.java new file mode 100644 index 0000000000..d4423d6795 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupConstants.java @@ -0,0 +1,22 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.stable.Constants; + +public interface MobilePopupConstants { + int[] BORDER_LINE_STYLE_ARRAY = new int[]{ + Constants.LINE_NONE, + Constants.LINE_THIN, + Constants.LINE_MEDIUM, + Constants.LINE_THICK, + }; + + String Target_Template= "template"; + String Target_Text = "text"; + String Regular_Custom = "custom"; + String Regular_Auto_Height = "auto_height"; + + double Popup_Center_Default_Width = 95; + double Popup_Center_Default_Height = 95; + double Popup_Follow_Default_Width = 40; + double Popup_Follow_Default_Height = 10; +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupPane.java new file mode 100644 index 0000000000..f4389d9539 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupPane.java @@ -0,0 +1,81 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.i18n.Toolkit; +import com.fr.js.MobilePopupHyperlink; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MobilePopupPane extends FurtherBasicBeanPane { + private ContentSettingPane contentSettingPane; + private StyleSettingPane styleSettingPane; + + public MobilePopupPane() { + this.initComponents(); + this.setDefaultBean(); + } + + protected void initComponents() { + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + + JPanel scrollContent = new JPanel(); + scrollContent.setLayout(new BorderLayout(10, 10)); + contentSettingPane = new ContentSettingPane(); + scrollContent.add(contentSettingPane, BorderLayout.NORTH); + styleSettingPane = new StyleSettingPane(); + scrollContent.add(styleSettingPane, BorderLayout.CENTER); + + contentSettingPane.addTargetRadioActionListener(radioActionListener); + + UIScrollPane scrollPane= new UIScrollPane(scrollContent); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + + JComponent scrollComponent = new JLayer(scrollPane, new WheelScrollLayerUI()); + + this.add(scrollComponent, BorderLayout.CENTER); + } + + private void setDefaultBean() { + this.populateBean(new MobilePopupHyperlink()); + } + private ActionListener radioActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + styleSettingPane.resetPane(contentSettingPane.getTargetType()); + } + }; + + @Override + public void populateBean(MobilePopupHyperlink mobilePopupHyperlink) { + contentSettingPane.populateBean(mobilePopupHyperlink); + styleSettingPane.populateBean(mobilePopupHyperlink); + } + + @Override + public MobilePopupHyperlink updateBean() { + MobilePopupHyperlink mobilePopupHyperlink = new MobilePopupHyperlink(); + contentSettingPane.updateBean(mobilePopupHyperlink); + styleSettingPane.updateBean(mobilePopupHyperlink); + return mobilePopupHyperlink; + } + + @Override + public boolean accept(Object ob) { + return ob instanceof MobilePopupHyperlink; + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup"); + } + + @Override + public void reset() { + this.setDefaultBean(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupRegularPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupRegularPane.java new file mode 100644 index 0000000000..65e5085d15 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupRegularPane.java @@ -0,0 +1,157 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIRadioButton; +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.VerticalFlowLayout; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MobilePopupRegularPane extends BasicPane { + private String label; + + private JPanel radiosPane; + private UIRadioButton customRadio; + private UIRadioButton autoRadio; + private ButtonGroup radioButtons; + + private JPanel spinnerGroupPane; + private UISpinner widthSpinner; + private JPanel widthSpinnerPane; + private UISpinner heightSpinner; + private JPanel heightSpinnerPane; + + + public MobilePopupRegularPane(String label) { + this.label = label; + this.initComponent(); + } + + private void initComponent() { + this.setLayout(new BorderLayout()); + this.add(this.createRadioButtonGroupPane(), BorderLayout.NORTH); + spinnerGroupPane = this.createSpinnerPane(); + this.add(spinnerGroupPane, BorderLayout.CENTER); + } + + private JPanel createRadioButtonGroupPane() { + radiosPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); + + customRadio = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Custom")); + customRadio.addActionListener(radioActionListener); + autoRadio = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Height_Adaptive")); + autoRadio.addActionListener(radioActionListener); + + radioButtons = new ButtonGroup(); + radioButtons.add(customRadio); + radioButtons.add(autoRadio); + + radiosPane.add(customRadio); + radiosPane.add(autoRadio); + + return MobilePopupUIUtils.createLeftTileRightContentPanel(this.label, radiosPane); + } + + private ActionListener radioActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + resetSpinnerGroupPane(customRadio.isSelected()); + } + }; + + private JPanel createSpinnerPane() { + JPanel spinnerPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 15, 5)); + spinnerPane.setBorder(BorderFactory.createEmptyBorder(0, MobilePopupUIUtils.Left_Title_width, 0, 0)); + widthSpinner = new UISpinner(0, 100, 1, 95); + widthSpinnerPane = this.createSpinnerLabelPane(widthSpinner, Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Width")); + heightSpinner = new UISpinner(0, 100, 1, 95); + heightSpinnerPane = this.createSpinnerLabelPane(heightSpinner, Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Height")); + + spinnerPane.add(widthSpinnerPane); + spinnerPane.add(heightSpinnerPane); + + return spinnerPane; + } + + private JPanel createSpinnerLabelPane(UISpinner spinner, String labelText) { + JPanel spinnerLabelPane = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 5)); + + JPanel spinnerPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 2,0)); + Dimension dimension = new Dimension(60, 20); + spinner.setPreferredSize(dimension); + UILabel percent = new UILabel("%"); + spinnerPane.add(spinner); + spinnerPane.add(percent); + + UILabel label = new UILabel(labelText); + label.setPreferredSize(dimension); + label.setHorizontalAlignment(SwingConstants.CENTER); + + spinnerLabelPane.add(spinnerPane); + spinnerLabelPane.add(label); + + return spinnerLabelPane; + } + + private void resetSpinnerGroupPane(boolean showHeightSpinnerPane) { + spinnerGroupPane.removeAll(); + spinnerGroupPane.add(widthSpinnerPane); + if(showHeightSpinnerPane) { + spinnerGroupPane.add(heightSpinnerPane); + } + spinnerGroupPane.revalidate(); + spinnerGroupPane.repaint(); + } + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + + public void setRegularType(String regularType) { + if (StringUtils.equals(regularType, MobilePopupConstants.Regular_Auto_Height)) { + radioButtons.setSelected(autoRadio.getModel(), true); + } else { + radioButtons.setSelected(customRadio.getModel(), true); + } + resetSpinnerGroupPane(customRadio.isSelected()); + } + + public String getRegularType() { + if (autoRadio.isSelected()) { + return MobilePopupConstants.Regular_Auto_Height; + } else { + return MobilePopupConstants.Regular_Custom; + } + } + + public void setWidthSpinnerValue(double width) { + widthSpinner.setValue(width); + } + + public double getWidthSpinnerValue() { + return widthSpinner.getValue(); + } + + public void setHeightSpinnerValue(double height) { + heightSpinner.setValue(height); + } + + public double getHeightSpinnerValue() { + return heightSpinner.getValue(); + } + + public void resetPane(String regularType, double width, double height) { + this.setRegularType(regularType); + this.setWidthSpinnerValue(width); + this.setHeightSpinnerValue(height); + resetSpinnerGroupPane(StringUtils.equals(regularType, MobilePopupConstants.Regular_Custom)); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupUIUtils.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupUIUtils.java new file mode 100644 index 0000000000..cb3fbad58e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupUIUtils.java @@ -0,0 +1,36 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.widget.UITitleSplitLine; + +import javax.swing.*; +import java.awt.*; + +public class MobilePopupUIUtils { + static public int Line_Height = 20; + static public int SplitLineWidth = 520; + static public int Left_Title_width = 80; + + static public JPanel createLeftTileRightContentPanel(String title, JComponent contentPanel) { + JPanel jp = new JPanel(); + jp.setBorder(BorderFactory.createEmptyBorder(0,0,0, 30)); + jp.setLayout(new BorderLayout(10,0)); + UILabel titleLabel = new UILabel(title + ":"); + titleLabel.setPreferredSize(new Dimension(MobilePopupUIUtils.Left_Title_width, Line_Height)); + titleLabel.setHorizontalAlignment(SwingConstants.RIGHT); + jp.add(titleLabel, BorderLayout.WEST); + jp.add(contentPanel, BorderLayout.CENTER); + return jp; + } + + static public JPanel createTitleSplitLineContentPane(String title, JComponent contentPanel) { + JPanel jp = new JPanel(); + jp.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + jp.setLayout(new BorderLayout(0, 10)); + UITitleSplitLine titleLine = new UITitleSplitLine(title, SplitLineWidth); + titleLine.setPreferredSize(new Dimension(SplitLineWidth, Line_Height)); + jp.add(titleLine, BorderLayout.NORTH); + jp.add(contentPanel, BorderLayout.CENTER); + return jp; + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/StyleSettingPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/StyleSettingPane.java new file mode 100644 index 0000000000..1bebe3dfc8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/StyleSettingPane.java @@ -0,0 +1,205 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.frpane.UINumberDragPane; +import com.fr.design.gui.icombobox.LineComboBox; +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.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.js.MobilePopupHyperlink; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; + +public class StyleSettingPane extends BasicBeanPane { + private double maxNumber = 100; + private double maxBorderRadius = 24; + + JPanel typePane; + UILabel popupTypeLabel; + + JPanel stylePane; + LineComboBox borderType; + NewColorSelectBox borderColor; + UISpinner borderRadiusSpinner; + + NewColorSelectBox bgColor; + //透明度 + UINumberDragPane numberDragPane; + + MobilePopupRegularPane mobileRegularPane; + MobilePopupRegularPane padRegularPane; + + public StyleSettingPane() { + this.initComponent(); + } + + private void initComponent() { + this.setLayout(new BorderLayout(0, 10)); + this.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Style"))); + + typePane = this.createTypePane(); + this.add(typePane, BorderLayout.NORTH); + stylePane = this.createStylePane(); + this.add(stylePane, BorderLayout.CENTER); + } + + private JPanel createTypePane() { + JPanel typePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + popupTypeLabel = new UILabel(""); + typePane.add(popupTypeLabel, BorderLayout.CENTER); + return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Type"), typePane); + } + + private JPanel createStylePane() { + JPanel stylePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + stylePane.add(this.createBorderSettingPane(), BorderLayout.NORTH); + stylePane.add(this.createBackgroundSettingPane(), BorderLayout.CENTER); + stylePane.add(this.createPopupSizePane(), BorderLayout.SOUTH); + return stylePane; + } + + private JPanel createBorderSettingPane() { + JPanel borderPane = new JPanel(); + VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 10); + layout.setAlignLeft(true); + borderPane.setLayout(layout); + + borderType = new LineComboBox(MobilePopupConstants.BORDER_LINE_STYLE_ARRAY); + borderType.setPreferredSize(new Dimension(115, 20)); + borderPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Line"), borderType)); + borderColor = new NewColorSelectBox(100); + borderPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Colors"), borderColor)); + borderRadiusSpinner = new UISpinner(0, maxBorderRadius, 1, 20); + borderRadiusSpinner.setPreferredSize(new Dimension(120, 20)); + borderPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Radius"), borderRadiusSpinner)); + return MobilePopupUIUtils.createTitleSplitLineContentPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Border"), borderPane); + } + + private JPanel createBackgroundSettingPane() { + JPanel bgPane = new JPanel(); + VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 10); + layout.setAlignLeft(true); + bgPane.setLayout(layout); + + JPanel colorPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0)); + bgColor = new NewColorSelectBox(100); + colorPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Colors"), bgColor)); + bgPane.add(colorPane); + + JPanel transparencyPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.numberDragPane = new UINumberDragPane(0,100); + this.numberDragPane.setPreferredSize(new Dimension(140, 20)); + transparencyPane.add(numberDragPane, BorderLayout.CENTER); + transparencyPane.add(new UILabel(" %"), BorderLayout.EAST); + bgPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Opacity"), transparencyPane)); + return MobilePopupUIUtils.createTitleSplitLineContentPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Background"), bgPane); + } + + private JPanel createPopupSizePane() { + JPanel sizePane = new JPanel(new BorderLayout()); + + mobileRegularPane = new MobilePopupRegularPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Mobile_Rules")); + padRegularPane = new MobilePopupRegularPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Pad_Rules")); + + sizePane.add(mobileRegularPane, BorderLayout.NORTH); + sizePane.add(padRegularPane, BorderLayout.CENTER); + + return MobilePopupUIUtils.createTitleSplitLineContentPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Size"), sizePane); + } + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + + public void resetPane(String popupTargetType) { + if (StringUtils.equals(popupTargetType, MobilePopupConstants.Target_Template)) { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Center")); + mobileRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Center_Default_Width, MobilePopupConstants.Popup_Center_Default_Height); + padRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Center_Default_Width, MobilePopupConstants.Popup_Center_Default_Height); + } else { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Follow")); + mobileRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Follow_Default_Width, MobilePopupConstants.Popup_Follow_Default_Height); + padRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Follow_Default_Width, MobilePopupConstants.Popup_Follow_Default_Height); + } + + } + + @Override + public void populateBean(MobilePopupHyperlink link) { + this.populateTypeBean(link); + this.populateBorderSettingBean(link); + this.populateBackgroundSettingBean(link); + this.populatePopupSizeBean(link); + } + + @Override + public MobilePopupHyperlink updateBean() { + return null; + } + + @Override + public void updateBean(MobilePopupHyperlink link) { + this.updateBorderSettingBean(link); + this.updateBackgroundSettingBean(link); + this.updatePopupSizeBean(link); + + } + + private void populateTypeBean(MobilePopupHyperlink link) { + if (StringUtils.equals(link.getPopupTarget(), MobilePopupConstants.Target_Text)) { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Follow")); + } else { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Center")); + } + } + + private void populateBorderSettingBean(MobilePopupHyperlink link) { + borderType.setSelectedLineStyle(link.getBorderType()); + borderColor.setSelectObject(link.getBorderColor()); + borderRadiusSpinner.setValue(link.getBorderRadius()); + + } + + private void updateBorderSettingBean(MobilePopupHyperlink link) { + link.setBorderType(borderType.getSelectedLineStyle()); + link.setBorderColor(borderColor.getSelectObject()); + link.setBorderRadius(borderRadiusSpinner.getValue()); + + } + + private void populateBackgroundSettingBean(MobilePopupHyperlink link) { + bgColor.setSelectObject(link.getBgColor()); + numberDragPane.populateBean(link.getBgOpacity() * maxNumber); + } + + private void updateBackgroundSettingBean(MobilePopupHyperlink link) { + link.setBgColor(bgColor.getSelectObject()); + link.setBgOpacity((float)(numberDragPane.updateBean() / maxNumber)); + } + + private void populatePopupSizeBean(MobilePopupHyperlink link) { + mobileRegularPane.setRegularType(link.getMobileRegularType()); + mobileRegularPane.setWidthSpinnerValue(link.getMobileWidth()); + mobileRegularPane.setHeightSpinnerValue(link.getMobileHeight()); + padRegularPane.setRegularType(link.getPadRegularType()); + padRegularPane.setWidthSpinnerValue(link.getPadWidth()); + padRegularPane.setHeightSpinnerValue(link.getPadHeight()); + + } + + private void updatePopupSizeBean(MobilePopupHyperlink link) { + link.setMobileRegularType(mobileRegularPane.getRegularType()); + link.setMobileWidth(mobileRegularPane.getWidthSpinnerValue()); + link.setMobileHeight(mobileRegularPane.getHeightSpinnerValue()); + link.setPadRegularType(padRegularPane.getRegularType()); + link.setPadWidth(padRegularPane.getWidthSpinnerValue()); + link.setPadHeight(padRegularPane.getHeightSpinnerValue()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/WheelScrollLayerUI.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/WheelScrollLayerUI.java new file mode 100644 index 0000000000..8ab06766db --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/WheelScrollLayerUI.java @@ -0,0 +1,42 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.gui.icontainer.UIScrollPane; + +import javax.swing.*; +import javax.swing.plaf.LayerUI; +import java.awt.*; +import java.awt.event.MouseWheelEvent; + +class WheelScrollLayerUI extends LayerUI { + @Override + public void installUI(JComponent c) { + super.installUI(c); + if (c instanceof JLayer) { + ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + } + } + @Override + public void uninstallUI(JComponent c) { + if (c instanceof JLayer) { + ((JLayer) c).setLayerEventMask(0); + } + super.uninstallUI(c); + } + @Override + protected void processMouseWheelEvent(MouseWheelEvent e, JLayer l) { + Component c = e.getComponent(); + int dir = e.getWheelRotation(); + JScrollPane main = l.getView(); + if (c instanceof JScrollPane && !c.equals(main)) { + JScrollPane child = (JScrollPane) c; + BoundedRangeModel m = child.getVerticalScrollBar().getModel(); + int extent = m.getExtent(); + int minimum = m.getMinimum(); + int maximum = m.getMaximum(); + int value = m.getValue(); + if (value + extent >= maximum && dir > 0 || value <= minimum && dir < 0) { + main.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, main)); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/icon/LocalFileIcon.java b/designer-base/src/main/java/com/fr/design/icon/LocalFileIcon.java new file mode 100644 index 0000000000..e80af21c6a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/icon/LocalFileIcon.java @@ -0,0 +1,42 @@ +package com.fr.design.icon; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.itree.filetree.FileTreeIcon; + +import javax.swing.Icon; +import java.awt.Component; +import java.awt.Graphics; + +/** + * Created by kerry on 2021/11/11 + */ +public class LocalFileIcon implements Icon { + private static final Icon FILE_LOCKED_ICON = BaseUtils.readIcon(FileTreeIcon.FILE_LOCKED_ICON_PATH); + private static final int OFFSET_X = 9; + private static final int OFFSET_Y = 8; + private final Icon mainIcon; + private final boolean showLock; + + public LocalFileIcon(Icon mainIcon, boolean showLock) { + this.mainIcon = mainIcon; + this.showLock = showLock; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + mainIcon.paintIcon(c, g, x, y); + if (showLock) { + FILE_LOCKED_ICON.paintIcon(c, g, OFFSET_X, OFFSET_Y); + } + } + + @Override + public int getIconWidth() { + return mainIcon.getIconWidth(); + } + + @Override + public int getIconHeight() { + return mainIcon.getIconHeight(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/icon/LockIcon.java b/designer-base/src/main/java/com/fr/design/icon/LockIcon.java index 7ebffbdb79..e7c4000205 100644 --- a/designer-base/src/main/java/com/fr/design/icon/LockIcon.java +++ b/designer-base/src/main/java/com/fr/design/icon/LockIcon.java @@ -1,6 +1,7 @@ package com.fr.design.icon; import com.fr.base.BaseUtils; +import com.fr.design.gui.itree.filetree.FileTreeIcon; import com.fr.log.FineLoggerFactory; import javax.swing.GrayFilter; @@ -12,7 +13,7 @@ import java.awt.MediaTracker; import java.awt.image.ImageObserver; public class LockIcon extends ImageIcon { - private final static Image lockImage = BaseUtils.readImage("/com/fr/design/images/gui/locked.gif"); + private final static Image lockImage = BaseUtils.readImage(FileTreeIcon.FILE_LOCKED_ICON_PATH); private Image mainImage = null; @@ -107,4 +108,4 @@ public class LockIcon extends ImageIcon { { loadImage(lockImage); } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java b/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java index 460e838c51..6c2e46e985 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java @@ -3,6 +3,7 @@ package com.fr.design.javascript; import com.fr.base.BaseFormula; import com.fr.base.Parameter; import com.fr.base.extension.FileExtension; +import com.fr.design.border.UITitledBorder; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; @@ -15,6 +16,10 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIComboBoxRenderer; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.gui.itableeditorpane.UITableModelAdapter; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.design.hyperlink.AbstractHyperLinkPane; @@ -23,32 +28,40 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.DesignerContext; -import com.fr.design.scrollruler.ModLineBorder; import com.fr.file.filetree.IOFileNodeFilter; import com.fr.general.GeneralUtils; import com.fr.js.ExportJavaScript; +import com.fr.js.SingleJavaScript; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; import javax.swing.AbstractButton; +import javax.swing.AbstractCellEditor; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.DefaultComboBoxModel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JTable; import javax.swing.SwingUtilities; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; 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.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -59,21 +72,20 @@ public class ExportJavaScriptPane extends AbstractHyperLinkPane EXPORT_TYPES_MAP = new HashMap<>(); - private static final String CURRENT_TEMPLATE = "current"; - private static final String DEFAULT_FILENAME = "default"; - + private static final Map FILENAME_TYPE_MAP = new HashMap<>(); + private static final Map PARAMETER_TYPE_MAP = new HashMap<>(); + private static final String DEFAULT = "default"; + private static final String CUSTOM = "custom"; + private static final String CURRENT_TEMPLATE = "cur"; + private static final String OTHER_TEMPLATE = "other"; + private static final UILabel EMPTY_LABEL = new UILabel(); static { EXPORT_TYPES_MAP.put(ExportJavaScript.EXPORT_PDF, Toolkit.i18nText("Fine-Design_Basic_Export_JS_PDF")); @@ -82,135 +94,703 @@ public class ExportJavaScriptPane extends AbstractHyperLinkPane" + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Title_Tip_Front") + "\\/:*?\"<>|" + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Title_Tip_Back") + ""); + fileNameTipLabel.setVisible(false); + fileNameRadioGroup.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (defaultNameRadio.isSelected()) { + fileNameFormulaEditor.setVisible(false); + fileNameFormulaEditor.setEnabled(false); + fileNameTipLabel.setVisible(false); + } else { + fileNameFormulaEditor.setVisible(true); + fileNameFormulaEditor.setEnabled(true); + fileNameTipLabel.setVisible(true); + } + } + }); + Component[][] components = new Component[][]{{nameLabel, defaultNameRadio, customNameRadio, fileNameFormulaEditor}}; + JPanel fileNameRadioPane = TableLayoutHelper.createTableLayoutPane(components, new double[]{p}, new double[]{p, p, p, p}); + + JPanel fileNameTipPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + fileNameTipPane.add(fileNameTipLabel); + + JPanel fileNamePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + fileNamePane.add(fileNameRadioPane, BorderLayout.NORTH); + fileNamePane.add(fileNameTipPane, BorderLayout.CENTER); + fileNameTipPane.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2)); + fileNamePane.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2)); + return fileNamePane; + } + public void updateSingleJavaScript(SingleJavaScript js){ + js.setTemplatePath(DEFAULT); + js.setExportType(GeneralUtils.objectToString(exportTypeComboBox.getSelectedItem())); + js.setDefaultFileName(defaultNameRadio.isSelected()); + js.setFileName(getFileName()); + js.setExtendParameters(extendParametersCheckBox.isSelected()); + if (extendParametersCheckBox.isSelected()) { + js.setParameters(null); + } else { + if (parameterViewPane != null) { + List parameterList = parameterViewPane.update(); + if (!parameterList.isEmpty()) { + Parameter[] parameters = new Parameter[parameterList.size()]; + parameterList.toArray(parameters); + js.setParameters(parameters); + } + } + } + } + public void populateSingleJavaScript(SingleJavaScript js){ + exportTypeComboBox.setSelectedItem(js.getExportType()); + fileNameRadioGroup.selectIndexButton(js.isDefaultFileName() ? 0 : 1); + if (!js.isDefaultFileName()) { + fileNameFormulaEditor.setEnabled(true); + fileNameFormulaEditor.setVisible(true); + fileNameTipLabel.setVisible(true); + fileNameFormulaEditor.setValue(BaseFormula.createFormulaBuilder().build(js.getFileName())); + } else { + fileNameFormulaEditor.setVisible(false); + fileNameFormulaEditor.setValue(BaseFormula.createFormulaBuilder().build()); + } + if (js.isExtendParameters()) { + extendParametersCheckBox.setSelected(true); + } else { + extendParametersCheckBox.setSelected(false); + if (this.parameterViewPane != null) { + List parameterList = this.parameterViewPane.update(); + parameterList.clear(); + ParameterProvider[] parameters = js.getParameters(); + this.parameterViewPane.populate(parameters); + } + } + } + private JPanel initExportTypePane() { + UILabel typeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Type") + ":"); + exportTypeComboBox = getComboBoxWithModel(new String[]{ExportJavaScript.EXPORT_PDF, ExportJavaScript.EXPORT_EXCEL_PAGE, ExportJavaScript.EXPORT_EXCEL_SIMPLE, ExportJavaScript.EXPORT_EXCEL_SHEET, ExportJavaScript.EXPORT_WORD, ExportJavaScript.EXPORT_IMAGE} + , EXPORT_TYPES_MAP); + Component[][] components = new Component[][]{{typeLabel, exportTypeComboBox}}; + + JPanel exportTypePane = TableLayoutHelper.createTableLayoutPane(components, new double[]{p}, new double[]{p, p}); + exportTypePane.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2)); + return exportTypePane; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Export_JS_Setting"); + } + } - private void initComponents() { - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - this.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), Toolkit.i18nText("Fine-Design_Basic_Export_JS_Setting"))); + // 其他模板 + class OtherTemplatePane extends BasicPane { - //导出模板+导出方式+导出文件名 - JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + private UITableEditorPane editorPane; - //导出模板 - JPanel chooseTemplatePane = initChooseTemplatePane(); - northPane.add(chooseTemplatePane, BorderLayout.NORTH); + public OtherTemplatePane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Template_Other"))); - //导出方式 - JPanel exportTypePane = initExportTypePane(); - northPane.add(exportTypePane, BorderLayout.CENTER); + editorPane = new UITableEditorPane<>(new ExportJSTableModel()); + editorPane.setHeaderResizing(false); - //导出文件名 - JPanel fileNamePane = initFileNamePane(); - northPane.add(fileNamePane, BorderLayout.SOUTH); + this.add(editorPane, BorderLayout.CENTER); + } - //参数 - JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JPanel paramsPane = initParamsPane(); - centerPane.add(paramsPane); + public void reset() { + editorPane.populate(new SingleJavaScript[0]); + } + public void updateExportJavaScript(ExportJavaScript exportJavaScript){ + List javaScripts = editorPane.update(); + for (SingleJavaScript js : javaScripts) { + exportJavaScript.addOtherTemplateJS(js); + } + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Export_JS_Setting"); + } - this.add(northPane, BorderLayout.NORTH); - this.add(centerPane, BorderLayout.CENTER); } - private JPanel initParamsPane() { - extendParametersCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Extends_Report_Parameters")); - extendParametersCheckBox.setSelected(true); - parameterViewPane = new ReportletParameterViewPane(getChartParaType(), getValueEditorPane(), getValueEditorPane()); - parameterViewPane.setVisible(false); - parameterViewPane.addTableEditorListener(new TableModelListener() { - public void tableChanged(TableModelEvent e) { - List list = parameterViewPane.update(); - HashSet tempSet = new HashSet<>(); - for (int i = 0; i < list.size(); i++) { - if (StringUtils.isEmpty(list.get(i).getName())) { - continue; + class ExportJSTableModel extends UITableModelAdapter { + + private static final long serialVersionUID = -3697206557955735642L; + + public ExportJSTableModel() { + super(new String[]{ + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Template_File"), + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Type"), + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Filename"), + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Filename_Custom"), + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Parameters_Setting"), + StringUtils.EMPTY}); + this.setColumnClass(new Class[]{ + ExportTemplateChooser.class, + ExportTypeCombobox.class, + FileNameCombobox.class, + FileNameFormulaEditor.class, + ParameterCombobox.class, + ParameterSettingButton.class + }); + this.setDefaultEditor(ExportTemplateChooser.class, new ExportTemplateChooser()); + this.setDefaultRenderer(ExportTemplateChooser.class, new ExportTemplateChooser()); + this.setDefaultEditor(ExportTypeCombobox.class, new ExportTypeCombobox()); + this.setDefaultEditor(FileNameCombobox.class, new FileNameCombobox()); + this.setDefaultEditor(FileNameFormulaEditor.class, new FileNameFormulaEditor()); + this.setDefaultEditor(ParameterCombobox.class, new ParameterCombobox()); + this.setDefaultEditor(ParameterSettingButton.class, new ParameterSettingButton()); + this.setDefaultRenderer(ParameterSettingButton.class, new ParameterSettingButton()); + this.createTable().getColumnModel().getColumn(2).setMaxWidth(60); + this.createTable().getColumnModel().getColumn(4).setMaxWidth(60); + this.createTable().getColumnModel().getColumn(5).setMaxWidth(50); + } + + @Override + public UITableEditAction[] createAction() { + return new UITableEditAction[]{new AddJSAction(), new DeleteAction()}; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + SingleJavaScript js = this.getList().get(rowIndex); + switch (columnIndex) { + case 0: + return js.getTemplatePath(); + case 1: + return EXPORT_TYPES_MAP.get(js.getExportType()); + case 2: + return js.isDefaultFileName() ? Toolkit.i18nText("Fine-Design_Basic_Export_JS_Filename_Default") : Toolkit.i18nText("Fine-Design_Basic_Export_JS_Custom"); + case 3: + return js.getFileName(); + case 4: + return js.isExtendParameters() ? Toolkit.i18nText("Fine-Design_Basic_Export_JS_Extend_Parameters") : Toolkit.i18nText("Fine-Design_Basic_Export_JS_Custom"); + case 5: + return js.getParameters(); + } + return null; + } + + @Override + public boolean isCellEditable(int row, int col) { + if (col == 3) { + // 命名详情 + return this.getList().get(row) != null && !this.getList().get(row).isDefaultFileName(); + } + return true; + } + + private class AddJSAction extends AddTableRowAction { + + public AddJSAction() { + + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + if (otherTemplatePane.editorPane.getTableModel().getList().size() <= 50) { + addJS(); + } else { + FineJOptionPane.showMessageDialog(otherTemplatePane, Toolkit.i18nText("Fine-Design_Basic_Export_JS_Batch_Export_Limit")); + } + } + } + + private void addJS() { + SingleJavaScript js = new SingleJavaScript(); + addRow(js); + fireTableDataChanged(); + table.getSelectionModel().setSelectionInterval(table.getRowCount() - 1, table.getRowCount() - 1); + } + + // 导出文件选择 + class ExportTemplateChooser extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { + + private static final long serialVersionUID = -9112506131272704717L; + private JPanel reportletNamePane; + private UITextField reportPathTextField; + private UIButton browserButton; + + public ExportTemplateChooser() { + // 路径输入框 + reportPathTextField = new UITextField(8); + reportPathTextField.setEnabled(false); + + // 选择路径按钮 + browserButton = new UIButton("..."); + browserButton.setVisible(true); + + Component[][] templateChooserComponent = {{reportPathTextField, browserButton}}; + double[] rowSize = {TableLayout.PREFERRED}; + double[] columnSize = {TableLayout.FILL, 22}; + reportletNamePane = TableLayoutHelper.createCommonTableLayoutPane(templateChooserComponent, rowSize, columnSize, 0); + + browserButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + final ReportletPane reportletPane = new ReportletPane(); + reportletPane.setSelectedReportletPath(reportPathTextField.getText()); + BasicDialog reportletDialog = reportletPane.showWindow(SwingUtilities.getWindowAncestor(ExportJavaScriptPane.this)); + + reportletDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + reportPathTextField.setText(reportletPane.getSelectedReportletPath()); + } + }); + reportletDialog.setVisible(true); } - if (tempSet.contains(list.get(i).toString())) { - list.remove(i); - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Parameter_Duplicate_Name") + "!"); - return; + }); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + } - tempSet.add(list.get(i).toString()); + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1) { + return; + } + SingleJavaScript js = getList().get(table.getSelectedRow()); + String value = StringUtils.trimToNull(reportPathTextField.getText()); + js.setTemplatePath(value); + js.setCurrentTemplate(false); + fireTableDataChanged(); + } + }); + + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + reportPathTextField.setText((String) value); + return reportletNamePane; + } + + @Override + public Object getCellEditorValue() { + return reportPathTextField.getText(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + reportPathTextField.setText((String) value); + return reportletNamePane; + } + } + + // 导出方式下拉框 + class ExportTypeCombobox extends AbstractCellEditor implements TableCellEditor { + + private static final long serialVersionUID = -6564079764032351372L; + + private UIComboBox exportTypeComboBox; + + public ExportTypeCombobox() { + exportTypeComboBox = getComboBoxWithModel(new String[]{ExportJavaScript.EXPORT_PDF, ExportJavaScript.EXPORT_EXCEL_PAGE, ExportJavaScript.EXPORT_EXCEL_SIMPLE, ExportJavaScript.EXPORT_EXCEL_SHEET, ExportJavaScript.EXPORT_WORD, ExportJavaScript.EXPORT_IMAGE} + , EXPORT_TYPES_MAP); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1) { + return; + } + SingleJavaScript js = getList().get(table.getSelectedRow()); + Object ob = exportTypeComboBox.getSelectedItem(); + if (ob != null) { + String value = ob.toString(); + js.setExportType(value); + } + fireTableDataChanged(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + exportTypeComboBox.setSelectedItem(getList().get(row).getExportType()); + return exportTypeComboBox; + } + + @Override + public Object getCellEditorValue() { + Object ob = exportTypeComboBox.getSelectedItem(); + if (ob != null) { + return ob.toString(); } + return ExportJavaScript.EXPORT_PDF; } - }); - extendParametersCheckBox.addItemListener(new ItemListener() { + } + + // 命名方式下拉框 + class FileNameCombobox extends AbstractCellEditor implements TableCellEditor { + + private static final long serialVersionUID = 1829005772744444269L; + private UIComboBox fileNameComboBox; + + public FileNameCombobox() { + fileNameComboBox = getComboBoxWithModel(new String[]{DEFAULT, CUSTOM}, FILENAME_TYPE_MAP); + fileNameComboBox.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + final int row = table.getSelectedRow(); + if (row == -1) { + return; + } + SingleJavaScript js = getList().get(row); + Object ob = fileNameComboBox.getSelectedItem(); + if (ob != null) { + String value = ob.toString(); + js.setDefaultFileName(StringUtils.equals(value, DEFAULT)); + if (js.isDefaultFileName()) { + js.setFileName(StringUtils.EMPTY); + } + } + table.repaint(); + } + }); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + fireTableDataChanged(); + } + }); + } + @Override - public void itemStateChanged(ItemEvent e) { - parameterViewPane.setVisible(e.getStateChange() == ItemEvent.DESELECTED); + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + fileNameComboBox.setSelectedItem(getList().get(row).isDefaultFileName() ? DEFAULT : CUSTOM); + return fileNameComboBox; } - }); - JPanel paramsPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - paramsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), Toolkit.i18nText("Fine-Design_Basic_Parameters"))); - paramsPane.add(extendParametersCheckBox, BorderLayout.NORTH); - JPanel dynamicPaneWrapper = FRGUIPaneFactory.createBorderLayout_S_Pane(); - dynamicPaneWrapper.add(parameterViewPane); - paramsPane.add(dynamicPaneWrapper, BorderLayout.CENTER); - return paramsPane; - } - private JPanel initFileNamePane() { - UILabel nameLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Filename") + ":"); - fileNameRadioGroup = new ExportRadioGroup(); - defaultNameRadio = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Filename_Default")); - defaultNameRadio.setSelected(true); - customNameRadio = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Filename_Custom")); - addRadioToGroup(fileNameRadioGroup, defaultNameRadio, customNameRadio); - fileNameFormulaEditor = new FormulaEditor(Toolkit.i18nText("Fine-Design_Report_Parameter_Formula")); - fileNameFormulaEditor.setEnabled(false); - fileNameRadioGroup.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { - if (defaultNameRadio.isSelected()) { - fileNameFormulaEditor.setEnabled(false); + public Object getCellEditorValue() { + return fileNameComboBox.getSelectedItem().toString(); + } + } + + // 命名方式公式框 + class FileNameFormulaEditor extends AbstractCellEditor implements TableCellEditor { + + private static final long serialVersionUID = 7120075192535645493L; + private FormulaEditor fileNameFormulaEditor; + + public FileNameFormulaEditor() { + fileNameFormulaEditor = new FormulaEditor(Toolkit.i18nText("Fine-Design_Report_Parameter_Formula")); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1) { + return; + } + SingleJavaScript js = getList().get(table.getSelectedRow()); + String value = fileNameFormulaEditor.getUITextField().getText(); + js.setFileName(value); + fireTableDataChanged(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (value != null) { + fileNameFormulaEditor.setValue(BaseFormula.createFormulaBuilder().build(value)); } else { - fileNameFormulaEditor.setEnabled(true); + fileNameFormulaEditor.setValue(BaseFormula.createFormulaBuilder().build()); } + return fileNameFormulaEditor; + } + + @Override + public Object getCellEditorValue() { + return fileNameFormulaEditor.getUITextField().getText(); + } + + public FormulaEditor getFileNameEditor() { + return fileNameFormulaEditor; + } + } + + //参数设置下拉框 + class ParameterCombobox extends AbstractCellEditor implements TableCellEditor { + + private static final long serialVersionUID = 2630964402770993584L; + private UIComboBox parameterSetting; + + public ParameterCombobox() { + parameterSetting = getComboBoxWithModel(new String[]{DEFAULT, CUSTOM}, PARAMETER_TYPE_MAP); + parameterSetting.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + final int row = table.getSelectedRow(); + if (row == -1) { + return; + } + SingleJavaScript js = getList().get(row); + Object ob = parameterSetting.getSelectedItem(); + if (ob != null) { + String value = ob.toString(); + js.setExtendParameters(StringUtils.equals(value, DEFAULT)); + } + // 单纯为了刷新表格,使某些联动生效 + table.repaint(); + } + }); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + // 这里重新触发是为了触发某些编辑后事件 + fireTableDataChanged(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + parameterSetting.setSelectedItem(getList().get(row).isExtendParameters() ? DEFAULT : CUSTOM); + return parameterSetting; } - }); - Component[][] components = new Component[][]{{nameLabel, defaultNameRadio, customNameRadio, fileNameFormulaEditor}}; - JPanel fileNameRadioPane = TableLayoutHelper.createTableLayoutPane(components, new double[]{p}, new double[]{p, p, p, p}); - - JPanel fileNameTipPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - UILabel fileNameTipLabel = new UILabel("" + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Title_Tip_Front") + "\\/:*?\"<>|" + Toolkit.i18nText("Fine-Design_Basic_Export_JS_Title_Tip_Back") + ""); - fileNameTipPane.add(fileNameTipLabel); - - JPanel fileNamePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - fileNamePane.add(fileNameRadioPane, BorderLayout.NORTH); - fileNamePane.add(fileNameTipPane, BorderLayout.CENTER); - fileNameTipPane.setBorder(BorderFactory.createEmptyBorder(5,2,5,2)); - fileNamePane.setBorder(BorderFactory.createEmptyBorder(5,2,5,2)); - return fileNamePane; - } - private JPanel initExportTypePane() { - UILabel typeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Type") + ":"); - exportTypeComboBox = new UIComboBox(new DefaultComboBoxModel()); - DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel) exportTypeComboBox.getModel(); - String[] allExportTypes = new String[]{ExportJavaScript.EXPORT_PDF, ExportJavaScript.EXPORT_EXCEL_PAGE, ExportJavaScript.EXPORT_EXCEL_SIMPLE, ExportJavaScript.EXPORT_EXCEL_SHEET, ExportJavaScript.EXPORT_WORD, ExportJavaScript.EXPORT_IMAGE}; - for (int i = 0; i < allExportTypes.length; i++) { - comboBoxModel.addElement(allExportTypes[i]); + @Override + public Object getCellEditorValue() { + return parameterSetting.getSelectedItem().toString(); + } } - this.exportTypeComboBox.setRenderer(new UIComboBoxRenderer() { + + // 参数设置按钮 + class ParameterSettingButton extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { + + private static final long serialVersionUID = 4021592871993049137L; + private UIButton paraButton; + private ParameterSettingPane paraSettingPane; + ParameterProvider[] parameterArr; + + public ParameterSettingButton() { + paraSettingPane = new ParameterSettingPane(); + paraButton = new UIButton(Toolkit.i18nText("Fine-Design_Report_Set")); + paraButton.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + BasicDialog dialog = paraSettingPane.showWindow(SwingUtilities.getWindowAncestor(ExportJavaScriptPane.this)); + dialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + List parameterList = paraSettingPane.getParameterList(); + parameterArr = parameterList.toArray(new Parameter[parameterList.size()]); + } + }); + dialog.setVisible(true); + } + + }); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1) { + return; + } + SingleJavaScript js = getList().get(table.getSelectedRow()); + if (parameterArr != null) { + js.setParameters(parameterArr); + } + parameterArr = null; + fireTableDataChanged(); + } + }); + + } @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (value instanceof String) { - this.setText(EXPORT_TYPES_MAP.get(value)); + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (getList().get(row) == null || getList().get(row).isExtendParameters()) { + return EMPTY_LABEL; } - return this; + ParameterProvider[] providers = (ParameterProvider[]) value; + if (providers != null) { + paraSettingPane.refresh(new ArrayList<>(Arrays.asList(providers))); + } + return paraButton; + } + + @Override + public Object getCellEditorValue() { + return paraSettingPane.getParameterList(); } - }); - Component[][] components = new Component[][]{{typeLabel, exportTypeComboBox}}; - JPanel exportTypePane = TableLayoutHelper.createTableLayoutPane(components, new double[]{p}, new double[]{p, p}); - exportTypePane.setBorder(BorderFactory.createEmptyBorder(5,2,5,2)); - return exportTypePane; + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (getList().get(row) == null || getList().get(row).isExtendParameters()) { + return EMPTY_LABEL; + } + return paraButton; + } + } + + // 参数设置弹出框 + class ParameterSettingPane extends BasicPane { + + private ReportletParameterViewPane parameterViewPane; + + public ParameterSettingPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + parameterViewPane = new ReportletParameterViewPane(ParameterTableModel.NO_CHART_USE, getValueEditorPane(), getValueEditorPane()); + addListener(parameterViewPane); + this.add(parameterViewPane); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Export_JS_Parameters_Setting"); + } + + public List getParameterList() { + return parameterViewPane.update(); + } + + public void refresh(List list) { + parameterViewPane.update(list); + } + + } + + } + + public ExportJavaScriptPane() { + initComponents(); + } + + private void initComponents() { + JPanel totalPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + totalPanel.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Export_JS_Setting"))); + + // 导出模板 + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel chooseTemplatePane = initChooseTemplatePane(); + northPane.add(chooseTemplatePane, BorderLayout.NORTH); + + // 默认当前模板 + currentTemplatePane = new CurrentTemplatePane(); + otherTemplatePane = new OtherTemplatePane(); + templatePanel = FRGUIPaneFactory.createCardLayout_S_Pane(); + card = new CardLayout(); + templatePanel.setLayout(card); + templatePanel.add(CURRENT_TEMPLATE, currentTemplatePane); + templatePanel.add(OTHER_TEMPLATE, otherTemplatePane); + + totalPanel.add(northPane, BorderLayout.NORTH); + totalPanel.add(templatePanel, BorderLayout.CENTER); + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(totalPanel); } private JPanel initChooseTemplatePane() { @@ -220,51 +800,28 @@ public class ExportJavaScriptPane extends AbstractHyperLinkPane parameterList = this.parameterViewPane.update(); - parameterList.clear(); - ParameterProvider[] parameters = ob.getParameters(); - this.parameterViewPane.populate(parameters); - } + currentTemplatePane.populateSingleJavaScript(ob.getCurrentTemplateJavaScript()); + + OtherTemplatePane pane = (OtherTemplatePane) this.templatePanel.getComponent(1); + pane.editorPane.populate(ob.getJsListForOtherTemplates().toArray(new SingleJavaScript[ob.getJsListForOtherTemplates().size()])); } @Override @@ -309,32 +848,59 @@ public class ExportJavaScriptPane extends AbstractHyperLinkPane parameterList = this.parameterViewPane.update(); - if (!parameterList.isEmpty()) { - Parameter[] parameters = new Parameter[parameterList.size()]; - parameterList.toArray(parameters); - exportJavaScript.setParameters(parameters); - } - } - } + boolean selected = currentTemplateRadio.isSelected(); + exportJavaScript.setCurrentTemplate(selected); + SingleJavaScript js = new SingleJavaScript(); + js.setCurrentTemplate(selected); + currentTemplatePane.updateSingleJavaScript(js); + exportJavaScript.addCurrentTemplateJS(js); - private String getTemplatePath() { - return currentTemplateRadio.isSelected() ? CURRENT_TEMPLATE : reportPathTextField.getText(); + otherTemplatePane.updateExportJavaScript(exportJavaScript); } private String getFileName() { - return defaultNameRadio.isSelected() ? DEFAULT_FILENAME : fileNameFormulaEditor.getUITextField().getText(); + return currentTemplatePane.defaultNameRadio.isSelected() ? DEFAULT : currentTemplatePane.fileNameFormulaEditor.getUITextField().getText(); } + private UIComboBox getComboBoxWithModel(String[] itemTextArr, Map itemTextDic) { + UIComboBox comboBox = new UIComboBox(new DefaultComboBoxModel()); + DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel) comboBox.getModel(); + for (int i = 0; i < itemTextArr.length; i++) { + comboBoxModel.addElement(itemTextArr[i]); + } + comboBox.setRenderer(new UIComboBoxRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof String) { + this.setText(itemTextDic.get(value)); + } + return this; + } + }); + return comboBox; + } + + private void addListener(ReportletParameterViewPane paraPane) { + paraPane.addTableEditorListener(new TableModelListener() { + public void tableChanged(TableModelEvent e) { + List list = paraPane.update(); + HashSet tempSet = new HashSet<>(); + for (int i = 0; i < list.size(); i++) { + if (StringUtils.isEmpty(list.get(i).getName())) { + continue; + } + if (tempSet.contains(list.get(i).toString())) { + list.remove(i); + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Parameter_Duplicate_Name") + "!"); + return; + } + tempSet.add(list.get(i).toString()); + } + } + }); + } @Override public boolean accept(Object ob) { diff --git a/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java b/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java index 89c9741eb2..999a1a0295 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java @@ -7,6 +7,7 @@ import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.fun.JavaScriptActionProvider; import com.fr.design.gui.frpane.UIComboBoxPane; import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.hyperlink.popup.MobilePopupPane; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.write.submit.DBManipulationPane; @@ -51,6 +52,7 @@ public abstract class JavaScriptActionPane extends UIComboBoxPane { if (workbook) { paneList.add(new ExportJavaScriptPane()); } + paneList.add(new MobilePopupPane()); Set javaScriptActionProviders = ExtraDesignClassManager.getInstance().getArray(JavaScriptActionProvider.XML_TAG); if (javaScriptActionProviders != null) { for (JavaScriptActionProvider jsp : javaScriptActionProviders) { diff --git a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java index da0a2131c6..071feee6ac 100644 --- a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java +++ b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java @@ -2,11 +2,12 @@ package com.fr.design.layout; import com.fr.design.border.UITitledBorder; import com.fr.design.gui.ilable.UILabel; - import com.fr.stable.AssistUtils; + import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.Icon; +import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JRadioButton; import java.awt.BorderLayout; @@ -46,6 +47,16 @@ public class FRGUIPaneFactory { return new FlowLayout(FlowLayout.LEFT, 0, 0); } + /** + * 创建一个靠左的布局,上下间隔为0,左右间隔为常量,首间隔为0 + * + * @return FlowLayout对象 + */ + public static LayoutManager createLeftZeroVgapNormalHgapLayout() { + return new FRLeftFlowLayout(0, 5, 0); + } + + /** * 创建一个靠右的布局 * @@ -581,6 +592,15 @@ public class FRGUIPaneFactory { return jp; } + public static JPanel createBorderLayout_NO_Opaque_Pane() { + JPanel jp = new JPanel(); + jp.setOpaque(false); + jp.setBackground(null); + jp.setLayout(FRGUIPaneFactory.createBorderLayout()); + return jp; + } + + /** * 创建卡片式布局 * @@ -612,6 +632,12 @@ public class FRGUIPaneFactory { return iconRadioPane; } + public static JPanel createBorderLayoutNorthPaneWithComponent(JComponent content) { + JPanel jPanel = new JPanel(new BorderLayout()); + jPanel.add(content, BorderLayout.NORTH); + return jPanel; + } + /** * 计算宽度 * diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/DoubleSplashMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/DoubleSplashMark.java new file mode 100644 index 0000000000..78ee72b508 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/locale/impl/DoubleSplashMark.java @@ -0,0 +1,33 @@ +package com.fr.design.locale.impl; + +import com.fr.design.DesignerEnvManager; +import com.fr.general.locale.LocaleMark; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/9/2 + */ +public class DoubleSplashMark implements LocaleMark { + + private final Map map = new HashMap(); + private static final String SPLASH_PATH_X2 = "/com/fr/design/images/splash@2x.png"; + private static final String SPLASH_PATH_EN_X2 = "/com/fr/design/images/splash_en@2x.png"; + + public DoubleSplashMark() { + map.put(Locale.CHINA, SPLASH_PATH_X2); + map.put(Locale.KOREA, SPLASH_PATH_EN_X2); + map.put(Locale.JAPAN, SPLASH_PATH_EN_X2); + map.put(Locale.US, SPLASH_PATH_EN_X2); + map.put(Locale.TAIWAN, SPLASH_PATH_EN_X2); + } + + @Override + public String getValue() { + String result = map.get(DesignerEnvManager.getEnvManager().getLanguage()); + return result == null ? SPLASH_PATH_EN_X2 : result; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/ShowOnlineWidgetMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/ShowOnlineWidgetMark.java new file mode 100644 index 0000000000..024f991ae5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/locale/impl/ShowOnlineWidgetMark.java @@ -0,0 +1,26 @@ +package com.fr.design.locale.impl; + +import com.fr.general.GeneralContext; +import com.fr.general.locale.LocaleMark; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +public class ShowOnlineWidgetMark implements LocaleMark { + private Map map = new HashMap<>(); + + public ShowOnlineWidgetMark() { + map.put(Locale.CHINA, true); + map.put(Locale.TAIWAN, true); + map.put(Locale.US, false); + map.put(Locale.KOREA, false); + map.put(Locale.JAPAN, false); + } + + @Override + public Boolean getValue() { + Boolean result = map.get(GeneralContext.getLocale()); + return result == null ? false : result; + } +} diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java index 8cf75c0587..93995eeddc 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java @@ -15,8 +15,8 @@ import java.util.Map; public class SplashMark implements LocaleMark { private Map map = new HashMap(); - private static final String SPLASH_PATH = "/com/fr/design/images/splash_10.png"; - private static final String SPLASH_EN_PATH = "/com/fr/design/images/splash_10_en.png"; + private static final String SPLASH_PATH = "/com/fr/design/images/splash.png"; + private static final String SPLASH_EN_PATH = "/com/fr/design/images/splash_en.png"; public SplashMark() { map.put(Locale.CHINA, SPLASH_PATH); diff --git a/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java b/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java new file mode 100644 index 0000000000..a0fd544d53 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java @@ -0,0 +1,122 @@ +package com.fr.design.lock; + +import com.fr.design.file.TemplateTreePane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.DesignSizeI18nManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.utils.TemplateUtils; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.IOUtils; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.workspace.base.UserInfo; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/12/2 + */ +public class LockInfoDialog extends JDialog { + + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); + + public LockInfoDialog(UserInfo userInfo) { + super(DesignerContext.getDesignerFrame()); + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + panel.add(createContentPane(userInfo), BorderLayout.CENTER); + panel.add(createControlPane(), BorderLayout.SOUTH); + this.getContentPane().add(panel); + this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Title_Hint")); + this.setSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.lock.LockInfoDialog")); + this.setResizable(false); + this.setModal(true); + GUICoreUtils.centerWindow(this); + this.setVisible(true); + } + + private JPanel createContentPane(UserInfo userInfo) { + JPanel contentPanel = new JPanel(new BorderLayout()); + contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + JPanel messagePane = new JPanel(new BorderLayout(13, 0)); + UILabel iconLabel = new UILabel(IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png")); + iconLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + messagePane.add(iconLabel, BorderLayout.WEST); + UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Template_Lock_And_SaveAs_Tip")); + tipLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + messagePane.add(tipLabel, BorderLayout.CENTER); + contentPanel.add(messagePane, BorderLayout.NORTH); + JPanel detailInfoPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + detailInfoPane.setBorder(BorderFactory.createEmptyBorder(0, 45, 0,0)); + if (userInfo != null && StringUtils.isNotEmpty(userInfo.getUserName())) { + UILabel label = createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Holder", userInfo.getUserName())); + label .setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + detailInfoPane.add(label); + } + if (userInfo != null && StringUtils.isNotEmpty(userInfo.getIp())) { + detailInfoPane.add(createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Holder_Ip", userInfo.getIp()) )); + } + detailInfoPane.add(createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Get_Time", FORMATTER.format(LocalDateTime.now())))); + contentPanel.add(detailInfoPane, BorderLayout.CENTER); + return contentPanel; + } + + private UILabel createLabel(String text) { + UILabel label = new UILabel(text); + label.setForeground(Color.GRAY); + label.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0)); + return label; + } + + private JPanel createControlPane() { + JPanel controlPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5)); + controlPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0,5)); + UIButton saveAsButton = new UIButton(Toolkit.i18nText("Fine_Design_Template_Lock_Save_As")); + UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")); + saveAsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + FileNode node = TemplateTreePane.getInstance().getFileNode(); + if (node == null) { + return; + } + final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getFilePath()); + TemplateUtils.createAndOpenTemplate(Toolkit.i18nText("Fine_Design_Template_Lock_Copy"), new FileNodeFILE(new FileNode(selectedFilePath, false)), true); + } + }); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + controlPane.add(saveAsButton); + controlPane.add(cancelButton); + return controlPane; + } + + + public static void show(UserInfo userInfo) { + DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode()); + new LockInfoDialog(userInfo); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/lock/LockInfoUtils.java b/designer-base/src/main/java/com/fr/design/lock/LockInfoUtils.java new file mode 100644 index 0000000000..52a2c526c7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/lock/LockInfoUtils.java @@ -0,0 +1,23 @@ +package com.fr.design.lock; + +import com.fr.report.lock.DefaultLockInfoOperator; +import com.fr.report.lock.LockInfoOperator; +import com.fr.start.server.FineEmbedServer; +import com.fr.workspace.WorkContext; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/12/8 + */ +public class LockInfoUtils { + + public static boolean isCompatibleOperator() { + LockInfoOperator lockInfoOperator = WorkContext.getCurrent().get(LockInfoOperator.class); + return lockInfoOperator instanceof DefaultLockInfoOperator; + } + + public static boolean unableGetLockInfo() { + return WorkContext.getCurrent().isLocal() && !FineEmbedServer.isRunning(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java index 36507cf37d..d31b5ede09 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java @@ -19,10 +19,14 @@ import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.border.MatteBorder; import java.awt.BorderLayout; +import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Insets; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + /** * @author shine @@ -96,7 +100,7 @@ public class CenterRegionContainerPane extends JPanel { } - private ToolBarMenuDock getToolBarMenuDock() { + public ToolBarMenuDock getToolBarMenuDock() { return DesignerContext.getDesignerFrame().getToolBarMenuDock(); } @@ -267,12 +271,13 @@ public class CenterRegionContainerPane extends JPanel { return centerTemplateCardPane; } - protected void refreshUIToolBar() { + public Map getToolbarComponentState() { + Map toolbarComponentState = new HashMap<>(); if (toolbarComponent instanceof UIToolbar) { - ((UIToolbar ) toolbarComponent).refreshUIToolBar(); + toolbarComponentState.putAll(((UIToolbar) toolbarComponent).getComponentState()); } - combineUp.refreshUIToolBar(); - getToolBarMenuDock().updateEnable(); + toolbarComponentState.putAll(combineUp.getComponentState()); + return toolbarComponentState; } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/ComponentReuseNotifyUtil.java b/designer-base/src/main/java/com/fr/design/mainframe/ComponentReuseNotifyUtil.java index 2175804dcf..2dc77bb62c 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/ComponentReuseNotifyUtil.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/ComponentReuseNotifyUtil.java @@ -12,7 +12,7 @@ import com.fr.design.notification.SnapChatKey; * Created by kerry on 5/8/21 */ public class ComponentReuseNotifyUtil { - private static final String COMPONENT_SNAP_CHAT_KEY = "com.fr.component.share-components"; + public static final String COMPONENT_SNAP_CHAT_KEY = "com.fr.component.share-components"; private ComponentReuseNotifyUtil() { 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 798441c536..be841f79a3 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 @@ -35,8 +35,11 @@ import com.fr.design.menu.ShortCut; import com.fr.design.os.impl.MacOsAddListenerAction; import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.design.utils.TemplateUtils; +import com.fr.design.lock.LockInfoDialog; import com.fr.event.EventDispatcher; import com.fr.exception.DecryptTemplateException; +import com.fr.exception.TplLockedException; import com.fr.exit.DesignerExiter; import com.fr.file.FILE; import com.fr.file.FILEFactory; @@ -57,6 +60,7 @@ import com.fr.workspace.WorkContext; import com.fr.workspace.Workspace; import com.fr.workspace.connect.WorkspaceConnectionInfo; +import java.util.UUID; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JFrame; @@ -136,6 +140,8 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta //用于判断设计器是否打开了 private boolean designerOpened = false; + private boolean serverConfig = false; + private int contentWidth = (int) (java.awt.Toolkit.getDefaultToolkit().getScreenSize().getWidth()); private int contentHeight = (int) (java.awt.Toolkit.getDefaultToolkit().getScreenSize().getHeight()); @@ -365,14 +371,9 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta } public DesktopCardPane getCenterTemplateCardPane() { - return CenterRegionContainerPane.getInstance().getCenterTemplateCardPane(); } - public void refreshUIToolBar() { - CenterRegionContainerPane.getInstance().refreshUIToolBar(); - } - /** * 初始menuPane的方法 方便OEM时修改该组件 */ @@ -681,7 +682,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta if (!editingTemplate.getEditingFILE().exists()) { path = FILEFactory.MEM_PREFIX + path; } else if (path.startsWith(ProjectConstants.REPORTLETS_NAME)) { - path = workspace.getPath() + File.separator + path; + path = workspace.getPath() + File.separator + TemplateUtils.createLockeTemplatedName(editingTemplate, path); } defaultTitleSB.append(" ").append(path); } @@ -965,6 +966,11 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta } } catch (Throwable t) { FineLoggerFactory.getLogger().error(t.getMessage(), t); + if (t.getCause() instanceof TplLockedException) { + TemplateTreePane.getInstance().getFileNode().setLock(UUID.randomUUID().toString()); + LockInfoDialog.show(null); + return; + } addAndActivateJTemplate(); } @@ -1182,4 +1188,19 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta return designerOpened; } + /** + * 判断是否正在进行服务器配置 + * @return boolean + */ + public boolean isServerConfig() { + return serverConfig; + } + + /** + * 设置是否正在进行服务器配置 + * @param serverConfig + */ + public void setServerConfig(boolean serverConfig) { + this.serverConfig = serverConfig; + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java index a33aa91d5d..2b7a321a82 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java @@ -43,6 +43,7 @@ import com.fr.file.FileNodeFILE; import com.fr.file.filetree.FileNode; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; +import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContext; import com.fr.plugin.injectable.PluginModule; @@ -56,6 +57,7 @@ import com.fr.stable.project.ProjectConstants; import com.fr.third.org.apache.commons.io.FilenameUtils; import com.fr.workspace.WorkContext; +import com.fr.report.lock.LockInfoOperator; import javax.swing.BorderFactory; import javax.swing.JDialog; import javax.swing.JOptionPane; @@ -127,6 +129,8 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt private UIToolbar toolBar; + private UIToolbar rightToolBar; + private NewFolderAction newFolderAction = new NewFolderAction(); private RefreshTreeAction refreshTreeAction = new RefreshTreeAction(); @@ -148,7 +152,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt toolBar.setBorderPainted(true); JPanel tooBarPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); JPanel parent = new JPanel(new BorderLayout()); - parent.add(toolBar, BorderLayout.CENTER); + parent.add(createUpToolBarPane(), BorderLayout.CENTER); parent.setBorder(BorderFactory.createEmptyBorder(3, 0, 4, 0)); tooBarPane.add(parent, BorderLayout.CENTER); tooBarPane.add(new UIMenuHighLight(), BorderLayout.SOUTH); @@ -186,6 +190,56 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt selectedOperation.refresh(); } + private JPanel createUpToolBarPane() { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(toolBar, BorderLayout.CENTER); + if (WorkContext.getCurrent().isRoot()) { + rightToolBar = new UIToolbar(FlowLayout.RIGHT); + rightToolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); + rightToolBar.setBorderPainted(true); + UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine_Design_Template_Lock_Status")); + tipLabel.setForeground(Color.GRAY); + rightToolBar.add(tipLabel); + UIButton button = new UIButton(IOUtils.readIcon("/com/fr/design/images/toolbarbtn/lock.png")); + button.setRolloverIcon(IOUtils.readIcon("/com/fr/design/images/toolbarbtn/unlock.png")); + button.setBorderPainted(false); + button.setContentAreaFilled(false); + button.set4ToolbarButton(); + button.setToolTipText(Toolkit.i18nText("Fine_Design_Template_Unlock_Tip")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int option = FineJOptionPane.showOptionDialog(DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine_Design_Template_UnLock_Tip"), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE, + IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"), + new Object[] {Toolkit.i18nText("Fine_Design_Template_UnLock_I_Known"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null); + if (option == JOptionPane.YES_OPTION) { + String path = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getTemplateFileTree().getSelectedTemplatePath()); + boolean success = WorkContext.getCurrent().get(LockInfoOperator.class).unLockTpl(path); + if (success) { + FileNode fileNode = TemplateTreePane.getInstance().getFileNode(); + refreshRightToolBarBy(fileNode); + } else { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design_Template_Unlock_Failed"), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + FineLoggerFactory.getLogger().error("Unlock {} failed", path); + } + TemplateTreePane.getInstance().refresh(); + } + } + }); + rightToolBar.add(button); + refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode()); + panel.add(rightToolBar, BorderLayout.EAST); + } + return panel; + } + public final void setCurrentEditingTemplate(JTemplate jt) { DesignModelAdapter.setCurrentModelAdapter(jt.getModel()); @@ -545,6 +599,19 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } } + public void refreshRightToolBarBy(FileNode fileNode) { + if (rightToolBar != null) { + boolean locked = fileNode != null + && StringUtils.isNotEmpty(fileNode.getLock()) + && !ComparatorUtils.equals(fileNode.getLock(), fileNode.getUserID()); + boolean visible = locked + && WorkContext.getCurrent().isRoot() + && WorkContext.getCurrent().get(LockInfoOperator.class).isUnLockable() + && !WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(fileNode.getEnvPath()); + rightToolBar.setVisible(visible); + } + } + /** * 重命名对话框 * 支持快捷键Enter,ESC diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java new file mode 100644 index 0000000000..1e072d956a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java @@ -0,0 +1,104 @@ +package com.fr.design.mainframe; + +import com.fr.base.ScreenResolution; +import com.fr.design.fun.ReportLengthUNITProvider; +import com.fr.design.unit.UnitConvertUtil; +import com.fr.general.ComparatorUtils; +import com.fr.stable.Constants; + +/** + * Created by kerry on 2020-06-05 + */ +public class DesignerUIModeConfig { + private DesignerUIMode mode = DesignerUIMode.ABSOLUTE_MEASURE_UI_MODE; + + private static class DesignerUIModeConfigHolder { + private static final DesignerUIModeConfig designerUIModeConfig = new DesignerUIModeConfig(); + } + + private DesignerUIModeConfig() { + + } + + public static DesignerUIModeConfig getInstance() { + return DesignerUIModeConfigHolder.designerUIModeConfig; + } + + + /** + * 判断是否是新ui模式 + * + * @return boolean + */ + public boolean simulateWebUIMode() { + return ComparatorUtils.equals(DesignerUIMode.SIMULATE_WEB_UI_MODE, mode); + } + + /** + * 设置新ui模式 + */ + public void setSimulateWebUIMode() { + this.mode = DesignerUIMode.SIMULATE_WEB_UI_MODE; + } + + /** + * 设置老ui模式 + */ + public void setAbsoluteMeasureUIMode() { + this.mode = DesignerUIMode.ABSOLUTE_MEASURE_UI_MODE; + } + + /** + * 解析不同模式下的尺寸单位 + * + * @param unitType 尺寸类型 + * @return ReportLengthUNITProvider对象 + */ + public ReportLengthUNITProvider parseLengthUNIT(int unitType) { + return mode.parseLengthUNIT(unitType); + } + + /** + * 获取不同模式下的屏幕分辨率 + * + * @return 分辨率 + */ + public int getScreenResolution() { + return mode.getScreenResolution(); + } + + + private enum DesignerUIMode { + ABSOLUTE_MEASURE_UI_MODE { + @Override + protected ReportLengthUNITProvider parseLengthUNIT(int unitType) { + return UnitConvertUtil.parseLengthUNIT(unitType); + } + + @Override + protected int getScreenResolution() { + return ScreenResolution.getScreenResolution(); + } + + }, + SIMULATE_WEB_UI_MODE { + @Override + protected ReportLengthUNITProvider parseLengthUNIT(int unitType) { + return new PXReportLengthUNIT(); + } + + @Override + protected int getScreenResolution() { + return Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION; + } + + }; + + protected abstract ReportLengthUNITProvider parseLengthUNIT(int unitType); + + + protected abstract int getScreenResolution(); + + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java index a2c6efcb2b..9757b0f0b5 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java @@ -10,11 +10,16 @@ import com.fr.design.data.BasicTableDataTreePane; import com.fr.design.dialog.BasicPane; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.utils.LoadingUtils; import javax.swing.JComponent; import javax.swing.JLayeredPane; +import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Component; +import java.util.HashMap; +import java.util.Map; /** @@ -27,12 +32,17 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener private static final int TRANSPARENT_LAYER = 1; private static final int LOADING_LAYER = 2; private static final int FAILED_LAYER = 3; + private static final int FORBIDDEN_LAYER = 4; private static final long serialVersionUID = 1L; private JTemplate component; private TransparentPane transparentPane = new TransparentPane(); - private OpenLoadingPane loadingPane = new OpenLoadingPane(); + private JPanel loadingPane = LoadingUtils.createLoadingPane(); private OpenFailedPane failedPane = new OpenFailedPane(); + private ForbiddenPane forbiddenPane = new ForbiddenPane(); + + Map backUpToolbarComponentState = new HashMap<>(); + private JLayeredPane layeredPane = new JLayeredPane() { @Override public void doLayout() { @@ -46,6 +56,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener setLayout(new BorderLayout()); layeredPane.add(transparentPane, TRANSPARENT_LAYER); layeredPane.add(failedPane, FAILED_LAYER); + layeredPane.add(forbiddenPane, FORBIDDEN_LAYER); add(layeredPane, BorderLayout.CENTER); } @@ -87,6 +98,8 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener showOpenStatus(); } else if (jt.isOpenFailed()) { showOpenFailedCover(jt.getTemplateOpenFailedTip()); + } else if (jt.isForbidden()) { + showForbiddenStatus(); } else { hideCover(); } @@ -103,7 +116,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } private void showOpenStatus() { - DesignerContext.getDesignerFrame().refreshUIToolBar(); + forbidToolBar(); DesignerFrameFileDealerPane.getInstance().stateChange(); EastRegionContainerPane.getInstance().updateAllPropertyPane(); JComponent downPane = WestRegionContainerPane.getInstance().getDownPane(); @@ -121,9 +134,9 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } public void showCover() { + forbidToolBar(); transparentPane.start(); layeredPane.moveToFront(transparentPane); - DesignerContext.getDesignerFrame().refreshUIToolBar(); EastRegionContainerPane.getInstance().updateAllPropertyPane(); JComponent downPane = WestRegionContainerPane.getInstance().getDownPane(); if (downPane instanceof BasicTableDataTreePane) { @@ -132,7 +145,15 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } } + public void showForbiddenStatus() { + component.setVisible(false); + layeredPane.moveToFront(forbiddenPane); + forbidToolBar(); + EastRegionContainerPane.getInstance().updateAllPropertyPane(); + } + public void hideCover() { + recoverToolBar(); transparentPane.stop(); layeredPane.moveToFront(component); EastRegionContainerPane.getInstance().updateAllPropertyPane(); @@ -143,6 +164,22 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } } + private void forbidToolBar() { + CenterRegionContainerPane centerRegionContainerPane = CenterRegionContainerPane.getInstance(); + backUpToolbarComponentState = centerRegionContainerPane.getToolbarComponentState(); + for (Component component : backUpToolbarComponentState.keySet()) { + component.setEnabled(false); + } + centerRegionContainerPane.getToolBarMenuDock().updateEnable(); + } + + private void recoverToolBar() { + UIToolbar.resetComponentState(backUpToolbarComponentState); + backUpToolbarComponentState.clear(); + CenterRegionContainerPane centerRegionContainerPane = CenterRegionContainerPane.getInstance(); + centerRegionContainerPane.getToolBarMenuDock().updateEnable(); + } + protected JTemplate getSelectedJTemplate() { return component; } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java index 84993411e5..43097e3669 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java @@ -13,7 +13,6 @@ import com.fr.design.gui.ibutton.UIButtonUI; import com.fr.design.gui.icontainer.UIEastResizableContainer; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.VerticalFlowLayout; -import com.fr.design.mainframe.reuse.ReuseGuideDialog; import com.fr.design.mainframe.reuse.SnapChatKeys; import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.notification.SnapChat; @@ -292,7 +291,12 @@ public class EastRegionContainerPane extends UIEastResizableContainer { // 控件设置 PropertyItem widgetSettings = new PropertyItem(KEY_WIDGET_SETTINGS, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Component_Settings"), "widgetsettings", new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.REPORT_FLOAT, PropertyMode.FORM, PropertyMode.POLY}, - new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.FORM, PropertyMode.POLY_REPORT, PropertyMode.POLY_CHART}); + new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.FORM, PropertyMode.POLY_REPORT, PropertyMode.POLY_CHART}, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ComponentCollector.getInstance().clickComponentSetting(); + } + }); // 条件属性 PropertyItem conditionAttr = new PropertyItem(KEY_CONDITION_ATTR, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Condition_Attributes"), "conditionattr", new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.REPORT_FLOAT, PropertyMode.POLY, PropertyMode.POLY_CHART}, @@ -458,6 +462,7 @@ public class EastRegionContainerPane extends UIEastResizableContainer { for (PropertyItem item : propertyItemMap.values()) { item.onResize(); } + super.onResize(); } public EastRegionContainerPane(JPanel leftPane, JPanel rightPane) { @@ -537,9 +542,6 @@ public class EastRegionContainerPane extends UIEastResizableContainer { } public PromptWindow getWidgetLibPromptWindow() { - if (!getWidgetLibSnapChat().hasRead()) { - return new ReuseGuideDialog(DesignerContext.getDesignerFrame()); - } return null; } @@ -1004,9 +1006,10 @@ public class EastRegionContainerPane extends UIEastResizableContainer { button.addActionListener(actionListener); } button.setToolTipText(title); + button.setName(name); } - public void processSnapChat(){ + public void processSnapChat() { if (snapChat != null && !snapChat.hasRead()) { snapChat.markRead(); if (promptWindow != null) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/ForbiddenPane.java b/designer-base/src/main/java/com/fr/design/mainframe/ForbiddenPane.java new file mode 100644 index 0000000000..9c33534c7b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/ForbiddenPane.java @@ -0,0 +1,190 @@ +package com.fr.design.mainframe; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.DesignSizeI18nManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.guide.base.GuideView; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.workspace.WorkContext; +import com.fr.report.lock.LockInfoOperator; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LayoutManager; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingWorker; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/12/6 + */ +public class ForbiddenPane extends JPanel { + + private static final ImageIcon LOCK_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/lock_template.png")); + private static final Color TIP_COLOR = new Color(108, 174, 235); + private static final Color BUTTON_COLOR = new Color(63, 155, 249); + private static final int Y_GAP = 10; + private static final int X_GAP = 10; + private static final int ARC = 4; + + private final UILabel lockLabel; + private final UILabel tipLabel; + private final JButton refreshButton; + + public ForbiddenPane() { + + setLayout(new LayoutManager() { + + @Override + public void removeLayoutComponent(Component comp) { + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return parent.getPreferredSize(); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + int width = parent.getParent().getWidth(); + int height = parent.getParent().getHeight(); + int lockLabelWidth = lockLabel.getPreferredSize().width; + int lockLabelHeight = lockLabel.getPreferredSize().height; + int lockLabelX = (width - lockLabelWidth) / 2; + int lockLabelY = (height - lockLabelHeight) / 2; + int tipLabelWidth = tipLabel.getPreferredSize().width; + int tipLabelHeight = tipLabel.getPreferredSize().height; + int tipLabelX = (width - tipLabelWidth) / 2 + X_GAP; + int tipLabelY = lockLabelY + lockLabelHeight; + int refreshButtonWidth = refreshButton.getPreferredSize().width; + int refreshButtonHeight = refreshButton.getPreferredSize().height; + int refreshButtonX = (width - refreshButtonWidth) / 2 + X_GAP; + int refreshButtonY = tipLabelY + refreshButtonHeight + Y_GAP; + lockLabel.setBounds(lockLabelX, lockLabelY, lockLabelWidth, lockLabelHeight); + tipLabel.setBounds(tipLabelX, tipLabelY, tipLabelWidth, tipLabelHeight); + refreshButton.setBounds(refreshButtonX, refreshButtonY, refreshButtonWidth, refreshButtonHeight); + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + }); + setBackground(Color.WHITE); + lockLabel = new UILabel(LOCK_ICON); + tipLabel = new UILabel(Toolkit.i18nText("Fine_Design_Template_Has_Been_Locked_Tip")); + Font labelFont = tipLabel.getFont(); + tipLabel.setFont(new Font(labelFont.getName(), labelFont.getStyle(), 14)); + tipLabel.setForeground(TIP_COLOR); + refreshButton = new JButton(Toolkit.i18nText("Fine-Design_Basic_Refresh")) { + @Override + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setColor(BUTTON_COLOR); + g2d.fillRoundRect(0, 0, getWidth(), getHeight(), ARC, ARC); + super.paintComponent(g2d); + } + }; + refreshButton.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.ForbiddenPane.refreshButton")); + refreshButton.setForeground(Color.WHITE); + refreshButton.setBorderPainted(false); + refreshButton.setContentAreaFilled(false); + refreshButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template == null) { + return; + } + // 展示下画面 + LoadingDialog loadingDialog = new LoadingDialog(); + loadingDialog.showDialog(); + new SwingWorker(){ + + @Override + protected Boolean doInBackground() throws Exception { + return WorkContext.getCurrent().get(LockInfoOperator.class).isTplLocked(template.getEditingFILE().getPath()); + } + + @Override + protected void done() { + boolean unLocked; + loadingDialog.hideDialog(); + try { + unLocked = !get(); + if (unLocked) { + template.whenClose(); + JTemplate newTemplate = JTemplateFactory.createJTemplate(template.getEditingFILE()); + HistoryTemplateListCache.getInstance().replaceCurrentEditingTemplate(newTemplate); + DesignerContext.getDesignerFrame().addAndActivateJTemplate(newTemplate); + } + } catch (Exception e) { + loadingDialog.hideDialog(); + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + }.execute(); + } + }); + add(lockLabel); + add(tipLabel); + add(refreshButton); + } +} + +class LoadingDialog extends JDialog { + + private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/refreh_icon.png")); + + private GuideView guideView; + + public LoadingDialog() { + super(DesignerContext.getDesignerFrame()); + setLayout(new BorderLayout()); + this.getContentPane().setBackground(Color.WHITE); + this.setResizable(false); + this.setUndecorated(true); + this.setAlwaysOnTop(true); + this.setModal(false); + this.setSize(new Dimension(400, 100)); + this.add(new UILabel(LOADING_ICON, UILabel.CENTER), BorderLayout.NORTH); + this.add(new UILabel(Toolkit.i18nText(Toolkit.i18nText("Fine_Design_Template_Refresh")), UILabel.CENTER), BorderLayout.CENTER); + GUICoreUtils.centerWindow(this); + } + + public void showDialog() { + DesignerContext.getDesignerFrame().setExtendedState(JFrame.MAXIMIZED_BOTH); + guideView = new GuideView(DesignerContext.getDesignerFrame()); + GUICoreUtils.centerWindow(DesignerContext.getDesignerFrame(), guideView); + guideView.setBounds(DesignerContext.getDesignerFrame().getBounds()); + guideView.setVisible(true); + this.setVisible(true); + } + + public void hideDialog() { + this.dispose(); + guideView.dismissGuide(); + } + +} 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 e990012f8b..f1a40ccdc7 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,10 +2,17 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; import com.fr.base.Parameter; +import com.fr.base.extension.FileExtension; import com.fr.base.io.BaseBook; import com.fr.base.iofile.attr.DesignBanCopyAttrMark; import com.fr.base.iofile.attr.TemplateIdAttrMark; +import com.fr.base.iofile.attr.TemplateThemeAttrMark; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.ThemedTemplate; import com.fr.base.vcs.DesignerMode; +import com.fr.decision.config.FSConfig; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.DesignerEnvManager; @@ -36,6 +43,7 @@ import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.authority.JTemplateAuthorityChecker; import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.mainframe.check.CheckButton; import com.fr.design.mainframe.template.info.TemplateProcessInfo; @@ -50,6 +58,7 @@ import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.DesignUtils; import com.fr.design.worker.save.CallbackSaveWorker; import com.fr.design.worker.save.EmptyCallBackSaveWorker; +import com.fr.design.worker.save.SaveFailureHandler; import com.fr.design.write.submit.DBManipulationInWidgetEventPane; import com.fr.design.write.submit.DBManipulationPane; import com.fr.event.EventDispatcher; @@ -60,7 +69,14 @@ import com.fr.file.StashedFILE; import com.fr.form.ui.NoneWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; +import com.fr.nx.app.designer.toolbar.TemplateTransformer; +import com.fr.nx.app.designer.utils.CptAndCptxCompatibilityUtil; +import com.fr.nx.app.designer.utils.CptCompileUtil; +import com.fr.nx.cptx.entry.metadata.CptxMetadata; +import com.fr.nx.cptx.utils.CptxFileUtils; import com.fr.plugin.context.PluginContext; import com.fr.plugin.context.PluginRuntime; import com.fr.plugin.injectable.PluginModule; @@ -69,8 +85,11 @@ import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; import com.fr.plugin.observer.PluginEventType; import com.fr.plugin.observer.PluginListenerRegistration; +import com.fr.report.InconsistentLockException; +import com.fr.report.UnLockedException; import com.fr.report.cell.Elem; import com.fr.report.cell.cellattr.CellImage; +import com.fr.report.lock.LockInfoOperator; import com.fr.stable.ArrayUtils; import com.fr.stable.Filter; import com.fr.stable.ProductConstants; @@ -83,28 +102,36 @@ import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JComponent; 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.util.Set; import java.util.concurrent.Callable; /** * 报表设计和表单设计的编辑区域(设计器编辑的IO文件) */ -public abstract class JTemplate> extends TargetComponent implements ToolBarMenuDockPlus, DesignerProxy, JTemplateSave, TabChangeListener { +public abstract class JTemplate> extends TargetComponent implements ToolBarMenuDockPlus, DesignerProxy, JTemplateSave, TabChangeListener, ThemedTemplate { // TODO ALEX_SEP editingFILE这个属性一定要吗?如果非要不可,有没有可能保证不为null + private static final int PREDEFINED_ICON_WIDTH = 27; private static final int PREFIX_NUM = 3000; protected FILE editingFILE = null; // alex:初始状态为saved,这样不管是新建模板,还是打开模板,如果未做任何操作直接关闭,不提示保存 private boolean saved = true; private boolean authoritySaved = true; + private UIButton templateThemeButton; private UndoManager undoMananger; private UndoManager authorityUndoManager; protected U undoState; protected U authorityUndoState = null; protected T template; // 当前模板 + private boolean isNewCreateTpl = false; //当前模板是否为新建模板 + private volatile boolean forbidden; + /** * 模板过程的相关信息 * @@ -135,9 +162,12 @@ public abstract class JTemplate> private final String runtimeId = UUID.randomUUID().toString(); private PluginEventListener pluginListener; + // 监听全局主题数据更新 + private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener; public JTemplate() { initAndStartPlugin(); + startListenThemeConfig(); } public JTemplate(T t, String defaultFileName) { @@ -176,9 +206,15 @@ public abstract class JTemplate> designModel = createDesignModel(parameters); } addCenterPane(); + isNewCreateTpl = isNewFile; + if (isNewCreateTpl) { + // REPORT-58486: 必须在初始的UndoState创建前设置主题,使得初始的UndoState就包含了主题效果 + setUpTheme4NewTemplate(); + } this.undoState = createUndoState(); initAndStartPlugin(); + startListenThemeConfig(); } private void initAndStartPlugin() { @@ -208,6 +244,36 @@ public abstract class JTemplate> PluginListenerRegistration.getInstance().listen(PluginEventType.AfterRun, this.pluginListener, filter); } + private void startListenThemeConfig() { + if (themeConfigChangeListener == null) { + themeConfigChangeListener = new TemplateThemeConfig.ThemeConfigChangeListener() { + @Override + public void onThemeConfigChanged(TemplateThemeConfig.ThemeConfigEvent event) { + TemplateTheme usingTheme = getTemplateTheme(); + boolean isUsingThemeChanged = StringUtils.equals(event.themName, usingTheme.getName()); + + if (isUsingThemeChanged && (event.action == TemplateThemeConfig.ThemeConfigAction.REMOVE || + event.action == TemplateThemeConfig.ThemeConfigAction.UPDATE)) { + checkAndResetTheme(); + } + } + }; + TemplateThemeConfig config = getUsingTemplateThemeConfig(); + if (config != null) { + config.addThemeConfigChangeListener(themeConfigChangeListener); + } + } + } + + private void stopListenThemeConfig() { + if (themeConfigChangeListener != null) { + TemplateThemeConfig config = getUsingTemplateThemeConfig(); + if (config != null) { + config.removeThemeConfigChangeListener(themeConfigChangeListener); + } + } + } + private void initPluginPane() { ExtraDesignClassManager classManager = PluginModule.getAgent(PluginModule.ExtraDesign); @@ -221,7 +287,7 @@ public abstract class JTemplate> public void fireTabChange() { // do nothing } - + protected void addPane(PropertyItemPaneProvider provider) { // do nothing } @@ -371,6 +437,7 @@ public abstract class JTemplate> public void whenClose() { // stop的时候 pluginListener 和 PluginFilter 都会移除 PluginListenerRegistration.getInstance().stopListen(this.pluginListener); + stopListenThemeConfig(); } public FILE templateToStashFile() { @@ -587,6 +654,8 @@ public abstract class JTemplate> */ public void undo() { this.getUndoManager().undo(); + // 撤销前模版使用主题可能已经被删除或修改,需要重置模版样式 + checkAndResetTheme(); fireSuperTargetModified(); } @@ -595,7 +664,8 @@ public abstract class JTemplate> */ public void redo() { this.getUndoManager().redo(); - + // 重做前模版使用主题可能已经被删除或修改,需要重置模版样式 + checkAndResetTheme(); fireSuperTargetModified(); } @@ -657,6 +727,14 @@ public abstract class JTemplate> super.fireTargetModified(); } + public void fireTargetModified(boolean shouldCreateNewUndoState) { + if (shouldCreateNewUndoState) { + fireTargetModified(); + } else { + super.fireTargetModified(); + } + } + protected abstract U createUndoState(); protected abstract void applyUndoState(U u); @@ -852,10 +930,12 @@ public abstract class JTemplate> protected boolean saveToNewFile(String oldName) { boolean result = false; + String path = this.editingFILE.getPath(); Set providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG); for (ReportSupportedFileUIProvider provider : providers) { - result = result || provider.saveToNewFile(this.editingFILE.getPath(), this); + result = result || provider.saveToNewFile(path, this); } + result = result || saveToNewFile4Cptx(path); if (!result) { result = this.saveFile(); //更换最近打开 @@ -865,6 +945,14 @@ public abstract class JTemplate> return result; } + private boolean saveToNewFile4Cptx(String targetPath) { + if (FileExtension.CPTX.matchExtension(targetPath)) { + TemplateTransformer.TO_CPTX.transform(this); + return true; + } + return false; + } + protected void mkNewFile(FILE file) { try { file.mkfile(); @@ -897,10 +985,11 @@ public abstract class JTemplate> return false; } try { + checkBeforeSave(); export(); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage(), "Save Error", JOptionPane.ERROR_MESSAGE); + SaveFailureHandler.getInstance().process(e); return false; } this.editingFILE = editingFILE; @@ -911,6 +1000,21 @@ public abstract class JTemplate> return true; } + public boolean isNewCreateTpl(){ + return isNewCreateTpl; + } + + protected void checkBeforeSave() throws Exception { + // 保存前校验下未解锁 + if (WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(getEditingFILE().getPath())) { + throw new UnLockedException(); + } + // 校验锁定信息是否一致 + if (getEditingFILE().exists() && !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath())) { + throw new InconsistentLockException(); + } + } + protected boolean export() throws Exception { return this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(getEditingFILE())); @@ -1381,11 +1485,13 @@ public abstract class JTemplate> * @return 按钮组 */ public UIButton[] createExtraButtons() { - Set providers = ExtraDesignClassManager.getInstance().getArray(DesignerFrameUpButtonProvider.XML_TAG); UIButton[] uiButtons = new UIButton[0]; + Set providers = ExtraDesignClassManager.getInstance().getArray(DesignerFrameUpButtonProvider.XML_TAG); for (DesignerFrameUpButtonProvider provider : providers) { uiButtons = ArrayUtils.addAll(uiButtons, provider.getUpButtons(getMenuState())); } + templateThemeButton = createTemplateThemeButton(); + uiButtons = ArrayUtils.addAll(uiButtons, templateThemeButton); return uiButtons; } @@ -1394,6 +1500,24 @@ public abstract class JTemplate> return new UIButton[]{new CheckButton()}; } + protected UIButton createTemplateThemeButton() { + UIButton button = new UIButton(IOUtils.readIcon("/com/fr/design/icon/icon_predefined_style.png")) { + @Override + public Dimension getPreferredSize() { + FontMetrics metrics = getFontMetrics(getFont()); + int width = Math.min(metrics.stringWidth(getText()) + PREDEFINED_ICON_WIDTH, 100); + return new Dimension(width, 20); + } + }; + button.setToolTipText(getTemplateTheme().getName()); + button.setText(getTemplateTheme().getName()); + button.setName(getTemplateTheme().getName()); + button.setAlignmentX(SwingConstants.LEFT); + button.set4ToolbarButton(); + button.setEnabled(true); + return button; + } + /** * 由于老版本的模板没有模板ID,当勾选使用参数模板时候,就加一个模板ID attr * @@ -1414,7 +1538,27 @@ public abstract class JTemplate> public abstract String route(); public String getTemplateName() { - return getEditingFILE().getName(); + return getEditingFILE().getName() + compatibilityTip(); + } + + /** + * 设置新引擎后,有不支持的功能时,设计器中模板的标题需要加上“兼容模式”或者“不支持分页引擎”来提示用户 + * */ + private String compatibilityTip() { + if (!CptAndCptxCompatibilityUtil.isEngineXEnable(this.getTarget(), getEditingFILE().getPath())) { + return StringUtils.EMPTY; + } + String path = this.getEditingFILE().getPath(); + CptxMetadata metadata = CptxFileUtils.getMetadata(path); + //是否是兼容模式,兼容模式下,设置了新引擎的cpt和cptx的后缀不同 + if (metadata != null && metadata.isForceCpt()) { + if (path.endsWith(".cptx")) { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Compatibility_Mode"); + } else if (path.endsWith(".cpt")) { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Paging_Engine_Not_Work"); + } + } + return StringUtils.EMPTY; } public String getTemplatePredefinedStyle() { @@ -1483,6 +1627,8 @@ public abstract class JTemplate> @Override public void run() { callBackForSave(); + //在保存后的回调中执行预编译流程 + CptCompileUtil.compile(JTemplate.this); } }); @@ -1505,13 +1651,31 @@ public abstract class JTemplate> } private boolean saveRealFile() throws Exception { - FILE editingFILE = this.getEditingFILE(); - if (editingFILE == null || editingFILE instanceof MemFILE) { + if (checkJTemplateAuthority()) { + FILE editingFILE = this.getEditingFILE(); + if (editingFILE == null || editingFILE instanceof MemFILE) { + return false; + } + checkBeforeSave(); + export(); + this.editingFILE = editingFILE; + return true; + } else { + return false; + } + } + + private boolean checkJTemplateAuthority() { + if (!FSConfig.getInstance().getAuthorizeAttr().isDataConnectionAuthority()) { + return true; + } + JTemplateAuthorityChecker jTemplateAuthorityChecker = new JTemplateAuthorityChecker(this); + if (jTemplateAuthorityChecker.isAuthority()) { + return true; + } else { + jTemplateAuthorityChecker.showAuthorityFailPromptDialog(); return false; } - export(); - this.editingFILE = editingFILE; - return true; } private CallbackSaveWorker saveAs(boolean showLoc) { @@ -1547,6 +1711,10 @@ public abstract class JTemplate> worker.addSuccessCallback(new Runnable() { @Override public void run() { + boolean isChangedFile = !JTemplate.this.saved; + if (isChangedFile) { + CptCompileUtil.compile(JTemplate.this); + } callBackForSave(); // 当前打开的是正在保存的模板才刷新 if (ComparatorUtils.equals(JTemplate.this.template.getTemplateID(), @@ -1556,7 +1724,6 @@ public abstract class JTemplate> DesignerFrameFileDealerPane.getInstance().refresh(); } }); - return worker; } @@ -1607,6 +1774,14 @@ public abstract class JTemplate> result = result || provider.saveToNewFile(this.editingFILE.getPath(), this); } if (!result) { + /* + * 1.在CptCompileUtil::haveChanged改变报表引擎属性 + * 2.在这三种情况下:1.cptx文件另存为cpt文件 2.cptx另存为cptx文件 3.设置了新引擎的cpt文件另存为cpt文件, + * 因为文件的编译目录改变了,需要重新预编译,因此设置jTemplate的保存状态为false + * */ + if (CptAndCptxCompatibilityUtil.needRecompile(oldName, this)) { + this.saved = false; + } result = this.saveRealFile(); // 更换最近打开 DesignerEnvManager.getEnvManager().replaceRecentOpenedFilePath(oldName, this.getPath()); @@ -1670,14 +1845,33 @@ public abstract class JTemplate> this.openFailed = openFailed; } + public boolean isForbidden() { + return forbidden; + } + + public void setForbidden(boolean forbidden) { + this.forbidden = forbidden; + } + public boolean checkEnable() { - return !isSaving() && !isOpening() && !isOpenFailed(); + return !isSaving() && !isOpening() && !isOpenFailed() && !isForbidden(); } public String getRuntimeId() { return runtimeId; } + protected void setUpTheme4NewTemplate() { + TemplateTheme theme = getUsingTemplateThemeConfig().cachedFetchTheme4NewTemplate(); + TemplateThemeAttrMark themeAttrMark = template.getAttrMark(TemplateThemeAttrMark.XML_TAG); + if (themeAttrMark == null) { + themeAttrMark = new TemplateThemeAttrMark(); + template.addAttrMark(themeAttrMark); + } + themeAttrMark.setName(theme.getName()); + themeAttrMark.setDark(theme.isDark()); + } + public String getTemplateOpenFailedTip() { return templateOpenFailedTip; } @@ -1685,4 +1879,21 @@ public abstract class JTemplate> public void setTemplateOpenFailedTip(String templateOpenFailedTip) { this.templateOpenFailedTip = templateOpenFailedTip; } -} + + @Override + public void setTemplateTheme(TemplateTheme newTheme, TemplateThemeCompatible compatible) { + ThemedTemplate.super.setTemplateTheme(newTheme, compatible); + String name = newTheme.getName(); + templateThemeButton.setText(name); + templateThemeButton.setToolTipText(name); + } + + public void generateForBiddenTemplate() { + + } + + public void setDesignerUIMode(){ + DesignerUIModeConfig.getInstance().setAbsoluteMeasureUIMode(); + } + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java index 91899e5b54..544dc392a6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java @@ -151,13 +151,14 @@ public class NorthRegionContainerPane extends JPanel { public void execute(Object... objects) { bbsLoginPane[0] = ad.createBBSLoginPane(); } - }, SupportOSImpl.USERINFOPANE); + }, SupportOSImpl. BBS_USER_LOGIN_PANE); processor.hold(northEastPane, LogMessageBar.getInstance(), bbsLoginPane[0]); } northEastPane.add(ad.createAlphaFinePane()); if (!DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isEnabled()) { ad.createAlphaFinePane().setVisible(false); } + northEastPane.add(ad.createGuideEntryPane()); northEastPane.add(ad.createNotificationCenterPane()); OSSupportCenter.buildAction(new OSBasedAction() { @@ -165,7 +166,7 @@ public class NorthRegionContainerPane extends JPanel { public void execute(Object... objects) { northEastPane.add(ad.createBBSLoginPane()); } - }, SupportOSImpl.USERINFOPANE); + }, SupportOSImpl.BBS_USER_LOGIN_PANE); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/PX.java b/designer-base/src/main/java/com/fr/design/mainframe/PX.java new file mode 100644 index 0000000000..8fd9ac0edc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/PX.java @@ -0,0 +1,27 @@ +package com.fr.design.mainframe; + +import com.fr.stable.Constants; +import com.fr.stable.unit.LEN_UNIT; + +public class PX extends LEN_UNIT { + private static final long FU_SCALE = 36576L; + + public PX(float var1) { + super(var1); + } + + + public boolean equals(Object var1) { + return var1 instanceof PX && super.equals(var1); + } + + protected long getMoreFUScale() { + int dpi = DesignerUIModeConfig.getInstance().getScreenResolution(); + return FU_SCALE / dpi; + } + + public static double toPixWithResolution(double value, int resolution) { + return value * resolution / Constants.FR_PAINT_RESOLUTION; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/PXReportLengthUNIT.java b/designer-base/src/main/java/com/fr/design/mainframe/PXReportLengthUNIT.java new file mode 100644 index 0000000000..69d46480e9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/PXReportLengthUNIT.java @@ -0,0 +1,32 @@ +package com.fr.design.mainframe; + +import com.fr.design.fun.impl.AbstractReportLengthUNITProvider; +import com.fr.stable.unit.UNIT; + +/** + * Created by kerry on 2020-04-09 + */ +public class PXReportLengthUNIT extends AbstractReportLengthUNITProvider { + public static final short UNIT_TYPE = 4; + + @Override + public String unitText() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Px"); + } + + @Override + public int unitType() { + return UNIT_TYPE; + } + + @Override + public float unit2Value4Scale(UNIT value) { + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); + return value.toPixF(resolution); + } + + @Override + public UNIT float2UNIT(float value) { + return new PX(value); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java new file mode 100644 index 0000000000..fdab6ea2a2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java @@ -0,0 +1,20 @@ +package com.fr.design.mainframe.authority; + +import com.fr.report.cell.cellattr.core.group.DSColumn; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class DSColumnAuthorityChecker extends ElementAuthorityChecker { + + @Override + @Nullable + Set getNoAuthDatasetNames(DSColumn dsColumn, Set authDatasetNames) { + if (!authDatasetNames.contains(dsColumn.getDSName())) { + return new HashSet<>(Arrays.asList(dsColumn.getDSName())); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java new file mode 100644 index 0000000000..67d0f1da36 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java @@ -0,0 +1,45 @@ +package com.fr.design.mainframe.authority; + +import org.jetbrains.annotations.Nullable; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; + +import java.lang.reflect.Type; +import java.util.Set; + + +public abstract class ElementAuthorityChecker { + + + /** + * @Description 获取越权的数据连接 + * @param: t 待检查的对象 + * @param: authConnectionNames 有权限的数据连接名 + * @return 如果有返回名称,没有返回null + */ + @Nullable + Set getNoAuthConnectionNames(T t, Set authConnectionNames) { + return null; + } + + + /** + * @Description 获取越权的服务器数据集 + * @param: t 待检查的对象 + * @param: authDatasetNames 有权限的服务器数据集名 + * @return 如果有返回名称,没有返回null + */ + @Nullable + Set getNoAuthDatasetNames(T t, Set authDatasetNames) { + return null; + } + + /** + * @Description 要检查对象的className + * @return className + */ + String getCheckClassName() { + ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) this.getClass().getGenericSuperclass(); + Type type = parameterizedType.getActualTypeArguments()[0]; + return type.getTypeName(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java new file mode 100644 index 0000000000..15a7f4853f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java @@ -0,0 +1,97 @@ +package com.fr.design.mainframe.authority; + +import com.fr.base.Formula; +import com.fr.general.ComparatorUtils; +import com.fr.parser.FunctionCall; +import com.fr.parser.StringLiteral; +import com.fr.script.Calculator; +import com.fr.stable.script.Node; +import org.jetbrains.annotations.Nullable; + +import java.util.HashSet; +import java.util.Set; + +public class FormulaAuthorityChecker extends ElementAuthorityChecker { + private static final Set CONNECTION_NAME_FORMULA_PARSER = new HashSet<>(); + private static final Set DATASET_NAME_FORMULA_PARSER = new HashSet<>(); + + static { + CONNECTION_NAME_FORMULA_PARSER.add(new FormulaParser("SQL", 0)); + DATASET_NAME_FORMULA_PARSER.add(new FormulaParser("VALUE", 0)); + } + + @Override + @Nullable + public Set getNoAuthConnectionNames(Formula formula, Set authConnectionNames) { + return getNoAuthNames(formula, CONNECTION_NAME_FORMULA_PARSER, authConnectionNames); + } + + + @Override + @Nullable + Set getNoAuthDatasetNames(Formula formula, Set authDatasetNames) { + return getNoAuthNames(formula, DATASET_NAME_FORMULA_PARSER, authDatasetNames); + } + + private Set getNoAuthNames(Formula formula, Set formulaParsers, Set authNames) { + Set noAuthNames = new HashSet<>(); + try { + FunctionCall functionCall = (FunctionCall) Calculator.createCalculator().parse(formula.getContent()).getConditionalExpression(); + handleNoAuthNames(functionCall, formulaParsers, authNames, noAuthNames); + } catch (Exception ignore) { + + } finally { + return noAuthNames; + } + } + + private void handleNoAuthNames(FunctionCall functionCall, Set formulaParsers, Set authNames, Set noAuthNames) { + for (FormulaParser formulaPattern : formulaParsers) { + String noAuthName = formulaPattern.getNoAuthName(functionCall, authNames); + if (noAuthName != null) { + noAuthNames.add(noAuthName); + } + } + Node[] nodes = functionCall.getArguments(); + if (nodes != null) { + for (int i = 0; i < nodes.length; i++) { + Node node = nodes[i]; + if (node instanceof FunctionCall) { + handleNoAuthNames((FunctionCall) node, formulaParsers, authNames, noAuthNames); + } + } + } + + } + + + static class FormulaParser { + //函数的名称 + public String name; + //要检测的位置 + public int index; + + + FormulaParser(String name, int index) { + this.name = name; + this.index = index; + } + + String getNoAuthName(FunctionCall functionCall, Set authNames) { + if (functionCall.getName() != null && ComparatorUtils.equals(functionCall.getName().toUpperCase(), name)) { + Node node = functionCall.getArguments()[index]; + if (node instanceof StringLiteral) { + String stringLiteral = node.toString(); + if (stringLiteral.length() > 2) { + String value = stringLiteral.substring(1, stringLiteral.length() - 1); + if (!authNames.contains(value)) { + return value; + } + } + } + } + return null; + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java new file mode 100644 index 0000000000..d76031f654 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java @@ -0,0 +1,188 @@ +package com.fr.design.mainframe.authority; + + +import com.fr.design.dialog.FineJOptionPane; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mod.ModClassFilter; +import com.fr.file.ConnectionConfig; +import com.fr.file.TableDataConfig; +import com.fr.invoke.ClassHelper; + +import com.fr.log.FineLoggerFactory; +import com.fr.stable.Filter; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.authority.user.UserAuthority; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + + +import static javax.swing.JOptionPane.WARNING_MESSAGE; + + +public class JTemplateAuthorityChecker { + JTemplate jTemplate; + Set allConnectionNames; + Set authConnectionNames; + Set allDatasetNames; + Set authDatasetNames; + Map checkerMap = new HashMap<>(); + Set authFailConnectionNames = new HashSet<>(); + Set authFailDatasetNames = new HashSet<>(); + + + public JTemplateAuthorityChecker(JTemplate jTemplate) { + long s = System.currentTimeMillis(); + this.jTemplate = jTemplate; + this.initAuthNames(); + this.initChecker(); + FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker init time consume:" + (System.currentTimeMillis() - s)); + } + + private void initAuthNames() { + allDatasetNames = new HashSet<>(); + for (String authServerDataSetName : TableDataConfig.getInstance().getTableDatas().keySet()) { + allDatasetNames.add(authServerDataSetName); + } + + allConnectionNames = ConnectionConfig.getInstance().getConnections().keySet(); + + UserAuthority templateAuthority = WorkContext.getCurrent().get(UserAuthority.class); + Map> authNamesMap = templateAuthority.getAuthServerDataSetAndConnectionNames(); + if (authNamesMap != null) { + //有权限的数据连接名称 + authConnectionNames = authNamesMap.get(UserAuthority.AUTH_CONNECTION_NAMES); + //有权限的数据集名称 + authDatasetNames = authNamesMap.get(UserAuthority.AUTH_SERVER_DATASET_NAMES); + } + } + + private void initChecker() { + registerChecker(new NameDatabaseConnectionAuthorityChecker()); + registerChecker(new DSColumnAuthorityChecker()); + registerChecker(new FormulaAuthorityChecker()); + registerChecker(new NameTableDataAuthorityChecker()); + } + + private void registerChecker(ElementAuthorityChecker checker) { + checkerMap.put(checker.getCheckClassName(), checker); + } + + + public boolean isAuthority() { + long s = System.currentTimeMillis(); + //遍历模板对象,根据checkerMap.keySet()把感兴趣的对象找出来 + Map> targetObjects = ClassHelper.searchObject(jTemplate.getTarget(), checkerMap.keySet(), ClassFilter.getInstance()); + + //找到对应的checker,对对象进行检查 + for (String name : targetObjects.keySet()) { + ElementAuthorityChecker checker = checkerMap.get(name); + for (Object object : targetObjects.get(name)) { + if (authConnectionNames != null) { + Set noAuthName = checker.getNoAuthConnectionNames(object, authConnectionNames); + if (noAuthName != null) { + authFailConnectionNames.addAll(noAuthName); + } + } + if (authDatasetNames != null) { + Set noAuthName = checker.getNoAuthDatasetNames(object, authDatasetNames); + if (noAuthName != null) { + authFailDatasetNames.addAll(noAuthName); + } + } + } + } + authFailConnectionNames.retainAll(allConnectionNames); + authFailDatasetNames.retainAll(allDatasetNames); + FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker check time consume:" + (System.currentTimeMillis() - s)); + return authFailConnectionNames.size() == 0 && authFailDatasetNames.size() == 0; + } + + public void showAuthorityFailPromptDialog() { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(Toolkit.i18nText("Fine-Design-Basic_Save_Failure")); + stringBuffer.append("\n"); + stringBuffer.append(getPromptInfo(authFailDatasetNames, + Toolkit.i18nText("Fine-Design_Template_Authority_Check_Server_Dataset_Authority"))); + stringBuffer.append(getPromptInfo(authFailConnectionNames, + Toolkit.i18nText("Fine-Design_Template_Authority_Check_Data_Connection_Authority"))); + FineJOptionPane.showMessageDialog( + DesignerContext.getDesignerFrame(), + stringBuffer.toString(), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + WARNING_MESSAGE); + } + + private String getPromptInfo(Set authFailNames, String message) { + StringBuffer stringBuffer = new StringBuffer(); + if (authFailNames.size() > 0) { + stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Current_Operator_Miss")); + stringBuffer.append(authFailNames.size()); + stringBuffer.append(Toolkit.i18nText("Fine-Design_Report_Ge")); + stringBuffer.append(message); + stringBuffer.append("\n"); + stringBuffer.append(getNoAuthNameSequence(authFailNames)); + } + return stringBuffer.toString(); + } + + private String getNoAuthNameSequence(Set names) { + StringBuffer stringBuffer = new StringBuffer(); + int showMaxCount = 3; + int count = 0; + for (String name : names) { + if (count == showMaxCount) { + stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Etc")); + break; + } + stringBuffer.append(name); + if (count != names.size() - 1 && count != showMaxCount - 1) { + stringBuffer.append(";"); + } + count++; + } + stringBuffer.append("\n"); + return stringBuffer.toString(); + } + + static class ClassFilter implements Filter { + + private static final Set FILTER_SET = new HashSet<>(); + private static final Set START_WITH_SET = new HashSet<>(); + private static final Filter INSTANCE = new ModClassFilter(); + + public static Filter getInstance() { + return INSTANCE; + } + + static { + FILTER_SET.add("java.awt.image.BufferedImage"); + FILTER_SET.add("sun.awt.AppContext"); + FILTER_SET.add("com.fr.poly.creator.ECBlockCreator"); + FILTER_SET.add("io.netty.channel.nio.SelectedSelectionKeySet"); + FILTER_SET.add("com.fr.form.ui.ElementCaseImage"); + FILTER_SET.add("this$0"); + START_WITH_SET.add("com.fr.design"); + } + + @Override + public boolean accept(String s) { + if (FILTER_SET.contains(s)) { + return true; + } + for (String start : START_WITH_SET) { + if (s.startsWith(start)) { + return true; + } + } + return false; + } + } +} + diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java new file mode 100644 index 0000000000..96bc0b8c5d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java @@ -0,0 +1,22 @@ +package com.fr.design.mainframe.authority; + +import com.fr.data.impl.NameDatabaseConnection; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +public class NameDatabaseConnectionAuthorityChecker extends ElementAuthorityChecker { + @Override + @Nullable + Set getNoAuthConnectionNames(NameDatabaseConnection nameDatabaseConnection, Set authConnectionNames) { + String name = nameDatabaseConnection.getName(); + if (!authConnectionNames.contains(name)) { + return new HashSet<>(Arrays.asList(name)); + } + return null; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java new file mode 100644 index 0000000000..13e7300856 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.authority; + +import com.fr.data.impl.NameTableData; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class NameTableDataAuthorityChecker extends ElementAuthorityChecker { + @Override + @Nullable + Set getNoAuthDatasetNames(NameTableData nameTableData, Set authDatasetNames) { + if (!authDatasetNames.contains(nameTableData.getName())) { + return new HashSet<>(Arrays.asList(nameTableData.getName())); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java b/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java index f9b4c160e5..9d9eb0058c 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java @@ -3,12 +3,8 @@ package com.fr.design.mainframe.backgroundpane; import com.fr.base.background.ColorBackground; import com.fr.design.event.UIObserverListener; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.style.color.NewColorSelectPane; +import com.fr.design.style.color.NewColorSelectBox; import com.fr.general.Background; - - -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.Color; @@ -18,13 +14,23 @@ import java.awt.Color; */ public class ColorBackgroundQuickPane extends BackgroundQuickPane { - private NewColorSelectPane detailColorSelectPane; + private NewColorSelectBox colorSelectBox; + public ColorBackgroundQuickPane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - - detailColorSelectPane = new NewColorSelectPane(); - this.add(detailColorSelectPane, BorderLayout.NORTH); + colorSelectBox = new NewColorSelectBox(100) { + @Override + public boolean shouldResponseChangeListener() { + // ColorBackgroundQuickPane注册监听器ChangeListenerImpl的逻辑不能丢,因为里面有修改字段backgroundChange的逻辑. + // 所以在监听器重复注册以及UndoState重复生成时,应该保留ChangeListenerImpl, 而放弃NewColorSelectBox内部自己注册 + // ChangeListener + // REPORT-63760 【主题切换】撤销以后,样式设置有问题 + // REPORT-64006 【模板主题】单元格自定义样式背景色设置不生效 + return false; + } + }; + this.add(colorSelectBox, BorderLayout.NORTH); } public void populateBean(Background background) { @@ -37,22 +43,16 @@ public class ColorBackgroundQuickPane extends BackgroundQuickPane { } public void populateColor(Color color) { - this.detailColorSelectPane.setColor(color); + this.colorSelectBox.setSelectObject(color); } public Color updateColor() { - this.detailColorSelectPane.updateUsedColor(); - return this.detailColorSelectPane.getNotNoneColor(); + return this.colorSelectBox.getSelectObject(); } - /** - * 给组件登记一个观察者监听事件 - * - * @param listener 观察者监听事件 - */ @Override public void registerChangeListener(final UIObserverListener listener) { - detailColorSelectPane.addChangeListener(new ChangeListenerImpl(listener)); + this.colorSelectBox.addSelectChangeListener(new ChangeListenerImpl(listener)); } @Override @@ -78,6 +78,6 @@ public class ColorBackgroundQuickPane extends BackgroundQuickPane { @Override public void reset() { - this.detailColorSelectPane.setColor(null); + this.colorSelectBox.setSelectObject(null); } } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditContext.java b/designer-base/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditContext.java similarity index 63% rename from designer-chart/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditContext.java rename to designer-base/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditContext.java index 23616a482a..51fe2f816a 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditContext.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditContext.java @@ -1,6 +1,7 @@ package com.fr.design.mainframe.chart.mode; import com.fr.common.annotations.Open; +import com.fr.design.base.mode.DesignModeContext; /** * @author shine @@ -23,4 +24,13 @@ public class ChartEditContext { public static boolean normalMode() { return current == ChartEditMode.NORMAL; } + + /** + * 是否支持 主题样式 设置 + * + * @return duchamp大屏模板模式 不支持 图表组件&cpt组件中的图表 都不支持 + */ + public static boolean supportTheme() { + return !DesignModeContext.isDuchampMode(); + } } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditMode.java b/designer-base/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditMode.java similarity index 100% rename from designer-chart/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditMode.java rename to designer-base/src/main/java/com/fr/design/mainframe/chart/mode/ChartEditMode.java diff --git a/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java index a8c19c6976..0671ed1b63 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java @@ -7,8 +7,8 @@ import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.CloudCenter; import com.fr.general.IOUtils; -import com.fr.i18n.UrlI18nManager; import javax.swing.BorderFactory; import javax.swing.JDialog; @@ -49,8 +49,7 @@ public class CheckFontInfoDialog extends JDialog implements ActionListener { JPanel messagePanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); MessageWithLink linkMessage = new MessageWithLink(Toolkit.i18nText("Fine_Designer_Check_Font_Message"), Toolkit.i18nText("Fine_Designer_Check_Font_Install_Font"), - UrlI18nManager.getInstance().getI18nUrl("help.install.font") - ); + CloudCenter.getInstance().acquireUrlByKind("help.install.font", "https://help.fanruan.com/finereport/doc-view-3999.html")); linkMessage.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink")); messagePanel.add(linkMessage); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/Guide.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/Guide.java new file mode 100644 index 0000000000..c8d3e6801d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/Guide.java @@ -0,0 +1,203 @@ +package com.fr.design.mainframe.guide.base; + +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.guide.collect.GuideCollector; +import com.fr.design.mainframe.guide.scene.GuideScene; +import com.fr.design.mainframe.guide.ui.GuideCompleteDialog; +import com.fr.design.mainframe.guide.ui.GuideManageDialog; +import com.fr.stable.StringUtils; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; + +public class Guide { + private String id; + private String name; + private String description; + private String completeMessage; + private GuideView guideView; + private GuideLifecycle lifecycle; + private boolean isComplete; + private GuideScene scene; + + public Guide() { + this(null, null, null); + } + + public Guide(String id, String name, String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + if (StringUtils.isNotEmpty(description)) { + return description; + } + return name; + } + + public String getCompleteMessage() { + return completeMessage; + } + + public void setCompleteMessage(String completeMessage) { + this.completeMessage = completeMessage; + } + + public void setGuideView(GuideView guideView) { + this.guideView = guideView; + } + + public GuideView getGuideView() { + return guideView; + } + + public void setComplete(boolean complete) { + isComplete = complete; + } + + public boolean isComplete() { + return isComplete; + } + + public void setScene(GuideScene scene) { + this.scene = scene; + } + + public GuideScene getScene() { + return scene; + } + + /** + * 开启引导流程 + */ + public void go() { + DesignerContext.getDesignerFrame().setExtendedState(JFrame.MAXIMIZED_BOTH); + // 同时只能启动一个引导 + if (GuideManager.getInstance().getCurrentGuide() != null) { + return; + } + GuideManager.getInstance().setCurrentGuide(this); + guideView.showLoading(); + guideView.addHierarchyListener(loadingHierarchyListener); + new SwingWorker() { + @Override + protected Boolean doInBackground() { + try { + if (lifecycle != null && !lifecycle.prepared()) { + return false; + } + return true; + } catch (Exception e) { + e.printStackTrace(); + guideView.hideLoading(); + terminate(); + return false; + } + } + + @Override + protected void done() { + try { + if (get()) { + start(); + } + } catch (Exception e) { + e.printStackTrace(); + guideView.hideLoading(); + terminate(); + } + } + }.execute(); + } + + public void start() { + guideView.hideLoading(); + } + + private void startScene() { + if (scene != null) { + guideView.setScene(scene); + guideView.showGuide(); + if (lifecycle != null) { + lifecycle.onStart(); + } + } else { + complete(); + } + } + + public void complete() { + if (lifecycle != null) { + lifecycle.onComplete(); + } + setComplete(true); + GuideCollector.getInstance().saveInfo(); + guideView.dismissGuide(); + GuideCompleteDialog.getInstance().showDialog(getCompleteMessage()); + end(); + } + + public void terminate() { + if (lifecycle != null) { + lifecycle.onTerminate(); + } + guideView.removeHierarchyListener(loadingHierarchyListener); + end(); + } + + public void end() { + guideView.dismissGuide(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (lifecycle != null) { + lifecycle.onEnd(); + } + GuideManager.getInstance().setCurrentGuide(null); + GuideManageDialog.getInstance().showDialog(); + } + }); + + } + + public void registerLifecycle(GuideLifecycle lifecycle) { + this.lifecycle = lifecycle; + } + + public void removeGuideLifecycle() { + this.lifecycle = null; + } + + private HierarchyListener loadingHierarchyListener = new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + guideView.removeHierarchyListener(loadingHierarchyListener); + startScene(); + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideBuilder.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideBuilder.java new file mode 100644 index 0000000000..a1974bf924 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideBuilder.java @@ -0,0 +1,51 @@ +package com.fr.design.mainframe.guide.base; + +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.guide.scene.GuideScene; + +public class GuideBuilder { + private Guide guide; + + public static GuideBuilder newInstance() { + return new GuideBuilder(); + } + + public GuideBuilder() { + guide = new Guide(); + guide.setGuideView(new GuideView(DesignerContext.getDesignerFrame(), guide)); + } + + public GuideBuilder setID(String id) { + guide.setId(id); + return this; + } + + public GuideBuilder setName(String name) { + guide.setName(name); + return this; + } + + public GuideBuilder setDescription(String description) { + guide.setDescription(description); + return this; + } + + public GuideBuilder setCompleteMessage(String message) { + guide.setCompleteMessage(message); + return this; + } + + public GuideBuilder addScene(GuideScene scene) { + guide.setScene(scene); + return this; + } + + public GuideBuilder registerLifecycle(GuideLifecycle lifecycle) { + guide.registerLifecycle(lifecycle); + return this; + } + + public Guide getGuide() { + return guide; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideGroup.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideGroup.java new file mode 100644 index 0000000000..cd5e0b5794 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideGroup.java @@ -0,0 +1,55 @@ +package com.fr.design.mainframe.guide.base; + +import java.util.ArrayList; +import java.util.List; + +public class GuideGroup { + private List guideList; + private String id; + private String name; + + public GuideGroup(String id, String name) { + this.id = id; + this.name = name; + guideList = new ArrayList<>(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void addGuide(Guide guide) { + guideList.add(guide); + } + + public List getGuideList() { + return guideList; + } + + public List getCompleteGuideList() { + List complete = new ArrayList<>(); + for (Guide guide : getGuideList()) { + if (guide.isComplete()) { + complete.add(guide); + } + } + return complete; + } + + public boolean isCompleteAll() { + return getCompleteGuideList().size() == getGuideList().size(); + } + + public boolean isCompleteSome() { + List completeGuides = getCompleteGuideList(); + return completeGuides.size() > 0 && completeGuides.size() < getGuideList().size(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycle.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycle.java new file mode 100644 index 0000000000..2ddfd975f1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycle.java @@ -0,0 +1,32 @@ +package com.fr.design.mainframe.guide.base; + +public interface GuideLifecycle{ + /** + * 准备环境 + * @return 返回true引导可继续执行 + */ + boolean prepared(); + + /** + * 开始引导教程 + */ + void onStart(); + + /** + * 完成引导教程 + */ + + void onComplete(); + + /** + * 终止引导教程 + */ + + void onTerminate(); + + /** + * 结束引导教程 + */ + void onEnd(); + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycleAdaptor.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycleAdaptor.java new file mode 100644 index 0000000000..c67f47e35f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycleAdaptor.java @@ -0,0 +1,28 @@ +package com.fr.design.mainframe.guide.base; + +public abstract class GuideLifecycleAdaptor implements GuideLifecycle{ + @Override + public boolean prepared() { + return true; + } + + @Override + public void onStart() { + + } + + @Override + public void onComplete() { + + } + + @Override + public void onTerminate() { + + } + + @Override + public void onEnd() { + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideManager.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideManager.java new file mode 100644 index 0000000000..08c46688d8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideManager.java @@ -0,0 +1,113 @@ +package com.fr.design.mainframe.guide.base; + +import com.fr.design.mainframe.guide.collect.GuideCollector; +import com.fr.stable.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class GuideManager { + private static GuideManager guideManager; + + private Guide currentGuide; + private List guideVersionList; + + public static GuideManager getInstance() { + if (guideManager == null) { + guideManager = new GuideManager(); + } + return guideManager; + } + + public GuideManager() { + guideVersionList = new ArrayList<>(); + } + + public Guide getCurrentGuide() { + return currentGuide; + } + + public void setCurrentGuide(Guide currentGuide) { + this.currentGuide = currentGuide; + } + + public void addGuideGroup(String version, GuideGroup guideGroup) { + GuideVersion guideVersion = getGuideVersion(version); + if (guideVersion == null) { + guideVersion = new GuideVersion(version); + guideVersionList.add(guideVersion); + } + guideVersion.addGuideGroup(guideGroup); + } + + public void addGuide(String groupId, Guide guide) { + GuideGroup guideGroup = getGuideGroup(groupId); + if (guideGroup != null) { + guideGroup.addGuide(guide); + } + } + + public List getGuideVersionList() { + return guideVersionList; + } + + public List getAllGuide() { + List guideList = new ArrayList<>(); + for (GuideVersion version : guideVersionList) { + for (GuideGroup group : version.getGuideGroupList()) { + for (Guide guide : group.getGuideList()) { + guideList.add(guide); + } + } + } + return guideList; + } + + public GuideVersion getGuideVersion(String version) { + for (GuideVersion guideVersion : guideVersionList) { + if (StringUtils.equals(version, guideVersion.getVersion())) { + return guideVersion; + } + } + return null; + } + + public GuideGroup getGuideGroup(String groupId) { + for (GuideVersion version : guideVersionList) { + for (GuideGroup group : version.getGuideGroupList()) { + if (StringUtils.equals(groupId, group.getId())) { + return group; + } + } + } + return null; + } + + public Guide getGuide(String guideId) { + for (GuideVersion version : guideVersionList) { + for (GuideGroup group : version.getGuideGroupList()) { + for (Guide guide : group.getGuideList()) { + if (StringUtils.equals(guideId, guide.getId())) { + return guide; + } + } + } + } + return null; + } + + public void completeAll() { + for (GuideVersion version : guideVersionList) { + for (GuideGroup group : version.getGuideGroupList()) { + for (Guide guide : group.getGuideList()) { + guide.setComplete(true); + } + } + } + GuideCollector.getInstance().saveInfo(); + } + + public void clearAll() { + guideVersionList.clear(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideVersion.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideVersion.java new file mode 100644 index 0000000000..3c365aa949 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideVersion.java @@ -0,0 +1,29 @@ +package com.fr.design.mainframe.guide.base; + +import java.util.ArrayList; +import java.util.List; + +public class GuideVersion { + private String version; + private List guideGroupList; + public GuideVersion(String version) { + guideGroupList = new ArrayList<>(); + this.version = version; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getGuideGroupList() { + return guideGroupList; + } + + public void addGuideGroup(GuideGroup guideGroup) { + guideGroupList.add(guideGroup); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideView.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideView.java new file mode 100644 index 0000000000..6a9a60615f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideView.java @@ -0,0 +1,137 @@ +package com.fr.design.mainframe.guide.base; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.guide.scene.AbstractGuideScene; +import com.fr.design.mainframe.guide.scene.GuideScene; +import com.fr.design.mainframe.guide.ui.GuideLoadingGlassPane; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.JDialog; +import javax.swing.SwingUtilities; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class GuideView extends JDialog { + private static GuideView guideView; + private Guide invoker; + private GuideScene scene; + private Color modalColor; + private float modalOpacity; + private Window window; + + public static GuideView getInstance(Guide guide) { + if (guideView == null) { + guideView = new GuideView(DesignerContext.getDesignerFrame(), guide); + } + return guideView; + } + + public GuideView(Window window) { + super(window); + this.setUndecorated(true); + this.window = window; + this.modalColor = Color.BLACK; + this.modalOpacity = 0.6f; + this.setPreferredSize(window.getSize()); + this.setSize(window.getSize()); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + setBg(); + DesignerContext.getDesignerFrame().addWindowListener(new WindowAdapter() { + + @Override + public void windowDeiconified(WindowEvent e) { + if (isVisible()) { + updateGuideViewLocation(); + // window 带透明的dialog在窗口最小化后再打开会不渲染,这边试了下重新设置visible可行 + setVisible(false); + setVisible(true); + } + } + }); + } + + public GuideView(Window window, Guide guide) { + this(window); + this.invoker = guide; + } + + public void setModalColor(Color color) { + modalColor = color; + setBg(); + } + + public void setModalOpacity(float opacity){ + modalOpacity = opacity; + setBg(); + } + + private void setBg() { + Color newColor = new Color(modalColor.getRed(), modalColor.getGreen(), modalColor.getBlue(), (int) (255 * modalOpacity)); + this.setBackground(newColor); + } + + public void setScene(GuideScene scene) { + if (scene instanceof AbstractGuideScene) { + ((AbstractGuideScene) scene).setContainer(this); + } + this.scene = scene; + } + + public void showGuide() { + updateGuideViewLocation(); + this.setVisible(true); + if (scene != null) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + scene.start(); + } + }); + } else { + GuideManager.getInstance().getCurrentGuide().complete(); + } + } + + public void dismissGuide() { + this.getLayeredPane().removeAll(); + revalidate(); + repaint(); + setVisible(false); + dispose(); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + } + + public void showLoading() { + this.setGlassPane(GuideLoadingGlassPane.getInstance()); + GuideLoadingGlassPane.getInstance().startLoading(); + updateGuideViewLocation(); + this.setVisible(true); + this.invalidate(); + this.getGlassPane().setVisible(true); + } + + public void hideLoading() { + GuideLoadingGlassPane.getInstance().stopLoading(); + this.getGlassPane().setVisible(false); + repaint(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + setVisible(false); + } + }); + } + + private void updateGuideViewLocation() { + GUICoreUtils.centerWindow(window, this); + this.setBounds(window.getBounds()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/collect/GuideCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/collect/GuideCollector.java new file mode 100644 index 0000000000..4c4c40f768 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/collect/GuideCollector.java @@ -0,0 +1,155 @@ +package com.fr.design.mainframe.guide.collect; + +import com.fr.base.io.XMLReadHelper; +import com.fr.design.mainframe.guide.base.Guide; +import com.fr.design.mainframe.guide.base.GuideManager; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLTools; +import com.fr.stable.xml.XMLable; +import com.fr.stable.xml.XMLableReader; +import com.fr.third.javax.xml.stream.XMLStreamException; +import com.fr.third.org.apache.commons.io.FileUtils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +public class GuideCollector implements XMLable { + private static final String ROOT_XML = "GuideCollector"; + private static final String GUIDE_XML = "Guide"; + private static final String FILE_NAME = "guide.info"; + private static GuideCollector collector; + + private boolean showHint; + private List cacheGuides; + + public static GuideCollector getInstance() { + if (collector == null) { + collector = new GuideCollector(); + } + return collector; + } + + public GuideCollector() { + cacheGuides = new ArrayList<>(); + } + + public boolean isShowHint() { + return showHint; + } + + public void setShowHint(boolean showHint) { + this.showHint = showHint; + saveInfo(); + } + + public void load() { + for(Guide cacheGuide : cacheGuides) { + Guide guide = GuideManager.getInstance().getGuide(cacheGuide.getId()); + if (guide != null) { + guide.setComplete(cacheGuide.isComplete()); + } + } + } + + public void saveInfo() { + cacheGuides = GuideManager.getInstance().getAllGuide(); + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLTools.writeOutputStreamXML(this, out); + out.flush(); + out.close(); + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8); + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage()); + } + } + + private File getInfoFile() { + File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME)); + try { + if (!file.exists()) { + file.createNewFile(); + } + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return file; + } + + public void loadFromFile() { + if (!getInfoFile().exists()) { + return; + } + XMLableReader reader = null; + try (InputStream in = new FileInputStream(getInfoFile())) { + reader = XMLReadHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER); + if (reader == null) { + return; + } + reader.readXMLObject(this); + } catch (FileNotFoundException e) { + } catch (XMLStreamException | IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (XMLStreamException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + @Override + public void readXML(XMLableReader xmLableReader) { + String tagName = xmLableReader.getTagName(); + if (tagName.equals(ROOT_XML)) { + showHint = xmLableReader.getAttrAsBoolean("showHint", false); + xmLableReader.readXMLObject(new XMLReadable() { + public void readXML(XMLableReader reader) { + String tagName = reader.getTagName(); + if (tagName.equals(GUIDE_XML)) { + Guide guide = new Guide(); + guide.setId(reader.getAttrAsString("id", null)); + guide.setComplete(reader.getAttrAsBoolean("isComplete", false)); + cacheGuides.add(guide); + } + + } + }); + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(ROOT_XML); + writer.attr("showHint", showHint); + for(Guide guide : GuideManager.getInstance().getAllGuide()) { + writer.startTAG(GUIDE_XML); + writer.attr("id", guide.getId()); + writer.attr("isComplete", guide.isComplete()); + writer.end(); + } + writer.end(); + + + } + + @Override + public Object clone() throws CloneNotSupportedException { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/AbstractGuideScene.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/AbstractGuideScene.java new file mode 100644 index 0000000000..cdb1765ffb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/AbstractGuideScene.java @@ -0,0 +1,503 @@ +package com.fr.design.mainframe.guide.scene; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.guide.base.GuideManager; +import com.fr.design.mainframe.guide.base.GuideView; +import com.fr.design.mainframe.guide.utils.ScreenImage; +import com.fr.design.mainframe.guide.tip.BubbleTip; +import com.fr.design.mainframe.guide.tip.GuideTip; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import java.awt.AWTException; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +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.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractGuideScene extends JPanel implements GuideScene { + private static final int DEFAULT_ARROW_HEIGHT = 12; + private static final int DEFAULT_ARROW_WIDTH = 18; + public static final Insets DEFAULT_HIGHLIGHT_INSETS = new Insets(5, 5, 5, 5); + + private GuideScene nextScene; + private SceneFilter sceneFilter; + private GuideSceneLifecycle lifecycle; + private GuideView container; + private List targetList; + private List highlightList; + private Component nextButton; + private List pointsList; + + + public AbstractGuideScene() { + this.setLayout(null); + this.setOpaque(false); + targetList = new ArrayList<>(); + highlightList = new ArrayList<>(); + pointsList = new ArrayList<>(); + } + + /** + * 根据设计器上组件添加高亮区域视图, + * JComponent 采用组件绘制方式 + * Component 采用屏幕截图方式 + * @param component 设计器组件对象 + * @return + */ + public boolean addTarget(Component component) { + try { + if (component == null || container == null) { + return false; + } + + Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane()); + Rectangle rectangle = new Rectangle(point, component.getSize()); + BufferedImage image; + + if (component instanceof JComponent) { + JComponent jComponent = (JComponent) component; + image = ScreenImage.createImage(jComponent); + highlightList.add(getTargetComponentWithImage(image, rectangle, !(component.getParent() instanceof JPopupMenu))); + } else if (component instanceof Window) { + image = ScreenImage.createImage(component); + highlightList.add(getTargetComponentWithImage(image, rectangle, false)); + } else { + image = captureImage(component); + highlightList.add(getTargetComponentWithImage(image, rectangle,true)); + } + targetList.add(component); + + return true; + } catch (AWTException e) { + e.printStackTrace(); + GuideManager.getInstance().getCurrentGuide().terminate(); + return false; + } + } + + /** + * 根据设计器上选定区域获取高亮视图,采用截屏的方式 + * @param rectangle 选定区域,相对屏幕 + * @return + */ + public boolean addTarget(Rectangle rectangle) { + try { + targetList.add(null); + BufferedImage image = captureImage(rectangle); + highlightList.add(getTargetComponentWithImage(image, rectangle, true)); + return true; + } catch (AWTException e) { + e.printStackTrace(); + GuideManager.getInstance().getCurrentGuide().terminate(); + return false; + } + } + + /** + * 根据设计器组件,选定其中某个区域,添加高亮视图 + * @param component 设计器组件 + * @param origin 相对组件的区域 + * @return + */ + public boolean addTarget(Component component, Rectangle origin) { + try { + if (component == null) { + return false; + } + Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane()); + + origin = origin.intersection(new Rectangle(0,0,component.getWidth(), component.getHeight())); + Rectangle rectangle = new Rectangle(point.x + origin.x, point.y + origin.y, origin.width, origin.height); + + BufferedImage image; + + if (component instanceof JComponent) { + JComponent jComponent = (JComponent) component; + image = ScreenImage.createImage(jComponent, origin); + } else { + image = ScreenImage.createImage(component).getSubimage(origin.x, origin.y, origin.width, origin.height); + } + targetList.add(component); + highlightList.add(getTargetComponentWithImage(image, rectangle, true)); + return true; + } catch (AWTException e) { + e.printStackTrace(); + GuideManager.getInstance().getCurrentGuide().terminate(); + return false; + } + } + + /** + * 添加自定义组件 + * @param component 自定义组件 + * @param rectangle 相对引导页的区域 + * @return + */ + public boolean addCustomTarget(Component component, Rectangle rectangle) { + if (component == null) { + return false; + } + component.setBounds(rectangle); + targetList.add(component); + highlightList.add(component); + return true; + } + + public boolean addCustomTarget(Component component, Point location) { + return addCustomTarget(component, new Rectangle(location, component.getPreferredSize())); + } + + protected List getTargetList() { + return targetList; + } + + public List getHighlightList() { + return highlightList; + } + + private UILabel getTargetComponentWithImage(BufferedImage image, Rectangle rectangle, boolean showBorder) { + ImageIcon ic = new ImageIcon(image); + UILabel label; + if (showBorder) { + label = new UILabel(ic){ + @Override + public Insets getInsets() { + return DEFAULT_HIGHLIGHT_INSETS; + } + }; + label.setBackground(Color.WHITE); + label.setOpaque(true); + label.setBounds(new Rectangle( + rectangle.x - DEFAULT_HIGHLIGHT_INSETS.left, + rectangle.y - DEFAULT_HIGHLIGHT_INSETS.top, + rectangle.width + DEFAULT_HIGHLIGHT_INSETS.left + DEFAULT_HIGHLIGHT_INSETS.right, + rectangle.height + DEFAULT_HIGHLIGHT_INSETS.top + DEFAULT_HIGHLIGHT_INSETS.bottom + )); + } else { + label = new UILabel(ic); + label.setBounds(rectangle); + } + + return label; + } + + private BufferedImage captureImage(Rectangle rectangle) throws AWTException { + container.setVisible(false); + BufferedImage image = ScreenImage.createImage(rectangle); + showContainer(); + return image; + } + + private BufferedImage captureImage(Component component) throws AWTException { + container.setVisible(false); + BufferedImage image = ScreenImage.createImage(component); + showContainer(); + return image; + } + + private void showContainer() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + container.setVisible(true); + container.toFront(); + container.requestFocus(); + } + }); + } + + + /** + * 自定义位置添加气泡提示组件 + * @param title 提示标题 + * @param content 提示内容 + * @param direction 气泡窗口位置方向 + * @param anchor 气泡窗口箭头坐标 + * @param bubbleTailStart 气泡窗口箭头坐标相对于位置方向交叉轴的比例(从左到右,从上到下) + */ + public void addBubbleTip(String title, String content, GuideTip.Direction direction, Point anchor, float bubbleTailStart) { + BubbleTip bt = new BubbleTip(title, content, direction, bubbleTailStart); + bt.setAnchor(anchor); + this.add(bt.getTip()); + } + + /** + * 以上一个添加的引导目标窗口为基础,添加对应的气泡窗 + * @param title 提示标题 + * @param content 提示内容 + * @param direction + * @param anchorStart + * @param bubbleTailStart + */ + public void addBubbleTip(String title, String content, GuideTip.Direction direction, float anchorStart, float bubbleTailStart) { + if (highlightList.size() == 0) { + return; + } + Component lastTarget = highlightList.get(highlightList.size() - 1); + Rectangle bounds = lastTarget.getBounds(); + Point anchor = new Point(0,0); + if (direction == GuideTip.Direction.TOP) { + anchor = new Point(bounds.x + (int)(bounds.width * anchorStart), bounds.y); + } else if (direction == GuideTip.Direction.BOTTOM) { + anchor = new Point(bounds.x + (int)(bounds.width * anchorStart), bounds.y + bounds.height); + } else if (direction == GuideTip.Direction.LEFT) { + anchor = new Point(bounds.x, bounds.y + (int)(bounds.height * anchorStart)); + } else if (direction == GuideTip.Direction.RIGHT) { + anchor = new Point(bounds.x + bounds.width, bounds.y + (int) (bounds.height * anchorStart)); + } + addBubbleTip(title, content, direction, anchor, bubbleTailStart); + } + + public void addBubbleTip(String title, String content, GuideTip.Direction direction) { + addBubbleTip(title, content, direction, 0.5f, 0.5f); + } + + public void addBubbleTip(String title, GuideTip.Direction direction) { + addBubbleTip(title, StringUtils.EMPTY, direction); + } + + public void addTip(GuideTip tip) { + this.add(tip.getTip()); + } + + public void addLineArrow(Point... points) { + pointsList.add(points); + } + + public void setContainer(GuideView container) { + this.container = container; + } + + public GuideView getContainer() { + return container; + } + + @Override + public GuideScene nextScene(GuideScene scene) { + nextScene = scene; + return nextScene; + } + + @Override + public void addSceneFilter(SceneFilter filter) { + sceneFilter = filter; + } + + @Override + public void start() { + clear(); + if (lifecycle != null && !lifecycle.prepared()) { + return; + } + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + showScene(); + } + }); + } + + @Override + public void showScene() { + if (container != null) { + container.setContentPane(AbstractGuideScene.this); + setBounds(0, 0 , getSceneWidth(), getSceneWidth()); + + // show target + for (int index = highlightList.size() - 1; index >= 0; index--) { + add(highlightList.get(index)); + } + // show next button + if (nextButton != null) { + nextButton.setBounds((getSceneWidth() - 60) / 2, getSceneHeight() - 100, 60, 30); + add(nextButton); + } + } + showContainer(); + if (lifecycle != null) { + lifecycle.onShow(); + } + } + + @Override + public void complete() { + clear(); + if (lifecycle != null && !lifecycle.onComplete()) { + return; + } + if (sceneFilter != null) { + nextScene = sceneFilter.getFilterScene(); + } + if (nextScene != null) { + if (nextScene instanceof AbstractGuideScene) { + ((AbstractGuideScene) nextScene).setContainer(container); + } + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + nextScene.start(); + } + }); + } else { + GuideManager.getInstance().getCurrentGuide().complete(); + } + } + + @Override + public void registerLifecycle(GuideSceneLifecycle lifecycle) { + this.lifecycle = lifecycle; + } + + @Override + public void removeLifecycle() { + this.lifecycle = null; + } + + public void showNextButton() { + UIButton nextButton = new UIButton("Next"); + nextButton.setPreferredSize(new Dimension(60, 30)); + nextButton.setOpaque(false); + nextButton.setFont(nextButton.getFont().deriveFont(20)); + nextButton.setRoundBorder(true, 8); + nextButton.setForeground(Color.WHITE); + nextButton.setNormalPainted(false); + nextButton.setPressedPainted(false); + nextButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + complete(); + } + }); + this.nextButton = nextButton; + } + + private int getSceneWidth() { + if (container == null) { + return 0; + } + return container.getLayeredPane().getWidth(); + + } + + private int getSceneHeight() { + if (container == null) { + return 0; + } + return container.getLayeredPane().getHeight(); + } + + public void clear() { + targetList.clear(); + highlightList.clear(); + pointsList.clear(); + this.nextButton = null; + if (this.getComponentCount() > 0) { + this.removeAll(); + invalidate(); + repaint(); + } + } + + @Override + public void paint(Graphics g) { + super.paint(g); + if (pointsList.isEmpty()) { + return; + } + Graphics2D g2d = (Graphics2D) g; + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + g2d.setColor(Color.WHITE); + for (Point[] points : pointsList) { + if (points.length <= 1) { + continue; + } + Point startPoint = points[0]; + Point endPoint = startPoint; + for (int index = 1; index < points.length; index++) { + startPoint = endPoint; + endPoint = points[index]; + g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y); + } + + drawArrow(g2d, startPoint, endPoint); + } + g2d.setComposite(oldComposite); + } + + /** + * 根据最后两点坐标计算出三角箭头的三个点坐标,绘制箭头 + * 这里实现以终点坐标为坐标轴圆点计算 + * @param start 起始点坐标 + * @param end 重点坐标 + */ + private void drawArrow(Graphics2D g2d, Point start, Point end) { + try{ + double dealtPointX = start.x - end.x; + double dealtPointY = -(start.y - end.y); + + double pointDistance = calDistance(dealtPointX, dealtPointY); + double triangleHeight = Math.min(DEFAULT_ARROW_HEIGHT, pointDistance); + double triangleWidth = triangleHeight * (DEFAULT_ARROW_WIDTH / 2) / DEFAULT_ARROW_WIDTH; + if (triangleHeight < 1 || triangleWidth < 1 || pointDistance < 1) { + return; + } + + double pointAngle; + double abs = 1; + if (dealtPointX == 0) { + pointAngle = Math.PI / 2; + } else { + pointAngle = Math.atan(dealtPointY / dealtPointX); + } + if (dealtPointY < 0) { + pointAngle += Math.PI; + abs = -1; + } + + double deltaAngle = Math.atan(triangleWidth / triangleHeight); + double triangleDistance = calDistance(triangleWidth, triangleHeight); + + Point p1 =calPoint(end, triangleDistance, pointAngle - deltaAngle, abs); + Point p2 = calPoint(end, triangleDistance, pointAngle + deltaAngle, abs); + + int xPoints[] = {end.x, p1.x, p2.x}; + int yPoints[] = {end.y, p1.y, p2.y}; + + g2d.fillPolygon(xPoints, yPoints, 3); + } catch (Exception e) { + e.printStackTrace(); + GuideManager.getInstance().getCurrentGuide().terminate(); + } + } + + private double calDistance(double x, double y) { + return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + } + + private Point calPoint(Point relativePoint, double distance, double angle, double abs) { + int x = (int)(relativePoint.x + abs * distance * Math.cos(angle)); + int y = (int)(relativePoint.y - abs * distance * Math.sin(angle)); + return new Point(x, y); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/ClickScene.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/ClickScene.java new file mode 100644 index 0000000000..0d8b5711b0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/ClickScene.java @@ -0,0 +1,136 @@ +package com.fr.design.mainframe.guide.scene; + +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.mainframe.guide.base.GuideManager; + +import javax.swing.AbstractButton; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ClickScene extends AbstractGuideScene{ + public enum ClickType { + LEFT, LEFT_DOUBLE, RIGHT + } + + public void addClickTarget(Component component, ClickType clickType) { + addClickTarget(component, clickType, false); + } + + public void addClickTarget(Component component, ClickType clickType, boolean isDispatch) { + if (super.addTarget(component)) { + addTargetClickListener(clickType, isDispatch); + } + } + + public void addClickTarget(Rectangle rectangle, ClickType clickType) { + if (super.addTarget(rectangle)) { + addTargetClickListener(clickType,false); + } + } + + public void addClickTarget(Component component, Rectangle rectangle, ClickType clickType) { + if (super.addTarget(component, rectangle)) { + addTargetClickListener(clickType, false); + } + } + + public void addCustomClickTarget(Component component, Rectangle rectangle, ClickType clickType) { + if (super.addCustomTarget(component, rectangle)) { + addTargetClickListener(clickType, false); + } + } + + public void addCustomClickTarget(Component component, Point location, ClickType clickType) { + if (super.addCustomTarget(component, location)) { + addTargetClickListener(clickType, false); + } + } + + private void addTargetClickListener(ClickType clickType, boolean isDispatch) { + Component highlight = getHighlightList().get(getHighlightList().size() - 1); + Component target = getTargetList().get(getTargetList().size() - 1); + highlight.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + if ((e.getClickCount() == 1 && clickType == ClickType.LEFT) || (e.getClickCount() == 2 && clickType == ClickType.LEFT_DOUBLE)) { + dealWithDispatchLeftClick(target, e, isDispatch); + } + } else if (e.getButton() == MouseEvent.BUTTON3 && clickType == ClickType.RIGHT) { + clear(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (isDispatch) { + redispatchMouseEvent(e, target); + } + complete(); + } + }); + } + + } + + + @Override + public void mousePressed(MouseEvent e) { + if ((target instanceof AbstractButton) && (target.getParent() instanceof UIButtonGroup)) { + if (isDispatch) { + redispatchMouseEvent(e, target); + } + } + + } + }); + } + + private void dealWithDispatchLeftClick(Component target, MouseEvent e, boolean isDispatch) { + clear(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (isDispatch) { + if (target instanceof AbstractButton) { + AbstractButton button = (AbstractButton) target; + ActionListener[] actionListeners= button.getActionListeners(); + for(int i = 0; i < actionListeners.length; i++) { + ActionListener actionListener = actionListeners[i]; + actionListener.actionPerformed(new ActionEvent( + button, + ActionEvent.ACTION_PERFORMED, + button.getActionCommand(), + e.getWhen(), + e.getModifiers() + )); + } + } else { + redispatchMouseEvent(e, target); + } + } + complete(); + } + }); + } + + private void redispatchMouseEvent(MouseEvent e, Component component) { + component.dispatchEvent(new MouseEvent(component, e.getID(), e + .getWhen(), e.getModifiers(), e.getX(), + e.getY(), e.getClickCount(), e.isPopupTrigger())); + } + + @Override + public void showScene() { + // 交互类的 scene 如果没有高亮内容块载,需要及时终止Guide,否则就没法去掉模态框影响到设计器主功能的使用了 + if (this.getComponentCount() == 0 && getHighlightList().isEmpty()) { + GuideManager.getInstance().getCurrentGuide().terminate(); + } else { + super.showScene(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DisplayScene.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DisplayScene.java new file mode 100644 index 0000000000..21ebe972de --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DisplayScene.java @@ -0,0 +1,37 @@ +package com.fr.design.mainframe.guide.scene; + +import java.util.Timer; +import java.util.TimerTask; + +public class DisplayScene extends AbstractGuideScene { + private long delay; + private static final long DEFAULT_DELAY = 1000; + private static Timer displayTimer = new Timer(); + + public DisplayScene() { + this(DEFAULT_DELAY); + } + + public DisplayScene(long delay) { + super(); + this.delay = delay; + } + + public void setDelay(long delay) { + this.delay = delay; + } + + @Override + public void showScene() { + super.showScene(); + // 实例化Timer类 + displayTimer.schedule(new TimerTask() { + @Override + public void run() { + complete(); + displayTimer.purge(); + } + }, delay); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DragScene.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DragScene.java new file mode 100644 index 0000000000..fdf8b2d4db --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DragScene.java @@ -0,0 +1,64 @@ +package com.fr.design.mainframe.guide.scene; + +import com.fr.design.mainframe.guide.scene.drag.DragAndDropDragGestureListener; + +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDropEvent; + +public class DragScene extends AbstractGuideScene{ + public enum DragType{ + NONE, FROM, TO + } + + public void addDragTarget(Component component, DragType type) { + if (super.addTarget(component)) { + addDragTargetListener(type); + } + } + + public void addDragTarget(Rectangle rectangle, DragType type) { + if (super.addTarget(rectangle)) { + addDragTargetListener(type); + } + } + + public void addDragTarget(Component component, Rectangle rectangle, DragType type) { + if (super.addTarget(component, rectangle)) { + addDragTargetListener(type); + } + } + + public void addCustomDragTarget(Component component, Rectangle rectangle, DragType type) { + if (super.addCustomTarget(component, rectangle)) { + addDragTargetListener(type); + } + } + + private void addDragTargetListener(DragType dragType) { + Component target = getHighlightList().get(getHighlightList().size() - 1); + + if (dragType == DragType.FROM) { + new DragAndDropDragGestureListener(target, DnDConstants.ACTION_COPY_OR_MOVE){ + @Override + public void dragDropEnd(DragSourceDropEvent dsde) { + if (dsde.getDropSuccess()) { + complete(); + } + } + }; + } else if (dragType == DragType.TO) { + target.setDropTarget(new DropSceneTarget()); + } + } + + private class DropSceneTarget extends DropTarget { + @Override + public synchronized void drop(DropTargetDropEvent dtde) { + dtde.dropComplete(true); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideScene.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideScene.java new file mode 100644 index 0000000000..e62ca4d9a9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideScene.java @@ -0,0 +1,18 @@ +package com.fr.design.mainframe.guide.scene; + + +public interface GuideScene { + GuideScene nextScene(GuideScene scene); + + void addSceneFilter(SceneFilter filter); + + void start(); + + void showScene(); + + void complete(); + + void registerLifecycle(GuideSceneLifecycle lifecycle); + + void removeLifecycle(); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycle.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycle.java new file mode 100644 index 0000000000..36734a619f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycle.java @@ -0,0 +1,21 @@ +package com.fr.design.mainframe.guide.scene; + +public interface GuideSceneLifecycle { + /** + * 引导场景准备工作 + * 给 scene 添加 target 应该在这个阶段处理 + * @return 返回true自动执行scene, 返回false需要手动触发 + */ + boolean prepared(); + + /** + * scene 显示后 + */ + void onShow(); + + /** + * scene 交互完成后处理 + * @return 返回true自动进入下一个scene,返回false需要手动触发 + */ + boolean onComplete(); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycleAdaptor.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycleAdaptor.java new file mode 100644 index 0000000000..1ed99dca6f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycleAdaptor.java @@ -0,0 +1,18 @@ +package com.fr.design.mainframe.guide.scene; + +public abstract class GuideSceneLifecycleAdaptor implements GuideSceneLifecycle { + @Override + public boolean prepared() { + return true; + } + + @Override + public void onShow() { + + } + + @Override + public boolean onComplete() { + return true; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/SceneFilter.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/SceneFilter.java new file mode 100644 index 0000000000..ea4ccf28fa --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/SceneFilter.java @@ -0,0 +1,5 @@ +package com.fr.design.mainframe.guide.scene; + +public interface SceneFilter { + GuideScene getFilterScene(); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/drag/DragAndDropDragGestureListener.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/drag/DragAndDropDragGestureListener.java new file mode 100644 index 0000000000..25979925d4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/scene/drag/DragAndDropDragGestureListener.java @@ -0,0 +1,60 @@ +package com.fr.design.mainframe.guide.scene.drag; + +import com.fr.general.ComparatorUtils; +import org.jetbrains.annotations.NotNull; + +import java.awt.Component; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; + +public class DragAndDropDragGestureListener extends DragSourceAdapter implements DragGestureListener { + private Component component; + + public DragAndDropDragGestureListener(Component component, int actions) { + this.component = component; + DragSource source = new DragSource(); + source.createDefaultDragGestureRecognizer(component, actions, this); + } + + public void dragGestureRecognized(DragGestureEvent dge) { + if (component != null) { + try { + DragAndDropTransferable dragAndDropTransferable = new DragAndDropTransferable(component); + dge.startDrag(DragSource.DefaultCopyDrop, dragAndDropTransferable, this); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private static class DragAndDropTransferable implements Transferable { + private Component component; + + public DragAndDropTransferable(Component component) { + this.component = component; + } + + DataFlavor[] flavors = {new DataFlavor(Component.class, "Component")}; + + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + for (DataFlavor df : flavors) { + if (ComparatorUtils.equals(df, flavor)) { + return true; + } + } + return false; + } + @NotNull + public Object getTransferData(DataFlavor df) { + return component; + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/tip/BubbleTip.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/tip/BubbleTip.java new file mode 100644 index 0000000000..13e5dc28f0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/tip/BubbleTip.java @@ -0,0 +1,97 @@ +package com.fr.design.mainframe.guide.tip; + +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.guide.base.Guide; +import com.fr.design.mainframe.guide.base.GuideManager; +import com.fr.design.mainframe.guide.ui.bubble.Bubble; +import com.fr.design.mainframe.guide.ui.bubble.BubbleWithClose; + +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class BubbleTip implements GuideTip { + private static final int GAP = 5; + private BubbleWithClose bubbleBox; + private Point anchor; + + + /** + * + * @param title 标题 + * @param content 内容 + * @param direction 气泡提示相对anchor的方向,这里方向会和气泡组件箭头方向相反 + * @param tailStart 气泡尾巴相对当前边垂直方向偏移位置比例,值在0-1范围 + */ + public BubbleTip(String title, String content, Direction direction, float tailStart) { + bubbleBox = new BubbleWithClose(title, content, getBubbleBoxTailDirection(direction), tailStart); + bubbleBox.addCloseActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Guide currentGuide = GuideManager.getInstance().getCurrentGuide(); + if (currentGuide != null) { + + int returnVal = FineJOptionPane.showConfirmDialog( + currentGuide.getGuideView(), + Toolkit.i18nText("Fine-Design_Guide_Option_Warning_Terminal"), + Toolkit.i18nText("Fine-Design_Basic_Confirm"), + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + if (returnVal == JOptionPane.YES_OPTION) { + currentGuide.terminate(); + } + } + } + }); + } + @Override + public JComponent getTip() { + if(anchor == null) { + return new BubbleWithClose(bubbleBox.getTitle(), bubbleBox.getContent(), Bubble.TailDirection.TOP, 0); + } else { + setBubbleBoxBound(); + return bubbleBox; + } + } + + /** + * 设置锚点坐标 + * 这里可以指定气泡组件箭头坐标的箭头坐标 + * @param anchor + */ + public void setAnchor(Point anchor) { + this.anchor = anchor; + } + + private void setBubbleBoxBound() { + int bubbleW = bubbleBox.getPreferredSize().width; + int bubbleH = bubbleBox.getPreferredSize().height; + if (bubbleBox.isTailHorizontal()) { + int x = bubbleBox.isTailLeft() ? anchor.x + GAP : anchor.x - bubbleW - GAP; + int y = anchor.y - (int) (bubbleH * bubbleBox.getTailStart()); + bubbleBox.setBounds(x, y, bubbleW, bubbleH); + } else if (bubbleBox.isTailVertical()) { + int x = anchor.x - (int) (bubbleW * bubbleBox.getTailStart()); + int y = bubbleBox.isTailTop() ? anchor.y + GAP : anchor.y - bubbleH - GAP; + bubbleBox.setBounds(x, y, bubbleW, bubbleH); + } + } + + private Bubble.TailDirection getBubbleBoxTailDirection(Direction direction) { + switch (direction) { + case TOP: + return Bubble.TailDirection.BOTTOM; + case BOTTOM: + return Bubble.TailDirection.TOP; + case LEFT: + return Bubble.TailDirection.RIGHT; + case RIGHT: + default: + return Bubble.TailDirection.LEFT; + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/tip/GuideTip.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/tip/GuideTip.java new file mode 100644 index 0000000000..e1573601f8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/tip/GuideTip.java @@ -0,0 +1,14 @@ +package com.fr.design.mainframe.guide.tip; + +import javax.swing.JComponent; +import java.awt.Point; + +public interface GuideTip { + enum Direction { + TOP, BOTTOM, LEFT, RIGHT + } + + JComponent getTip(); + + void setAnchor(Point anchor); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHint.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHint.java new file mode 100644 index 0000000000..79d49d1925 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHint.java @@ -0,0 +1,84 @@ +package com.fr.design.mainframe.guide.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.mainframe.guide.ui.bubble.Bubble; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionListener; + +public class BubbleHint extends Bubble { + private UIButton confirmButton; + private static final Color CONTENT_TEXT_COLOR = new Color(51, 51, 52); + + public BubbleHint() { + super(TailDirection.TOP, 0.9f); + initComponent(); + } + + private void initComponent() { + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(10 + Bubble.TAIL_HEIGHT, 15, 10, 15)); + this.setPreferredSize(new Dimension(220, 140)); + + JPanel contentPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(false, VerticalFlowLayout.CENTER, 0, 0); + contentPane.setOpaque(false); + + UILabel title = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Tips_Title")); + title.setFont(title.getFont().deriveFont(16.0f)); + title.setForeground(new Color(62, 155, 249)); + title.setPreferredSize(new Dimension(190, 30)); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); + + UILabel content1 = createContentLabel(Toolkit.i18nText("Fine-Design_Guide_Tips_Content1")); + + UILabel content2 = createContentLabel(Toolkit.i18nText("Fine-Design_Guide_Tips_Content2")); + + JPanel buttonContainer= FRGUIPaneFactory.createCenterFlowZeroGapBorderPane(); + buttonContainer.setBorder(BorderFactory.createEmptyBorder(15, 0, 0, 0)); + buttonContainer.setPreferredSize(new Dimension(190,40)); + buttonContainer.setOpaque(false); + + confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Guide_Tips_Know")) { + public Dimension getPreferredSize() { + return new Dimension(78, 24); + } + }; + + buttonContainer.add(confirmButton); + + contentPane.add(title); + contentPane.add(content1); + contentPane.add(content2); + contentPane.add(buttonContainer); + + this.add(contentPane, BorderLayout.CENTER); + } + + public void addConfirmAction(ActionListener listener) { + confirmButton.addActionListener(listener); + } + + public void removeConfirmAction(ActionListener listener) { + confirmButton.removeActionListener(listener); + } + + private UILabel createContentLabel(String text) { + UILabel content = new UILabel(text); + content.setPreferredSize(new Dimension(190,20)); + content.setHorizontalAlignment(SwingConstants.CENTER); + content.setFont(content.getFont().deriveFont(14.0f)); + content.setForeground(CONTENT_TEXT_COLOR); + return content; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/ExpandPane.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/ExpandPane.java new file mode 100644 index 0000000000..c4e6e01601 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/ExpandPane.java @@ -0,0 +1,78 @@ +package com.fr.design.mainframe.guide.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.general.IOUtils; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ExpandPane extends JPanel { + private static final Icon downIcon = IOUtils.readIcon("/com/fr/design/mainframe/guide/arrow_down.png"); + private static final Icon rightIcon = IOUtils.readIcon("/com/fr/design/mainframe/guide/arrow_right.png"); + private String title; + private boolean expand; + private UILabel arrow; + private JPanel headerPane; + private JPanel contentPane; + + public ExpandPane(String title, JPanel contentPane) { + this.title = title; + this.expand = true; + this.contentPane = contentPane; + initComponent(); + } + + private void initComponent() { + VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 0); + layout.setAlignLeft(true); + this.setLayout(layout); + + JPanel headerPane = createHeader(); + this.add(headerPane); + this.add(contentPane); + headerPane.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + setExpand(!expand); + } + }); + } + + private JPanel createHeader() { + headerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + headerPane.setPreferredSize(new Dimension(200, 16)); + UILabel headerTitle = new UILabel(this.title); + headerTitle.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + arrow = new UILabel(downIcon); + arrow.setOpaque(false); + arrow.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + headerPane.add(headerTitle, BorderLayout.CENTER); + headerPane.add(arrow, BorderLayout.WEST); + return headerPane; + } + + @Override + public void setPreferredSize(Dimension preferredSize) { + super.setPreferredSize(preferredSize); + headerPane.setPreferredSize(new Dimension(preferredSize.width, headerPane.getPreferredSize().height)); + contentPane.setPreferredSize(new Dimension(preferredSize.width, contentPane.getPreferredSize().height)); + } + + public void setExpand(boolean isExpand) { + this.expand = isExpand; + arrow.setIcon(isExpand ? downIcon : rightIcon); + contentPane.setVisible(isExpand); + } + + public boolean isExpand() { + return expand; + } +} + diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideCompleteDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideCompleteDialog.java new file mode 100644 index 0000000000..1d5b907e3b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideCompleteDialog.java @@ -0,0 +1,142 @@ +package com.fr.design.mainframe.guide.ui; + +import com.fr.design.gui.frpane.UITextPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIButtonUI; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.guide.utils.GuideUIUtils; +import com.fr.design.utils.gui.GUIPaintUtils; +import com.fr.general.IOUtils; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class GuideCompleteDialog extends JDialog { + private static final int DIALOG_WIDTH = 340; + private static final int DIALOG_HEIGHT = 367; + private static final Icon SUCCESS_ICON = IOUtils.readIcon("/com/fr/design/mainframe/guide/success.png"); + private static final int ICON_HEIGHT = 182; + private static final Color FONT_COLOR = new Color(51, 51, 52); + private static final Color BUTTON_BG_COLOR = new Color(65, 155,249); + private static final Font TITLE_FONT = new Font("Default", Font.BOLD, 22); + private static final Font CONTENT_FONT = new Font("Default", Font.PLAIN, 18); + private static final Font BUTTON_FONT = new Font("Default", Font.BOLD, 14); + private static GuideCompleteDialog dialog; + + public static GuideCompleteDialog getInstance() { + if (dialog == null) { + dialog = new GuideCompleteDialog(DesignerContext.getDesignerFrame()); + } + dialog = new GuideCompleteDialog(DesignerContext.getDesignerFrame()); + return dialog; + } + + private UITextPane textArea; + + public GuideCompleteDialog(Window window) { + super(window); + setSize(DIALOG_WIDTH, DIALOG_HEIGHT); + setUndecorated(true); + setModal(true); + setLocationRelativeTo(window); + this.setContentPane(getContentPane()); + } + + @Override + public Container getContentPane() { + JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + UILabel completeImage = new UILabel(SUCCESS_ICON); + completeImage.setPreferredSize(new Dimension(DIALOG_WIDTH, ICON_HEIGHT)); + + JPanel container = new JPanel(new BorderLayout(0, 10)); + container.setBorder(BorderFactory.createEmptyBorder(15, 52, 25, 52)); + + UILabel title = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Complete_Confirm")); + title.setFont(TITLE_FONT); + title.setPreferredSize(new Dimension(190, 30)); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setForeground(FONT_COLOR); + + textArea = new UITextPane(); + textArea.setFont(CONTENT_FONT); + GuideUIUtils.setTextPaneLineHeight(textArea, 26); + textArea.setEnabled(false); + textArea.setOpaque(false); + textArea.setPreferredSize(new Dimension(236, 52)); + textArea.setDisabledTextColor(FONT_COLOR); + StyledDocument doc = textArea.getStyledDocument(); + SimpleAttributeSet center = new SimpleAttributeSet(); + StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); + doc.setParagraphAttributes(0, doc.getLength(), center, false); + + JPanel buttonContainer= FRGUIPaneFactory.createCenterFlowZeroGapBorderPane(); + buttonContainer.setPreferredSize(new Dimension(190,43)); + buttonContainer.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + buttonContainer.setOpaque(false); + + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Guide_Complete_End")){ + @Override + public Dimension getPreferredSize() { + return new Dimension(122, 38); + } + }; + button.setFont(BUTTON_FONT); + button.setUI(confirmButtonUI); + button.setRoundBorder(true); + button.setForeground(Color.WHITE); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setVisible(false); + dispose(); + } + }); + + buttonContainer.add(button); + container.add(title, BorderLayout.NORTH); + container.add(textArea, BorderLayout.CENTER); + container.add(buttonContainer,BorderLayout.SOUTH); + + contentPane.add(completeImage, BorderLayout.NORTH); + contentPane.add(container, BorderLayout.CENTER); + + return contentPane; + } + + public void showDialog(String str) { + textArea.setText(str); + repaint(); + this.setVisible(true); + } + + private UIButtonUI confirmButtonUI = new UIButtonUI() { + protected void doExtraPainting(UIButton b, Graphics2D g2d, int w, int h, String selectedRoles) { + if (isPressed(b) && b.isPressedPainted()) { + GUIPaintUtils.fillPressed(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), BUTTON_BG_COLOR); + } else if (isRollOver(b)) { + GUIPaintUtils.fillRollOver(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted(), BUTTON_BG_COLOR); + } else if (b.isNormalPainted()) { + GUIPaintUtils.fillNormal(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted(), BUTTON_BG_COLOR); + } + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideLoadingGlassPane.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideLoadingGlassPane.java new file mode 100644 index 0000000000..44590540da --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideLoadingGlassPane.java @@ -0,0 +1,60 @@ +package com.fr.design.mainframe.guide.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; + +public class GuideLoadingGlassPane extends JPanel { + private static GuideLoadingGlassPane loadingPane; + + public static GuideLoadingGlassPane getInstance() { + if (loadingPane == null) { + loadingPane = new GuideLoadingGlassPane(); + } + return loadingPane; + } + + public GuideLoadingGlassPane() { + this.setLayout(new GridBagLayout()); + this.setOpaque(false); + initComponent(); + } + + public void initComponent() { + JPanel loadingView = FRGUIPaneFactory.createBorderLayout_S_Pane(); + loadingView.setOpaque(false); + loadingView.setPreferredSize(new Dimension(150, 90)); + + JPanel imageContainer = FRGUIPaneFactory.createCenterFlowInnerContainer_S_Pane(); + imageContainer.setOpaque(false); + + imageContainer.add(GuideLoadingPane.getInstance()); + + UILabel hintLabel = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Loading_Wait")); + hintLabel.setFont(new Font("Default", Font.PLAIN, 14)); + hintLabel.setHorizontalAlignment(SwingConstants.CENTER); + hintLabel.setForeground(Color.WHITE); + + loadingView.add(imageContainer, BorderLayout.NORTH); + loadingView.add(hintLabel, BorderLayout.SOUTH); + + this.add(loadingView, new GridBagConstraints()); + } + + public void startLoading() { + GuideLoadingPane.getInstance().start(); + } + + public void stopLoading() { + GuideLoadingPane.getInstance().stop(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideLoadingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideLoadingPane.java new file mode 100644 index 0000000000..0a290c784c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideLoadingPane.java @@ -0,0 +1,98 @@ +package com.fr.design.mainframe.guide.ui; + +import javax.swing.JPanel; +import javax.swing.Timer; +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Created by kerry on 2020-10-23 + */ +public class GuideLoadingPane extends JPanel { + private static final BasicStroke STROKE = new BasicStroke(4); + private static final int FPS = 30; + private static final int START_ANGLE = 90; + private static GuideLoadingPane imagePanel; + private Image image; + private int angle; + private Timer timer; + + public static GuideLoadingPane getInstance() { + if (imagePanel == null) { + imagePanel = new GuideLoadingPane(); + } + return imagePanel; + } + + public GuideLoadingPane() { + this.setOpaque(false); + this.setPreferredSize(new Dimension(50, 50)); + timer = new Timer(1000 / FPS, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + repaint(); + angle -= 180 / FPS; // 5 degrees per 100 ms = 50 degrees/second + if (angle > -270) { + angle += 2 * 360; + } + } + }); + } + + public void start() { + angle = START_ANGLE; + timer.start(); + } + + public void stop() { + timer.stop(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Composite oldComposite = g2.getComposite(); + Stroke oldStroke = g2.getStroke(); + + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + + int d = Math.min(getWidth(), getHeight()); + int r = d / 2; + Point circlePoint = new Point(getWidth() / 2, getHeight() / 2); + + g2.setColor(Color.WHITE); + g2.fillOval(circlePoint.x - r, circlePoint.y - r, d, d); + + g2.setColor(Color.BLACK); + int waitCircleD = d / 10; + int waitCircleR = waitCircleD / 2; + + g2.fillOval(circlePoint.x - r / 3 - waitCircleR, circlePoint.y - waitCircleR, waitCircleD, waitCircleD); + g2.fillOval(circlePoint.x - waitCircleR, circlePoint.y - waitCircleR, waitCircleD, waitCircleD); + g2.fillOval(circlePoint.x + r / 3 - waitCircleR, circlePoint.y - waitCircleR, waitCircleD, waitCircleD); + + + g2.setStroke(STROKE); + g2.setColor(Color.decode("#419BF9")); + + int lineWidth = (int) STROKE.getLineWidth(); + g2.drawArc(circlePoint.x - r + lineWidth / 2 , circlePoint.y - r + lineWidth / 2, d - lineWidth, d - lineWidth, angle, -90); + + g2.setStroke(oldStroke); + g2.setComposite(oldComposite); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideManageDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideManageDialog.java new file mode 100644 index 0000000000..ca53613c46 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideManageDialog.java @@ -0,0 +1,233 @@ +package com.fr.design.mainframe.guide.ui; + + +import com.fr.base.svg.IconUtils; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.guide.base.Guide; +import com.fr.design.mainframe.guide.base.GuideGroup; +import com.fr.design.mainframe.guide.base.GuideManager; +import com.fr.design.mainframe.guide.base.GuideVersion; +import com.fr.design.mainframe.guide.collect.GuideCollector; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.border.Border; +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; + +public class GuideManageDialog extends JDialog { + private static final int DEFAULT_HEIGHT = 400; + private static final int DEFAULT_WIDTH = 600; + private static final Icon GROUP_COMPLETE_NONE = IconUtils.readIcon("/com/fr/design/mainframe/guide/complete_none.svg"); + private static final Icon GROUP_COMPLETE_SOME = IconUtils.readIcon("/com/fr/design/mainframe/guide/complete_some.svg"); + private static final Icon GROUP_COMPLETE_ALL = IconUtils.readIcon("/com/fr/design/mainframe/guide/complete_all.svg"); + private static final Color BORDER_COLOR = new Color(224, 224, 225); + private static final Color UNCOMPLETE_FONT_COLOR = new Color(51, 51, 52); + private static final Color COMPLETE_FONT_COLOR = new Color(51,51,52,128); + private static GuideManageDialog dialog; + + private JPanel scrollContent; + + public static GuideManageDialog getInstance() { + if (dialog == null) { + dialog = new GuideManageDialog(DesignerContext.getDesignerFrame()); + } + return dialog; + } + + public GuideManageDialog(Window parent) { + super(parent); + GuideCollector.getInstance().load(); + initComponent(); + } + + private void initComponent() { + this.setTitle(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Title")); + setResizable(false); + setModal(true); + setLayout(FRGUIPaneFactory.createBorderLayout()); + setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); + GUICoreUtils.centerWindow(this); + JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + contentPane.add(createContentPanel(), BorderLayout.CENTER); + contentPane.add(createActionsPane(), BorderLayout.SOUTH); + setContentPane(contentPane); + } + + private UIScrollPane createContentPanel() { + scrollContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 5); + UIScrollPane scrollPane = new UIScrollPane(scrollContent); + return scrollPane; + } + + private JPanel createGuideVersionPane(GuideVersion guideVersion) { + JPanel expandContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 10); + for (GuideGroup guideGroup : guideVersion.getGuideGroupList()) { + JPanel guideGroupCard = createGuideGroupCard(guideGroup); + expandContent.add(guideGroupCard); + } + ExpandPane expandPane = new ExpandPane(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Version_Title", guideVersion.getVersion()), expandContent); + return expandPane; + } + + + private JPanel createGuideGroupCard(GuideGroup guideGroup) { + JPanel card = FRGUIPaneFactory.createBorderLayout_S_Pane(); + card.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + card.setBackground(Color.WHITE); + + JPanel cardContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + cardContainer.setOpaque(false); + cardContainer.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + card.add(cardContainer, BorderLayout.CENTER); + + cardContainer.add(createGroupTitlePane(guideGroup), BorderLayout.NORTH); + cardContainer.add(createGroupContentPane(guideGroup), BorderLayout.CENTER); + return card; + } + + private JPanel createGroupTitlePane(GuideGroup guideGroup) { + JPanel titleContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.CENTER, 0, 0); + titleContainer.setBorder(getBottomBorder()); + titleContainer.setOpaque(false); + + titleContainer.setPreferredSize(new Dimension(500, 40)); + JPanel titlePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 8,0 ); + titlePane.setOpaque(false); + + UILabel iconLabel = new UILabel(getGroupStateIcon(guideGroup)); + iconLabel.setPreferredSize(new Dimension(16, 16)); + iconLabel.setOpaque(false); + + UILabel titleLabel = new UILabel(guideGroup.getName()); + titleLabel.setPreferredSize(new Dimension(200, 16)); + titleLabel.setForeground(new Color(65, 155, 249)); + titleLabel.setOpaque(false); + + titlePane.add(iconLabel); + titlePane.add(titleLabel); + titleContainer.add(titlePane); + return titleContainer; + } + + private JPanel createGroupContentPane(GuideGroup guideGroup) { + JPanel groupContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 0); + groupContainer.setBorder(BorderFactory.createEmptyBorder(0,10,0,0)); + groupContainer.setOpaque(false); + for (int index = 0; index < guideGroup.getGuideList().size(); index++) { + JPanel guidePane = createGuidePane(guideGroup.getGuideList().get(index), index); + if (index != guideGroup.getGuideList().size() - 1) { + guidePane.setBorder(getBottomBorder()); + } + groupContainer.add(guidePane); + } + return groupContainer; + } + + + + private JPanel createGuidePane(Guide guide, int index) { + JPanel guidePaneContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.CENTER, 0, 0); + guidePaneContainer.setPreferredSize(new Dimension(540, 40)); + guidePaneContainer.setOpaque(false); + + JPanel guidePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 50,0 ); + guidePane.setOpaque(false); + + UILabel title = new UILabel((index + 1) + "、" + guide.getDescription()); + title.setPreferredSize(new Dimension(440, 20)); + title.setForeground(guide.isComplete() ? COMPLETE_FONT_COLOR : UNCOMPLETE_FONT_COLOR); + title.setOpaque(false); + + + UIButton button = new UIButton(guide.isComplete() ? Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Retry") : Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Show")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setVisible(false); + guide.go(); + } + }); + + button.setPreferredSize(new Dimension(48, 20)); + guidePane.add(title); + guidePane.add(button); + + guidePaneContainer.add(guidePane); + return guidePaneContainer; + } + + private Border getBottomBorder() { + return BorderFactory.createMatteBorder( + 0,0,1, 0, BORDER_COLOR + ); + } + + public void showDialog() { + resetScrollContent(); + this.setVisible(true); + } + + private Icon getGroupStateIcon(GuideGroup guideGroup) { + if (guideGroup.isCompleteAll()) { + return GROUP_COMPLETE_ALL; + } else if (guideGroup.isCompleteSome()) { + return GROUP_COMPLETE_SOME; + } else { + return GROUP_COMPLETE_NONE; + } + } + + private UIButton createCompleteAllButton() { + UIButton button = new UIButton(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Complete_All"))); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + GuideManager.getInstance().completeAll(); + resetScrollContent(); + } + }); + return button; + } + + private UIButton createCloseButton() { + UIButton button = new UIButton(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Close"))); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + return button; + } + + private JPanel createActionsPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createEmptyBorder(7, 10, 7, 10)); + container.add(createCompleteAllButton(), BorderLayout.WEST); + container.add(createCloseButton(), BorderLayout.EAST); + return container; + } + + private void resetScrollContent() { + scrollContent.removeAll(); + for (GuideVersion guideVersion : GuideManager.getInstance().getGuideVersionList()) { + scrollContent.add(createGuideVersionPane(guideVersion)); + } + revalidate(); + repaint(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/Bubble.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/Bubble.java new file mode 100644 index 0000000000..10b04362e1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/Bubble.java @@ -0,0 +1,152 @@ +package com.fr.design.mainframe.guide.ui.bubble; + +import javax.swing.JComponent; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; + +public class Bubble extends JComponent { + public enum TailDirection { + TOP, BOTTOM, LEFT, RIGHT + } + protected static final int TAIL_HEIGHT = 7; + protected static final int TAIL_WIDTH = 14; + protected static final int BUBBLE_WIDTH = 170; + protected static final Color BG_COLOR = new Color(240,240,241); + protected static final int BORDER_RADIUS = 10; + + + private TailDirection tailDirection; + private float tailStart; + + public Bubble() { + this(TailDirection.LEFT, 0.5f); + } + + public Bubble(TailDirection tailDirection, float tailStart) { + this.tailDirection = tailDirection; + this.tailStart = tailStart; + this.setOpaque(false); + } + + public void setTailDirection(TailDirection tailDirection) { + this.tailDirection = tailDirection; + } + + public TailDirection getTailDirection() { + return tailDirection; + } + + public void setTailStart(float tailStart) { + this.tailStart = tailStart; + } + + public float getTailStart() { + return tailStart; + } + + + @Override + public Dimension getPreferredSize() { + if (isPreferredSizeSet()) { + return super.getPreferredSize(); + } + return new Dimension(getDefaultWidth(), getDefaultHeight()); + + } + + protected int getDefaultWidth() { + return (isTailHorizontal() ? TAIL_HEIGHT : 0) + BUBBLE_WIDTH; + } + + protected int getDefaultHeight() { + return (isTailVertical() ? TAIL_HEIGHT : 0); + } + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + Composite oldComposite = g2.getComposite(); + paintBubbleBg(g2); + g2.setComposite(oldComposite); + super.paintComponent(g); + } + + protected void paintBubbleBg(Graphics2D g2) { + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + paintRectBg(g2); + paintTailBg(g2); + } + + protected void paintRectBg(Graphics2D g2) { + g2.setColor(BG_COLOR); + Rectangle bounds = getRectBounds(); + g2.fillRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, BORDER_RADIUS, BORDER_RADIUS); + } + + protected void paintTailBg(Graphics2D g2) { + int width = getWidth(); + int height = getHeight(); + if (isTailVertical()) { + int tailX = (int) (width * tailStart); + int startX = Math.max(tailX - TAIL_WIDTH / 2, 0); + int endX = startX + TAIL_WIDTH; + int[] xPoints = {startX, endX, tailX}; + int[] yPoints = isTailTop() ? new int[]{TAIL_HEIGHT, TAIL_HEIGHT, 0} : new int[]{height - TAIL_HEIGHT, height - TAIL_HEIGHT, height}; + g2.fillPolygon(xPoints, yPoints, 3); + } else if (isTailHorizontal()) { + int tailY = (int) (height * tailStart); + int startY = Math.max(tailY - TAIL_WIDTH / 2, 0); + int endY = startY + TAIL_WIDTH; + int[] xPoints = isTailLeft() ? new int[]{TAIL_HEIGHT, TAIL_HEIGHT, 0} : new int[]{width - TAIL_HEIGHT, width - TAIL_HEIGHT, width}; + int[] yPoints = {startY, endY, tailY}; + g2.fillPolygon(xPoints, yPoints, 3); + } + } + + public Rectangle getRectBounds() { + int width = getWidth(); + int height = getHeight(); + switch (tailDirection) { + case TOP: + return new Rectangle(0, TAIL_HEIGHT, width, height - TAIL_HEIGHT); + case LEFT: + return new Rectangle(TAIL_HEIGHT, 0, width - TAIL_HEIGHT, height); + case RIGHT: + return new Rectangle(0, 0 , width - TAIL_HEIGHT, height); + case BOTTOM: + return new Rectangle(0, 0, width, height - TAIL_HEIGHT); + default: + return new Rectangle(0,0,0,0); + } + } + + public boolean isTailHorizontal() { + return isTailLeft() || isTailRight(); + } + + public boolean isTailVertical() { + return isTailTop() || isTailBottom(); + } + + public boolean isTailLeft() { + return tailDirection == TailDirection.LEFT; + } + + public boolean isTailRight() { + return tailDirection == TailDirection.RIGHT; + } + + public boolean isTailTop() { + return tailDirection == TailDirection.TOP; + } + + public boolean isTailBottom() { + return tailDirection == TailDirection.BOTTOM; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/BubbleWithClose.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/BubbleWithClose.java new file mode 100644 index 0000000000..6851c09cd5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/BubbleWithClose.java @@ -0,0 +1,282 @@ +package com.fr.design.mainframe.guide.ui.bubble; + + +import com.fr.base.GraphHelper; +import com.fr.design.gui.frpane.UITextPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.guide.utils.GuideUIUtils; +import com.fr.general.IOUtils; +import com.fr.stable.StringUtils; + +import javax.swing.Icon; +import javax.swing.JTextPane; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + +public class BubbleWithClose extends Bubble { + private static final Font TITLE_FONT = new Font("Default", Font.PLAIN, 14); + private static final Font CONTENT_FONT = new Font("Default", Font.PLAIN, 12); + private static final int TITLE_LINE_HEIGHT = 22; + private static final int CONTENT_LINE_HEIGHT = 18; + + private static final Icon ICON = IOUtils.readIcon("/com/fr/design/mainframe/guide/close.png"); + private static final Color TITLE_COLOR = new Color(51, 51, 52); + private static final Color CONTENT_COLOR = new Color(51,51,52,128); + private static final Color HIGHLIGHT_COLOR = new Color(65, 155, 249); + private static final Insets DEFAULT_INSET = new Insets(15, 15, 15, 15); + private static final int MIN_WIDTH = 140; + private static final int MAX_WIDTH = 275; + private static final int ICON_GAP = 10; + private static final int ICON_SIZE = 10; + private static final int TEXT_GAP = 5; + + + private String title; + private String content; + private UITextPane titleTextArea; + private UITextPane contentTextArea; + private UIButton closeButton; + private Dimension titleSize; + private Dimension contentSize; + + public BubbleWithClose(String title, String content) { + this(title, content, TailDirection.LEFT, 0.5f); + } + + public BubbleWithClose(String title, String content, TailDirection tailDirection, float tailStart) { + super(tailDirection, tailStart); + this.title = title; + this.content = content; + this.initComponent(); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + protected void initComponent() { + this.setLayout(getLayoutManager()); + createCloseButton(); + createContentPane(); + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(ComponentEvent e) { + super.componentShown(e); + } + + @Override + public void componentResized(ComponentEvent e) { + Rectangle rectBounds = getRectBounds(); + + closeButton.setBounds(rectBounds.x + rectBounds.width - DEFAULT_INSET.right - ICON_SIZE, rectBounds.y + 21, ICON_SIZE, ICON_SIZE); + if (titleTextArea != null) { + int x = rectBounds.x + DEFAULT_INSET.left; + int y = rectBounds.y + DEFAULT_INSET.top; + titleTextArea.setBounds(x, y, titleSize.width, titleSize.height); + } + + if (contentTextArea != null) { + int x = rectBounds.x + DEFAULT_INSET.left; + int y = rectBounds.y + DEFAULT_INSET.top + (titleSize.height == 0 ? 0 : titleSize.height + getTextGap()); + contentTextArea.setBounds(x,y, contentSize.width, contentSize.height); + } + setSize(getPreferredSize().width, getPreferredSize().height); + repaint(); + } + }); + } + + private void createCloseButton() { + closeButton = new UIButton(); + closeButton.setIcon(ICON); + closeButton.set4ToolbarButton(); + closeButton.setPreferredSize(new Dimension(ICON_SIZE, ICON_SIZE)); + closeButton.setRolloverEnabled(false); + closeButton.setPressedPainted(false); + this.add(closeButton); + } + + public void addCloseActionListener(ActionListener actionListener) { + closeButton.addActionListener(actionListener); + + } + + public void removeCloseActionListener(ActionListener actionListener){ + closeButton.removeActionListener(actionListener); + } + + private void createContentPane() { + createTitleTextArea(); + createContentTextArea(); + } + + private void createTitleTextArea() { + if (StringUtils.isNotEmpty(title)) { + titleTextArea = createTextArea(title, TITLE_FONT, TITLE_LINE_HEIGHT, TITLE_COLOR); + this.add(titleTextArea); + } + titleSize = calTextSize(titleTextArea, TITLE_LINE_HEIGHT, getTextAreaWidth(MAX_WIDTH), getTextAreaWidth(MIN_WIDTH)); + } + + private void createContentTextArea() { + if (StringUtils.isNotEmpty(content)) { + contentTextArea = createTextArea(content, CONTENT_FONT, CONTENT_LINE_HEIGHT, CONTENT_COLOR); + this.add(contentTextArea); + } + contentSize = calTextSize(contentTextArea, CONTENT_LINE_HEIGHT, getTextAreaWidth(MAX_WIDTH), getTextAreaWidth(MIN_WIDTH)); + } + + private UITextPane createTextArea(String str, Font font, int lineHeight, Color foreground) { + UITextPane textArea= new UITextPane(); + textArea.setFont(font); + GuideUIUtils.setTextPaneLineHeight(textArea, lineHeight); + textArea.setEditable(false); + textArea.setForeground(foreground); + textArea.setDisabledTextColor(foreground); + textArea.setOpaque(false); + textArea.setText(str); + highlightText(textArea); + return textArea; + } + + private void highlightText(JTextPane textArea) { + SimpleAttributeSet sas = new SimpleAttributeSet(); + StyleConstants.setForeground(sas, HIGHLIGHT_COLOR); + StyledDocument doc = textArea.getStyledDocument(); + String text = textArea.getText(); + int startPos = -1; + for (int i = 0; i < text.length(); i ++) { + char ch = text.charAt(i); + if (ch == '【') { + startPos = i; + } + if (ch == '】') { + if (startPos > 0) { + try { + doc.setCharacterAttributes(startPos, (i - startPos + 1), sas, false); + startPos = -1; + } catch (Exception e) { + } + } + } + } + + } + + @Override + protected int getDefaultWidth() { + return Math.max(titleSize.width, contentSize.width) + getHorizontalInsets() + ICON_GAP + ICON_SIZE + (isTailHorizontal() ? TAIL_HEIGHT : 0) ; + } + + @Override + protected int getDefaultHeight() { + return titleSize.height + contentSize.height + getTextGap() + getVerticalInsets() + (isTailVertical() ? TAIL_HEIGHT : 0); + } + + private int getTextGap() { + return (titleSize.height != 0 && contentSize.height != 0) ? TEXT_GAP : 0; + } + + private LayoutManager getLayoutManager() { + return new LayoutManager() { + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void removeLayoutComponent(Component comp) { + + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return parent.getPreferredSize(); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + + } + }; + } + + private int countLines(JTextPane textArea, int max_width) { + AttributedString text = new AttributedString(textArea.getText()); + text.addAttribute(TextAttribute.FONT, textArea.getFont()); + FontRenderContext frc = textArea.getFontMetrics(textArea.getFont()) + .getFontRenderContext(); + AttributedCharacterIterator charIt = text.getIterator(); + LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc); + lineMeasurer.setPosition(charIt.getBeginIndex()); + int lines = 0; + while (lineMeasurer.getPosition() < charIt.getEndIndex()) { + lineMeasurer.nextLayout(max_width); + lines++; + } + return lines; + } + + private Dimension calTextSize(JTextPane textArea, int lineHeight, int maxWidth, int minWidth) { + if (textArea == null) { + return new Dimension(minWidth, 0); + } + FontMetrics fontMetrics = GraphHelper.getFontMetrics(textArea.getFont()); + int line = countLines(textArea, maxWidth); + int width = maxWidth; + if (line == 1) { + width = Math.max(fontMetrics.stringWidth(textArea.getText()), minWidth); + } + int height = lineHeight * line; + return new Dimension(width, height); + } + + + private int getTextAreaWidth(int bubbleWidth) { + return bubbleWidth - getHorizontalInsets() - ICON_SIZE - ICON_GAP; + } + + + private int getHorizontalInsets() { + return DEFAULT_INSET.left + DEFAULT_INSET.right; + } + + private int getVerticalInsets() { + return DEFAULT_INSET.top + DEFAULT_INSET.bottom; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/utils/GuideUIUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/utils/GuideUIUtils.java new file mode 100644 index 0000000000..bd6ee33102 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/utils/GuideUIUtils.java @@ -0,0 +1,28 @@ +package com.fr.design.mainframe.guide.utils; + +import com.fr.base.GraphHelper; + +import javax.swing.BorderFactory; +import javax.swing.JTextPane; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import java.awt.FontMetrics; +import java.awt.Insets; + +public class GuideUIUtils { + public static void setTextPaneLineHeight(JTextPane pane, int lineHeight) { + pane.selectAll(); + pane.setMargin(new Insets(0,0,0,0)); + MutableAttributeSet set = new SimpleAttributeSet(pane.getParagraphAttributes()); + FontMetrics fontMetrics = GraphHelper.getFontMetrics(pane.getFont()); + int delta = (lineHeight - fontMetrics.getHeight()) / 2 * 2 ; + if (delta > 0) { + StyleConstants.setLineSpacing(set, delta/ 2.0f / fontMetrics.getHeight()); + pane.setParagraphAttributes(set, false); + int dis = fontMetrics.getDescent() - fontMetrics.getLeading(); + int marginTop = dis > 0 ? ((delta - dis) / 2 + dis) : ((delta - dis) / 2); + pane.setBorder(BorderFactory.createEmptyBorder(marginTop, 0,0,0)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/guide/utils/ScreenImage.java b/designer-base/src/main/java/com/fr/design/mainframe/guide/utils/ScreenImage.java new file mode 100644 index 0000000000..8705d0e8a4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/guide/utils/ScreenImage.java @@ -0,0 +1,98 @@ +package com.fr.design.mainframe.guide.utils; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import java.awt.AWTException; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; + +public class ScreenImage { + + public static BufferedImage createImage(JComponent component) { + return ScreenImage.createImage(component, getRegion(component)); + } + + public static BufferedImage createImage(JComponent component, Rectangle region) { + if (! component.isDisplayable()) { + Dimension d = component.getSize(); + + if (d.width == 0 || d.height == 0) { + d = component.getPreferredSize(); + component.setSize( d ); + } + + layoutComponent( component ); + } + + BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = image.createGraphics(); + + if (! component.isOpaque()) { + g2d.setColor( component.getBackground() ); + g2d.fillRect(region.x, region.y, region.width, region.height); + } + + g2d.translate(-region.x, -region.y); + component.print( g2d ); + g2d.dispose(); + return image; + } + + public static BufferedImage createImage(Component component) + throws AWTException { + Point p = new Point(0, 0); + SwingUtilities.convertPointToScreen(p, component); + Rectangle region = component.getBounds(); + region.x = p.x; + region.y = p.y; + return ScreenImage.createImage(region); + } + + public static BufferedImage createImageWithModal(JComponent component) { + Rectangle region = getRegion(component); + BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = image.createGraphics(); + g2d.drawImage(createImage(component), 0, 0, null); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f)); + g2d.setColor(Color.BLACK); + g2d.fillRect(0, 0, region.width, region.height); + g2d.dispose(); + return image; + } + + public static BufferedImage createImage(Rectangle region) + throws AWTException { + BufferedImage image = new Robot().createScreenCapture( region ); + return image; + } + + private static Rectangle getRegion(Component component) { + Dimension d = component.getSize(); + if (d.width == 0 || d.height == 0) { + d = component.getPreferredSize(); + component.setSize( d ); + } + return new Rectangle(0, 0, d.width, d.height); + } + + static void layoutComponent(Component component) { + synchronized (component.getTreeLock()) { + component.doLayout(); + + if (component instanceof Container) { + for (Component child : ((Container)component).getComponents()) { + layoutComponent(child); + } + } + } + } + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java index 118ea2e321..f965c21725 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java @@ -1,41 +1,41 @@ package com.fr.design.mainframe.loghandler; - -import com.fr.third.apache.log4j.AppenderSkeleton; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; - +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.Filter; +import com.fr.third.apache.logging.log4j.core.Layout; +import com.fr.third.apache.logging.log4j.core.LogEvent; +import com.fr.third.apache.logging.log4j.core.appender.AbstractAppender; +import com.fr.third.apache.logging.log4j.core.config.Property; +import com.fr.third.apache.logging.log4j.core.layout.PatternLayout; +import java.io.Serializable; import java.util.Date; /** * Created by Administrator on 2017/7/18 0018. */ -public class DesignerLogAppender extends AppenderSkeleton { +public class DesignerLogAppender extends AbstractAppender { - public DesignerLogAppender() { - this.layout = new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"); + protected DesignerLogAppender(String name, Filter filter, + Layout layout, + boolean ignoreExceptions, + Property[] properties) { + super(name, filter, layout, ignoreExceptions, properties); } - protected void append(LoggingEvent event) { - this.subAppend(event); + public static DesignerLogAppender createDesignerLogAppender() { + return new DesignerLogAppender(DesignerLogAppender.class.getSimpleName(), null, PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n %throwable{0}").build(), false, Property.EMPTY_ARRAY); } - public boolean requiresLayout() { - return true; + @Override + public void append(LogEvent event) { + this.subAppend(event); } - public synchronized void close() { - if (this.closed) { - return; - } - this.closed = true; - - } - public void subAppend(LoggingEvent event) { + public void subAppend(LogEvent event) { synchronized (DesignerLogHandler.getInstance()) { Level level = event.getLevel(); - String msg = this.layout.format(event); + String msg = (String) this.toSerializable(event); DesignerLogHandler.getInstance().printRemoteLog(msg, level, new Date()); } } 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 1d67c47df1..1cb8e5d1aa 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 @@ -9,10 +9,9 @@ import com.fr.general.ComparatorUtils; import com.fr.general.log.Log4jConfig; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; -import com.fr.third.apache.log4j.spi.ThrowableInformation; +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.LogEvent; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; @@ -128,7 +127,7 @@ public class DesignerLogHandler { JPopupMenu jPopupMenu = new JPopupMenu(); - int logLevelInt = Log4jConfig.getInstance().getRootLevel().toInt(); + int logLevelInt = Log4jConfig.getInstance().getRootLevel().intLevel(); if (logLevelInt <= DesignerLogger.INFO_INT) { jPopupMenu.add(showInfo); jPopupMenu.add(showError); @@ -240,23 +239,22 @@ public class DesignerLogHandler { return resultPane; } - public void printStackTrace(LoggingEvent event) { + public void printStackTrace(LogEvent event) { - int intLevel = event.getLevel().toInt(); - Date date = new Date(event.getTimeStamp()); - ThrowableInformation information = event.getThrowableInformation(); + int intLevel = event.getLevel().intLevel(); + Date date = new Date(event.getTimeMillis()); if (intLevel == DesignerLogger.INFO_INT && showInfo.isSelected()) { - printMessage(event.getRenderedMessage(), intLevel, date, information == null ? null : information.getThrowable()); + printMessage(event.getMessage().getFormattedMessage(), intLevel, date, event.getThrown()); } else if (intLevel == DesignerLogger.ERROR_INT && showError.isSelected()) { - printMessage(event.getRenderedMessage(), intLevel, date, information == null ? null : information.getThrowable()); + printMessage(event.getMessage().getFormattedMessage(), intLevel, date, event.getThrown()); } else if (intLevel == DesignerLogger.WARN_INT && showServer.isSelected()) { - printMessage(event.getRenderedMessage(), intLevel, date, information == null ? null : information.getThrowable()); + printMessage(event.getMessage().getFormattedMessage(), intLevel, date, event.getThrown()); } } public void printStackTrace(String message, Level level, Date date) { - int intLevel = level.toInt(); + int intLevel = level.intLevel(); if (intLevel == DesignerLogger.INFO_INT && showInfo.isSelected()) { printMessage(message, intLevel, date); } else if (intLevel == DesignerLogger.ERROR_INT && showError.isSelected()) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java index b2b35da1cd..3b6d4bf7a6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java @@ -1,26 +1,25 @@ package com.fr.design.mainframe.loghandler; import com.fr.log.FineLoggerFactory; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; -import com.fr.third.apache.log4j.spi.ThrowableInformation; +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.LogEvent; /** * 设计器日志记录 */ public class DesignerLogger { - public static final int INFO_INT = Level.INFO.toInt(); + public static final int INFO_INT = Level.INFO.intLevel(); - public static final int ERROR_INT = Level.ERROR.toInt(); + public static final int ERROR_INT = Level.ERROR.intLevel(); - public static final int WARN_INT = Level.WARN.toInt(); + public static final int WARN_INT = Level.WARN.intLevel(); /** * 记录LoggingEvent对象 * * @param event */ - public static void log(LoggingEvent event) { + public static void log(LogEvent event) { if (event == null) { return; } @@ -30,29 +29,27 @@ public class DesignerLogger { public enum LogParser { DEFAULT(-1) { @Override - public void log(LoggingEvent event) { + public void log(LogEvent event) { } }, - INFO(Level.INFO.toInt()) { + INFO(Level.INFO.intLevel()) { @Override - public void log(LoggingEvent event) { - FineLoggerFactory.getLogger().info(event.getRenderedMessage()); + public void log(LogEvent event) { + FineLoggerFactory.getLogger().info(event.getMessage().getFormattedMessage()); } }, - WARN(Level.WARN.toInt()) { + WARN(Level.WARN.intLevel()) { @Override - public void log(LoggingEvent event) { - ThrowableInformation information = event.getThrowableInformation(); - FineLoggerFactory.getLogger().warn(event.getRenderedMessage(), information == null ? null : information.getThrowable()); + public void log(LogEvent event) { + FineLoggerFactory.getLogger().warn(event.getMessage().getFormattedMessage(), event.getThrown()); } }, - ERROR(Level.ERROR.toInt()) { + ERROR(Level.ERROR.intLevel()) { @Override - public void log(LoggingEvent event) { - ThrowableInformation information = event.getThrowableInformation(); - FineLoggerFactory.getLogger().error(event.getRenderedMessage(), information == null ? null : information.getThrowable()); + public void log(LogEvent event) { + FineLoggerFactory.getLogger().error(event.getMessage().getFormattedMessage(), event.getThrown()); } }; private int level; @@ -65,8 +62,8 @@ public class DesignerLogger { return level; } - public static LogParser parse(LoggingEvent event) { - int intLevel = event.getLevel().toInt(); + public static LogParser parse(LogEvent event) { + int intLevel = event.getLevel().intLevel(); for (LogParser logParser : values()) { if (logParser.getLevel() == intLevel) { return logParser; @@ -76,7 +73,7 @@ public class DesignerLogger { } - public void log(LoggingEvent event) { + public void log(LogEvent event) { } } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboCheckBoxStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboCheckBoxStyleProvider.java new file mode 100644 index 0000000000..027e95df3e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboCheckBoxStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.combo; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.combo.SimpleComboPane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.combo.SimpleComboStyle; + +public class SimpleComboCheckBoxStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return SimpleComboStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleComboPane.class; + } + + @Override + public String xTypeForWidget() { + return "tagcombocheckbox"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-SimpleCombo_SimpleComboStyle"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboStyleProvider.java new file mode 100644 index 0000000000..23aa3f9460 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.combo; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.combo.SimpleComboPane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.combo.SimpleComboStyle; + +public class SimpleComboStyleProvider extends AbstractMobileWidgetStyleProvider{ + @Override + public Class classForMobileStyle() { + return SimpleComboStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleComboPane.class; + } + + @Override + public String xTypeForWidget() { + return "combo"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-SimpleCombo_SimpleComboStyle"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/NavigationStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/NavigationStyleProvider.java new file mode 100644 index 0000000000..89a64eb6d3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/NavigationStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.date; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.date.NavigationCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.NavigationMobileStyle; + +public class NavigationStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return NavigationMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return NavigationCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "datetime"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-Date_Navigation_Calendar"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleDateStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleDateStyleProvider.java new file mode 100644 index 0000000000..f9743acbf6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleDateStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.date; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.date.SimpleDateCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.SimpleDateMobileStyle; + +public class SimpleDateStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return SimpleDateMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleDateCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "datetime"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-SimpleDate_Style"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleStyleProvider.java new file mode 100644 index 0000000000..2fa34625e7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.date; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.date.SimpleCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.SimpleMobileStyle; + +public class SimpleStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return SimpleMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "datetime"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-Date_Simple_Calendar"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/CapsuleRadioGroupStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/CapsuleRadioGroupStyleProvider.java new file mode 100644 index 0000000000..0f8f005eb5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/CapsuleRadioGroupStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.radiogroup; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.radiogroup.CapsuleCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.CapsuleMobileStyle; + +public class CapsuleRadioGroupStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return CapsuleMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return CapsuleCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "radiogroup"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-RadioGroup_Capsule_Button"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/ImageRadioGroupStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/ImageRadioGroupStyleProvider.java new file mode 100644 index 0000000000..1bdcc6a2cf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/ImageRadioGroupStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.radiogroup; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.radiogroup.ImageCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.ImageMobileStyle; + +public class ImageRadioGroupStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return ImageMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return ImageCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "radiogroup"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-RadioGroup_Graphic_Button"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/UnitedRadioGroupStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/UnitedRadioGroupStyleProvider.java new file mode 100644 index 0000000000..91e1dde048 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/UnitedRadioGroupStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.radiogroup; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.radiogroup.UnitedCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.UnitedMobileStyle; + +public class UnitedRadioGroupStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return UnitedMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return UnitedCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "radiogroup"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-RadioGroup_Linkage_Button"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/topparam/MobileTopParamStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/topparam/MobileTopParamStyleProvider.java new file mode 100644 index 0000000000..9e91527a4d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/topparam/MobileTopParamStyleProvider.java @@ -0,0 +1,25 @@ +package com.fr.design.mainframe.mobile.provider.topparam; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.fun.impl.AbstractMobileParamUIProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.topparam.MobileTopParamPane; +import com.fr.form.ui.mobile.MobileParamStyle; +import com.fr.form.ui.mobile.impl.MobileTopParamStyle; + +public class MobileTopParamStyleProvider extends AbstractMobileParamUIProvider { + @Override + public Class classForMobileParamStyle() { + return MobileTopParamStyle.class; + } + + @Override + public Class> classForMobileParamAppearance() { + return MobileTopParamPane.class; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-TopParam_Name"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java index 7f1d270af5..eb7496607d 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java @@ -7,7 +7,7 @@ import com.fr.design.fun.MobileParamUIProvider; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.mobile.provider.DefaultMobileParamUIProvider; import com.fr.design.mainframe.mobile.provider.EmptyMobileParamUIProvider; -import com.fr.form.ui.container.WParameterLayout; +import com.fr.design.mainframe.mobile.utils.MobileStyleProviderManager; import com.fr.form.ui.mobile.MobileParamStyle; import com.fr.general.ComparatorUtils; import com.fr.report.ExtraReportClassManager; @@ -101,7 +101,7 @@ public class MobileParamSettingPane extends BasicPane { MobileParamUIProvider[] mobileParamUIProviders = getMobileParamUIProviders(); for (int i = 0; i < mobileParamUIProviders.length; i++) { MobileParamUIProvider provider = mobileParamUIProviders[i]; - if (ComparatorUtils.equals(mobileParamStyle.disPlayName(), provider.displayName())) { + if (ComparatorUtils.equals(mobileParamStyle.displayName(), provider.displayName())) { String displayName = provider.displayName(); paramStyleList.setSelectedIndex(i); // 如果是兼容空类型 无须填充面板 @@ -136,9 +136,11 @@ public class MobileParamSettingPane extends BasicPane { private MobileParamUIProvider[] getMobileParamUIProviders() { Set paramUIProviders = ExtraDesignClassManager.getInstance().getArray(MobileParamUIProvider.XML_TAG); + Set otherParamUIProviders = MobileStyleProviderManager.getArray(MobileParamUIProvider.XML_TAG); List result = new ArrayList<>(); result.add(new DefaultMobileParamUIProvider()); result.addAll(paramUIProviders); + result.addAll(otherParamUIProviders); Set nameSets = paramUIProviders.stream().map(MobileParamUIProvider::displayName).collect(Collectors.toSet()); // 兼容老接口 Set paramStyleProviders = ExtraReportClassManager.getInstance().getArray(MobileParamStyleProvider.MARK_STRING); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/combo/SimpleComboPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/combo/SimpleComboPane.java new file mode 100644 index 0000000000..b71588ebfd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/combo/SimpleComboPane.java @@ -0,0 +1,304 @@ +package com.fr.design.mainframe.mobile.ui.combo; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icombobox.LineComboBox; +import com.fr.design.gui.icombobox.UIComboBox; +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.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.mainframe.mobile.utils.IconConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.combo.SimpleComboStyle; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class SimpleComboPane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + private FontConfigPane labelFontPane; + private FontConfigPane valueFontPane; + private IconConfigPane expandIconPane; + private IconConfigPane unexpandIconPane; + private NewColorSelectBox background; + private LineComboBox borderType; + private NewColorSelectBox borderColor; + private UISpinner borderRadius; + private UIRadioButton fillButton; + private UIRadioButton customButton; + private UISpinner widthSpinner; + + private UIRadioButton floatFillButton; + private UIRadioButton floatSameWidthButton; + + public SimpleComboPane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-SimpleCombo_Style_Default"), Toolkit.i18nText("Fine-Plugin-SimpleCombo_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + JPanel stylePanel = DesignerUtils.createLeftRightComponentsPane(buttonStyleLabel, custom); + panel.add(stylePanel); + scrollPanel.add(panel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + addLabelNamePane(); + addValuePane(); + addIconPane(); + addWidgetSettingPane(); + scrollPanel.add(centerPane, BorderLayout.CENTER); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addLabelNamePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Label_Name"))); + labelFontPane = new FontConfigPane(); + JPanel fontPanel = createFontPane(labelFontPane); + centerPane.add(fontPanel); + } + + private void addValuePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Value"))); + valueFontPane = new FontConfigPane(); + JPanel fontPanel = createFontPane(valueFontPane); + valueFontPane.setFontColor(new Color(153, 153, 153)); + centerPane.add(fontPanel); + } + + private JPanel createFontPane(FontConfigPane fontConfigPane) { + UILabel fontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Character")); + JPanel fontPanel = DesignerUtils.createLeftRightComponentsPane(fontLabel, fontConfigPane); + return fontPanel; + } + + private void addIconPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Arrow"))); + UILabel tipLabel = new UILabel(); + tipLabel.setFont(new Font(tipLabel.getName(), Font.PLAIN, 10)); + tipLabel.setSize(470, 40); + tipLabel.setText(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Tips")); + tipLabel.setForeground(Color.decode("#9B9B9B")); + centerPane.add(tipLabel); + + + UILabel expandLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Expand_Icon")); + UILabel unexpandLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Collapse_Icon")); + + expandIconPane = new IconConfigPane(); + unexpandIconPane = new IconConfigPane(); + + JPanel expandPane = DesignerUtils.createLeftRightComponentsPane(expandLabel, expandIconPane); + centerPane.add(expandPane); + + JPanel unexpandPane = DesignerUtils.createLeftRightComponentsPane(unexpandLabel, unexpandIconPane); + centerPane.add(unexpandPane); + } + + private void addWidgetSettingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Region"))); + background = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + borderType = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + borderType.setSelectedLineStyle(Constants.LINE_THIN); + borderType.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + borderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + borderRadius = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + borderRadius.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + JComponent[] controlComponents = new JComponent[]{background, borderType, borderColor, borderRadius}; + String[] comboBoxNames = new String[]{ + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Background"), + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Border"), + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Border_Color"), + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Radius"), + }; + + Component[][] components = new Component[4][]; + + for (int i = 0; i < 4; i++) { + UILabel label = DesignerUtils.createConfigLabel(comboBoxNames[i]); + components[i] = new Component[]{label, controlComponents[i]}; + } + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p, }; + double[] columnSize = {p, p}; + JPanel controlPanel = TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, 10); + centerPane.add(controlPanel); + + fillButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Horizontal_Fill")); + fillButton.setSelected(true); + customButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Custom_Width")); + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + widthSpinner.setVisible(customButton.isSelected()); + } + }; + fillButton.addActionListener(listener); + customButton.addActionListener(listener); + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(fillButton); + buttonGroup.add(customButton); + widthSpinner = new UISpinner(1, Integer.MAX_VALUE, 1, 200); + widthSpinner.setPreferredSize(new Dimension(78, 20)); + widthSpinner.setVisible(false); + UILabel widthLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Width")); + JPanel buttonsPane = createButtonPane(); + buttonsPane.add(fillButton); + buttonsPane.add(customButton); + JPanel widthSetting = DesignerUtils.createLeftRightComponentsPane(widthLabel, buttonsPane, widthSpinner); + centerPane.add(widthSetting); + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Floating_Layer"))); + UILabel floatLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Width")); + floatFillButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Horizontal_Fill")); + floatFillButton.setSelected(true); + floatSameWidthButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Follow_Control")); + ButtonGroup floatButtonGroup = new ButtonGroup(); + floatButtonGroup.add(floatFillButton); + floatButtonGroup.add(floatSameWidthButton); + JPanel floatButtonPane = createButtonPane(); + floatButtonPane.add(floatFillButton); + floatButtonPane.add(floatSameWidthButton); + JPanel floatSetting = DesignerUtils.createLeftRightComponentsPane(floatLabel, floatFillButton, floatSameWidthButton); + centerPane.add(floatSetting); + } + + private JPanel createButtonPane() { + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new GridLayout(0, 2, 14, 0)); + buttonPane.setPreferredSize(new Dimension(220, 20)); + return buttonPane; + } + + @Override + public void populateBean(MobileStyle ob) { + SimpleComboStyle mobileStyle = (SimpleComboStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + expandIconPane.populate(mobileStyle.getExpandIcon()); + unexpandIconPane.populate(mobileStyle.getUnexpandIcon()); + if (mobileStyle.getLabelFont() != null) { + labelFontPane.populate(mobileStyle.getLabelFont()); + } + if (mobileStyle.getValueFont() != null) { + valueFontPane.populate(mobileStyle.getValueFont()); + } + if (mobileStyle.getBackgroundColor() != null) { + background.setSelectObject(mobileStyle.getBackgroundColor()); + } + if (mobileStyle.getBorderColor() != null) { + borderColor.setSelectObject(mobileStyle.getBorderColor()); + } + borderType.setSelectedLineStyle(mobileStyle.getBorderType()); + borderRadius.setValue(mobileStyle.getBorderRadius()); + if (mobileStyle.isCustomWidth()) { + fillButton.setSelected(false); + customButton.setSelected(true); + widthSpinner.setVisible(true); + widthSpinner.setValue(mobileStyle.getWidth()); + } else { + fillButton.setSelected(true); + customButton.setSelected(false); + widthSpinner.setVisible(false); + } + if (mobileStyle.isFloatWidthFollow()) { + floatFillButton.setSelected(false); + floatSameWidthButton.setSelected(true); + } else { + floatFillButton.setSelected(true); + floatSameWidthButton.setSelected(false); + } + } + + @Override + public MobileStyle updateBean() { + SimpleComboStyle mobileStyle = (SimpleComboStyle) this.widget.getMobileStyle(); + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setExpandIcon(expandIconPane.update()); + mobileStyle.setUnexpandIcon(unexpandIconPane.update()); + mobileStyle.setLabelFont(labelFontPane.update()); + mobileStyle.setValueFont(valueFontPane.update()); + mobileStyle.setBackgroundColor(background.getSelectObject()); + mobileStyle.setBorderColor(borderColor.getSelectObject()); + mobileStyle.setBorderType(borderType.getSelectedLineStyle()); + mobileStyle.setBorderRadius(borderRadius.getValue()); + mobileStyle.setCustomWidth(customButton.isSelected()); + mobileStyle.setWidth(widthSpinner.getValue()); + mobileStyle.setFloatWidthFollow(floatSameWidthButton.isSelected()); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/NavigationCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/NavigationCustomDefinePane.java new file mode 100644 index 0000000000..e64ba926db --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/NavigationCustomDefinePane.java @@ -0,0 +1,272 @@ +package com.fr.design.mainframe.mobile.ui.date; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIColorButton; +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.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.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.NavigationMobileStyle; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class NavigationCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UIComboBox expand; + private UIComboBox dateFontSize; + private NewColorSelectBox buttonColorSelectBox; + private NewColorSelectBox titleSplitLineColorSelectBox; + private UICheckBox showTitleEditor; + private NewColorSelectBox arrowColorSelectBox; + private UIColorButton mainFontColor; + private UIColorButton specialFontColor; + + private Color titleSplitLineDisableColor = new Color(234, 234, 234); + private Color titleSplitLineColor; + + public NavigationCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Style_Default"), Toolkit.i18nText("Fine-Plugin-Date_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + addExpandPane(); + addHeaderLinePane(); + addButtonColorPane(); + addFontColorPane(); + addArrowPane(); + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private void addExpandPane() { + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Status")); + expand = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Status_Collapse"), Toolkit.i18nText("Fine-Plugin-Date_Status_Expand")}); + expand.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(expand); + centerPane.add(panel); + } + + private void addButtonColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Button"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Button_Color")); + buttonColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + buttonColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(buttonColorSelectBox); + centerPane.add(panel); + } + + private void addHeaderLinePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Title_Line"))); + + UILabel titleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_SubTitle_Line")); + showTitleEditor = DesignerUtils.createCheckBox(Toolkit.i18nText("Fine-Plugin-Date_Show_Title_Line"), true); + JPanel headerPanel = new JPanel(); + headerPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + headerPanel.add(titleLabel); + headerPanel.add(showTitleEditor); + centerPane.add(headerPanel); + + final UILabel splitLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Title_Split_Line_Color")); + titleSplitLineColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if(showTitleEditor.isSelected()) { + titleSplitLineColor = titleSplitLineColorSelectBox.getSelectObject(); + } + } + }); + titleSplitLineColorSelectBox.setSelectObject(new Color(234, 234, 234)); + final JPanel splitLineColorPanel = new JPanel(); + splitLineColorPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + splitLineColorPanel.add(splitLabel); + splitLineColorPanel.add(titleSplitLineColorSelectBox); + + + showTitleEditor.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + if(showTitleEditor.isSelected()) { + titleSplitLineColorSelectBox.setSelectObject(titleSplitLineColor); + } else { + titleSplitLineColorSelectBox.setSelectObject(titleSplitLineDisableColor); + } + + titleSplitLineColorSelectBox.setEnabled(showTitleEditor.isSelected()); + splitLabel.setEnabled(showTitleEditor.isSelected()); + } + }); + centerPane.add(splitLineColorPanel); + } + + private void addFontColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Font"))); + UILabel mainLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Main")); + mainFontColor = new UIColorButton(); + mainFontColor.setColor(new Color(51, 51, 51)); + mainFontColor.setPreferredSize(new Dimension(20, 20)); + + UILabel specialLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Special")); + specialFontColor = new UIColorButton(); + specialFontColor.setColor(new Color(255, 148, 84)); + specialFontColor.setPreferredSize(new Dimension(20, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel panel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][] { + {mainLabel, mainFontColor}, + {specialLabel, specialFontColor} + }, rowSize, columnSize, 10); + + centerPane.add(panel); + + + UILabel fontSizeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Size")); + dateFontSize = new UIComboBox(new Integer[]{12, 13, 14, 15, 16, 17, 18}); + dateFontSize.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + dateFontSize.setSelectedItem(14); + JPanel fontPanel = new JPanel(); + fontPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + fontPanel.add(fontSizeLabel); + fontPanel.add(dateFontSize); + centerPane.add(fontPanel); + } + + private void addArrowPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Arrow"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Arrow_Color")); + arrowColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + arrowColorSelectBox.setSelectObject(new Color(234, 234, 234)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(arrowColorSelectBox ); + centerPane.add(panel); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + @Override + public void populateBean(MobileStyle ob) { + NavigationMobileStyle mobileStyle = (NavigationMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + expand.setSelectedIndex(mobileStyle.isExpand() ? 1 : 0); + buttonColorSelectBox.setSelectObject(mobileStyle.getButtonBackgroundColor()); + mainFontColor.setColor(mobileStyle.getMainFontColor()); + specialFontColor.setColor(mobileStyle.getSpecialFontColor()); + showTitleEditor.setSelected(mobileStyle.isShowTitleLine()); + if(mobileStyle.isShowTitleLine()) { + titleSplitLineColorSelectBox.setSelectObject(mobileStyle.getTitleSplitLineColor()); + } else { + titleSplitLineColorSelectBox.setSelectObject(titleSplitLineDisableColor); + titleSplitLineColor = mobileStyle.getTitleSplitLineColor(); + } + dateFontSize.setSelectedItem(mobileStyle.getDateFontSize()); + arrowColorSelectBox.setSelectObject(mobileStyle.getArrowColor()); + } + + @Override + public MobileStyle updateBean() { + NavigationMobileStyle mobileStyle = (NavigationMobileStyle)this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setExpand(expand.getSelectedIndex() == 1); + mobileStyle.setButtonBackgroundColor(buttonColorSelectBox.getSelectObject()); + mobileStyle.setMainFontColor(mainFontColor.getColor()); + mobileStyle.setSpecialFontColor(specialFontColor.getColor()); + mobileStyle.setShowTitleLine(showTitleEditor.isSelected()); + if(showTitleEditor.isSelected()) { + mobileStyle.setTitleSplitLineColor(titleSplitLineColorSelectBox.getSelectObject()); + } else { + mobileStyle.setTitleSplitLineColor(titleSplitLineColor); + } + mobileStyle.setDateFontSize(Integer.parseInt(dateFontSize.getSelectedItem().toString())); + mobileStyle.setArrowColor(arrowColorSelectBox.getSelectObject()); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleCustomDefinePane.java new file mode 100644 index 0000000000..3a5cb5444a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleCustomDefinePane.java @@ -0,0 +1,230 @@ +package com.fr.design.mainframe.mobile.ui.date; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIColorButton; +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.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.SimpleMobileStyle; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class SimpleCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UIComboBox expand; + private UIComboBox dateFontSize; + private NewColorSelectBox buttonColorSelectBox; + private NewColorSelectBox titleSplitLineColorSelectBox; + private NewColorSelectBox arrowColorSelectBox; + private UIColorButton mainFontColor; + private UIColorButton specialFontColor; + + public SimpleCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Style_Default"), + Toolkit.i18nText("Fine-Plugin-Date_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + addExpandPane(); + addHeaderLinePane(); + addButtonColorPane(); + addFontColorPane(); + addArrowPane(); + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private void addExpandPane() { + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Status")); + expand = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Status_Collapse"), Toolkit.i18nText("Fine-Plugin-Date_Status_Expand")}); + expand.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(expand); + centerPane.add(panel); + } + + private void addHeaderLinePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Title_Line"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Title_Split_Line_Color")); + titleSplitLineColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + titleSplitLineColorSelectBox.setSelectObject(new Color(234, 234, 234)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(titleSplitLineColorSelectBox); + centerPane.add(panel); + } + + private void addButtonColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Button"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Button_Color")); + buttonColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + buttonColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(buttonColorSelectBox); + centerPane.add(panel); + } + + private void addFontColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Font"))); + UILabel mainLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Main")); + mainFontColor = new UIColorButton(); + mainFontColor.setColor(new Color(51, 51, 51)); + mainFontColor.setPreferredSize(new Dimension(20, 20)); + + UILabel specialLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Special")); + specialFontColor = new UIColorButton(); + specialFontColor.setColor(new Color(255, 148, 84)); + specialFontColor.setPreferredSize(new Dimension(20, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel panel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][] { + {mainLabel, mainFontColor}, + {specialLabel, specialFontColor} + }, rowSize, columnSize, 10); + + centerPane.add(panel); + + UILabel fontSizeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Size")); + dateFontSize = new UIComboBox(new Integer[]{12, 13, 14, 15, 16, 17, 18}); + dateFontSize.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + dateFontSize.setSelectedItem(14); + JPanel fontPanel = new JPanel(); + fontPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + fontPanel.add(fontSizeLabel); + fontPanel.add(dateFontSize); + centerPane.add(fontPanel); + } + + private void addArrowPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Arrow"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Arrow_Color")); + arrowColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + arrowColorSelectBox.setSelectObject(new Color(234, 234, 234)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(arrowColorSelectBox ); + centerPane.add(panel); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + @Override + public void populateBean(MobileStyle ob) { + SimpleMobileStyle mobileStyle = (SimpleMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + expand.setSelectedIndex(mobileStyle.isExpand() ? 1 : 0); + buttonColorSelectBox.setSelectObject(mobileStyle.getButtonBackgroundColor()); + mainFontColor.setColor(mobileStyle.getMainFontColor()); + specialFontColor.setColor(mobileStyle.getSpecialFontColor()); + titleSplitLineColorSelectBox.setSelectObject(mobileStyle.getTitleSplitLineColor()); + dateFontSize.setSelectedItem(mobileStyle.getDateFontSize()); + arrowColorSelectBox.setSelectObject(mobileStyle.getArrowColor()); + } + + @Override + public MobileStyle updateBean() { + SimpleMobileStyle mobileStyle = (SimpleMobileStyle)this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setExpand(expand.getSelectedIndex() == 1); + mobileStyle.setButtonBackgroundColor(buttonColorSelectBox.getSelectObject()); + mobileStyle.setMainFontColor(mainFontColor.getColor()); + mobileStyle.setSpecialFontColor(specialFontColor.getColor()); + mobileStyle.setTitleSplitLineColor(titleSplitLineColorSelectBox.getSelectObject()); + mobileStyle.setDateFontSize(Integer.parseInt(dateFontSize.getSelectedItem().toString())); + mobileStyle.setArrowColor(arrowColorSelectBox.getSelectObject()); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleDateCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleDateCustomDefinePane.java new file mode 100644 index 0000000000..ad79f499e7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleDateCustomDefinePane.java @@ -0,0 +1,267 @@ +package com.fr.design.mainframe.mobile.ui.date; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icombobox.LineComboBox; +import com.fr.design.gui.icombobox.UIComboBox; +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.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.mainframe.mobile.utils.IconConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.ControlStyle; +import com.fr.form.ui.mobile.date.SimpleDateMobileStyle; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class SimpleDateCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + private FontConfigPane labelFontConfigPane; + private FontConfigPane controlValueConfigPane; + private NewColorSelectBox controlBackground; + private LineComboBox controlBorder; + private NewColorSelectBox controlBorderColor; + private UISpinner controlWidgetRadius; + private UISpinner widthSpinner; + private UIRadioButton fillButton; + private UIRadioButton customButton; + private IconConfigPane iconConfigPane; + + public SimpleDateCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-SimpleDate_Style_Default"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + centerPane.setVisible(false); + + addFontConfigPane(); + addIconConfigPane(); + addControlConfigPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + } + + private void addControlConfigPane() { + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Region"))); + controlBackground = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + controlBorder = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + controlBorder.setSelectedLineStyle(Constants.LINE_THIN); + controlBorder.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + controlBorderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + controlWidgetRadius = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + controlWidgetRadius.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + JComponent[] controlComponents = new JComponent[]{controlBackground, controlBorder, controlBorderColor, controlWidgetRadius}; + String[] comboBoxNames = new String[]{ + Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Background"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Border"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Border_Color"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Radius") + }; + + Component[][] components = new Component[4][]; + + for (int i = 0; i < 4; i++) { + UILabel label = DesignerUtils.createConfigLabel(comboBoxNames[i]); + components[i] = new Component[]{label, controlComponents[i]}; + } + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, p}; + JPanel controlPanel = TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, 10); + centerPane.add(controlPanel); + + this.fillButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleDate_Horizontal_Fill")); + this.customButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleDate_Width_Custom")); + + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(fillButton); + buttonGroup.add(customButton); + + JPanel panel = new JPanel(); + panel.add(fillButton); + panel.add(customButton); + panel.setLayout(new GridLayout(0, 2, 14, 0)); + panel.setPreferredSize(new Dimension(174, 20)); + fillButton.setSelected(true); + + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + widthSpinner.setVisible(customButton.isSelected()); + } + }; + + fillButton.addActionListener(listener); + customButton.addActionListener(listener); + + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleDate_Width")); + widthSpinner = new UISpinner(1, Integer.MAX_VALUE, 1, 200); + widthSpinner.setPreferredSize(new Dimension(78, 20)); + widthSpinner.setVisible(false); + centerPane.add(DesignerUtils.createLeftRightComponentsPane(label, panel, widthSpinner)); + + } + + private void addFontConfigPane() { + + String[] titleSplitLineNames = new String[]{ + Toolkit.i18nText("Fine-Plugin-SimpleDate_Label_Name"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Value") + }; + labelFontConfigPane = new FontConfigPane(); + controlValueConfigPane = new FontConfigPane(); + FontConfigPane[] fontConfigPanes = new FontConfigPane[]{labelFontConfigPane, controlValueConfigPane}; + for (int i = 0; i < 2; i++) { + centerPane.add(DesignerUtils.createTitleSplitLine(titleSplitLineNames[i])); + UILabel fontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleDate_Character")); + JPanel fontPanel = DesignerUtils.createLeftRightComponentsPane(fontLabel, fontConfigPanes[i]); + centerPane.add(fontPanel); + } + } + + private void addIconConfigPane() { + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleDate_Icon"))); + UILabel tipLabel = new UILabel(); + tipLabel.setFont(new Font(tipLabel.getName(), Font.PLAIN, 10)); + tipLabel.setSize(470, 40); + tipLabel.setText(Toolkit.i18nText("Fine-Plugin-SimpleDate_Tip")); + tipLabel.setForeground(Color.decode("#9B9B9B")); + centerPane.add(tipLabel); + + JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + + + iconConfigPane = new IconConfigPane(); + centerPane.add(iconConfigPane); + + } + + @Override + public void populateBean(MobileStyle mobileStyle) { + SimpleDateMobileStyle simpleDateMobileStyle = (SimpleDateMobileStyle) mobileStyle; + custom.setSelectedIndex(simpleDateMobileStyle.isCustom() ? 1 : 0); + iconConfigPane.populate(simpleDateMobileStyle.getIconValue()); + labelFontConfigPane.populate(simpleDateMobileStyle.getLabelFontStyle()); + controlValueConfigPane.populate(simpleDateMobileStyle.getValueFontStyle()); + + ControlStyle controlStyle = simpleDateMobileStyle.getControlStyle(); + + if (controlStyle != null) { + controlBackground.setSelectObject(controlStyle.getBackground()); + controlBorderColor.setSelectObject(controlStyle.getBorderColor()); + controlBorder.setSelectedLineStyle(controlStyle.getBorderType()); + controlWidgetRadius.setValue(controlStyle.getBorderRadius()); + if (controlStyle.isCustomWidth()) { + widthSpinner.setVisible(true); + widthSpinner.setValue(controlStyle.getWidth()); + customButton.setSelected(true); + fillButton.setSelected(false); + } else { + widthSpinner.setVisible(false); + customButton.setSelected(false); + fillButton.setSelected(true); + } + } + + } + + @Override + public MobileStyle updateBean() { + SimpleDateMobileStyle simpleDateMobileStyle = (SimpleDateMobileStyle) this.widget.getMobileStyle(); + simpleDateMobileStyle.setCustom(custom.getSelectedIndex() == 1); + simpleDateMobileStyle.setIconValue(iconConfigPane.update()); + simpleDateMobileStyle.setLabelFontStyle(labelFontConfigPane.update()); + simpleDateMobileStyle.setValueFontStyle(controlValueConfigPane.update()); + ControlStyle controlStyle = new ControlStyle(); + controlStyle.setBackground(controlBackground.getSelectObject()); + controlStyle.setBorderColor(controlBorderColor.getSelectObject()); + controlStyle.setBorderType(controlBorder.getSelectedLineStyle()); + controlStyle.setBorderRadius(controlWidgetRadius.getValue()); + controlStyle.setCustomWidth(customButton.isSelected()); + controlStyle.setWidth(widthSpinner.getValue()); + simpleDateMobileStyle.setControlStyle(controlStyle); + return simpleDateMobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/CapsuleCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/CapsuleCustomDefinePane.java new file mode 100644 index 0000000000..072a7a57a1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/CapsuleCustomDefinePane.java @@ -0,0 +1,310 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +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.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +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.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.CapsuleMobileStyle; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class CapsuleCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UISpinner leftSpinner; + private UISpinner rightSpinner; + private UISpinner topSpinner; + private UISpinner bottomSpinner; + + private JRadioButton leftAlignRadioButton; + private JRadioButton centerAlignRadioButton; + + private NewColorSelectBox initialColorSelectBox; + private NewColorSelectBox selectedColorSelectBox; + + private LineComboBox borderLineCombo; + private NewColorSelectBox initialBorderColor; + private NewColorSelectBox selectedBorderColor; + private UISpinner borderRadiusSpinner; + + private FontConfigPane initialFontConfPane; + private UIColorButton selectedFontColor; + + + public CapsuleCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Default"), + Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + + addPaddingPane(); + addBackgroundPane(); + addBorderPane(); + addFontPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addPaddingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Layout"))); + + UILabel paddingHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Button_Padding")); + UILabel emptyHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("")); + UILabel buttonAlignHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Alignment")); + + UILabel leftLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Left")); + leftSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel rightLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Right")); + rightSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel topLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Top")); + topSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + UILabel bottomLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Bottom")); + bottomSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + leftAlignRadioButton = new JRadioButton(Toolkit.i18nText("Fine-Plugin-RadioGroup_Alignment_Left"), true); + centerAlignRadioButton = new JRadioButton(Toolkit.i18nText("Fine-Plugin-RadioGroup_Alignment_Center"), false); + + JPanel leftSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftLabel, leftSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel rightSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{rightLabel, rightSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel topSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topLabel, topSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel bottomSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{bottomLabel, bottomSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + + JPanel vPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topSpinnerPanel, bottomSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + JPanel hPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftSpinnerPanel, rightSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + JPanel layoutPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftAlignRadioButton, centerAlignRadioButton}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + ButtonGroup layoutRadioButtonGroup = new ButtonGroup(); + layoutRadioButtonGroup.add(leftAlignRadioButton); + layoutRadioButtonGroup.add(centerAlignRadioButton); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p}; + double[] columnSize = {p, p}; + JPanel paddingPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {paddingHintLabel, vPaddingSpinnerPanel}, + {emptyHintLabel, hPaddingSpinnerPanel}, + {buttonAlignHintLabel, layoutPanel}, + }, rowSize, columnSize, 10); + centerPane.add(paddingPanel); + } + + private void addBackgroundPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background"))); + + UILabel initialColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Init")); + initialColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + initialColorSelectBox.setSelectObject(new Color(244, 244, 244)); + JPanel initialColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialColorLabel, initialColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(initialColorSelectPane); + + UILabel selectedColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Select")); + selectedColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + + } + }); + selectedColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel selectedColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedColorLabel, selectedColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectedColorSelectPane); + } + + private void addBorderPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border"))); + + UILabel borderTypeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Line")); + borderLineCombo = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + borderLineCombo.setSelectedLineStyle(Constants.LINE_THIN); + + UILabel initialColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Init_Color")); + initialBorderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + initialBorderColor.setSelectObject(new Color(244, 244, 244)); + + UILabel selectedColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Select_Color")); + selectedBorderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + selectedBorderColor.setSelectObject(new Color(31, 173, 229)); + + UILabel radiusLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Radius")); + borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 20); + borderRadiusSpinner.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, p}; + JPanel borderPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {borderTypeLabel, borderLineCombo}, + {initialColorLabel, initialBorderColor}, + {selectedColorLabel, selectedBorderColor}, + {radiusLabel, borderRadiusSpinner} + }, rowSize, columnSize, 10); + + centerPane.add(borderPanel); + + } + + private void addFontPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font"))); + + UILabel initialFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_init")); + initialFontConfPane = new FontConfigPane(); + initialFontConfPane.setFontColor(new Color(204, 204, 204)); + JPanel fontPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialFontLabel, initialFontConfPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(fontPanel); + UILabel selectedFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_Select")); + selectedFontColor = new UIColorButton(); + selectedFontColor.setColor(Color.WHITE); + selectedFontColor.setPreferredSize(new Dimension(20, 20)); + JPanel selectFontColorPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedFontLabel, selectedFontColor}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectFontColorPanel); + + } + + @Override + public void populateBean(MobileStyle ob) { + CapsuleMobileStyle mobileStyle = (CapsuleMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + leftSpinner.setValue(mobileStyle.getLeftPadding()); + rightSpinner.setValue(mobileStyle.getRightPadding()); + topSpinner.setValue(mobileStyle.getTopPadding()); + bottomSpinner.setValue(mobileStyle.getBottomPadding()); + leftAlignRadioButton.setSelected(mobileStyle.getButtonAlign() == DesignerUtils.kAlignLeft); + centerAlignRadioButton.setSelected(mobileStyle.getButtonAlign() == DesignerUtils.kAlignCenter); + initialColorSelectBox.setSelectObject(mobileStyle.getInitialBackgroundColor()); + selectedColorSelectBox.setSelectObject(mobileStyle.getSelectedBackgroundColor()); + borderLineCombo.setSelectedLineStyle(mobileStyle.getBorderType()); + initialBorderColor.setSelectObject(mobileStyle.getInitialBorderColor()); + selectedBorderColor.setSelectObject(mobileStyle.getSelectedBorderColor()); + borderRadiusSpinner.setValue(mobileStyle.getBorderRadius()); + if (mobileStyle.getInitialFont() != null) { + initialFontConfPane.populate(mobileStyle.getInitialFont()); + } + if (mobileStyle.getSelectedFont() != null) { + selectedFontColor.setColor(mobileStyle.getSelectedFont().getForeground()); + } + } + + @Override + public MobileStyle updateBean() { + CapsuleMobileStyle mobileStyle = (CapsuleMobileStyle) this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setLeftPadding(leftSpinner.getValue()); + mobileStyle.setRightPadding(rightSpinner.getValue()); + mobileStyle.setTopPadding(topSpinner.getValue()); + mobileStyle.setBottomPadding(bottomSpinner.getValue()); + mobileStyle.setButtonAlign(leftAlignRadioButton.isSelected() ? DesignerUtils.kAlignLeft : DesignerUtils.kAlignCenter); + mobileStyle.setInitialBackgroundColor(initialColorSelectBox.getSelectObject()); + mobileStyle.setSelectedBackgroundColor(selectedColorSelectBox.getSelectObject()); + mobileStyle.setBorderType(borderLineCombo.getSelectedLineStyle()); + mobileStyle.setInitialBorderColor(initialBorderColor.getSelectObject()); + mobileStyle.setSelectedBorderColor(selectedBorderColor.getSelectObject()); + mobileStyle.setBorderRadius(borderRadiusSpinner.getValue()); + + FRFont initialFont = initialFontConfPane.updateFont(null, null, null); + FRFont selectedFont = initialFontConfPane.updateFont(selectedFontColor.getColor(), null, null); + + mobileStyle.setInitialFont(initialFont); + mobileStyle.setSelectedFont(selectedFont); + + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/IconConfigPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/IconConfigPane.java new file mode 100644 index 0000000000..08e0ecd09a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/IconConfigPane.java @@ -0,0 +1,195 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.base.IconManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.web.CustomIconPane; +import com.fr.form.ui.WidgetInfoConfig; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRFont; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; + +public class IconConfigPane extends JPanel { + private UIButton editIconButton; + private UIButton deleteIconButton; + private String curIconName; + private IconButton selectIconButton; + private ArrayList iconButtons = new ArrayList(); + + public IconConfigPane(int count) { + initComp(count); + } + + public void initComp(int count) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel panel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + editIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Edit")); + editIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + editIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(editIconButton); + editIconButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final CustomIconPane cip = new CustomIconPane(){ + protected String createDescriptionText(){ + return Toolkit.i18nText("Fine-Design_Mobile_Custom_Icon_Message"); + } + }; + BasicDialog editDialog = cip.showWindow(DesignerContext.getDesignerFrame()); + editDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + curIconName = cip.update(); + setShowIconImage(); + IconConfigPane.this.repaint(); + } + }); + editDialog.setVisible(true); + } + }); + editIconButton.setEnabled(false); + + deleteIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Delete")); + deleteIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + deleteIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(deleteIconButton); + deleteIconButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + selectIconButton.setIconName(StringUtils.EMPTY); + IconConfigPane.this.repaint(); + } + }); + deleteIconButton.setEnabled(false); + + + this.add(panel, BorderLayout.CENTER); + + JPanel northPane = new JPanel(); + northPane.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + for (int i = 0; i < count; i++) { + IconButton iconButton = new IconButton(""); + northPane.add(iconButton); + iconButtons.add(iconButton); + } + this.add(northPane, BorderLayout.NORTH); + } + + public void setShowIconImage() { + selectIconButton.setIconName(curIconName); + } + + public void populate(ArrayList iconArr) { + for (int i = 0; i < iconButtons.size(); i++) { + iconButtons.get(i).setIconName(iconArr.get(i)); + } + } + + public ArrayList update() { + ArrayList iconNames = new ArrayList(); + for (int i = 0; i < iconButtons.size(); i++) { + iconNames.add(iconButtons.get(i).getIconName()); + } + return iconNames; + } + + + private class IconButton extends JToggleButton implements ActionListener { + private String iconName; + private Image iconImage = null; + private static final int ICON_BUTTON_SIZE = 20; + private static final int ICON_X = 2; + private static final int ICON_Y = 2; + + public IconButton(String name) { + this.iconName = name; + this.addActionListener(this); + this.setBackground(Color.WHITE); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(name); + } + + @Override + public void updateUI() { + setUI(new BasicButtonUI() { + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + } + }); + } + + protected void paintBorder(Graphics g) { + super.paintBorder(g); + if (ComparatorUtils.equals(this, selectIconButton)) { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#419BF9"), 0, 0, 20, 20); + } else { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#D9DADD"), 0, 0, 20, 20); + } + + } + + public String getIconName() { + return iconName; + } + + public void setIconName(String iconName) { + this.iconName = iconName; + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(iconName); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g; + // carl:这里缩放显示 16 × 16 + if (iconImage != null) { + g2d.drawImage(iconImage, ICON_X, ICON_Y, IconManager.DEFAULT_ICONWIDTH, IconManager.DEFAULT_ICONHEIGHT, null); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(ICON_BUTTON_SIZE, ICON_BUTTON_SIZE); + } + + public void actionPerformed(ActionEvent evt) { + selectIconButton = this; + editIconButton.setEnabled(true); + if(StringUtils.isNotEmpty(this.iconName)) { + deleteIconButton.setEnabled(true); + } else { + deleteIconButton.setEnabled(false); + } + IconConfigPane.this.repaint();// repaint + } + + @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); + } + } + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/ImageCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/ImageCustomDefinePane.java new file mode 100644 index 0000000000..7288d3263c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/ImageCustomDefinePane.java @@ -0,0 +1,242 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +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.gui.ispinner.UISpinner; +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.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.ImageMobileStyle; +import com.fr.general.FRFont; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.Arrays; + +public class ImageCustomDefinePane extends MobileStyleCustomDefinePane { + + private static final Icon[] BOLD_ICONS = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold_white.png")}; + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UISpinner leftSpinner; + private UISpinner rightSpinner; + private UISpinner topSpinner; + private UISpinner bottomSpinner; + + private IconConfigPane initialIconConfigPane; + private IconConfigPane selectedIconConfigPane; + + private FontConfigPane initialFontConfPane; + private UIColorButton selectedFontColor; + private UIToggleButton selectedFontBold; + + public ImageCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Default"), + Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + + addPaddingPane(); + + addIconPane(); + + addFontPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addPaddingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Layout"))); + + UILabel paddingHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Button_Padding")); + UILabel emptyHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("")); + + UILabel leftLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Left")); + leftSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel rightLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Right")); + rightSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel topLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Top")); + topSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + UILabel bottomLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Bottom")); + bottomSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + JPanel leftSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftLabel, leftSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel rightSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{rightLabel, rightSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel topSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topLabel, topSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel bottomSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{bottomLabel, bottomSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + + JPanel vPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topSpinnerPanel, bottomSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + JPanel hPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftSpinnerPanel, rightSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel paddingPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {paddingHintLabel, vPaddingSpinnerPanel}, + {emptyHintLabel, hPaddingSpinnerPanel}, + }, rowSize, columnSize, 10); + + centerPane.add(paddingPanel); + } + + private void addIconPane() { + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Icon"))); + + UILabel initialLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Icon_Init")); + UILabel selectedLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Icon_Select")); + + initialIconConfigPane = new IconConfigPane(8); + selectedIconConfigPane = new IconConfigPane(8); + + JPanel container = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5); + + JPanel initialPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + initialPane.add(initialLabel); + initialPane.add(initialIconConfigPane); + container.add(initialPane); + + JPanel selectedPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + selectedPane.add(selectedLabel); + selectedPane.add(selectedIconConfigPane); + container.add(selectedPane); + + centerPane.add(container); + + } + + private void addFontPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font"))); + + UILabel initialFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_init")); + initialFontConfPane = new FontConfigPane(); + initialFontConfPane.setFontColor(new Color(204, 204, 204)); + JPanel fontPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialFontLabel, initialFontConfPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(fontPanel); + UILabel selectedFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_Select")); + selectedFontColor = new UIColorButton(); + selectedFontColor.setColor(new Color(31, 173, 229)); + selectedFontColor.setPreferredSize(new Dimension(20, 20)); + selectedFontBold = new UIToggleButton(BOLD_ICONS, true); + selectedFontBold.setPreferredSize(new Dimension(20, 20)); + JPanel selectFontColorPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedFontLabel, selectedFontColor, selectedFontBold}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectFontColorPanel); + + } + + @Override + public void populateBean(MobileStyle ob) { + ImageMobileStyle mobileStyle = (ImageMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + leftSpinner.setValue(mobileStyle.getLeftPadding()); + rightSpinner.setValue(mobileStyle.getRightPadding()); + topSpinner.setValue(mobileStyle.getTopPadding()); + bottomSpinner.setValue(mobileStyle.getBottomPadding()); + initialIconConfigPane.populate(new ArrayList<>(Arrays.asList(mobileStyle.getInitialIconNames()))); + selectedIconConfigPane.populate(new ArrayList<>(Arrays.asList(mobileStyle.getSelectedIconNames()))); + if(mobileStyle.getInitialFont() != null) { + initialFontConfPane.populate(mobileStyle.getInitialFont()); + } + if(mobileStyle.getSelectedFont() != null) { + selectedFontColor.setColor(mobileStyle.getSelectedFont().getForeground()); + selectedFontBold.setSelected(mobileStyle.getSelectedFont().isBold()); + } + } + + @Override + public MobileStyle updateBean() { + ImageMobileStyle mobileStyle = (ImageMobileStyle)this.widget.getMobileStyle(); + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setLeftPadding(leftSpinner.getValue()); + mobileStyle.setRightPadding(rightSpinner.getValue()); + mobileStyle.setTopPadding(topSpinner.getValue()); + mobileStyle.setBottomPadding(bottomSpinner.getValue()); + ArrayList initialIconNamesList = initialIconConfigPane.update(); + ArrayList selectedIconNamesList = selectedIconConfigPane.update(); + mobileStyle.setInitialIconNames(initialIconNamesList.toArray(new String[initialIconNamesList.size()])); + mobileStyle.setSelectedIconNames(selectedIconNamesList.toArray(new String[selectedIconNamesList.size()])); + FRFont initialFont = initialFontConfPane.updateFont(null, null, null); + FRFont selectedFont = initialFontConfPane.updateFont(selectedFontColor.getColor(), selectedFontBold.isSelected(), null); + mobileStyle.setInitialFont(initialFont); + mobileStyle.setSelectedFont(selectedFont); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/UnitedCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/UnitedCustomDefinePane.java new file mode 100644 index 0000000000..8d9b425740 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/UnitedCustomDefinePane.java @@ -0,0 +1,279 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +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.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +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.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.UnitedMobileStyle; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class UnitedCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UISpinner leftSpinner; + private UISpinner rightSpinner; + private UISpinner topSpinner; + private UISpinner bottomSpinner; + + private NewColorSelectBox initialColorSelectBox; + private NewColorSelectBox selectedColorSelectBox; + + private LineComboBox borderLineCombo; + private NewColorSelectBox borderColor; + private UISpinner borderRadiusSpinner; + + private FontConfigPane initialFontConfPane; + private UIColorButton selectedFontColor; + + public UnitedCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Default"), + Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + + addPaddingPane(); + addBackgroundPane(); + addBorderPane(); + addFontPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addPaddingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Layout"))); + + UILabel paddingHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Button_Padding")); + UILabel emptyHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("")); + + UILabel leftLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Left")); + leftSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel rightLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Right")); + rightSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel topLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Top")); + topSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + UILabel bottomLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Bottom")); + bottomSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + JPanel leftSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftLabel, leftSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel rightSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{rightLabel, rightSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel topSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topLabel, topSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel bottomSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{bottomLabel, bottomSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + + JPanel vPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topSpinnerPanel, bottomSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + JPanel hPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftSpinnerPanel, rightSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel paddingPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {paddingHintLabel, vPaddingSpinnerPanel}, + {emptyHintLabel, hPaddingSpinnerPanel}, + }, rowSize, columnSize, 10); + + centerPane.add(paddingPanel); + } + + private void addBackgroundPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background"))); + + UILabel initialColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Init")); + initialColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + initialColorSelectBox.setSelectObject(Color.WHITE); + JPanel initialColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialColorLabel, initialColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(initialColorSelectPane); + + UILabel selectedColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Select")); + selectedColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + + } + }); + selectedColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel selectedColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedColorLabel, selectedColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectedColorSelectPane); + } + + private void addBorderPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border"))); + + UILabel borderTypeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Line")); + borderLineCombo = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + borderLineCombo.setSelectedLineStyle(Constants.LINE_THIN); + + UILabel colorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Color")); + borderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + borderColor.setSelectObject(new Color(31, 173, 229) ); + + UILabel radiusLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Radius")); + borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + borderRadiusSpinner.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p}; + double[] columnSize = {p, p}; + JPanel borderPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][] { + {borderTypeLabel, borderLineCombo}, + {colorLabel, borderColor}, + {radiusLabel, borderRadiusSpinner} + }, rowSize, columnSize, 10); + + centerPane.add(borderPanel); + + } + + private void addFontPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font"))); + + UILabel initialFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_init")); + initialFontConfPane = new FontConfigPane(); + initialFontConfPane.setFontColor(new Color(31, 173, 229)); + JPanel fontPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialFontLabel, initialFontConfPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(fontPanel); + UILabel selectedFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_Select")); + selectedFontColor = new UIColorButton(); + selectedFontColor.setPreferredSize(new Dimension(20, 20)); + selectedFontColor.setColor(Color.WHITE); + JPanel selectFontColorPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedFontLabel, selectedFontColor}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectFontColorPanel); + + } + + @Override + public void populateBean(MobileStyle ob) { + UnitedMobileStyle mobileStyle = (UnitedMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + leftSpinner.setValue(mobileStyle.getLeftPadding()); + rightSpinner.setValue(mobileStyle.getRightPadding()); + topSpinner.setValue(mobileStyle.getTopPadding()); + bottomSpinner.setValue(mobileStyle.getBottomPadding()); + initialColorSelectBox.setSelectObject(mobileStyle.getInitialBackgroundColor()); + selectedColorSelectBox.setSelectObject(mobileStyle.getSelectedBackgroundColor()); + borderLineCombo.setSelectedLineStyle(mobileStyle.getBorderType()); + borderColor.setSelectObject(mobileStyle.getBorderColor()); + borderRadiusSpinner.setValue(mobileStyle.getBorderRadius()); + if(mobileStyle.getInitialFont() != null) { + initialFontConfPane.populate(mobileStyle.getInitialFont()); + } + if(mobileStyle.getSelectedFont() != null) { + selectedFontColor.setColor(mobileStyle.getSelectedFont().getForeground()); + } + } + + @Override + public MobileStyle updateBean() { + UnitedMobileStyle mobileStyle = (UnitedMobileStyle)this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setLeftPadding(leftSpinner.getValue()); + mobileStyle.setRightPadding(rightSpinner.getValue()); + mobileStyle.setTopPadding(topSpinner.getValue()); + mobileStyle.setBottomPadding(bottomSpinner.getValue()); + mobileStyle.setInitialBackgroundColor(initialColorSelectBox.getSelectObject()); + mobileStyle.setSelectedBackgroundColor(selectedColorSelectBox.getSelectObject()); + mobileStyle.setBorderType(borderLineCombo.getSelectedLineStyle()); + mobileStyle.setBorderColor(borderColor.getSelectObject()); + mobileStyle.setBorderRadius(borderRadiusSpinner.getValue()); + + FRFont initialFont = initialFontConfPane.updateFont(null, null, null); + FRFont selectedFont = initialFontConfPane.updateFont(selectedFontColor.getColor(), null, null); + selectedFont.setForeground(selectedFontColor.getColor()); + + mobileStyle.setInitialFont(initialFont); + mobileStyle.setSelectedFont(selectedFont); + + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/topparam/MobileTopParamPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/topparam/MobileTopParamPane.java new file mode 100644 index 0000000000..7f19bd3683 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/topparam/MobileTopParamPane.java @@ -0,0 +1,44 @@ +package com.fr.design.mainframe.mobile.ui.topparam; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.mobile.impl.MobileTopParamStyle; + +import javax.swing.*; +import java.awt.*; + +public class MobileTopParamPane extends BasicBeanPane { + private UICheckBox autoCommitCheckBox; + + public MobileTopParamPane() { + this.init(); + } + + private void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel panel = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Plugin-TopParam_Setting")); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + autoCommitCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Plugin-TopParam_AutoCommit"), true); + panel.add(autoCommitCheckBox); + this.add(panel, BorderLayout.CENTER); + } + + @Override + public void populateBean(MobileTopParamStyle topParamStyle) { + autoCommitCheckBox.setSelected(topParamStyle.isAutoCommit()); + } + + @Override + public MobileTopParamStyle updateBean() { + MobileTopParamStyle topParamStyle = new MobileTopParamStyle(); + topParamStyle.setAutoCommit(autoCommitCheckBox.isSelected()); + return topParamStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java new file mode 100644 index 0000000000..bcadac1c74 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java @@ -0,0 +1,57 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.widget.UITitleSplitLine; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeListener; +import java.awt.*; + +public class DesignerUtils { + + public static final int NORMAL_COMBO_WIDTH = 152; + public static final int kDefaultHorizontalPadding = 0; + public static final int kDefaultVerticalPadding = 15; + public static final int kAlignLeft = 0; + public static final int kAlignCenter = 1; + public static final int[] BORDER_LINE_STYLE_ARRAY = new int[]{ + Constants.LINE_NONE, + Constants.LINE_THIN, + Constants.LINE_MEDIUM, + Constants.LINE_THICK, + }; + + public static UITitleSplitLine createTitleSplitLine(String title) { + UITitleSplitLine splitLine = new UITitleSplitLine(title, 520); + splitLine.setPreferredSize(new Dimension(520, 20)); + return splitLine; + } + + public static UILabel createConfigLabel(String title) { + UILabel label = new UILabel(title, UILabel.RIGHT); + label.setPreferredSize(new Dimension(100, 20)); + return label; + } + + public static NewColorSelectBox createNormalColorSelectBox(ChangeListener changeListener) { + NewColorSelectBox colorSelectBox = new NewColorSelectBox(NORMAL_COMBO_WIDTH); + colorSelectBox.addSelectChangeListener(changeListener); + return colorSelectBox; + } + + public static UICheckBox createCheckBox(String text, boolean selected) { + UICheckBox uiCheckBox = new UICheckBox(text, selected); + return uiCheckBox; + } + + public static JPanel createLeftRightComponentsPane(Component... components) { + return TableLayoutHelper.createGapTableLayoutPane(new Component[][]{components}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/FontConfigPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/FontConfigPane.java new file mode 100644 index 0000000000..6386e31e01 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/FontConfigPane.java @@ -0,0 +1,137 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.base.BaseUtils; +import com.fr.base.Utils; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.general.FRFont; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Vector; + +public class FontConfigPane extends JPanel { + private static final Icon[] ITALIC_ICONS = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic_white.png")}; + private static final Icon[] BOLD_ICONS = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold_white.png")}; + + private EventListenerList fontChangeListener = new EventListenerList(); + private UIComboBox fontFamily; + private UIComboBox fontSize; + private UIToggleButton bold; + private UIColorButton color; + private UIToggleButton italic; + + + public FontConfigPane() { + super(); + init(); + } + + private void init() { + this.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + fontFamily = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); + Vector integerList = new Vector<>(); + for (int i = 1; i < 100; i++) { + integerList.add(i); + } + fontFamily.setPreferredSize(new Dimension(152, 20)); + fontSize = new UIComboBox(integerList); + fontSize.setSelectedIndex(14); + color = new UIColorButton(); + bold = new UIToggleButton(BOLD_ICONS, true); + italic = new UIToggleButton(ITALIC_ICONS, true); + fontFamily.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireFontStateChanged(); + } + }); + fontSize.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireFontStateChanged(); + } + }); + bold.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + fireFontStateChanged(); + } + }); + italic.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + fireFontStateChanged(); + } + }); + color.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + fireFontStateChanged(); + } + }); + this.add(fontFamily); + this.add(fontSize); + this.add(color); + this.add(bold); + this.add(italic); + + } + + public void setFontColor(Color fontColor) { + color.setColor(fontColor); + } + + public FRFont updateFont(Color fontColor, Boolean isBold, Boolean isItalic) { + String family = (String) fontFamily.getSelectedItem(); + int size = (int) fontSize.getSelectedItem(); + int style = Font.PLAIN; + boolean bold = (isBold == null) ? this.bold.isSelected() : isBold; + boolean italic = (isItalic == null) ? this.italic.isSelected() : isItalic; + style += bold ? Font.BOLD : Font.PLAIN; + style += italic ? Font.ITALIC : Font.PLAIN; + FRFont frFont = FRFont.getInstance(family, style, size, fontColor == null ? color.getColor() : fontColor); + return frFont; + } + + public FRFont update() { + String family = (String) fontFamily.getSelectedItem(); + int size = (int) fontSize.getSelectedItem(); + int style = Font.PLAIN; + style += this.bold.isSelected() ? Font.BOLD : Font.PLAIN; + style += this.italic.isSelected() ? Font.ITALIC : Font.PLAIN; + return FRFont.getInstance(family, style, size, color.getColor()); + } + + public void populate(FRFont frFont) { + fontFamily.setSelectedItem(frFont.getFamily()); + fontSize.setSelectedItem(frFont.getSize()); + color.setColor(frFont.getForeground()); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + + } + + /** + * 颜色状态改变 + */ + public void fireFontStateChanged() { + Object[] listeners = fontChangeListener.getListenerList(); + ChangeEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + if (e == null) { + e = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/IconConfigPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/IconConfigPane.java new file mode 100644 index 0000000000..6f8e188e3f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/IconConfigPane.java @@ -0,0 +1,185 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.base.IconManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.web.CustomIconPane; +import com.fr.form.ui.WidgetInfoConfig; +import com.fr.general.FRFont; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class IconConfigPane extends JPanel { + private UIButton editIconButton; + private UIButton deleteIconButton; + private IconButton iconButton; + + public IconConfigPane() { + initComp(); + } + + public void initComp() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + editIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Edit")); + editIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + editIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(editIconButton); + editIconButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final CustomIconPane cip = new CustomIconPane(){ + protected String createDescriptionText(){ + return Toolkit.i18nText("Fine-Design_Mobile_Custom_Icon_Message"); + } + }; + BasicDialog editDialog = cip.showWindow(new JFrame()); + editDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + IconConfigPane.this.iconButton.setIconName(cip.update()); + IconConfigPane.this.deleteIconButton.setEnabled(true); + IconConfigPane.this.repaint(); + } + }); + editDialog.setVisible(true); + } + }); + editIconButton.setEnabled(true); + + deleteIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Delete")); + deleteIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + deleteIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(deleteIconButton); + deleteIconButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + IconConfigPane.this.iconButton.setIconName(StringUtils.EMPTY); + IconConfigPane.this.deleteIconButton.setEnabled(false); + IconConfigPane.this.repaint(); + } + }); + deleteIconButton.setEnabled(false); + + + this.add(panel, BorderLayout.CENTER); + + JPanel westPane = new JPanel(); + iconButton = new IconButton(""); + westPane.add(iconButton); + this.add(westPane, BorderLayout.WEST); + } + + public void populate(String iconName) { + if(StringUtils.isNotEmpty(iconName)) { + deleteIconButton.setEnabled(true); + } else { + deleteIconButton.setEnabled(false); + } + iconButton.setIconName(iconName); + } + + public String update() { + return iconButton.getIconName(); + } + + + private class IconButton extends JToggleButton implements ActionListener { + private String iconName; + private Image iconImage = null; + private static final int ICON_BUTTON_SIZE = 20; + private static final int ICON_X = 2; + private static final int ICON_Y = 2; + + public IconButton(String name) { + this.iconName = name; + this.addActionListener(this); + this.setBackground(Color.WHITE); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(name); + } + + @Override + public void updateUI() { + setUI(new BasicButtonUI() { + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + } + }); + } + + protected void paintBorder(Graphics g) { + super.paintBorder(g); + if (StringUtils.isNotEmpty(iconButton.getIconName())) { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#419BF9"), 0, 0, 20, 20); + } else { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#D9DADD"), 0, 0, 20, 20); + } + + } + + public String getIconName() { + return iconName; + } + + public void setIconName(String iconName) { + this.iconName = iconName; + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(iconName); + this.repaint(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g; + // carl:这里缩放显示 16 × 16 + if (iconImage != null) { + g2d.drawImage(iconImage, ICON_X, ICON_Y, IconManager.DEFAULT_ICONWIDTH, IconManager.DEFAULT_ICONHEIGHT, null); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(ICON_BUTTON_SIZE, ICON_BUTTON_SIZE); + } + + public void actionPerformed(ActionEvent evt) { + IconConfigPane.this.repaint();// repaint + } + + @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); + } + } + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/MobileStyleProviderManager.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/MobileStyleProviderManager.java new file mode 100644 index 0000000000..7c3194ba61 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/MobileStyleProviderManager.java @@ -0,0 +1,41 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.design.mainframe.mobile.provider.combo.SimpleComboCheckBoxStyleProvider; +import com.fr.design.mainframe.mobile.provider.combo.SimpleComboStyleProvider; +import com.fr.design.mainframe.mobile.provider.date.NavigationStyleProvider; +import com.fr.design.mainframe.mobile.provider.date.SimpleDateStyleProvider; +import com.fr.design.mainframe.mobile.provider.date.SimpleStyleProvider; +import com.fr.design.mainframe.mobile.provider.radiogroup.CapsuleRadioGroupStyleProvider; +import com.fr.design.mainframe.mobile.provider.radiogroup.ImageRadioGroupStyleProvider; +import com.fr.design.mainframe.mobile.provider.radiogroup.UnitedRadioGroupStyleProvider; +import com.fr.design.mainframe.mobile.provider.topparam.MobileTopParamStyleProvider; +import com.fr.stable.fun.mark.Mutable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class MobileStyleProviderManager { + private static Set mobileWidgetStyleProviderSet = new HashSet() {{ + add(new SimpleStyleProvider()); + add(new NavigationStyleProvider()); + add(new SimpleDateStyleProvider()); + add(new SimpleComboStyleProvider()); + add(new SimpleComboCheckBoxStyleProvider()); + add(new CapsuleRadioGroupStyleProvider()); + add(new UnitedRadioGroupStyleProvider()); + add(new ImageRadioGroupStyleProvider()); + }}; + private static Set mobileParamUIProviderSet = new HashSet() {{ + add(new MobileTopParamStyleProvider()); + }}; + private static Map> map = new HashMap>() {{ + put("MobileWidgetStyleProvider", mobileWidgetStyleProviderSet); + put("MobileParamUIProvider", mobileParamUIProviderSet); + }}; + + public static Set getArray(String mark) { + return (Set) map.get(mark); + } +} 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 index 67b369a6c9..3508b35195 100644 --- 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 @@ -32,7 +32,7 @@ import java.awt.event.MouseListener; public class PredefinedStyleBlock extends JPanel { private PredefinedStyle previewObject; private PredefinedStyleSelectPane parentPane; - private Icon markedMode = IOUtils.readIcon("/com/fr/design/form/images/marked.png"); + 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; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java index 9e2a0d5efd..823dd6ff3a 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java @@ -15,7 +15,7 @@ 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.style.background.gradient.FixedGradientBar; +import com.fr.design.style.background.gradient.FixedGradientBarNoTheme; import com.fr.design.style.color.ColorAdjustPane; import com.fr.stable.StringUtils; @@ -40,7 +40,7 @@ public class ColorFillStylePane extends BasicBeanPane { private ColorSchemeComboBox styleSelectBox; private JPanel customPane; private JPanel changeColorSetPane; - private FixedGradientBar colorGradient; + private FixedGradientBarNoTheme colorGradient; private CardLayout cardLayout; @@ -69,8 +69,8 @@ public class ColorFillStylePane extends BasicBeanPane { }; changeColorSetPane = new JPanel(cardLayout = new CardLayout()); - changeColorSetPane.add(colorGradient = new FixedGradientBar(4, 130), "gradient"); - gradientColors = new Color[]{Color.WHITE, FixedGradientBar.NEW_CHARACTER}; + changeColorSetPane.add(colorGradient = new FixedGradientBarNoTheme(4, 130), "gradient"); + gradientColors = new Color[]{Color.WHITE, FixedGradientBarNoTheme.NEW_CHARACTER}; changeColorSetPane.add(colorAdjustPane = new ColorAdjustPane(), "acc"); accColors = ColorAdjustPane.DEFAULT_COLORS; cardLayout.show(changeColorSetPane, "acc"); 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 index b7034fd669..43d20d1bde 100644 --- 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 @@ -3,20 +3,10 @@ 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.gui.ibutton.UIButton; -import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; import com.fr.general.Background; - -import javax.swing.BorderFactory; -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; /** * Created by kerry on 2020-08-31 @@ -50,48 +40,9 @@ public class ColorDetailPane extends AbstractBackgroundDetailPane chartPreStyleProviders = vanChart.getChartPreStyleProvider(); - for (ChartPreStyleProvider chartPreStyleProvider : chartPreStyleProviders) { - chartPreStyleProvider.updatePreDefinedStyle(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(); + vanChart.attrChange();*/ } @Override diff --git a/designer-base/src/main/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfo.java b/designer-base/src/main/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfo.java index 3d305d8ace..ea8722f1b3 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfo.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfo.java @@ -1,6 +1,5 @@ package com.fr.design.mainframe.reuse; -import com.fr.design.DesignerEnvManager; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLable; import com.fr.stable.xml.XMLableReader; @@ -10,6 +9,7 @@ import com.fr.stable.xml.XMLableReader; */ public class ComponentReuseNotificationInfo implements XMLable { public static final String XML_TAG = "ComponentReuseNotificationInfo"; + private static final int INVALID_NUM = -1; private static final ComponentReuseNotificationInfo INSTANCE = new ComponentReuseNotificationInfo(); @@ -17,51 +17,66 @@ public class ComponentReuseNotificationInfo implements XMLable { return INSTANCE; } - private long lastNotifyTime = 0; + private boolean clickedWidgetLib = false; - private int notifiedNumber = 0; + private long firstDragEndTime = 0L; - private boolean clickedWidgetLib = false; + private boolean completeEmbedFilter = false; - private long lastGuidePopUpTime = 0; + private boolean firstDrag = true; private String historyCreatedReuses = "[]"; - public long getLastNotifyTime() { - return lastNotifyTime; + private boolean widgetLibHasRefreshed = false; + + private boolean completeFirstShowComponentLib = false; + + public boolean isClickedWidgetLib() { + return clickedWidgetLib; } - public void setLastNotifyTime(long lastNotifyTime) { - this.lastNotifyTime = lastNotifyTime; + public void setClickedWidgetLib(boolean clickedWidgetLib) { + this.clickedWidgetLib = clickedWidgetLib; } - public int getNotifiedNumber() { - return notifiedNumber; + public boolean isCompleteEmbedFilter() { + return completeEmbedFilter; } - public void setNotifiedNumber(int notifiedNumber) { - this.notifiedNumber = notifiedNumber; + public void setCompleteEmbedFilter(boolean completeEmbedFilter) { + this.completeEmbedFilter = completeEmbedFilter; } - public boolean isClickedWidgetLib() { - return clickedWidgetLib; + public long getFirstDragEndTime() { + return firstDragEndTime; } - public void setClickedWidgetLib(boolean clickedWidgetLib) { - this.clickedWidgetLib = clickedWidgetLib; + public void setFirstDragEndTime(long firstDragEndTime) { + this.firstDragEndTime = firstDragEndTime; } - public long getLastGuidePopUpTime() { - return lastGuidePopUpTime; + public boolean isFirstDrag() { + return firstDrag; } - public void setLastGuidePopUpTime(long lastGuidePopUpTime) { - this.lastGuidePopUpTime = lastGuidePopUpTime; + public void setFirstDrag(boolean firstDrag) { + this.firstDrag = firstDrag; } - public void updateLastGuidePopUpTime() { - this.setLastGuidePopUpTime(System.currentTimeMillis()); - DesignerEnvManager.getEnvManager().saveXMLFile(); + public boolean isWidgetLibHasRefreshed() { + return widgetLibHasRefreshed; + } + + public void setWidgetLibHasRefreshed(boolean widgetLibHasRefreshed) { + this.widgetLibHasRefreshed = widgetLibHasRefreshed; + } + + public boolean isCompleteFirstShowComponentLib() { + return completeFirstShowComponentLib; + } + + public void setCompleteFirstShowComponentLib(boolean completeFirstShowComponentLib) { + this.completeFirstShowComponentLib = completeFirstShowComponentLib; } public String getHistoryCreatedReuses() { @@ -72,23 +87,41 @@ public class ComponentReuseNotificationInfo implements XMLable { this.historyCreatedReuses = historyCreatedReuses; } + //兼容老版本云端埋点的记录 + public long getLastNotifyTime() { + return INVALID_NUM; + } + + public int getNotifiedNumber() { + return INVALID_NUM; + } + + public long getLastGuidePopUpTime() { + return INVALID_NUM; + } + @Override public void readXML(XMLableReader reader) { - this.setLastNotifyTime(reader.getAttrAsLong("lastNotifyTime", 0L)); - this.setNotifiedNumber(reader.getAttrAsInt("notifiedNumber", 0)); this.setClickedWidgetLib(reader.getAttrAsBoolean("clickedWidgetLib", false)); - this.setLastGuidePopUpTime(reader.getAttrAsLong("lastGuidePopUpTime", 0L)); + this.setCompleteEmbedFilter(reader.getAttrAsBoolean("completeEmbedFilter", false)); + this.setCompleteFirstShowComponentLib(reader.getAttrAsBoolean("completeFirstShowComponentLib", false)); + this.setWidgetLibHasRefreshed(reader.getAttrAsBoolean("widgetLibHasRefreshed", false)); + this.setFirstDrag(reader.getAttrAsBoolean("firstDrag", true)); this.setHistoryCreatedReuses(reader.getAttrAsString("historyCreatedReuses", "[]")); + this.setFirstDragEndTime(reader.getAttrAsLong("firstDragEndTime", 0L)); } @Override public void writeXML(XMLPrintWriter writer) { writer.startTAG("ComponentReuseNotificationInfo"); - writer.attr("lastNotifyTime", this.lastNotifyTime) - .attr("notifiedNumber", this.notifiedNumber) - .attr("clickedWidgetLib", this.clickedWidgetLib) - .attr("lastGuidePopUpTime", this.lastGuidePopUpTime) - .attr("historyCreatedReuses", this.historyCreatedReuses);; + writer.attr("clickedWidgetLib", this.clickedWidgetLib) + .attr("completeEmbedFilter", this.completeEmbedFilter) + .attr("completeFirstShowComponentLib", this.completeFirstShowComponentLib) + .attr("firstDrag", this.firstDrag) + .attr("widgetLibHasRefreshed", this.widgetLibHasRefreshed) + .attr("firstDragEndTime", this.firstDragEndTime) + .attr("historyCreatedReuses", this.historyCreatedReuses); + ; writer.end(); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/reuse/ReuseGuideDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/reuse/ReuseGuideDialog.java deleted file mode 100644 index a0e9166592..0000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/reuse/ReuseGuideDialog.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.fr.design.mainframe.reuse; - -import com.fr.base.background.ColorBackground; -import com.fr.design.dialog.UIDialog; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.PromptWindow; -import com.fr.design.mainframe.share.collect.ComponentCollector; -import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.IOUtils; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JPanel; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dialog; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.RenderingHints; -import java.awt.geom.RoundRectangle2D; - -public class ReuseGuideDialog extends UIDialog implements PromptWindow { - InnerDialog innerDialog; - private static final Dimension DEFAULT = new Dimension(735, 510); - - public ReuseGuideDialog(Frame parent) { - super(parent); - } - - @Override - public void showWindow() { - innerDialog = new InnerDialog(this); - JPanel backGroundPane = new JPanel() { - @Override - protected void paintComponent(Graphics g) { - Image icon = IOUtils.readImage("com/fr/base/images/share/background.png");// 003.jpg是测试图片在项目的根目录下 - g.drawImage(icon, 0, 0, getSize().width, getSize().height, this);// 图片会自动缩放 - } - }; - add(backGroundPane, BorderLayout.CENTER); - initStyle(); - innerDialog.showWindow(); - } - - private void initStyle() { - setSize(DEFAULT); - setUndecorated(true); - setBackground(new Color(0, 0, 0, 0)); - GUICoreUtils.centerWindow(this); - } - - @Override - public void hideWindow() { - ComponentReuseNotificationInfo.getInstance().updateLastGuidePopUpTime(); - this.setVisible(false); - if (innerDialog != null) { - innerDialog.setVisible(false); - innerDialog.dispose(); - innerDialog = null; - } - this.dispose(); - } - - @Override - public void checkValid() { - - } - - class InnerDialog extends UIDialog { - private final Dimension DEFAULT = new Dimension(700, 475); - private static final int TITLE_FONT_SIZE = 20; - - public InnerDialog(Dialog dialog) { - super(dialog); - } - - public void showWindow() { - add(createCenterPanel(), BorderLayout.CENTER); - add(createSouthPanel(), BorderLayout.SOUTH); - add(createNorthPanel(), BorderLayout.NORTH); - showDialog(); - } - - private JPanel createNorthPanel() { - JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - - //右上角关闭按钮 - JButton button = new JButton(new ImageIcon(IOUtils.readImage("/com/fr/base/images/share/close.png").getScaledInstance(15, 15, Image.SCALE_SMOOTH))); - button.setBorder(null); - button.setOpaque(false); - button.addActionListener(e -> ReuseGuideDialog.this.hideWindow()); - - northPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 15)); - northPanel.setOpaque(false); - northPanel.add(button); - return northPanel; - } - - private JPanel createCenterPanel() { - JPanel centerPanel = new JPanel(new BorderLayout()); - - UILabel titleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Share_Drag_And_Make_Component")); - UILabel imageLabel = new UILabel(new ImageIcon(IOUtils.readImage("com/fr/design/images/dashboard/guide.png").getScaledInstance(DEFAULT.width, DEFAULT.height, Image.SCALE_SMOOTH))); - titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, TITLE_FONT_SIZE)); - titleLabel.setBorder(BorderFactory.createEmptyBorder()); - - JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER)); - panel.setOpaque(false); - panel.add(titleLabel); - - centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - centerPanel.setOpaque(false); - centerPanel.add(imageLabel, BorderLayout.CENTER); - centerPanel.add(panel, BorderLayout.NORTH); - return centerPanel; - } - - private JPanel createSouthPanel() { - JPanel southPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); - - JButton button = new JButton(Toolkit.i18nText("Fine-Design_Share_Try_Drag")) { - @Override - public void paint(Graphics g) { - ColorBackground buttonBackground = ColorBackground.getInstance(Color.decode("#419BF9")); - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - buttonBackground.paint(g2d, new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), 8, 8)); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - super.paint(g); - } - }; - button.setBorder(null); - button.setForeground(Color.WHITE); - button.setOpaque(false); - button.addActionListener(e -> ReuseGuideDialog.this.hideWindow()); - - southPanel.setBorder(BorderFactory.createEmptyBorder(0, 290, 19, 290)); - southPanel.setPreferredSize(new Dimension(DEFAULT.width, 51)); - southPanel.setOpaque(false); - southPanel.add(button); - return southPanel; - } - - /** - * 显示窗口 - */ - private void showDialog() { - setSize(DEFAULT); - setUndecorated(true); - GUICoreUtils.centerWindow(this); - setModalityType(ModalityType.APPLICATION_MODAL); - ReuseGuideDialog.this.setVisible(true); - setVisible(true); - } - - @Override - public void checkValid() { - - } - } -} 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 new file mode 100644 index 0000000000..cec7fbc8fc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java @@ -0,0 +1,107 @@ +package com.fr.design.mainframe.share; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.locale.impl.ShowOnlineWidgetMark; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo; +import com.fr.form.share.constants.ComponentPath; +import com.fr.form.share.group.filter.ReuFilter; +import com.fr.design.DesignerCloudURLManager; +import com.fr.general.locale.LocaleCenter; +import com.fr.general.locale.LocaleMark; +import com.fr.workspace.WorkContext; + +/** + * Created by kerry on 2021/10/27 + */ +public class ComponentShareUtil { + private ComponentShareUtil() { + + } + + /** + * 判断是否需要切换到在线组件库 + * + * @return + */ + public static boolean needSwitch2OnlineTab() { + return DesignerCloudURLManager.getInstance().isConnected() && !hasTouched() && isCurrentTplNewCreate() && isShowOnlineWidgetRepoPane(); + } + + public static boolean isShowOnlineWidgetRepoPane() { + LocaleMark localeMark = LocaleCenter.getMark(ShowOnlineWidgetMark.class); + return localeMark.getValue(); + } + + /** + * 判断是否可触达 + * + * @return boolean + */ + public static boolean hasTouched() { + String sharePath = ComponentPath.SHARE_PATH.path(); + String[] components = WorkContext.getWorkResource().list(sharePath, new ReuFilter()); + return components != null && components.length > 6; + } + + /** + * 判断当前模板是否是新建模板 + * + * @return boolean + */ + public static boolean isCurrentTplNewCreate() { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return jTemplate.isNewCreateTpl(); + } + + /** + * 判断是否在需要展示组件库界面 + * + * @return boolean + */ + public static boolean needShowEmbedFilterPane() { + return !ComponentReuseNotificationInfo.getInstance().isCompleteEmbedFilter() && !hasTouched() && isCurrentTplNewCreate(); + } + + public static boolean needShowComponentLib() { + return !ComponentReuseNotificationInfo.getInstance().isCompleteFirstShowComponentLib() && !hasTouched() && isCurrentTplNewCreate(); + } + + /** + * 判断是否需要展示首次拖拽动效 + * + * @return boolean + */ + public static boolean needShowFirstDragAnimate() { + return ComponentReuseNotificationInfo.getInstance().isFirstDrag(); + } + + /** + * 完成嵌入式筛选 + */ + public static void completeEmbedFilter() { + boolean changed = false; + if (!ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed()) { + ComponentReuseNotificationInfo.getInstance().setWidgetLibHasRefreshed(true); + changed = true; + } + if (!ComponentReuseNotificationInfo.getInstance().isCompleteEmbedFilter()) { + ComponentReuseNotificationInfo.getInstance().setCompleteEmbedFilter(true); + changed = true; + } + if (changed) { + DesignerEnvManager.getEnvManager().saveXMLFile(); + } + } + + /** + * 记录组件库刷新 + */ + public static void recordWidgetLibHasRefreshed() { + if (!ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed()) { + ComponentReuseNotificationInfo.getInstance().setWidgetLibHasRefreshed(true); + DesignerEnvManager.getEnvManager().saveXMLFile(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java index 47b7dc7ef0..4776739784 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java @@ -4,6 +4,7 @@ import com.fr.base.io.XMLReadHelper; import com.fr.config.MarketConfig; import com.fr.design.DesignerEnvManager; import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo; +import com.fr.design.mainframe.share.ComponentShareUtil; import com.fr.form.share.DefaultSharableWidget; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.constants.ComponentPath; @@ -19,7 +20,6 @@ import com.fr.json.JSONException; import com.fr.json.JSONFactory; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; -import com.fr.plugin.context.PluginContexts; import com.fr.stable.ProductConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; @@ -48,10 +48,6 @@ import java.util.Iterator; public class ComponentCollector implements XMLable { private static final long ONE_MINUTE = 60 * 1000L; - private static final int REUSE_INFO_FIRST_POPUP = 1; - - private static final int REUSE_INFO_SECOND_POPUP = 2; - private static final String SIMPLE_DATE_PATTERN = "yyyy-MM-dd"; private static final String XML = "ComponentCollector"; @@ -98,11 +94,11 @@ public class ComponentCollector implements XMLable { private static final String MARKET_CLICK = "marketClick"; - private static final String PROMPT_JUMP = "promptJump"; + private static final String FIRST_SHOW_REACT = "firstShowReact"; - private static final String TOOLBAR_JUMP = "toolbarJump"; + private static final String EMBEDED_FILTER_REACT = "embededFilterReact"; - private static final String POPUP_JUMP = "popupJump"; + private static final String DYNAMIC_EFFECT_REACT = "dynamicEffectReact"; private static final String uuid = DesignerEnvManager.getEnvManager().getUUID(); @@ -116,11 +112,11 @@ public class ComponentCollector implements XMLable { private int cmpBoardClick = 0; - private int promptJump = 0; + private int firstShowReact = 0; - private int toolbarJump = 0; + private int embededFilterReact = 0; - private int popupJump = 0; + private int dynamicEffectReact = 0; private JSONArray activateRecord = JSONFactory.createJSON(JSON.ARRAY); @@ -291,7 +287,7 @@ public class ComponentCollector implements XMLable { try { DefaultShareGroupManager.getInstance().refresh(); Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup(); - for(Group group : groups) { + for (Group group : groups) { JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); jo.put(GROUP_NAME, group.getGroupName()); jo.put(CONTAIN_AMOUNT, group.getAllBindInfoList().length); @@ -338,41 +334,47 @@ public class ComponentCollector implements XMLable { saveInfo(); } - public void collectPromptJumpWhenJump(){ - if (ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() == REUSE_INFO_FIRST_POPUP) { - this.promptJump = 1; - saveInfo(); - }else if(ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() == REUSE_INFO_SECOND_POPUP){ - this.promptJump = 2; - saveInfo(); + public void collectFirstShowReact(int flag) { + if (this.firstShowReact == flag) { + return; } + this.firstShowReact = flag; + saveInfo(); } - - public void collectPromptJumpWhenShow() { - if (ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() == REUSE_INFO_SECOND_POPUP) { - this.promptJump = -1; - saveInfo(); + public void clickComponentSetting() { + int firstShowReact = ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed() ? 2 : -1; + if (this.firstShowReact != firstShowReact) { + collectFirstShowReact(firstShowReact); + } + if (this.embededFilterReact == 0 && ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed()) { + collectEmbededFilterReact(-1); } } - public void collectToolbarJump() { - if (this.toolbarJump == 0) { - this.toolbarJump = 1; - saveInfo(); + public void collectEmbededFilterReact(int flag) { + if (this.embededFilterReact == flag) { + return; } - + this.embededFilterReact = flag; + saveInfo(); } - public void collectPopupJump() { - long currentTime = System.currentTimeMillis(); - long lastGuidePopUpTime = ComponentReuseNotificationInfo.getInstance().getLastGuidePopUpTime(); - if (currentTime - lastGuidePopUpTime <= ONE_MINUTE && this.popupJump == 0) { - this.popupJump = 1; - saveInfo(); + public void collectDynamicEffectReact() { + if (this.dynamicEffectReact == 1) { + return; + } + if (System.currentTimeMillis() - ComponentReuseNotificationInfo.getInstance().getFirstDragEndTime() <= ONE_MINUTE) { + collectDynamicEffectReactFlag(1); } } + public void collectDynamicEffectReactFlag(int flag) { + this.dynamicEffectReact = flag; + saveInfo(); + } + + public void clearSortType() { sortType = JSONFactory.createJSON(JSON.ARRAY); } @@ -468,6 +470,10 @@ public class ComponentCollector implements XMLable { this.generateCmpNumber = reader.getAttrAsInt("generateCmpNumber", 0); this.uploadCmpNumber = reader.getAttrAsInt("uploadCmpNumber", 0); + this.firstShowReact = reader.getAttrAsInt(FIRST_SHOW_REACT, 0); + this.embededFilterReact = reader.getAttrAsInt(EMBEDED_FILTER_REACT, 0); + this.dynamicEffectReact = reader.getAttrAsInt(DYNAMIC_EFFECT_REACT, 0); + String activateRecordStr = reader.getAttrAsString("activateRecord", StringUtils.EMPTY); activateRecord = parseJSONArray(activateRecordStr); String generateCmpRecordStr = reader.getAttrAsString("generateCmpRecord", StringUtils.EMPTY); @@ -475,13 +481,9 @@ public class ComponentCollector implements XMLable { this.helpConfigInfo = parseJSONArray(reader.getAttrAsString(HELP_CONFIG_INFO, StringUtils.EMPTY)); this.helpConfigUseInfo = parseJSONArray(reader.getAttrAsString(HELP_CONFIG_USE_INFO, StringUtils.EMPTY)); - this.searchContent = parseJSONArray(reader.getAttrAsString(SEARCH_CONTENT,StringUtils.EMPTY)); + this.searchContent = parseJSONArray(reader.getAttrAsString(SEARCH_CONTENT, StringUtils.EMPTY)); this.filterContent = parseJSONArray(reader.getAttrAsString(FILTER_CONTENT, StringUtils.EMPTY)); this.sortType = parseJSONArray(reader.getAttrAsString(SORT_TYPE, StringUtils.EMPTY)); - this.promptJump = reader.getAttrAsInt(PROMPT_JUMP, 0); - this.toolbarJump = reader.getAttrAsInt(TOOLBAR_JUMP, 0); - this.popupJump = reader.getAttrAsInt(POPUP_JUMP, 0); - } } @@ -515,9 +517,9 @@ public class ComponentCollector implements XMLable { .attr(SEARCH_CONTENT, searchContent.toString()) .attr(FILTER_CONTENT, filterContent.toString()) .attr(SORT_TYPE, sortType.toString()) - .attr(PROMPT_JUMP, promptJump) - .attr(TOOLBAR_JUMP, toolbarJump) - .attr(POPUP_JUMP, popupJump) + .attr(FIRST_SHOW_REACT, firstShowReact) + .attr(EMBEDED_FILTER_REACT, embededFilterReact) + .attr(DYNAMIC_EFFECT_REACT, dynamicEffectReact) .end(); } @@ -530,7 +532,7 @@ public class ComponentCollector implements XMLable { jo.put("userId", MarketConfig.getInstance().getBBSAttr().getBbsUid()); jo.put("uuid", uuid); jo.put("cmpBoardClickDaily", cmpBoardClickDaily()); - jo.put("pluginVersion", GeneralUtils.readBuildNO()); + jo.put("pluginVersion", GeneralUtils.getVersion()); jo.put("localCmpNumber", localCmpNumber); jo.put("remoteCmpNumber", remoteCmpNumber); jo.put("uploadCmpNumber", uploadCmpNumber); @@ -542,15 +544,9 @@ public class ComponentCollector implements XMLable { jo.put(SEARCH_CONTENT, searchContent.toString()); jo.put(FILTER_CONTENT, filterContent.toString()); jo.put(SORT_TYPE, sortType.toString()); - jo.put("guideInfo", assembleGuideInfo()); - return jo.toString(); - } - - private String assembleGuideInfo() { - JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); - jo.put(PROMPT_JUMP, promptJump) - .put(TOOLBAR_JUMP, toolbarJump) - .put(POPUP_JUMP, popupJump); + jo.put(FIRST_SHOW_REACT, firstShowReact); + jo.put(EMBEDED_FILTER_REACT, embededFilterReact); + jo.put(DYNAMIC_EFFECT_REACT, dynamicEffectReact); return jo.toString(); } @@ -603,7 +599,7 @@ public class ComponentCollector implements XMLable { return JSONFactory.createJSON(JSON.ARRAY); } - public void clear(){ + public void clear() { clearActiveRecord(); clearGenerateCmpRecord(); clearFilterContent(); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java new file mode 100644 index 0000000000..3df87ac658 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java @@ -0,0 +1,81 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.concurrent.NamedThreadFactory; +import com.fr.module.ModuleContext; + +import javax.swing.SwingUtilities; +import java.util.concurrent.ExecutorService; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/24 + */ +public class AsyncThemeFetcher { + + private final ExecutorService executorService; + private final TemplateThemeConfig config; + + public AsyncThemeFetcher(int threads, TemplateThemeConfig config) { + this.executorService = ModuleContext.getExecutor().newFixedThreadPool( + threads, + new NamedThreadFactory(this.getClass().getName()) + ); + this.config = config; + } + + public void shutdown() { + executorService.shutdown(); + } + + public boolean isShutdown() { + return executorService.isShutdown(); + } + + public void submit(String themeName, AsyncThemeFetchCallback callback) { + if (callback != null) { + callback.beforeCachedFetch(); + } + executorService.submit(new Runnable() { + @Override + public void run() { + if (executorService.isShutdown()) { + return; + } + T theme = config.cachedFetch(themeName); + if (executorService.isShutdown()) { + return; + } + if (callback != null) { + // 后续任务不要在工作线程中执行,从而确保只在EDT线程操作UI + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + callback.afterCachedFetch(theme); + } + }); + } + } + }); + } + + public interface AsyncThemeFetchCallback { + void beforeCachedFetch(); + void afterCachedFetch(T theme); + } + + public static class AsyncThemeFetchCallbackAdapter implements AsyncThemeFetchCallback { + + @Override + public void beforeCachedFetch() { + + } + + @Override + public void afterCachedFetch(T theme) { + + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java new file mode 100644 index 0000000000..798bb73c59 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java @@ -0,0 +1,91 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.base.theme.settings.ThemedFormBodyStyle; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.edit.ChartStyleFormEditPane; +import com.fr.design.mainframe.theme.edit.ComponentStyleEditPane; +import com.fr.design.mainframe.theme.edit.FormBodyStyleEditPane; +import com.fr.design.mainframe.theme.preview.FormThemePreviewPane; + +import javax.swing.JPanel; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class FormThemeProfilePane extends TemplateThemeProfilePane { + public static final int LABEL_WIDTH = 60; + + private FormBodyStyleEditPane formBodyStyleSettingPane; + private ComponentStyleEditPane componentStyleSettingPane; + + public FormThemeProfilePane(TemplateThemeConfig config) { + super(config); + } + + @Override + public FormThemePreviewPane createThemePreviewPane() { + return new FormThemePreviewPane(); + } + + @Override + public TemplateThemeEditorPane createThemeEditorPane() { + return new FormThemeEditorPane(config); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Form_Theme_Profile_Dialog_Title"); + } + + private static class FormThemeEditorPane extends TemplateThemeEditorPane { + + private final FormBodyStyleEditPane formBodyStyleSettingPane; + private final ComponentStyleEditPane componentStyleSettingPane; + + public FormThemeEditorPane(TemplateThemeConfig config) { + super(config); + formBodyStyleSettingPane = new FormBodyStyleEditPane(); + addCustomEditorPane(i18nText("Fine-Design_Predefined_Template_Background"), formBodyStyleSettingPane); + + addCustomEditorPane(i18nText("Fine-Design_Predefined_Cell_Style"), createCellStyleSettingPane()); + addCustomEditorPane(i18nText("Fine-Design_Predefined_Chart_Style"), createChartStyleSettingPane()); + + + componentStyleSettingPane = new ComponentStyleEditPane(); + addCustomEditorPane(i18nText("Fine-Design_Predefined_Component_Style"), componentStyleSettingPane); + } + + @Override + protected JPanel createChartStyleSettingPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + chartStyleSettingPane = new ChartStyleFormEditPane(); + container.add(chartStyleSettingPane); + return container; + } + + @Override + protected void populateBean4CustomEditors(FormTheme theme) { + super.populateBean4CustomEditors(theme); + formBodyStyleSettingPane.populateBean(theme.getBodyStyle()); + componentStyleSettingPane.populateBean(theme.getComponentStyle()); + } + + @Override + protected void updateBean4CustomEditors(FormTheme theme) { + super.updateBean4CustomEditors(theme); + ThemedFormBodyStyle formBodyStyle = formBodyStyleSettingPane.updateBean(); + theme.setBodyStyle(formBodyStyle); + + ThemedComponentStyle componentStyle = componentStyleSettingPane.updateBean(); + theme.setComponentStyle(componentStyle); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java new file mode 100644 index 0000000000..f0f25f677f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java @@ -0,0 +1,61 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.theme.edit.ReportBodyStyleEditPane; +import com.fr.design.mainframe.theme.preview.ReportThemePreviewPane; +import javax.swing.JPanel; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ReportThemeProfilePane extends TemplateThemeProfilePane { + private ReportBodyStyleEditPane reportBodyStyleSettingPane; + + public ReportThemeProfilePane(TemplateThemeConfig config) { + super(config); + } + + @Override + public ReportThemePreviewPane createThemePreviewPane() { + return new ReportThemePreviewPane(); + } + + @Override + public TemplateThemeEditorPane createThemeEditorPane() { + return new ReportThemeEditorPane(config); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Report_Theme_Profile_Dialog_Title"); + } + + private static class ReportThemeEditorPane extends TemplateThemeEditorPane { + + private final ReportBodyStyleEditPane reportBodyStyleSettingPane; + + public ReportThemeEditorPane(TemplateThemeConfig config) { + super(config); + this.reportBodyStyleSettingPane = new ReportBodyStyleEditPane(); + addCustomEditorPane(Toolkit.i18nText("Fine-Design_Predefined_Template_Background"), reportBodyStyleSettingPane); + addCustomEditorPane(Toolkit.i18nText("Fine-Design_Predefined_Cell_Style"), createCellStyleSettingPane()); + addCustomEditorPane(Toolkit.i18nText("Fine-Design_Predefined_Chart_Style"), createChartStyleSettingPane()); + } + + @Override + public void populateBean4CustomEditors(ReportTheme theme) { + super.populateBean4CustomEditors(theme); + reportBodyStyleSettingPane.populateBean(theme.getBodyStyle()); + } + + @Override + public void updateBean4CustomEditors(ReportTheme theme) { + super.updateBean4CustomEditors(theme); + theme.setBodyStyle(this.reportBodyStyleSettingPane.updateBean()); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java new file mode 100644 index 0000000000..ea649033ea --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java @@ -0,0 +1,264 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.GraphHelper; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.general.IOUtils; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +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.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeBlock extends JPanel { + public static final int INFO_HEIGHT = 30; + public static final int CONTENT_WIDTH = ThemeThumbnail.WIDTH; + public static final int CONTENT_HEIGHT = ThemeThumbnail.HEIGHT + INFO_HEIGHT; + private static final Color HOVERING_BORDER_COLOR = new Color(65, 155, 249); + + private final String name; + private final TemplateThemeConfig config; + private T theme; + private final TemplateThemeProfilePane profilePane; + private final Icon theme4currentTemplateMarkIcon = IOUtils.readIcon("/com/fr/design/form/images/theme4currentTemplate.png"); + private final Icon theme4NewTemplateMarkIcon= IOUtils.readIcon("/com/fr/design/form/images/theme4newTemplate.png"); + private final Icon profileIcon = IOUtils.readIcon("/com/fr/design/icon/icon_edit.png"); + private final boolean displayTheme4NewTemplateMarker; + + private final ThumbnailPane thumbnailPane; + // UIButton会影响Block的手势监听,这里使用UILabel代替,点击事件也有Block代为处理 + private UILabel profileButton; + private boolean selected = false; + private boolean hovering = false; + + private MouseAdapter clickListener; + + public TemplateThemeBlock(String name, + boolean displayTheme4NewTemplateMarker, + TemplateThemeConfig config, + TemplateThemeProfilePane profilePane) { + this.name = name; + this.setName(name); + this.displayTheme4NewTemplateMarker = displayTheme4NewTemplateMarker; + this.config = config; + this.profilePane = profilePane; + this.thumbnailPane = new ThumbnailPane(); + + initializePane(); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (clickListener != null) { + clickListener.mouseClicked(e); + } + + if (profileButton != null && profilePane != null) { + delegateProfileButtonClick(e); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + hovering = true; + repaint(); + } + + @Override + public void mouseExited(MouseEvent e) { + hovering = false; + repaint(); + } + }); + } + + private void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + setBackground(Color.WHITE); + + thumbnailPane.setBackground(Color.WHITE); + thumbnailPane.setPreferredSize(new Dimension(ThemeThumbnail.WIDTH, ThemeThumbnail.HEIGHT)); + + JPanel infoPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + infoPane.setPreferredSize(new Dimension(CONTENT_WIDTH, INFO_HEIGHT)); + infoPane.setBackground(Color.WHITE); + infoPane.setBorder(BorderFactory.createEmptyBorder(0, IntervalConstants.INTERVAL_L7,0,IntervalConstants.INTERVAL_L7)); + + UILabel titleLabel = new UILabel(name); + titleLabel.setToolTipText(name); + infoPane.add(titleLabel, BorderLayout.CENTER); + + if (profilePane != null) { + addProfileButton(infoPane); + } + + add(thumbnailPane, BorderLayout.CENTER); + add(infoPane, BorderLayout.SOUTH); + } + + public void setTheme(T theme) { + this.theme = theme; + Image image = null; + if (theme != null) { + ThemeThumbnail thumbnail = theme.getThumbnail(); + if (thumbnail != null) { + image = thumbnail.getImage(); + } + } + thumbnailPane.setThumbnail(image); + invalidate(); + repaint(); + } + + public T getTheme() { + return this.theme; + } + + public void setSelected(boolean selected) { + this.selected = selected; + repaint(); + } + + public void addClickListener(MouseAdapter clickListener) { + this.clickListener = clickListener; + } + + private void addProfileButton(JPanel panel) { + profileButton = new UILabel(profileIcon); + profileButton.setPreferredSize(new Dimension(24, 24)); + panel.add(profileButton, BorderLayout.EAST); + } + + private void delegateProfileButtonClick(MouseEvent e) { + int x = e.getX(); + int y = e.getY(); + + int profileButtonX = profileButton.getX(); + int profileButtonY = thumbnailPane.getHeight() + profileButton.getY(); + + boolean inX = profileButtonX <= x && x <= profileButtonX + profileButton.getWidth(); + boolean inY = profileButtonY <= y && y <= profileButtonY + profileButton.getHeight(); + if (inX && inY) { + openProfileDialog(); + } + } + + private void openProfileDialog() { + if (theme == null) { + return; + } + Window parent = SwingUtilities.getWindowAncestor(TemplateThemeBlock.this); + TemplateThemeProfileDialog profileDialog = new TemplateThemeProfileDialog<>(parent, profilePane); + try { + profilePane.populateBean((T) theme.clone()); + } catch (CloneNotSupportedException ex) { + ex.printStackTrace(); + } + profileDialog.setVisible(true); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateThemeConfig templateUsingConfig = template.getUsingTemplateThemeConfig(); + TemplateTheme templateTheme = template.getTemplateTheme(); + if (templateUsingConfig == this.config && StringUtils.equals(templateTheme.getName(), name)) { + theme4currentTemplateMarkIcon.paintIcon(this, g, getWidth() - 25, 0); + } + } + + if (displayTheme4NewTemplateMarker && StringUtils.equals(config.getThemeName4NewTemplate(), name)) { + theme4NewTemplateMarkIcon.paintIcon(this, g, 0, thumbnailPane.getHeight() - 16); + } + + if (selected || this.hovering) { + g.setColor(HOVERING_BORDER_COLOR); + Rectangle rectangle = new Rectangle(1, 1, this.getWidth() - 2, this.getHeight() - 2); + GraphHelper.draw(g, rectangle, Constants.LINE_MEDIUM); + } + } + + private static class ThumbnailPane extends JPanel { + private static final Image LOADING_IMAGE = Toolkit.getDefaultToolkit().createImage(ThumbnailPane.class.getResource("/com/fr/design/images/mainframe/loading.gif")); + private Image thumbnail = null; + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + Color oldColor = g2d.getColor(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.setColor(oldColor); + + paintCenterImage(g2d, thumbnail != null ? thumbnail : LOADING_IMAGE); + } + + private void paintCenterImage(Graphics2D g2d, Image image) { + if (image == null) { + return; + } + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + int width = getWidth(); + int height = getHeight(); + int imgWidth = image.getWidth(null); + int imgHeight = image.getHeight(null); + + if (width <= 0 || height <= 0 || imgWidth <= 0 || imgHeight <= 0) { + return; + } + + float imgAspect = 1.0F * imgWidth / imgHeight; + + if (1.0F * width / height > 1.0F * imgWidth / imgHeight) { + imgHeight = height; + imgWidth = (int) (1.0F * imgHeight * imgAspect); + } else { + imgWidth = width; + imgHeight = (int) (1.0F * imgWidth / imgAspect); + } + int x = (width - imgWidth) / 2; + int y = (height - imgHeight) / 2; + + g2d.drawImage(image, x, y, imgWidth, imgHeight, null); + } + + public void setThumbnail(Image thumbnail) { + this.thumbnail = thumbnail; + invalidate(); + repaint(); + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeEditorPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeEditorPane.java new file mode 100644 index 0000000000..0b26f6f8e7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeEditorPane.java @@ -0,0 +1,298 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.FineColorFlushUtils; +import com.fr.base.theme.FineColorManager; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.base.theme.settings.ThemedColorScheme; +import com.fr.design.designer.IntervalConstants; +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.ilable.UILabel; +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.theme.edit.CellStyleListEditPane; +import com.fr.design.mainframe.theme.edit.ChartStyleEditPane; +import com.fr.design.mainframe.theme.edit.ui.ColorListPane; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; +import com.fr.design.mainframe.theme.ui.AutoCheckTextField; +import com.fr.design.mainframe.theme.ui.AutoCheckThemeNameTextField; +import com.fr.design.mainframe.theme.ui.BorderUtils; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +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.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class TemplateThemeEditorPane extends JPanel { + public static final int LEFT_TITLE_PANE_HEIGHT = 539; + + public static final int RIGHT_PANE_WIDTH = 362; + public static final int RIGHT_PANE_HEIGHT = LEFT_TITLE_PANE_HEIGHT; + + protected AutoCheckThemeNameTextField nameTextField; + private UILabel nameErrorLabel; + protected ColorListPane colorListPane; + protected CellStyleListEditPane cellStyleSettingPane; + protected ChartStyleEditPane chartStyleSettingPane; + + protected boolean isPopulating = false; + protected UITabbedPane uiTabbedPane; + + private final TemplateThemeConfig config; + + private boolean refreshingThemedColor = false; + private T theme; + + private AttributeChangeListener changeListener; + private AutoCheckTextField.CheckListener themeNameCheckListener; + + public TemplateThemeEditorPane(TemplateThemeConfig config) { + super(); + this.config = config; + theme = config.createNewTheme(); + initializePane(); + } + + private void initializePane() { + setLayout(new BorderLayout(0, 0)); + setPreferredSize(new Dimension(RIGHT_PANE_WIDTH, RIGHT_PANE_HEIGHT)); + JPanel nameEditPane = createNameEditPane(); + add(nameEditPane, BorderLayout.NORTH); + + JPanel settingPane = new JPanel(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); + settingPane.add(createColorSchemeEditPane(), BorderLayout.NORTH); + settingPane.add(createCustomEditorsPane(), BorderLayout.CENTER); + + add(settingPane, BorderLayout.CENTER); + } + + private JPanel createNameEditPane() { + nameErrorLabel = LabelUtils.createLabel(StringUtils.EMPTY, Color.RED); + nameErrorLabel.setVisible(false); + + nameTextField = new AutoCheckThemeNameTextField<>(); + nameTextField.setThemeConfig(config); + nameTextField.setEditable(false); + nameTextField.setEnabled(false); + nameTextField.setPreferredSize(new Dimension(165, 20)); + nameTextField.setNameCheckListener(new AutoCheckTextField.CheckListener() { + @Override + public void onChecked(String error, boolean valid) { + nameErrorLabel.setVisible(StringUtils.isNotEmpty(error)); + nameErrorLabel.setText(error); + + themeNameCheckListener.onChecked(error, valid); + } + }); + + double p = TableLayout.PREFERRED; + + JPanel container = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ + new Component[] { LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Name")), nameTextField }, + new Component[] { null, nameErrorLabel }, + }, new double[] { 20, 20}, new double[] { p, 165}, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_W0); + + container.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + return container; + } + + private JPanel createColorSchemeEditPane() { + colorListPane = new ColorListPane(); + + double p = TableLayout.PREFERRED; + double[] rowSize = new double[]{p, p, p}; + double[] columnSize = {p, p}; + + JPanel colorListContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + colorListContainerPane.add(colorListPane, BorderLayout.WEST); + + UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Tip"), new Color(153, 153, 153)); + + JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ + {LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Label")), colorListContainerPane}, + {null, tipLabel}, + }, + rowSize, columnSize, 18, 7); + content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + JPanel borderContainer = new JPanel(new BorderLayout()); + borderContainer.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Title"))); + borderContainer.add(content); + + JPanel container = new JPanel(new BorderLayout()); + container.add(borderContainer, BorderLayout.CENTER); + + colorListPane.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (refreshingThemedColor) { + return; + } + List colors = colorListPane.update(); + refreshingThemedColor = true; + onColorSchemeChanged(colors); + refreshingThemedColor = false; + + fireAttributeChange(); + } + }); + + return container; + } + private void onColorSchemeChanged(List colors) { + FineColorManager.FineColorReplaceByColorScheme replaceByColorScheme = new FineColorManager.FineColorReplaceByColorScheme(colors); + T theme = updateBean(); + FineColorFlushUtils.replaceCacheObject(theme, replaceByColorScheme); + FineColorManager.traverse(theme, replaceByColorScheme); + populateBean4CustomEditors(theme); + this.repaint(); + } + + protected JPanel createCustomEditorsPane() { + JPanel container = new JPanel(new BorderLayout()); + container.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Custom_Settings_Title"))); + + uiTabbedPane = new UITabbedPane(); + uiTabbedPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 1)); + container.add(uiTabbedPane, BorderLayout.CENTER); + + return container; + } + + public void addCustomEditorPane(String title, final Component component) { + AbstractAttrNoScrollPane settingPane = new NoBorderAbstractAttrNoScrollPane() { + @Override + protected JPanel createContentPane() { + JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + contentPane.add(component, BorderLayout.CENTER); + return contentPane; + } + }; + settingPane.addAttributeChangeListener(new AttributeChangeListener() { + @Override + public void attributeChange() { + fireAttributeChange(); + } + }); + uiTabbedPane.addTab(title, settingPane); + } + protected JPanel createCellStyleSettingPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + cellStyleSettingPane = new CellStyleListEditPane(); + cellStyleSettingPane.registerAttrChangeListener(new AttributeChangeListener() { + @Override + public void attributeChange() { + fireAttributeChange(); + } + }); + container.add(cellStyleSettingPane); + return container; + } + protected JPanel createChartStyleSettingPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + chartStyleSettingPane = new ChartStyleEditPane(); + container.add(chartStyleSettingPane); + return container; + } + + public void populateBean(T theme) { + this.theme = theme; + isPopulating = true; + + String name = theme.getName(); + setThemeNameEditable(StringUtils.isEmpty(name)); + + nameTextField.setText(name); + + colorListPane.populate(theme.getColorScheme().getColors()); + + populateBean4CustomEditors(theme); + isPopulating = false; + } + + protected void populateBean4CustomEditors(T theme) { + cellStyleSettingPane.populateBean(theme.getCellStyleList()); + chartStyleSettingPane.populateBean(theme.getChartStyle()); + } + + public T updateBean() { + if (theme == null) { + theme = config.createNewTheme(); + } + + theme.setName(this.nameTextField.getText()); + + ThemedColorScheme colorScheme = theme.getColorScheme(); + colorScheme.setColors(this.colorListPane.update()); + theme.setColorScheme(colorScheme); + + updateBean4CustomEditors(theme); + + return theme; + } + + protected void updateBean4CustomEditors(T theme) { + ThemedCellStyleList cellStyleConfig = this.cellStyleSettingPane.updateBean(); + theme.setCellStyleList(cellStyleConfig); + + theme.setChartStyle(this.chartStyleSettingPane.updateBean()); + } + + public void setThemeNameEditable(boolean editable) { + nameTextField.setEditable(editable); + nameTextField.setEnabled(editable); + } + + public boolean checkNameValid() { + return nameTextField.checkValid(); + } + + public String getThemeName() { + return nameTextField.getText(); + } + + public List getCurrentColorScheme() { + return colorListPane.update(); + } + + private void fireAttributeChange() { + if (!isPopulating && !refreshingThemedColor && changeListener != null) { + changeListener.attributeChange(); + } + } + + public void addAttributeChangeListener(AttributeChangeListener changeListener) { + this.changeListener = changeListener; + } + public void addThemeNameCheckListener(AutoCheckTextField.CheckListener checkListener) { + this.themeNameCheckListener = checkListener; + } + + private static abstract class NoBorderAbstractAttrNoScrollPane extends AbstractAttrNoScrollPane { + @Override + protected void initContentPane() { + super.initContentPane(); + if (leftContentPane != null) { + // 修正 AbstractAttrNoScrollPane 的默认行为 + leftContentPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + } + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridControlPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridControlPane.java new file mode 100644 index 0000000000..cdbd6d10f2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridControlPane.java @@ -0,0 +1,329 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.ReportThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.gui.ibutton.UIButton; +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.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.ToolBarDef; +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.third.javax.annotation.Nullable; +import com.fr.transaction.CallBackAdaptor; + +import javax.swing.BorderFactory; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.SwingUtilities; +import javax.swing.border.LineBorder; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeGridControlPane extends BasicPane { + public static final int CONTENT_WIDTH = TemplateThemeGridPane.CONTENT_WIDTH + 20; + public static final int CONTENT_HEIGHT = TemplateThemeGridPane.CONTENT_HEIGHT + 37; + private final RemoveThemeAction removeAction; + private final UIButton setTheme4NewTemplateButton; + + private final TemplateThemeConfig config; + private final TemplateThemeGridPane themeListPane; + private final TemplateThemeProfilePane profilePane; + + private final AsyncThemeFetcher asyncThemeFetcher; + + private final Window window; + + public static TemplateThemeGridControlPane createFormThemesManagerPane(@Nullable Window window) { + FormThemeConfig config = FormThemeConfig.getInstance(); + FormThemeProfilePane editPane = new FormThemeProfilePane(config); + return new TemplateThemeGridControlPane<>(window, config, editPane); + } + + public static TemplateThemeGridControlPane createReportThemesManagerPane(@Nullable Window window) { + ReportThemeConfig config = ReportThemeConfig.getInstance(); + ReportThemeProfilePane editPane = new ReportThemeProfilePane(config); + return new TemplateThemeGridControlPane<>(window, config, editPane); + } + + public TemplateThemeGridControlPane(@Nullable Window window, TemplateThemeConfig config, TemplateThemeProfilePane profilePane) { + this.window = window; + this.config = config; + this.profilePane = profilePane; + this.themeListPane = new TemplateThemeGridPane<>(window, true, config, profilePane); + this.removeAction = new RemoveThemeAction(false); + this.setTheme4NewTemplateButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Default_Setting")); + this.asyncThemeFetcher = new AsyncThemeFetcher<>(1, config); + + initializePane(); + registerWindowListener(); + } + + public TemplateThemeConfig getConfig() { + return config; + } + + private void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 10)); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + + add(createActionsContainer(), BorderLayout.NORTH); + + JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + add(nextContainer, BorderLayout.CENTER); + + nextContainer.add(new JSeparator(), BorderLayout.NORTH); + + themeListPane.setSelectedChangeListener(new ChangeListener() { + @Override + public void fireChanged(ChangeEvent event) { + resetEnableRemoveAction(themeListPane.getSelectedTheme(), removeAction); + resetEnableSetTheme4NewTemplateButton(themeListPane.getSelectedTheme(), setTheme4NewTemplateButton); + } + }); + nextContainer.add(themeListPane, BorderLayout.CENTER); + + resetEnableRemoveAction(themeListPane.getSelectedTheme(), removeAction); + resetEnableSetTheme4NewTemplateButton(themeListPane.getSelectedTheme(), setTheme4NewTemplateButton); + + repaint(); + } + + private void registerWindowListener() { + if (window != null) { + window.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + asyncThemeFetcher.shutdown(); + } + }); + } + } + + private void resetEnableRemoveAction(T selectedTheme, RemoveThemeAction removeAction) { + if (selectedTheme == null) { + removeAction.setEnabled(false); + return; + } + String selectedThemeName = selectedTheme.getName(); + if (StringUtils.isEmpty(selectedThemeName)) { + removeAction.setEnabled(false); + return; + } + + removeAction.setEnabled(selectedTheme.isRemovable()); + } + + private void resetEnableSetTheme4NewTemplateButton(T selectedTheme, UIButton setTheme4NewTemplateButton) { + if (selectedTheme == null) { + setTheme4NewTemplateButton.setEnabled(false); + return; + } + String selectedThemeName = selectedTheme.getName(); + if (StringUtils.isEmpty(selectedThemeName)) { + setTheme4NewTemplateButton.setEnabled(false); + return; + } + + T currentTheme4NewTemplate = config.cachedFetchTheme4NewTemplate(); + if (currentTheme4NewTemplate == null) { + setTheme4NewTemplateButton.setEnabled(true); + return; + } + String currentThemeName4NewTemplate = currentTheme4NewTemplate.getName(); + if (StringUtils.isEmpty(currentThemeName4NewTemplate)) { + setTheme4NewTemplateButton.setEnabled(true); + return; + } + + setTheme4NewTemplateButton.setEnabled(!StringUtils.equals(currentThemeName4NewTemplate, selectedTheme.getName())); + } + + private JPanel createActionsContainer() { + JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + content.setPreferredSize(new Dimension(content.getPreferredSize().width, 20)); + + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolBar.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + content.add(toolBar, BorderLayout.CENTER); + + MenuDef addMenuDef = createAddMenuDef(); + + ToolBarDef toolbarDef = new ToolBarDef(); + toolbarDef.addShortCut(addMenuDef, removeAction); + toolbarDef.updateToolBar(toolBar); + + setTheme4NewTemplateButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + T theme = themeListPane.getSelectedTheme(); + if (theme != null) { + config.setThemeName4NewTemplate(theme.getName(), new CallBackAdaptor() { + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeGridControlPane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + } + }); + content.add(setTheme4NewTemplateButton, BorderLayout.EAST); + + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + container.add(content, BorderLayout.CENTER); + + container.setPreferredSize(new Dimension(container.getPreferredSize().width, 30)); + + return container; + } + + private MenuDef createAddMenuDef() { + MenuDef menuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); + menuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + menuDef.setRePaint(true); + menuDef.addShortCut(new AddThemeAction(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Create_Light_Theme"), config.getDefaultLightThemeName())); + menuDef.addShortCut(new AddThemeAction(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Create_Dark_Theme"), config.getDefaultDarkThemeName())); + + return menuDef; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Title"); + } + + private class RemoveThemeAction extends UpdateAction { + + public RemoveThemeAction(boolean initialEnabled) { + setEnabled(initialEnabled); + setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); + setMnemonic('R'); + setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + T theme = TemplateThemeGridControlPane.this.themeListPane.getSelectedTheme(); + if (theme == null) { + return; + } + int result = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(TemplateThemeGridControlPane.this), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Delete_Tip", theme.getName()), + Toolkit.i18nText("Fine-Design_Basic_Delete"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (result == JOptionPane.YES_OPTION) { + config.removeTheme(theme.getName(), new CallBackAdaptor() { + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeGridControlPane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + } + } + + private class AddThemeAction extends UpdateAction { + private final String prototypeThemeName; + + public AddThemeAction(String name, String prototypeThemeName) { + setName(name); + setMnemonic('R'); + this.prototypeThemeName = prototypeThemeName; + } + + @Override + public void actionPerformed(ActionEvent e) { + asyncThemeFetcher.submit(prototypeThemeName, new AsyncThemeFetcher.AsyncThemeFetchCallbackAdapter() { + @Override + public void afterCachedFetch(T theme) { + super.afterCachedFetch(theme); + createNewTheme(theme); + } + }); + } + + private void createNewTheme(T prototypeTheme) { + Window parent = SwingUtilities.getWindowAncestor(TemplateThemeGridControlPane.this); + TemplateThemeProfileDialog profileDialog = new TemplateThemeProfileDialog<>(parent, profilePane); + try { + T theme = (T) prototypeTheme.clone(); + theme.setName(StringUtils.EMPTY); + theme.setMutable(true); + theme.setRemovable(true); + profilePane.populateBean(theme); + profileDialog.setVisible(true); + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + } + } + + public static class BottomLineBorder extends LineBorder { + + private BottomLineBorder(Color color, int thickness) { + super(color, thickness); + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D)g; + + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setColor(getLineColor()); + g2d.setStroke(new BasicStroke(getThickness() * 2)); + g2d.drawLine(0, height, width, height + getThickness() * 2); + + g2d.setStroke(oldStroke); + g2d.setColor(oldColor); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java new file mode 100644 index 0000000000..36e962c6af --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPagesPane.java @@ -0,0 +1,316 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.ScreenResolution; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.ReportThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.dialog.TemplateThemeDialog; +import com.fr.design.mainframe.theme.provider.ThemeManageActionProvider; +import com.fr.design.mainframe.theme.ui.BreadcrumbBar; +import com.fr.stable.ArrayUtils; +import com.fr.stable.unit.FU; +import com.fr.third.javax.annotation.Nullable; +import com.fr.workspace.WorkContext; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.border.CompoundBorder; +import javax.swing.border.LineBorder; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/10/9 + */ +public class TemplateThemeGridPagesPane extends JPanel { + public static final String COMPLETE_BUTTON = "theme_button_complete"; + private BreadcrumbBar breadcrumbBar; + private JPanel contentPane; + private CardLayout cardLayout; + + private TemplateThemeGridPagePane themeUsingPane; + private TemplateThemeGridPagePane themeManagingPane; + + private PageChangeListener pageChangeListener; + private TemplateThemeGridPagePane currentTemplateThemeGridPagePane; + + public TemplateThemeGridPagesPane() { + initializePane(null); + } + + public TemplateThemeGridPagesPane(@Nullable Window window) { + initializePane(window); + } + + private void initializePane(@Nullable Window window) { + setLayout(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); + + breadcrumbBar = new BreadcrumbBar(); + breadcrumbBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); + add(breadcrumbBar, BorderLayout.NORTH); + + contentPane = new JPanel(); + contentPane.setBorder(new CompoundBorder( + new TopLineBorder(new Color(0xE0E0E1), 1), + BorderFactory.createEmptyBorder(10, 0, 0, 0))); + cardLayout = new CardLayout(); + contentPane.setLayout(cardLayout); + add(contentPane, BorderLayout.CENTER); + + + themeUsingPane = new TemplateThemeUsingPane(window); + contentPane.add(themeUsingPane, themeUsingPane.getTitle()); + themeManagingPane = new TemplateThemeManagingPane(window); + contentPane.add(themeManagingPane, themeManagingPane.getTitle()); + + showThemeUsingPane(); + } + + public void showThemeUsingPane() { + if (currentTemplateThemeGridPagePane != themeUsingPane) { + cardLayout.show(contentPane, themeUsingPane.getTitle()); + currentTemplateThemeGridPagePane = themeUsingPane; + if (pageChangeListener != null) { + pageChangeListener.onPageChangeListener(); + } + breadcrumbBar.clear(); + breadcrumbBar.addCrumb(themeUsingPane.getTitle(), new BreadcrumbBar.BreadcrumbBackListener() { + @Override + public void onBreadcrumbBack(String text) { + cardLayout.show(contentPane, themeUsingPane.getTitle()); + currentTemplateThemeGridPagePane = themeUsingPane; + if (pageChangeListener != null) { + pageChangeListener.onPageChangeListener(); + } + } + }); + } + } + + public void showThemeManagingPane() { + if (currentTemplateThemeGridPagePane != themeManagingPane) { + cardLayout.show(contentPane, themeManagingPane.getTitle()); + currentTemplateThemeGridPagePane = themeManagingPane; + if (pageChangeListener != null) { + pageChangeListener.onPageChangeListener(); + } + breadcrumbBar.addCrumb(themeManagingPane.getTitle(), null); + } + } + + public UIButton[] createLeftButtons() { + UIButton[] buttons = new UIButton[] {}; + if (currentTemplateThemeGridPagePane != themeManagingPane && WorkContext.getCurrent().isRoot()) { + buttons = ArrayUtils.addAll(buttons, createOpenThemeManagerButton()); + } + return buttons; + } + + public UIButton[] createRightButtons() { + UIButton[] buttons = new UIButton[] {}; + buttons = ArrayUtils.addAll(buttons, createExtraButtons()); + buttons = ArrayUtils.addAll(buttons, createCloseButton()); + return buttons; + } + + private UIButton createOpenThemeManagerButton() { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Title")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showThemeManagingPane(); + } + }); + return button; + } + + private UIButton[] createExtraButtons() { + List uiButtonList = new ArrayList<>(); + + Set providers = ExtraDesignClassManager.getInstance().getArray(ThemeManageActionProvider.MARK_STRING); + for (ThemeManageActionProvider provider : providers) { + uiButtonList.add(provider.createButton(new ThemeManageActionProvider.ThemeManageActionContext() { + + @Override + public TemplateThemeDialog getDialog() { + Container container = getRootPane().getParent(); + if (container instanceof TemplateThemeDialog) { + return (TemplateThemeDialog) container; + } + return null; + } + + @Override + public TemplateThemeConfig getConfig() { + return currentTemplateThemeGridPagePane.getConfig(); + } + })); + } + + return uiButtonList.toArray(new UIButton[]{}); + } + + private UIButton createCloseButton() { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Close")); + button.setName(COMPLETE_BUTTON); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Container container = getRootPane().getParent(); + if (container instanceof TemplateThemeDialog) { + ((TemplateThemeDialog) container).exit(); + } + } + }); + return button; + } + + public void setPageChangeListener(PageChangeListener changeListener) { + this.pageChangeListener = changeListener; + } + + public interface PageChangeListener { + void onPageChangeListener(); + } + + public static class TopLineBorder extends LineBorder { + private final FU fu; + + private TopLineBorder(Color color, int thickness) { + super(color, thickness); + fu = FU.getInstance(thickness); + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D)g; + + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setColor(getLineColor()); + int thickness = Math.max(1, fu.toPixI(ScreenResolution.getScreenResolution())); + g2d.setStroke(new BasicStroke(thickness)); + g2d.drawLine(0, 0, width, thickness); + + g2d.setStroke(oldStroke); + g2d.setColor(oldColor); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + } + + public abstract static class TemplateThemeGridPagePane extends BasicPane { + public abstract TemplateThemeConfig getConfig(); + } + + public static class TemplateThemeUsingPane extends TemplateThemeGridPagePane { + private final JTemplate template; + public final TemplateThemeGridPane themeListPane; + + public TemplateThemeUsingPane(@Nullable Window window) { + super(); + setLayout(new BorderLayout()); + setBorder(new CompoundBorder( + BorderFactory.createLineBorder(new Color(0xE0E0E1)), + BorderFactory.createEmptyBorder(0, 10, 0, 10))); + + template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + TemplateThemeConfig config = template.getUsingTemplateThemeConfig(); + themeListPane = new TemplateThemeGridPane<>(window, false, config, null); + + themeListPane.setSelectedChangeListener(new ChangeListener() { + @Override + public void fireChanged(ChangeEvent event) { + TemplateTheme theme = themeListPane.getSelectedTheme(); + if (theme != null) { + template.setTemplateTheme(theme); + themeListPane.repaint(); + } + } + }); + + add(themeListPane, BorderLayout.CENTER); + } + + @Override + public TemplateThemeConfig getConfig() { + return template.getUsingTemplateThemeConfig(); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"); + } + } + + public static class TemplateThemeManagingPane extends TemplateThemeGridPagePane { + private final UITabbedPane tabbedPane; + + public TemplateThemeManagingPane(@Nullable Window window) { + setLayout(FRGUIPaneFactory.createBorderLayout()); + + tabbedPane = new UITabbedPane(); + tabbedPane.setTabBorderColor(new Color(0xE0E0E1)); + add(tabbedPane, BorderLayout.CENTER); + + TemplateThemeGridControlPane formThemesManagerPane = TemplateThemeGridControlPane.createFormThemesManagerPane(window); + TemplateThemeGridControlPane reportThemesManagerPane = TemplateThemeGridControlPane.createReportThemesManagerPane(window); + + tabbedPane.addTab(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Form_Tab"), formThemesManagerPane); + tabbedPane.addTab(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Report_Tab"), reportThemesManagerPane); + + tabbedPane.setSelectedIndex(0); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + TemplateThemeConfig config = template.getUsingTemplateThemeConfig(); + if (config == reportThemesManagerPane.getConfig()) { + tabbedPane.setSelectedIndex(1); + } + } + + @Override + public TemplateThemeConfig getConfig() { + if (tabbedPane.getSelectedIndex() == 0) { + return FormThemeConfig.getInstance(); + } else { + return ReportThemeConfig.getInstance(); + } + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Title"); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPane.java new file mode 100644 index 0000000000..bce8590519 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeGridPane.java @@ -0,0 +1,276 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; +import com.fr.third.javax.annotation.Nullable; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.ScrollPaneConstants; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeGridPane extends BasicPane { + public static final int BLOCK_COUNT_ROW_LINE = 3; + public static final int BLOCK_GAP = IntervalConstants.INTERVAL_L1; + public static final int CONTENT_WIDTH = TemplateThemeBlock.CONTENT_WIDTH * BLOCK_COUNT_ROW_LINE + BLOCK_GAP * (BLOCK_COUNT_ROW_LINE - 1) + 10; + public static final int BLOCK_ROWS_PER_PAGE = 3; + public static final int CONTENT_HEIGHT = Math.min(527, TemplateThemeBlock.CONTENT_HEIGHT * BLOCK_ROWS_PER_PAGE + BLOCK_GAP * (BLOCK_ROWS_PER_PAGE + 1)); + public static final int ASYNC_FETCH_THEME_THREAD_COUNT = 10; + + private final AsyncThemeFetcher asyncThemeFetcher; + + private final boolean displayTheme4NewTemplateMarker; + protected final TemplateThemeConfig config; + private final TemplateThemeProfilePane profilePane; + private final JPanel contentListPane; + + private final Map> blockCache = new HashMap<>(); + + private TemplateThemeBlock selectedBlock; + private TemplateThemeBlock block4newTemplate; + + private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener; + + private ChangeListener changeListener; + + private final Window window; + + public TemplateThemeGridPane(@Nullable Window window, boolean displayTheme4NewTemplateMarker, TemplateThemeConfig config, TemplateThemeProfilePane profilePane) { + this.window = window; + this.displayTheme4NewTemplateMarker = displayTheme4NewTemplateMarker; + this.config = config; + this.profilePane = profilePane; + this.contentListPane = new JPanel(); + this.asyncThemeFetcher = new AsyncThemeFetcher<>(ASYNC_FETCH_THEME_THREAD_COUNT, config); + initializePane(); + registerWindowListener(); + } + + private void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + + contentListPane.setBorder(BorderFactory.createEmptyBorder(BLOCK_GAP, 0, BLOCK_GAP, 10)); + contentListPane.setLayout(new GridLayout(0, BLOCK_COUNT_ROW_LINE, BLOCK_GAP, BLOCK_GAP)); + fillContentListPane(); + + JPanel wrapper1 = FRGUIPaneFactory.createBorderLayout_S_Pane(); + wrapper1.add(contentListPane, BorderLayout.NORTH); + JPanel wrapper2 = FRGUIPaneFactory.createBorderLayout_S_Pane(); + wrapper2.add(wrapper1, BorderLayout.WEST); + + UIScrollPane scrollPane = new UIScrollPane(wrapper2); + scrollPane.setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + add(scrollPane, BorderLayout.CENTER); + + } + + private void registerWindowListener() { + if (window != null) { + window.addWindowListener(new WindowAdapter() { + @Override + public void windowOpened(WindowEvent e) { + super.windowOpened(e); + startListenThemeConfig(); + asyncFetchThemes(); + } + + @Override + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + stopListenThemeConfig(); + asyncThemeFetcher.shutdown(); + } + }); + } + } + + public void fillContentListPane() { + contentListPane.removeAll(); + List names = config.getThemeNames(); + for (String name: names) { + if (config.contains(name)) { + TemplateThemeBlock block = createCachedTemplateThemeBlock(name); + contentListPane.add(block); + if (StringUtils.equals(name, config.getThemeName4NewTemplate())) { + block4newTemplate = block; + } + } + } + } + + private TemplateThemeBlock createCachedTemplateThemeBlock(String name) { + TemplateThemeBlock block = blockCache.get(name); + if (block == null) { + block = createNewTemplateThemeBlock(name); + blockCache.put(name, block); + } + return block; + } + + private TemplateThemeBlock createNewTemplateThemeBlock(String name) { + final TemplateThemeBlock block = new TemplateThemeBlock<>(name, displayTheme4NewTemplateMarker, config, profilePane); + block.addClickListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + setSelectedBlock(block); + } + }); + return block; + } + + public void setSelectedChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + private void setSelectedBlock(TemplateThemeBlock block) { + if (selectedBlock != block) { + if (selectedBlock != null) { + selectedBlock.setSelected(false); + } + selectedBlock = block; + if (selectedBlock != null) { + selectedBlock.setSelected(true); + } + if (changeListener != null) { + changeListener.fireChanged(new ChangeEvent(this)); + } + } + } + + private void asyncFetchTheme(String themeName) { + asyncThemeFetcher.submit(themeName, new AsyncThemeListItemFetchCallback(themeName)); + } + + private void asyncFetchThemes() { + List names = config.getThemeNames(); + for (String name: names) { + if (config.contains(name)) { + asyncThemeFetcher.submit(name, new AsyncThemeListItemFetchCallback(name)); + } + } + } + + @Override + protected String title4PopupWindow() { + return null; + } + + public T getSelectedTheme() { + return selectedBlock != null ? selectedBlock.getTheme() : null; + } + + private void startListenThemeConfig() { + if (themeConfigChangeListener == null) { + themeConfigChangeListener = new TemplateThemeConfig.ThemeConfigChangeListener() { + @Override + public void onThemeConfigChanged(TemplateThemeConfig.ThemeConfigEvent event) { + String themeName = event.themName; + TemplateThemeBlock existingBlock = blockCache.get(event.themName); + switch (event.action) { + case DEFAULT_THEME_4_NEW_TEMPLATE_UPDATE: { + if (block4newTemplate != null) { + block4newTemplate.repaint(); + } + if (existingBlock != null) { + existingBlock.repaint(); + } + block4newTemplate = existingBlock; + break; + } + case UPDATE: { + if (existingBlock != null) { + fillContentListPane(); + asyncFetchTheme(themeName); + validate(); + repaint(); + } + break; + } + case REMOVE: { + if (existingBlock != null) { + contentListPane.remove(existingBlock); + if (existingBlock == selectedBlock) { + setSelectedBlock(null); + } + validate(); + repaint(); + blockCache.remove(event.themName); + } + break; + } + case ADD: { + if (existingBlock == null) { + // TODO 这里是否还能继续优化? + fillContentListPane(); + asyncFetchTheme(themeName); + validate(); + repaint(); + } + break; + } + } + } + }; + config.addThemeConfigChangeListener(themeConfigChangeListener); + } + } + + private void stopListenThemeConfig() { + if (themeConfigChangeListener != null) { + config.removeThemeConfigChangeListener(themeConfigChangeListener); + themeConfigChangeListener = null; + } + } + + private class AsyncThemeListItemFetchCallback extends AsyncThemeFetcher.AsyncThemeFetchCallbackAdapter { + private final String themeName; + public AsyncThemeListItemFetchCallback(String themeName) { + this.themeName = themeName; + } + + @Override + public void beforeCachedFetch() { + super.beforeCachedFetch(); + TemplateThemeBlock block = blockCache.get(themeName); + if (block != null) { + block.setTheme(null); + } + } + + @Override + public void afterCachedFetch(T theme) { + super.afterCachedFetch(theme); + TemplateThemeBlock block = blockCache.get(themeName); + if (block != null) { + block.setTheme(theme); + } + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemePreviewPane.java new file mode 100644 index 0000000000..c302cf1ad8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemePreviewPane.java @@ -0,0 +1,85 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.chart.chartdata.CallbackEvent; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.log.FineLoggerFactory; + +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Transparency; +import java.awt.image.BufferedImage; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class TemplateThemePreviewPane extends JPanel implements CallbackEvent, ThemePreviewed { + private JPanel parent; + public static final int PREVIEW_WIDTH = 627; + public static final int PREVIEW_HEIGHT = 532; + + public void setParent(JPanel parent) { + this.parent = parent; + } + + @Override + public void callback() { + if (parent != null) { + parent.repaint(); + } else { + this.repaint(); + } + } + + protected Image createThumbnailImage() { + BufferedImage image = null; + + int thumbnailWidth = ThemeThumbnail.WIDTH; + int thumbnailHeight = ThemeThumbnail.HEIGHT; + + int width = getWidth(); + int height = getHeight(); + + try { + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = image.createGraphics(); + // 创建一个支持透明背景的buffer image + image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); + g2d.dispose(); + g2d = image.createGraphics(); + + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.clipRect(0, 0, width, height); + + paint(g2d); + + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + if (image != null) { + return image.getScaledInstance(thumbnailWidth, thumbnailHeight, BufferedImage.SCALE_SMOOTH); + } + + return null; + } + + @Override + public void paintComponent(Graphics g) { + g.clearRect(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT); + // 添加个默认白色,否则因为上面的clearRect导致无背景时会出现黑色 + g.setColor(Color.WHITE); + g.fillRect(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT); + paintBackground((Graphics2D) g); + } + + protected abstract void paintBackground(Graphics2D g); +} \ No newline at end of file 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 new file mode 100644 index 0000000000..9e88dfba1a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java @@ -0,0 +1,369 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.frpane.AttributeChangeListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; +import com.fr.design.mainframe.theme.ui.AutoCheckTextField; +import com.fr.design.mainframe.theme.ui.AutoCheckThemeNameTextField; +import com.fr.design.mainframe.theme.ui.BorderUtils; +import com.fr.design.mainframe.toast.DesignerToastMsgUtil; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.transaction.CallBackAdaptor; + +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class TemplateThemeProfilePane extends BasicPane { + public static final int TITLE_BORDER_FONT = 12; + public static final int LEFT_TITLE_PANE_WIDTH = 627; + public static final int LEFT_TITLE_PANE_HEIGHT = 539; + public static final int PREVIEW_PANE_WIDTH = LEFT_TITLE_PANE_WIDTH - 10; + public static final int PREVIEW_PANE_HEIGHT = LEFT_TITLE_PANE_HEIGHT - TITLE_BORDER_FONT - 16; + + protected TemplateThemePreviewPane themePreviewPane; + protected TemplateThemeEditorPane themeEditorPane; + + protected boolean isPopulating = false; + protected boolean isMutable = false; + + protected final TemplateThemeConfig config; + + private UIButton saveButton = new UIButton(); + private UIButton saveAsButton = new UIButton(); + + private TemplateThemeProfileActionListener actionListener = new TemplateThemeProfileActionAdapter(); + + public TemplateThemeProfilePane(TemplateThemeConfig config) { + super(); + this.config = config; + initializePane(); + } + + private void initializePane() { + setLayout(new BorderLayout(5, 0)); + setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 6)); + add(createLeftPane(), BorderLayout.CENTER); + add(createRightPane(), BorderLayout.EAST); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Dialog_Title"); + } + + private JPanel createLeftPane() { + JPanel titleContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + titleContainer.setPreferredSize(new Dimension(LEFT_TITLE_PANE_WIDTH, LEFT_TITLE_PANE_HEIGHT)); + titleContainer.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Preview_Pane_Title"), TITLE_BORDER_FONT)); + + JPanel previewContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + previewContainer.setBorder(BorderFactory.createEmptyBorder(5, 4, 10, 4)); + titleContainer.add(previewContainer, BorderLayout.CENTER); + + themePreviewPane = createThemePreviewPane(); + themePreviewPane.setPreferredSize(new Dimension(PREVIEW_PANE_WIDTH, PREVIEW_PANE_HEIGHT)); + previewContainer.add(themePreviewPane, BorderLayout.CENTER); + + return titleContainer; + } + private JPanel createRightPane() { + themeEditorPane = createThemeEditorPane(); + themeEditorPane.addAttributeChangeListener(new AttributeChangeListener() { + @Override + public void attributeChange() { + if (isPopulating) { + return; + } + themePreviewPane.refresh(updateBean()); + saveButton.setEnabled(themeEditorPane.checkNameValid() && isMutable); + } + }); + themeEditorPane.addThemeNameCheckListener(new AutoCheckTextField.CheckListener() { + @Override + public void onChecked(String error, boolean valid) { + if (isPopulating) { + return; + } + saveButton.setEnabled(valid && isMutable); + actionListener.onThemeNameChecked(themeEditorPane.getThemeName(), valid); + } + }); + + return themeEditorPane; + } + + public abstract TemplateThemePreviewPane createThemePreviewPane(); + public abstract TemplateThemeEditorPane createThemeEditorPane(); + + public void populateBean(T theme) { + isPopulating = true; + + isMutable = theme.isMutable(); + + themeEditorPane.populateBean(theme); + + themePreviewPane.refresh(theme); + + String name = theme.getName(); + + if (saveButton != null) { + saveButton.setEnabled(isMutable); + } + if (saveAsButton != null) { + saveAsButton.setEnabled(StringUtils.isNotEmpty(name)); + } + actionListener.onInitialize(theme); + + isPopulating = false; + } + + public T updateBean() { + T theme = themeEditorPane.updateBean(); + + Image thumbnailImage = themePreviewPane.createThumbnailImage(); + if (thumbnailImage != null) { + ThemeThumbnail thumbnail = new ThemeThumbnail(); + thumbnail.setImage(thumbnailImage); + theme.setThumbnail(thumbnail); + } + + return theme; + } + + public TemplateThemeEditorPane getThemeEditorPane() { + return themeEditorPane; + } + + public void save(CallBackAdaptor callBack) { + T theme; + try { + theme = (T) updateBean().clone(); + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + return; + } + save(theme, callBack); + } + public void save(String name, CallBackAdaptor callBack) { + T theme = null; + try { + theme = (T) updateBean().clone(); + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + return; + } + theme.setName(name); + save(theme, callBack); + } + private void save(T theme, CallBackAdaptor callBack) { + theme.setRemovable(true); + theme.setMutable(true); + config.addTheme(theme, true, new CallBackAdaptor() { + @Override + public void afterCommit() { + super.afterCommit(); + themeEditorPane.setThemeNameEditable(false); + callBack.afterCommit(); + } + + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeProfilePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + + public UIButton createSaveButton() { + saveButton = new UIButton(); + saveButton.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save")); + saveButton.setEnabled(false); + saveButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + save(new CallBackAdaptor() { + @Override + public void afterCommit() { + super.afterCommit(); + saveButton.setEnabled(false); + saveAsButton.setEnabled(true); + actionListener.onSaved(config.cachedFetch(getName())); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + DesignerToastMsgUtil.toastPrompt(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save_Successfully")); + } + }); + } + }); + } + }); + return saveButton; + } + public UIButton createSaveAsButton(final TemplateThemeProfileDialog profileDialog) { + saveAsButton = new UIButton(); + saveAsButton.removeAll(); + saveAsButton.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save_As")); + saveAsButton.setEnabled(false); + saveAsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new SaveAsDialog(profileDialog).setVisible(true); + } + }); + return saveAsButton; + } + private class SaveAsDialog extends JDialog { + private final TemplateThemeProfileDialog parent; + + private AutoCheckThemeNameTextField nameTextField; + private UILabel nameErrorLabel; + private UIButton confirmButton; + + public SaveAsDialog(TemplateThemeProfileDialog dialog) { + super(dialog, ModalityType.APPLICATION_MODAL); + + setTitle(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Save_As_Dialog_Title")); + setResizable(false); + setSize(new Dimension(300, 140)); + GUICoreUtils.centerWindow(this); + + parent = dialog; + + initializeComponents(); + add(createContentPane(), BorderLayout.CENTER); + add(createActionsContainer(), BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + exit(); + } + }); + } + + private void initializeComponents() { + nameTextField = new AutoCheckThemeNameTextField<>(); + nameTextField.setThemeConfig(config); + nameTextField.setPreferredSize(new Dimension(180, 20)); + nameTextField.setNameCheckListener(new AutoCheckTextField.CheckListener() { + @Override + public void onChecked(String error, boolean valid) { + nameErrorLabel.setVisible(StringUtils.isNotEmpty(error)); + nameErrorLabel.setText(error); + confirmButton.setEnabled(valid); + } + }); + + nameErrorLabel = LabelUtils.createLabel(StringUtils.EMPTY, Color.RED); + nameErrorLabel.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 0)); + + confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); + confirmButton.setEnabled(false); + confirmButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + save(nameTextField.getText(), new CallBackAdaptor() { + @Override + public void afterCommit() { + super.afterCommit(); + exit(); + parent.exit(); + } + }); + } + }); + } + + private JPanel createActionsContainer() { + + UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exit(); + } + }); + + JPanel container = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + container.add(confirmButton); + container.add(cancelButton); + + return container; + } + + private JPanel createContentPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + JPanel nameTextPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(20, 5); + nameTextPane.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); + nameTextPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Save_As_Pane_Name_Label"))); + nameTextPane.add(nameTextField); + + container.add(nameTextPane, BorderLayout.CENTER); + container.add(nameErrorLabel, BorderLayout.SOUTH); + + return container; + } + + public void exit() { + this.dispose(); + } + } + + public void addProfileActionListener(TemplateThemeProfileActionListener actionListener) { + if (actionListener != null) { + this.actionListener = actionListener; + } + } + public interface TemplateThemeProfileActionListener { + + void onInitialize(TemplateTheme theme); + + void onThemeNameChecked(String name, boolean valid); + + void onSaved(TemplateTheme theme); + } + public static class TemplateThemeProfileActionAdapter implements TemplateThemeProfileActionListener { + + @Override + public void onInitialize(TemplateTheme theme) {} + + @Override + public void onThemeNameChecked(String name, boolean valid) { } + + @Override + public void onSaved(TemplateTheme theme) {} + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ThemedCellStyleListPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ThemedCellStyleListPane.java new file mode 100644 index 0000000000..b3362e5fb0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ThemedCellStyleListPane.java @@ -0,0 +1,154 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.cell.CellRectangleStylePreviewPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerBean; +import com.fr.design.mainframe.JTemplate; +import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.io.Serializable; +import java.util.List; + +public class ThemedCellStyleListPane extends FurtherBasicBeanPane implements DesignerBean { + + private static final int LEFT_BORDER = 10; + private static final int RIGHT_BORDER = 10; + private final DefaultListModel defaultListModel; + private final JList styleList; + private ChangeListener changeListener; + + public ThemedCellStyleListPane(boolean supportInnerBorder) { + defaultListModel = new DefaultListModel<>(); + styleList = new JList<>(defaultListModel); + styleList.setCellRenderer(new RadioButtonListCellRangeRenderer(supportInnerBorder)); + styleList.setOpaque(false); + styleList.setBackground(null); + styleList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting() && changeListener != null) { + changeListener.stateChanged(new ChangeEvent(styleList)); + } + } + }); + setLayout(FRGUIPaneFactory.createBorderLayout()); + add(styleList, BorderLayout.CENTER); + setBorder(BorderFactory.createEmptyBorder(0 ,LEFT_BORDER, 0, RIGHT_BORDER)); + } + + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + /** + * 重置 + */ + public void reset() { + refreshBeanElement(); + styleList.setSelectedIndex(0); + } + + @Override + public void populateBean(ThemedCellStyle ob) { + refreshBeanElement(); + if (ob == null) { + styleList.setSelectedIndex(0); + return; + } + for (int i = 0; i < defaultListModel.getSize(); i++) { + if (ComparatorUtils.equals(ob.getName(), defaultListModel.get(i).getName())) { + styleList.setSelectedIndex(i); + break; + } + } + } + + @Override + public ThemedCellStyle updateBean() { + return styleList.getSelectedValue(); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Report_Predefined_Style"); + } + + @Override + public boolean accept(Object ob) { + return ob instanceof ThemedCellStyle; + } + + @Override + public void refreshBeanElement() { + defaultListModel.removeAllElements(); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + List styleList = theme.getCellStyleList().getCellStyleList(); + for (ThemedCellStyle themedCellStyle: styleList) { + defaultListModel.addElement(themedCellStyle); + } + } + styleList.setModel(defaultListModel); + } + + private static class RadioButtonListCellRangeRenderer extends JPanel implements ListCellRenderer, Serializable { + + private static final Icon selectedMarkIcon = IOUtils.readIcon("/com/fr/design/form/images/marked.png"); + + private final CellRectangleStylePreviewPane previewArea; + private boolean selected = false; + + public RadioButtonListCellRangeRenderer(boolean supportInnerBorder) { + super(); + setLayout(new BorderLayout(5, 0)); + setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + previewArea = new CellRectangleStylePreviewPane(supportInnerBorder); + add(previewArea, BorderLayout.CENTER); + } + + @Override + public Component getListCellRendererComponent(JList list, ThemedCellStyle value, int index, boolean isSelected, boolean cellHasFocus) { + this.selected = isSelected; + previewArea.setPlainText(value.getName()); + previewArea.setStyle(value.getStyle(), value.getCellBorderStyle()); + + int preferredWidth = list.getWidth() - 15; + preferredWidth = Math.max(0, preferredWidth); + int preferredHeight = 0; + previewArea.setPreferredSize(new Dimension(preferredWidth, preferredHeight)); + + return this; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + if (selected) { + selectedMarkIcon.paintIcon(this, g, getWidth() - selectedMarkIcon.getIconWidth(), 5); + } + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ThemedFeatureController.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ThemedFeatureController.java new file mode 100644 index 0000000000..2e0fc5c387 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ThemedFeatureController.java @@ -0,0 +1,17 @@ +package com.fr.design.mainframe.theme; + +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.theme.SupportThemedCellInnerBorderFeature; +import com.fr.workspace.server.theme.ThemedCellBorderFeature; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/11/26 + */ +public class ThemedFeatureController { + public static boolean isCellStyleSupportInnerBorder() { + ThemedCellBorderFeature controller = WorkContext.getCurrent().get(ThemedCellBorderFeature.class); + return controller instanceof SupportThemedCellInnerBorderFeature; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeDialog.java new file mode 100644 index 0000000000..1864a91b1f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeDialog.java @@ -0,0 +1,127 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/16 + */ +public abstract class TemplateThemeDialog extends JDialog { + public static final int DIALOG_TITLE_HEIGHT = 28; + + public static final int DIALOG_BOTTOM_ACTION_BAR_HEIGHT = 30; + public static final int DIALOG_BOTTOM_ACTION_BUTTON_GAP = 10; + public static final int DIALOG_BOTTOM_ACTION_BUTTON_HEIGHT = 20; + + private final JPanel contentContainer; + private final JPanel actionContainer; + private final int dialogContentHeight; + + public TemplateThemeDialog(Window parent, String title, int contentWidth, int contentHeight) { + super(parent, ModalityType.APPLICATION_MODAL); + setTitle(title); + setResizable(false); + setLayout(FRGUIPaneFactory.createBorderLayout()); + dialogContentHeight = contentHeight + DIALOG_BOTTOM_ACTION_BAR_HEIGHT; + int dialogWindowHeight = dialogContentHeight + DIALOG_TITLE_HEIGHT; + + setSize(new Dimension(contentWidth, dialogWindowHeight)); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + exit(); + } + }); + GUICoreUtils.centerWindow(this); + + contentContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + actionContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + contentContainer.add(actionContainer, BorderLayout.SOUTH); + setContentPane(contentContainer); + } + + @Override + public void doLayout() { + this.setSize(new Dimension(this.getWidth(), dialogContentHeight + this.getInsets().top)); + super.doLayout(); + } + + protected void setupContentPane() { + contentContainer.add(createContentPane(), BorderLayout.CENTER, 0); + } + + protected JPanel createContentPane() { + return new JPanel(); + } + + protected UIButton[] createLeftButtons() { + return new UIButton[]{}; + } + + protected UIButton[] createRightButtons() { + return new UIButton[]{}; + } + + public void setupActionButtons() { + JPanel leftPane = createActionsContainer(FlowLayout.LEFT, createLeftButtons()); + JPanel rightPane = createActionsContainer(FlowLayout.RIGHT, createRightButtons()); + + actionContainer.removeAll(); + actionContainer.add(leftPane, BorderLayout.WEST); + actionContainer.add(rightPane, BorderLayout.EAST); + + actionContainer.invalidate(); + actionContainer.repaint(); + } + + protected final JPanel createDialogContentPane(JPanel contentPane, UIButton[] rightButtons) { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(contentPane, BorderLayout.CENTER); + container.add(createRightActionsContainer(rightButtons), BorderLayout.SOUTH); + return container; + } + + private JPanel createActionsContainer(int align, UIButton... buttons) { + JPanel container = new JPanel(new FlowLayout(align, DIALOG_BOTTOM_ACTION_BUTTON_GAP, 0)); + int paddingVertical = getPaddingVertical(); + container.setBorder(BorderFactory.createEmptyBorder(paddingVertical, 0, paddingVertical, 0)); + + if (buttons == null || buttons.length == 0) { + return container; + } + + for (UIButton button : buttons) { + if (button != null) { + button.setPreferredSize(new Dimension(button.getPreferredSize().width, DIALOG_BOTTOM_ACTION_BUTTON_HEIGHT)); + container.add(button); + } + } + + return container; + } + + private JPanel createRightActionsContainer(UIButton... buttons) { + return createActionsContainer(FlowLayout.RIGHT, buttons); + } + + private int getPaddingVertical() { + return (DIALOG_BOTTOM_ACTION_BAR_HEIGHT - DIALOG_BOTTOM_ACTION_BUTTON_HEIGHT) / 2; + } + + public void exit() { + this.dispose(); + } +} 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 new file mode 100644 index 0000000000..da0649d804 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeGridPagesDialog.java @@ -0,0 +1,50 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.theme.TemplateThemeGridPagesPane; +import com.fr.design.mainframe.theme.TemplateThemeGridPane; + +import javax.swing.JPanel; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeGridPagesDialog extends TemplateThemeDialog implements TemplateThemeGridPagesPane.PageChangeListener { + public static final int CONTENT_WIDTH = TemplateThemeGridPane.CONTENT_WIDTH + 48; + public static final int CONTENT_HEIGHT = TemplateThemeGridPane.CONTENT_HEIGHT + 37; + + protected TemplateThemeGridPagesPane overallPane; + + public TemplateThemeGridPagesDialog() { + super(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"), CONTENT_WIDTH, CONTENT_HEIGHT); + + setupContentPane(); + setupActionButtons(); + } + + @Override + protected JPanel createContentPane() { + overallPane = new TemplateThemeGridPagesPane(this); + overallPane.setPageChangeListener(this); + return overallPane; + } + + @Override + protected UIButton[] createLeftButtons() { + return overallPane.createLeftButtons(); + } + + @Override + protected UIButton[] createRightButtons() { + return overallPane.createRightButtons(); + } + + @Override + public void onPageChangeListener() { + setupActionButtons(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeManageDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeManageDialog.java new file mode 100644 index 0000000000..93e5b09e60 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeManageDialog.java @@ -0,0 +1,42 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.ReportThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.TemplateThemeGridControlPane; +import com.fr.design.mainframe.theme.provider.ThemeManageActionProvider; + +import javax.swing.BorderFactory; +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.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeManageDialog extends TemplateThemeGridPagesDialog { + + public TemplateThemeManageDialog() { + super(); + overallPane.showThemeManagingPane(); + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..a76597f8e8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java @@ -0,0 +1,110 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemeProfilePane; +import com.fr.design.mainframe.theme.provider.ThemeProfileActionProvider; + +import javax.swing.JPanel; +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.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeProfileDialog extends TemplateThemeDialog { + public static TemplateThemeProfilePane currentVisibleProfilePane; + + public static final int CONTENT_WIDTH = 1010; + public static final int CONTENT_HEIGHT = 542; + private final TemplateThemeProfilePane profilePane; + + public TemplateThemeProfileDialog(Window parent, TemplateThemeProfilePane profilePane) { + super(parent, profilePane.getTitle(), CONTENT_WIDTH, CONTENT_HEIGHT); + + this.profilePane = profilePane; + TemplateThemeProfileDialog.currentVisibleProfilePane = profilePane; + + setupContentPane(); + setupActionButtons(); + } + + @Override + protected JPanel createContentPane() { + JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + content.setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + content.add(profilePane, BorderLayout.CENTER); + return content; + } + + @Override + protected UIButton[] createRightButtons() { + return createActionButtons(profilePane); + } + + @Override + public void exit() { + currentVisibleProfilePane = null; + super.exit(); + } + + public static List getEditingColorScheme() { + if (currentVisibleProfilePane != null) { + return currentVisibleProfilePane.getThemeEditorPane().getCurrentColorScheme(); + } + return null; + } + + public static boolean isEditingTheme() { + return currentVisibleProfilePane != null; + } + + + private UIButton[] createActionButtons(final TemplateThemeProfilePane profilePane) { + List uiButtonList = new ArrayList<>(); + + Set providers = ExtraDesignClassManager.getInstance().getArray(ThemeProfileActionProvider.MARK_STRING); + for (ThemeProfileActionProvider provider : providers) { + uiButtonList.add(provider.createButton(new ThemeProfileActionProvider.ThemeProfileActionContext() { + @Override + public TemplateThemeDialog getDialog() { + return TemplateThemeProfileDialog.this; + } + + @Override + public TemplateThemeProfilePane getProfilePane() { + return profilePane; + } + })); + } + + uiButtonList.add(profilePane.createSaveButton()); + uiButtonList.add(profilePane.createSaveAsButton(TemplateThemeProfileDialog.this)); + uiButtonList.add(createCancelButton()); + + return uiButtonList.toArray(new UIButton[]{}); + } + + private UIButton createCancelButton() { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exit(); + } + }); + return button; + } +} 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 new file mode 100644 index 0000000000..420a7ed439 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java @@ -0,0 +1,13 @@ +package com.fr.design.mainframe.theme.dialog; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeUsingDialog extends TemplateThemeGridPagesDialog { + public TemplateThemeUsingDialog() { + super(); + overallPane.showThemeUsingPane(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/CellStyleListEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/CellStyleListEditPane.java new file mode 100644 index 0000000000..3f198f230a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/CellStyleListEditPane.java @@ -0,0 +1,329 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.actions.UpdateAction; +import com.fr.design.beans.BasicBeanPane; +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.DefaultListCellEditor; +import com.fr.design.gui.ilist.JNameEdList; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.design.gui.ilist.ModNameActionListener; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.edit.cell.CellStyleEditPane; +import com.fr.design.mainframe.theme.edit.cell.NoBorderPaneCellStyleEditPane; +import com.fr.design.menu.ShortCut; +import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; +import com.fr.general.NameObject; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.ListModel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * Created by kerry on 2020-09-27 + */ +public class CellStyleListEditPane extends JListControlPane { + private boolean namePermitted = true; + private AttributeChangeListener attributeChangeListener; + + public CellStyleListEditPane() { + super(); + setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); + 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(i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Cell_Style_Empty_Name_Tip"), index); + nameableList.setNameAt(oldName, index); + return; + } + if (isNameRepeated(new List[]{Arrays.asList(allNames)}, newName)) { + showTipDialogAndReset(i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Cell_Style_Duplicated_Name_Tip", newName), index); + nameableList.setNameAt(oldName, index); + return; + } + populateSelectedValue(); + } + }); + } + + public void registerAttrChangeListener(AttributeChangeListener listener){ + this.attributeChangeListener = listener; + } + + + private void showTipDialogAndReset(String content, int index) { + nameableList.stopEditing(); + + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(CellStyleListEditPane.this), + content, + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + setIllegalIndex(index); + namePermitted = false; + } + + @Override + public NameableCreator[] createNameableCreators() { + return new NameableCreator[]{ new DefaultCellStyleNameObjectCreator(), new CellStyleNameObjectCreator() }; + } + + @Override + protected JNameEdList createJNameList() { + JNameEdList nameEdList = new NoIconNamedList(new DefaultListModel()); + nameEdList.setCellEditor(new UnEditableListCellEditor(new UITextField())); + nameEdList.setCellRenderer(new NoIconNameableListCellRenderer()); + return nameEdList; + } + + @Override + public BasicBeanPane createPaneByCreators(NameableCreator creator) { + CellStyleEditPane stylePane = (CellStyleEditPane) 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(); + leftPane.setPreferredSize(new Dimension(90, 0)); + cardPane.setPreferredSize(new Dimension(270, 0)); + JPanel mainSplitPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + mainSplitPane.add(leftPane, BorderLayout.WEST); + mainSplitPane.add(cardPane, BorderLayout.CENTER); + + this.add(mainSplitPane, BorderLayout.CENTER); + this.checkButtonEnabled(); + } + + @Override + protected void initToolBar() { + super.initToolBar(); + UIToolbar toolbar = getToolBar(); + toolbar.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + } + + @Override + protected ShortCut4JControlPane[] createShortcuts() { + return new ShortCut4JControlPane[]{ + createAddItemShortCut4JControlPane(), + new RemoveItemShortCut4JControlPane(new RemoveItemAction()) + }; + } + + private ShortCut4JControlPane createAddItemShortCut4JControlPane (){ + ShortCut shortCut = shortCutFactory.createAddItemUpdateAction(new NameableCreator[]{new CellStyleNameObjectCreator()}); + return new AddItemShortCut4JControlPane(shortCut); + } + + public void populateBean(ThemedCellStyleList ob) { + if (ob == null) { + return; + } + + int oldSelectedIndex = getSelectedIndex(); + + List nameObjectList = new ArrayList<>(); + + List cellStyleList = ob.getCellStyleList(); + for (ThemedCellStyle cellStyle: cellStyleList) { + nameObjectList.add(new NameObject(cellStyle.getName(), cellStyle)); + } + + NameObject[] nameObjectArray = new NameObject[nameObjectList.size()]; + nameObjectList.toArray(nameObjectArray); + + populate(nameObjectArray); + + int newSelectedIndex = oldSelectedIndex; + if (newSelectedIndex >= nameObjectArray.length) { + newSelectedIndex = 0; + } + setSelectedIndex(newSelectedIndex); + } + + public ThemedCellStyleList updateBean() { + nameableList.stopEditing(); + + Nameable[] nameables = this.update(); + ThemedCellStyleList styleConfig = new ThemedCellStyleList(); + for (Nameable nameable : nameables) { + ThemedCellStyle tmpStyle = (ThemedCellStyle) ((NameObject) nameable).getObject(); + tmpStyle.setName(nameable.getName()); + styleConfig.addThemedCellStyle(tmpStyle); + } + return styleConfig; + } + + private static 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 = CellStyleListEditPane.this.getSelectedValue(); + if (selectModel != null) { + NameObject selectNameObject = (NameObject) selectModel.wrapper; + ThemedCellStyle cellStyle = (ThemedCellStyle) (selectNameObject.getObject()); + this.shortCut.setEnabled(cellStyle.isRemovable() && !cellStyle.isUse4Default()); + } else { + this.shortCut.setEnabled(false); + } + + } + } + + private class RemoveItemAction extends UpdateAction { + RemoveItemAction() { + setName(i18nText(("Fine-Design_Basic_Action_Remove"))); + setMnemonic('R'); + setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent evt) { + CellStyleListEditPane.this.onRemoveItem(); + } + } + + private static class CellStyleNameObjectCreator extends NameObjectCreator { + + public CellStyleNameObjectCreator() { + this(CellStyleEditPane.class); + } + + public CellStyleNameObjectCreator(Class> updatePane) { + super(i18nText("Fine-Design_Predefined_Cell_New_Style"), ThemedCellStyle.class, updatePane); + } + + @Override + public Nameable createNameable(UnrepeatedNameHelper helper) { + ThemedCellStyle cellStyle = ThemedCellStyle.createInstanceUsed4New(); + cellStyle.setName(menuName); + + return new NameObject(helper.createUnrepeatedName(this.menuName()), cellStyle); + } + + @Override + public Object acceptObject2Populate(Object ob) { + if (ob instanceof NameObject) { + ob = ((NameObject) ob).getObject(); + } + if (clazzOfObject != null && clazzOfObject.isInstance(ob) && acceptNameObject(ob)) { + doSthChanged4Icon(ob); + return ob; + } + return null; + } + + public boolean acceptNameObject(Object ob) { + return !((ThemedCellStyle) ob).isUse4Default(); + } + } + + private static class DefaultCellStyleNameObjectCreator extends CellStyleNameObjectCreator { + + public DefaultCellStyleNameObjectCreator() { + super(NoBorderPaneCellStyleEditPane.class); + } + + @Override + public boolean acceptNameObject(Object ob) { + return ((ThemedCellStyle) ob).isUse4Default(); + } + } + + private class NoIconNameableListCellRenderer extends NameableListCellRenderer { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (component instanceof NameableListCellRenderer) { + ((NameableListCellRenderer) component).setIcon(null); + ((NameableListCellRenderer) component).setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0)); + } + return component; + } + } + private class NoIconNamedList extends JNameEdList { + + public NoIconNamedList(ListModel dataModel) { + super(dataModel); + } + + @Override + public int getIconWidth() { + return 0; + } + } + private class UnEditableListCellEditor extends DefaultListCellEditor { + + public UnEditableListCellEditor(UITextField textField) { + super(textField); + } + + @Override + public Component getListCellEditorComponent(JList list, Object value, boolean isSelected, int index) { + ListModelElement element = (ListModelElement) getModel().getElementAt(index); + if (element != null) { + NameObject selectNameObject = (NameObject) element.wrapper; + ThemedCellStyle cellStyle = (ThemedCellStyle) (selectNameObject.getObject()); + if (!cellStyle.isRemovable()) { + return null; + } + } + return super.getListCellEditorComponent(list, value, isSelected, index); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleEditPane.java new file mode 100644 index 0000000000..4d75622aed --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleEditPane.java @@ -0,0 +1,99 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.MultiTabPane; +import com.fr.design.mainframe.theme.edit.chart.ChartAxisStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartDataSheetStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartLabelStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartLegendStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartSeriesStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartTitleAndBackgroundStylePane; + +import javax.swing.BorderFactory; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartStyleEditPane extends MultiTabPane { + + private ChartSeriesStylePane chartSeriesStylePane; + private ChartLegendStylePane chartLegendStylePane; + private ChartLabelStylePane chartLabelPane; + private ChartAxisStylePane chartAxisStylePane; + private ChartDataSheetStylePane chartDataSheetStylePane; + private ChartTitleAndBackgroundStylePane chartTitleAndBackgroundStylePane; + + public ChartStyleEditPane() { + } + + @Override + protected void initLayout() { + super.initLayout(); + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + } + + @Override + protected List initPaneList() { + this.chartSeriesStylePane = new ChartSeriesStylePane(); + this.chartLegendStylePane = new ChartLegendStylePane(); + this.chartLabelPane = new ChartLabelStylePane(); + this.chartAxisStylePane = new ChartAxisStylePane(); + this.chartDataSheetStylePane = new ChartDataSheetStylePane(); + this.chartTitleAndBackgroundStylePane = createChartTitleAndBackgroundStylePane(); + paneList = new ArrayList<>(); + paneList.add(this.chartSeriesStylePane); + paneList.add(this.chartLegendStylePane); + paneList.add(this.chartLabelPane); + paneList.add(this.chartAxisStylePane); + paneList.add(this.chartDataSheetStylePane); + paneList.add(this.chartTitleAndBackgroundStylePane); + return paneList; + } + + protected ChartTitleAndBackgroundStylePane createChartTitleAndBackgroundStylePane() { + return new ChartTitleAndBackgroundStylePane(); + } + + @Override + public void populateBean(ThemedChartStyle ob) { + chartSeriesStylePane.populate(ob); + chartLegendStylePane.populate(ob); + chartLabelPane.populate(ob); + chartAxisStylePane.populate(ob); + chartDataSheetStylePane.populate(ob); + chartTitleAndBackgroundStylePane.populate(ob); + } + + @Override + public void updateBean(ThemedChartStyle ob) { + + } + + + @Override + public ThemedChartStyle updateBean() { + ThemedChartStyle chartStyle = new ThemedChartStyle(); + chartSeriesStylePane.update(chartStyle); + chartLegendStylePane.update(chartStyle); + chartLabelPane.update(chartStyle); + chartAxisStylePane.update(chartStyle); + chartDataSheetStylePane.update(chartStyle); + chartTitleAndBackgroundStylePane.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/theme/edit/ChartStyleFormEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleFormEditPane.java new file mode 100644 index 0000000000..f0886804d3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleFormEditPane.java @@ -0,0 +1,16 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.design.mainframe.theme.edit.chart.ChartTitleAndBackgroundStyleFormPane; +import com.fr.design.mainframe.theme.edit.chart.ChartTitleAndBackgroundStylePane; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-30 + */ +public class ChartStyleFormEditPane extends ChartStyleEditPane { + + protected ChartTitleAndBackgroundStylePane createChartTitleAndBackgroundStylePane() { + return new ChartTitleAndBackgroundStyleFormPane(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java new file mode 100644 index 0000000000..de62a195d4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java @@ -0,0 +1,135 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.style.ComponentBodyStylePane; +import com.fr.design.gui.style.ComponentIntegralStylePane; +import com.fr.design.gui.style.ComponentTitleStylePane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.edit.component.ComponentMarginStylePane; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; +import com.fr.design.mainframe.theme.edit.ui.TabbedPane; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.general.act.BorderPacker; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import java.awt.BorderLayout; +import java.awt.Color; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class ComponentStyleEditPane extends JPanel { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ComponentTitleStylePane componentTitleStylePane; + private final ComponentBodyStylePane componentBodyStylePane; + private final ExtendedComponentIntegralStylePane componentIntegralStylePane; + + public ComponentStyleEditPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + componentTitleStylePane = new ThemedComponentTitleStylePane(LABEL_WIDTH, SETTING_WIDTH); + componentBodyStylePane = new ComponentBodyStylePane(LABEL_WIDTH, SETTING_WIDTH); + componentIntegralStylePane = new ExtendedComponentIntegralStylePane(); + + JPanel content = new TabbedPane( + new String[] { + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Title"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Body"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Integral") + }, + new JComponent[] { createTabContainer(componentTitleStylePane), createTabContainer(componentBodyStylePane), createTabContainer(componentIntegralStylePane) } + ); + content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + add(content, BorderLayout.CENTER); + } + + public void populateBean(ThemedComponentStyle style) { + componentTitleStylePane.populateBean(style.getStyle()); + componentBodyStylePane.populateBean(style.getStyle()); + componentIntegralStylePane.populateBean(style); + } + + public ThemedComponentStyle updateBean() { + ThemedComponentStyle style = new ThemedComponentStyle(); + + componentTitleStylePane.updateBean(style.getStyle()); + componentBodyStylePane.updateBean(style.getStyle()); + componentIntegralStylePane.updateBean(style); + return style; + } + + private static class ExtendedComponentIntegralStylePane extends JPanel { + private final ComponentIntegralStylePane integralStylePane; + private final ComponentMarginStylePane marginStylePane; + + public ExtendedComponentIntegralStylePane() { + setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); + integralStylePane = new ComponentIntegralStylePane(LABEL_WIDTH, SETTING_WIDTH); + marginStylePane = new ComponentMarginStylePane(LABEL_WIDTH, SETTING_WIDTH); + + add(integralStylePane, BorderLayout.NORTH); + add(marginStylePane, BorderLayout.CENTER); + } + + public void populateBean(ThemedComponentStyle style) { + integralStylePane.populateBean(style.getStyle()); + marginStylePane.populate(style); + } + + public void updateBean(ThemedComponentStyle style) { + integralStylePane.updateBean(style.getStyle()); + marginStylePane.update(style); + } + } + + private static class ThemedComponentTitleStylePane extends ComponentTitleStylePane { + + public ThemedComponentTitleStylePane(int uiLabelWidth, int uiSettingWidth) { + super(uiLabelWidth, uiSettingWidth); + setSupportTitleVisible(false); + setSupportTitleContent(false); + setSupportOtherSetting(true); + } + + @Override + public void populateBean(BorderPacker style) { + style.setType(LayoutBorderStyle.TITLE); + super.populateBean(style); + } + + @Override + public void updateBean(BorderPacker style) { + super.updateBean(style); + style.setType(LayoutBorderStyle.TITLE); + } + } + + private JComponent createTabContainer(final JPanel component) { + JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + JPanel tipLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + tipLabelPane.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0)); + JTextArea tipLabel = LabelUtils.createAutoWrapLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Style_Tip"), new Color(153, 153, 153)); + tipLabelPane.add(tipLabel); + content.add(tipLabelPane, BorderLayout.NORTH); + content.add(component, BorderLayout.CENTER); + + UIScrollPane scrollPane = new UIScrollPane(content); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(scrollPane, BorderLayout.CENTER); + + return container; + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/FormBodyStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/FormBodyStyleEditPane.java new file mode 100644 index 0000000000..1f2089e69d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/FormBodyStyleEditPane.java @@ -0,0 +1,44 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedFormBodyStyle; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.style.ComponentBodyStylePane; + +import javax.swing.BorderFactory; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class FormBodyStyleEditPane extends JScrollPane { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ComponentBodyStylePane bodyStylePane; + + public FormBodyStyleEditPane() { + bodyStylePane = new ComponentBodyStylePane(LABEL_WIDTH, SETTING_WIDTH); + bodyStylePane.setBorder(BorderFactory.createEmptyBorder( + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1 + )); + setViewportView(bodyStylePane); + setBorder(BorderFactory.createEmptyBorder()); + setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + } + + public void populateBean(ThemedFormBodyStyle style) { + bodyStylePane.populateBean(style.getStyle()); + } + + public ThemedFormBodyStyle updateBean() { + ThemedFormBodyStyle formBodyStyle = new ThemedFormBodyStyle(); + bodyStylePane.updateBean(formBodyStyle.getStyle()); + return formBodyStyle; + } +} 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 new file mode 100644 index 0000000000..ec36c29703 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java @@ -0,0 +1,65 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedReportBodyStyle; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.style.ReportBackgroundSpecialPane; +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; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class ReportBodyStyleEditPane extends JScrollPane { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ReportBackgroundSpecialPane backgroundPane; + + public ReportBodyStyleEditPane() { + backgroundPane = new ReportBackgroundSpecialPane(); + + double p = TableLayout.PREFERRED; + + JPanel uiLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + uiLabelPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Background_Fill")), BorderLayout.NORTH); + uiLabelPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + JPanel backgroundLabeledPane = TableLayoutHelper.createCommonTableLayoutPane( + new Component[][]{ new Component[] { uiLabelPane, backgroundPane } }, + new double[] { p }, new double[] { LABEL_WIDTH, SETTING_WIDTH}, IntervalConstants.INTERVAL_L1 + ); + backgroundLabeledPane.setBorder(BorderFactory.createEmptyBorder( + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1 + )); + + setViewportView(backgroundLabeledPane); + setBorder(BorderFactory.createEmptyBorder()); + setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + } + + public void populateBean(ThemedReportBodyStyle style) { + backgroundPane.populateBean(style.getBackground()); + } + + public ThemedReportBodyStyle updateBean() { + ThemedReportBodyStyle style = new ThemedReportBodyStyle(); + style.setBackground(backgroundPane.update()); + return style; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/AbstractBackgroundDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/AbstractBackgroundDetailPane.java new file mode 100644 index 0000000000..76f948ffdb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/AbstractBackgroundDetailPane.java @@ -0,0 +1,51 @@ +package com.fr.design.mainframe.theme.edit.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/theme/edit/background/BackgroundSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/BackgroundSettingPane.java new file mode 100644 index 0000000000..667c601141 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/BackgroundSettingPane.java @@ -0,0 +1,136 @@ +package com.fr.design.mainframe.theme.edit.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.i18n.Toolkit; +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(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/theme/edit/background/ColorDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ColorDetailPane.java new file mode 100644 index 0000000000..12eea2c520 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ColorDetailPane.java @@ -0,0 +1,105 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.base.background.ColorBackground; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +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.style.color.ColorSelectPane; +import com.fr.general.Background; + +import javax.swing.BorderFactory; +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; + +/** + * Created by kerry on 2020-08-31 + */ +public class ColorDetailPane extends AbstractBackgroundDetailPane { + public static final String SPACE_4 = " "; + 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 Toolkit.i18nText("Fine-Design_Basic_Color"); + } + + @Override + public boolean accept(Background background) { + return background instanceof ColorBackground; + } + + class ColorBackgroundSelectPane extends ColorSelectPane implements UIObserver { + protected UIObserverListener uiObserverListener; + + protected void initialCompents(boolean isSupportTransparent) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder()); + if (isSupportTransparent) { + this.add(createNorthPane(), BorderLayout.NORTH); + } + JPanel centerPane = createCenterPane(); + this.add(centerPane, BorderLayout.CENTER); + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + } + }); + } + + private JPanel createNorthPane() { + UIButton transpanrentBtn = new UIButton(); + transpanrentBtn.setPreferredSize(new Dimension(160, 20)); + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Color")), + transpanrentBtn}}, TableLayoutHelper.FILL_NONE, 33, 5); + jPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); + return jPanel; + } + + protected JPanel createCenterPane() { + JPanel centerPane = new JPanel(); + + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{new UILabel(SPACE_4), centerPane}}, TableLayoutHelper.FILL_NONE, 33, 5); + jPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); + return jPanel; + } + + @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/theme/edit/background/EmptyBackgroundPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/EmptyBackgroundPane.java new file mode 100644 index 0000000000..b7b345c63a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/EmptyBackgroundPane.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.design.i18n.Toolkit; +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 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/theme/edit/background/GradientDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/GradientDetailPane.java new file mode 100644 index 0000000000..042e8d4d32 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/GradientDetailPane.java @@ -0,0 +1,160 @@ +package com.fr.design.mainframe.theme.edit.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.i18n.Toolkit; +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(Toolkit.i18nText("Fine-Design_Basic_Page_Setup_Horizontal")); + jp.add(left2right); + left2right.setSelected(true); + left2right.addActionListener(reviewListener); + + top2bottom = new UIRadioButton(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(Toolkit.i18nText("Fine-Design_Basic_Background_Gradient_Setting")), gradientPanel}, + new Component[]{new UILabel(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 Toolkit.i18nText("Fine-Design_Basic_Gradient_Color"); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ImageDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ImageDetailPane.java new file mode 100644 index 0000000000..208c210450 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ImageDetailPane.java @@ -0,0 +1,216 @@ +package com.fr.design.mainframe.theme.edit.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.i18n.Toolkit; +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( + Toolkit.i18nText("Fine-Design_Basic_Background_Image_Select")); + selectPictureButton.setMnemonic('S'); + selectPictureButton.addActionListener(selectPictureActionListener); + selectPictureButton.setPreferredSize(new Dimension(160, 20)); + //布局 + defaultRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Default")); + tiledRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Titled")); + extendRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Extend")); + adjustRadioButton = new UIRadioButton(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(Toolkit.i18nText("Fine-Design_Basic_Background_Image")), selectPictureButton}, + new Component[]{new UILabel(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 Toolkit.i18nText("Fine-Design_Basic_Background_Image"); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/PatternDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/PatternDetailPane.java new file mode 100644 index 0000000000..7d5ee66a73 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/PatternDetailPane.java @@ -0,0 +1,120 @@ +package com.fr.design.mainframe.theme.edit.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.i18n.Toolkit; +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 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(Toolkit.i18nText("Fine-Design_Basic_Background_Pattern")); + label.setVerticalAlignment(SwingConstants.TOP); + Component[][] components = new Component[][]{ + new Component[]{label, jPanel}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_ForeBackground_Color")), foregroundColorPane}, + new Component[]{new UILabel(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/theme/edit/background/TextureDetailObservePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/TextureDetailObservePane.java new file mode 100644 index 0000000000..a1d0fcb2cd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/TextureDetailObservePane.java @@ -0,0 +1,98 @@ +package com.fr.design.mainframe.theme.edit.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.i18n.Toolkit; +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(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 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/theme/edit/cell/CellStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java new file mode 100644 index 0000000000..d8a4096ceb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java @@ -0,0 +1,204 @@ +package com.fr.design.mainframe.theme.edit.cell; + +import com.fr.base.CellBorderStyle; +import com.fr.base.Style; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.cell.CellRectangleStylePreviewPane; +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.TextFontTippedPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.ThemedFeatureController; +import com.fr.design.mainframe.theme.ui.BorderUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.List; + +import static com.fr.design.i18n.Toolkit.i18nText; + + +/** + * 哎,复杂的原型图导致复杂的画法。非我所愿也 + * + * @author zhou + * @since 2012-5-24上午10:36:10 + */ +public class CellStyleEditPane extends MultiTabPane { + private ThemedCellStyle cellStyle; + private CellRectangleStylePreviewPane previewArea; + private boolean populating; + private AttributeChangeListener attributeChangeListener; + + public CellStyleEditPane() { + 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(); + } + } + + public String title4PopupWindow() { + return i18nText("Fine-Design_Report_Custom_Style"); + } + + public void reset() { + populateBean(null); + } + + @Override + public void populateBean(ThemedCellStyle ob) { + this.populating = true; + this.cellStyle = ob; + + for (BasicPane basicPane : paneList) { + ((AbstractBasicStylePane) basicPane).populateBean(ob.getStyle()); + previewArea.setPlainText(ob.getName()); + previewArea.setStyle(ob.getStyle(), ob.getCellBorderStyle()); + if (ThemedFeatureController.isCellStyleSupportInnerBorder() && basicPane instanceof BorderPane) { + ((BorderPane) basicPane).populateBean(ob.getCellBorderStyle(), true, false); + } + } + this.populating = false; + } + + @Override + public ThemedCellStyle updateBean() { + AbstractBasicStylePane basicStylePane = (AbstractBasicStylePane) paneList.get(tabPane.getSelectedIndex()); + Style style = basicStylePane.update(this.cellStyle.getStyle()); + CellBorderStyle borderStyle = createDefaultBorderStyleFromStyle(style); + + + if (ThemedFeatureController.isCellStyleSupportInnerBorder() && basicStylePane instanceof BorderPane) { + borderStyle = ((BorderPane) basicStylePane).update(); + } + + this.cellStyle.setStyle(style); + this.cellStyle.setCellBorderStyle(borderStyle); + + return this.cellStyle; + } + private CellBorderStyle createDefaultBorderStyleFromStyle(Style style) { + CellBorderStyle cellBorderStyle = new CellBorderStyle(); + cellBorderStyle.setTopStyle(style.getBorderTop()); + cellBorderStyle.setTopColor(style.getBorderTopColor()); + + cellBorderStyle.setBottomStyle(style.getBorderBottom()); + cellBorderStyle.setBottomColor(style.getBorderBottomColor()); + + cellBorderStyle.setLeftStyle(style.getBorderLeft()); + cellBorderStyle.setLeftColor(style.getBorderLeftColor()); + + cellBorderStyle.setRightStyle(style.getBorderRight()); + cellBorderStyle.setRightColor(style.getBorderRightColor()); + + return cellBorderStyle; + } + + @Override + public boolean accept(Object ob) { + return ob instanceof ThemedCellStyle; + } + + @Override + protected List initPaneList() { + paneList = new ArrayList<>(); + paneList.add(new TextFontTippedPane(false)); + paneList.add(new BorderPane()); + paneList.add(new AlignmentPane()); + return paneList; + } + + @Override + protected void initLayout() { + this.setLayout(new BorderLayout(0, 10)); + this.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4)); + + JPanel previewPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + previewArea = new CellRectangleStylePreviewPane(true); + previewArea.setPreferredSize(new Dimension(207, 48)); + previewPane.setBorder(BorderFactory.createCompoundBorder( + BorderUtils.createTitleBorder(i18nText("Fine-Design_Basic_Preview")), + BorderFactory.createEmptyBorder(4, 4, 4, 4))); + previewPane.add(previewArea, BorderLayout.NORTH); + + this.add(previewPane, BorderLayout.NORTH); + + JPanel settingsPane = new JPanel(); + this.add(settingsPane, BorderLayout.CENTER); + + settingsPane.setLayout(new BorderLayout(0, 4)); + + settingsPane.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; + } + ThemedCellStyle cellStyle = updateBean(); + if (cellStyle != null) { + previewArea.setPlainText(cellStyle.getName()); + previewArea.setStyle(cellStyle.getStyle(), cellStyle.getCellBorderStyle()); + } + fireAttrChangeListener(); + } + }); + return new EmptyBorderAttrScrollPane() { + @Override + protected JPanel createContentPane() { + return centerPane; + } + }; + } + }; + settingsPane.add(attrListenerPane, BorderLayout.CENTER); + } + + @Override + public void updateBean(ThemedCellStyle ob) {} + + + private static abstract class EmptyBorderAttrScrollPane extends AttrScrollPane { + + @Override + protected void layoutContentPane() { + super.layoutContentPane(); + leftcontentPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 5, original)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/NoBorderPaneCellStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/NoBorderPaneCellStyleEditPane.java new file mode 100644 index 0000000000..a70a24d8d9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/NoBorderPaneCellStyleEditPane.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.theme.edit.cell; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.style.AlignmentPane; +import com.fr.design.gui.style.TextFontTippedPane; + +import java.util.ArrayList; +import java.util.List; + +public class NoBorderPaneCellStyleEditPane extends CellStyleEditPane { + + @Override + protected List initPaneList() { + paneList = new ArrayList<>(); + paneList.add(new TextFontTippedPane(false)); + paneList.add(new AlignmentPane()); + return paneList; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java new file mode 100644 index 0000000000..e96bcd7bb5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java @@ -0,0 +1,50 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +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 e1 = 75; + double e = 155; + double p = TableLayout.PREFERRED; + double[] columnSize = {e1, 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(ThemedChartStyle chartStyle); + + public abstract void update(ThemedChartStyle chartStyle); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartAxisStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartAxisStylePane.java new file mode 100644 index 0000000000..5a52bb28c4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartAxisStylePane.java @@ -0,0 +1,69 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +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 Toolkit.i18nText("Fine-Design_Chart_Axis"); + } + + public void populate(ThemedChartStyle chartStyle) { + titleFontPane.populate(chartStyle.getAxisTitleFont()); + labelFontPane.populate(chartStyle.getAxisLabelFont()); + axisLineColor.setSelectObject(chartStyle.getAxisLineColor()); + } + + + public void update(ThemedChartStyle 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/theme/edit/chart/ChartDataSheetStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartDataSheetStylePane.java new file mode 100644 index 0000000000..07ec893f7a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartDataSheetStylePane.java @@ -0,0 +1,58 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +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 Toolkit.i18nText("Fine-Design_Chart_Data_Sheet"); + } + + public void populate(ThemedChartStyle chartStyle) { + fontPane.populate(chartStyle.getDataSheetFont()); + borderColor.setSelectObject(chartStyle.getDataSheetBorderColor()); + } + + + public void update(ThemedChartStyle 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/theme/edit/chart/ChartFontPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java new file mode 100644 index 0000000000..2b19b232e3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java @@ -0,0 +1,165 @@ +package com.fr.design.mainframe.theme.edit.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 = getColorButton(); + } + + protected UIColorButton getColorButton() { + return 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 e1 = 75; + double e = 155; + double p = TableLayout.PREFERRED; + double[] rows = {p, p, p}; + double[] columnSize = {e1, 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/theme/edit/chart/ChartLabelStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLabelStylePane.java new file mode 100644 index 0000000000..c94dd6ef22 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLabelStylePane.java @@ -0,0 +1,85 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIColorButtonWithAuto; +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() { + @Override + protected UIColorButton getColorButton() { + return new UIColorButtonWithAuto(); + } + + 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 Toolkit.i18nText("Fine-Design_Chart_Label"); + } + + public void populate(ThemedChartStyle chartStyle) { + autoButton.setSelectedIndex(chartStyle.isAutoLabelFont() ? 0 : 1); + chartFontPane.populate(chartStyle.getLabelFont()); + checkPreButton(); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setAutoLabelFont(autoButton.getSelectedIndex() == 0); + chartStyle.setLabelFont(chartFontPane.update()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLegendStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLegendStylePane.java new file mode 100644 index 0000000000..40f4652a0e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLegendStylePane.java @@ -0,0 +1,49 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +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 Toolkit.i18nText("Fine-Design_Chart_Legend"); + } + + public void populate(ThemedChartStyle chartStyle) { + chartFontPane.populate(chartStyle.getLegendFont()); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setLegendFont(chartFontPane.update()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartSeriesStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartSeriesStylePane.java new file mode 100644 index 0000000000..f9ca4edf32 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartSeriesStylePane.java @@ -0,0 +1,83 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.FineColor; +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.style.background.gradient.FixedGradientBar; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-17 + */ +public class ChartSeriesStylePane extends AbstractChartStylePane { + + private UIButtonGroup colorTypeButton; + private FixedGradientBar gradientBar; + + protected void initComponents() { + colorTypeButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Custom_Color"), + Toolkit.i18nText("Fine-Design_Chart_Legend_Gradual")}); + gradientBar = new FixedGradientBar(4, 130); + initListener(); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{null, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Match_Color_Scheme")), colorTypeButton}, + new Component[]{null, gradientBar} + }; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p}; + } + + private void initListener() { + colorTypeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkTypeButton(); + } + }); + } + + private void checkTypeButton() { + gradientBar.setVisible(colorTypeButton.getSelectedIndex() == 1); + gradientBar.setPreferredSize(colorTypeButton.getSelectedIndex() == 1 ? new Dimension(0, 60) : new Dimension(0, 0)); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Series"); + } + + public void populate(ThemedChartStyle chartStyle) { + if (chartStyle.getThemedChartSeriesColor().isCombineColor()) { + List editingColorScheme = TemplateThemeProfileDialog.getEditingColorScheme(); + colorTypeButton.setSelectedIndex(0); + gradientBar.updateColor(new FineColor(0, 0, editingColorScheme.get(0)), new FineColor(1, 0, editingColorScheme.get(1))); + } else { + colorTypeButton.setSelectedIndex(1); + gradientBar.updateColor(chartStyle.getThemedChartSeriesColor().getBeginColor(), chartStyle.getThemedChartSeriesColor().getEndColor()); + } + checkTypeButton(); + } + + public void update(ThemedChartStyle chartStyle) { + chartStyle.getThemedChartSeriesColor().setCombineColor(colorTypeButton.getSelectedIndex() == 0); + chartStyle.getThemedChartSeriesColor().setBeginColor(gradientBar.getSelectColorPointBtnP1().getColorInner()); + chartStyle.getThemedChartSeriesColor().setEndColor(gradientBar.getSelectColorPointBtnP2().getColorInner()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStyleFormPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStyleFormPane.java new file mode 100644 index 0000000000..204bde0764 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStyleFormPane.java @@ -0,0 +1,36 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; + +import java.awt.Color; +import java.awt.Component; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-30 + */ +public class ChartTitleAndBackgroundStyleFormPane extends ChartTitleAndBackgroundStylePane { + + private UILabel tooltipLabel; + + protected void initComponents() { + super.initComponents(); + tooltipLabel = new UILabel("" + Toolkit.i18nText("Fine-Design_Chart_Title_Background_Tooltip") + ""); + tooltipLabel.setForeground(new Color(153, 153, 153)); + } + + protected Component[][] getComponent() { + Component[][] component = super.getComponent(); + Component[][] newComponent = new Component[component.length + 2][]; + System.arraycopy(component, 0, newComponent, 2, component.length); + newComponent[0] = new Component[]{null, null}; + newComponent[1] = new Component[]{tooltipLabel, null}; + return newComponent; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p, p, p, p, p}; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStylePane.java new file mode 100644 index 0000000000..6bac518763 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStylePane.java @@ -0,0 +1,127 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.background.ImageBackground; +import com.fr.base.theme.settings.ThemedChartStyle; +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-16 + */ +public class ChartTitleAndBackgroundStylePane extends AbstractChartStylePane { + + //字体样式 + private ChartFontPane chartFontPane; + + private UIComboBox typeComboBox; + private List paneList; + private JPanel centerPane; + + //网格线颜色 + private ColorSelectBox mainGridColor; + + protected void initComponents() { + chartFontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Title_Character"); + } + }; + + 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()); + } + }); + } + + private void initList() { + paneList = new ArrayList<>(); + paneList.add(new NullBackgroundQuickPane()); + paneList.add(new ColorBackgroundQuickPane()); + paneList.add(new ImageBackgroundQuickPane(false)); + paneList.add(new VanChartGradientPane()); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{chartFontPane, null}, + 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, p}; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Title_Background"); + } + + public void populate(ThemedChartStyle chartStyle) { + chartFontPane.populate(chartStyle.getTitleFont()); + 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(ThemedChartStyle chartStyle) { + chartStyle.setTitleFont(chartFontPane.update()); + 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/theme/edit/component/ComponentMarginStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/component/ComponentMarginStylePane.java new file mode 100644 index 0000000000..643c1e9601 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/component/ComponentMarginStylePane.java @@ -0,0 +1,101 @@ +package com.fr.design.mainframe.theme.edit.component; + +import com.fr.base.theme.settings.ThemedComponentStyle; +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.Component; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * Created by kerry on 2020-09-01 + */ +public class ComponentMarginStylePane extends JPanel { + private final int uiLabelWidth; + private final int uiSettingWidth; + + protected UISpinner top; + protected UISpinner bottom; + protected UISpinner left; + protected UISpinner right; + + public ComponentMarginStylePane(int uiLabelWidth, int uiSettingWidth) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + 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(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + bottom.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + left.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + right.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + + UILabel uiLabel = new UILabel(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + uiLabel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + uiLabel.setVerticalAlignment(SwingConstants.TOP); + + + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = { p }; + double[] columnSize = { this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f }; + + JPanel panel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{uiLabel, createPaddingPane()}}, + rowSize, columnSize, + IntervalConstants.INTERVAL_L1, 0 + ); + this.add(panel); + } + + + public JPanel createPaddingPane() { + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {f, f}; + + Component[][] paddingPane = new Component[][]{ + new Component[]{top, bottom}, + new Component[]{createLabelByKey("Fine-Design_Report_Top"), createLabelByKey("Fine-Design_Report_Bottom")}, + new Component[]{left, right}, + new Component[]{createLabelByKey("Fine-Design_Report_Left"), createLabelByKey("Fine-Design_Basic_Right")} + }; + + return TableLayoutHelper.createGapTableLayoutPane(paddingPane, rowSize, columnSize, IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L6); + } + + public void populate(ThemedComponentStyle componentStyle) { + this.top.setValue(componentStyle.getPaddingTop()); + this.bottom.setValue(componentStyle.getPaddingBottom()); + this.left.setValue(componentStyle.getPaddingLeft()); + this.right.setValue(componentStyle.getPaddingRight()); + } + + public void update(ThemedComponentStyle componentStyle) { + componentStyle.setPaddingTop((int) this.top.getValue()); + componentStyle.setPaddingBottom((int) this.bottom.getValue()); + componentStyle.setPaddingLeft((int) this.left.getValue()); + componentStyle.setPaddingRight((int) this.right.getValue()); + } + + private UILabel createLabelByKey(String key) { + return new UILabel(i18nText(key), SwingConstants.CENTER); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListExtendedPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListExtendedPane.java new file mode 100644 index 0000000000..9d02180e7d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListExtendedPane.java @@ -0,0 +1,144 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.base.theme.FineColorManager; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/7 + */ +public class ColorListExtendedPane extends JPanel implements MouseListener { + public static final int DEFAULT_COLOR_COUNT = 8; + public static final int DEFAULT_EXTENDED_COUNT = 5; + public static final int DEFAULT_COLOR_SIZE = 16; + public static final int DEFAULT_COLOR_GAP = 3; + + public static final ExtendedColorComputer DEFAULT_EXTENDED_COMPUTER = new ExtendedColorComputer() { + @Override + public Color computeExtendedColor(Color color, int index, int count) { + return FineColorManager.computeExtendedColor(color, index, count); + } + }; + + private final boolean selectable; + private final int colorCount; + private final int extendedCount; + private final int boxSize; + private final int boxGap; + + private final List colorList = new ArrayList<>(); + private ExtendedColorComputer extendedColorComputer = DEFAULT_EXTENDED_COMPUTER; + + private int selectedColorIndex = -1; + private int selectedExtendedIndex = -1; + + public ColorListExtendedPane() { + this(false, DEFAULT_COLOR_COUNT, DEFAULT_EXTENDED_COUNT, DEFAULT_COLOR_SIZE, DEFAULT_COLOR_GAP); + } + + public ColorListExtendedPane(boolean selectable, int colorCount, int extendedCount, int boxSize, int boxGap) { + setLayout(FRGUIPaneFactory.createBorderLayout()); + this.selectable = selectable; + this.colorCount = Math.max(1, colorCount); + this.extendedCount = extendedCount; + this.boxSize = boxSize; + this.boxGap = boxGap; + + for (int i = 0; i < colorCount; i++) { + colorList.add(Color.WHITE); + } + + int width = colorCount * boxSize + (colorCount - 1) * boxGap; + int height = extendedCount * boxSize + (extendedCount - 1) * boxGap; + setPreferredSize(new Dimension(width, height)); + } + + public void populate(List colors) { + if (colors.size() > 0) { + colorList.clear(); + colorList.addAll(colors); + repaint(); + } + } + + public List update() { + return new ArrayList<>(colorList); + } + + public void setExtendedColorComputer(ExtendedColorComputer extendedColorComputer) { + this.extendedColorComputer = extendedColorComputer; + } + + @Override + public void mouseClicked(MouseEvent e) { + int x = e.getX(); + int y = e.getY(); + + int colorIndex = x / (boxSize + boxGap); + int colorX = colorIndex * (boxSize + boxGap); + + int extendedIndex = y / boxSize; + int extendedY = extendedIndex * boxSize; + + if (colorX <= x && x <= colorX + boxSize && extendedY <= y && y <= extendedY + boxSize) { + selectedColorIndex = colorIndex; + selectedExtendedIndex = extendedIndex; + } else { + selectedColorIndex = -1; + selectedExtendedIndex = -1; + } + repaint(); + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + + public interface ExtendedColorComputer { + Color computeExtendedColor(Color color, int index, int count); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Color oldColor = g.getColor(); + + for (int i = 0; i < colorCount; i++) { + int x = i * (boxSize + boxGap); + for (int j = 0; j < extendedCount; j++) { + Color color = extendedColorComputer.computeExtendedColor(colorList.get(i), j, extendedCount); + g.setColor(color); + int y = j * (boxSize + boxGap); + g.fillRect(x, y, boxSize, boxSize); + } + } + + g.setColor(oldColor); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListPane.java new file mode 100644 index 0000000000..ab5d8a4ecf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListPane.java @@ -0,0 +1,213 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.base.FineColor; +import com.fr.base.background.ColorBackground; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.style.AbstractSelectBox; +import com.fr.design.style.color.NewColorSelectPane; + +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/7 + */ +public class ColorListPane extends JPanel implements UIObserver { + public static final int DEFAULT_COLOR_COUNT = 8; + public static final int DEFAULT_COLOR_SIZE = 16; + public static final int DEFAULT_COLOR_GAP = 3; + + private final int colorCount; + + private final List colorList = new ArrayList<>(); + private final List colorButtons = new ArrayList<>(); + + private final EventListenerList colorChangeListenerList = new EventListenerList(); + private UIObserverListener uiObserverListener; + + private boolean isPopulating = false; + + public ColorListPane() { + this(DEFAULT_COLOR_COUNT, DEFAULT_COLOR_SIZE, DEFAULT_COLOR_GAP); + } + + public ColorListPane(int colorCount, int boxSize, int boxGap) { + this.colorCount = Math.max(1, colorCount); + + for (int i = 0; i < colorCount; i++) { + colorList.add(Color.WHITE); + } + + setLayout(new GridLayout(1, 8, boxGap, 0)); + + for (int i = 0; i < colorCount; i++) { + ColorButton colorButton = new ColorButton(null); + colorButton.setPreferredSize(new Dimension(boxSize, boxSize)); + add(colorButton); + int index = i; + colorButton.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (isPopulating) { + return; + } + colorList.set(index, colorButton.getSelectObject()); + fireColorStateChanged(); + } + }); + + colorButtons.add(colorButton); + } + + setPreferredSize(new Dimension(colorCount * boxSize + (colorCount - 1) * boxGap, boxSize)); + iniListener(); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + public void populate(List colors) { + isPopulating = true; + colorList.clear(); + for (int i = 0; i < colors.size(); i++) { + Color color = colors.get(i); + colorList.add(color); + if (i < colorCount) { + colorButtons.get(i).setSelectObject(color); + } + } + isPopulating = false; + } + + public List update() { + return new ArrayList<>(colorList); + } + + public void addColorChangeListener(ChangeListener changeListener) { + colorChangeListenerList.add(ChangeListener.class, changeListener); + } + + public void removeColorChangeListener(ChangeListener changeListener) { + colorChangeListenerList.remove(ChangeListener.class, changeListener); + } + + public void fireColorStateChanged() { + Object[] listeners = colorChangeListenerList.getListenerList(); + ChangeEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + if (e == null) { + e = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } + + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + public boolean shouldResponseChangeListener() { + return true; + } + + public static class ColorButton extends AbstractSelectBox { + private Color color; + private NewColorSelectPane colorPane; + private ChangeListener changeListener; + + public ColorButton(Color color) { + this.color = color; + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + showPopupMenu(); + } + }); + } + + @Override + public JPanel initWindowPane(double preferredWidth) { + colorPane = new NewColorSelectPane(false) { + @Override + public void setVisible(boolean b) { + super.setVisible(b); + } + + @Override + protected boolean selectRealTime() { + return false; + } + }; + colorPane.setColor(this.getSelectObject()); + colorPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + hidePopupMenu(); + FineColor fineColor = ((NewColorSelectPane) e.getSource()).getColor(); + // 不要直接使用原始的FineColor对象,它的值会变化,这里实际需要的内部的真实颜色 + color = fineColor.getColor(); + fireDisplayComponent(ColorBackground.getInstance(color)); + ColorListPane.ColorButton.this.fireStateChanged(); + } + }); + return colorPane; + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setPaint(color); + g2d.fill(new Rectangle2D.Double(0, 0, getWidth(), getHeight())); + } + + public void fireStateChanged() { + if (changeListener != null) { + changeListener.stateChanged(null); + } + } + + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + public Color getSelectObject() { + return this.color; + } + + public void setSelectObject(Color color) { + this.color = color; + if (this.colorPane != null) { + this.colorPane.setColor(color); + } + fireDisplayComponent(ColorBackground.getInstance(color)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java new file mode 100644 index 0000000000..53de406afe --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java @@ -0,0 +1,48 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.general.FRFont; + +import javax.swing.BorderFactory; +import javax.swing.JTextArea; +import javax.swing.plaf.basic.BasicTextAreaUI; +import java.awt.Color; +import java.awt.Font; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/15 + */ +public class LabelUtils { + public static UILabel createLabel(String title) { + return createLabel(title, new Color(51, 51, 52)); + } + + public static UILabel createLabel(String title, Color color) { + return createLabel(title, color, 12); + } + public static UILabel createLabel(String title, Color color, int size) { + UILabel uiLabel = new UILabel(title); + uiLabel.setForeground(color); + Font newFont = FRFont.getInstance(uiLabel.getFont().getFontName(), Font.PLAIN, size); + uiLabel.setFont(newFont); + return uiLabel; + } + + public static JTextArea createAutoWrapLabel(String title, Color color) { + JTextArea tipLabel = new JTextArea(); + tipLabel.setUI(new BasicTextAreaUI()); + tipLabel.setForeground(color); + Font newFont = FRFont.getInstance(tipLabel.getFont().getFontName(), Font.PLAIN, 12); + tipLabel.setFont(newFont); + tipLabel.setBorder(BorderFactory.createEmptyBorder()); + tipLabel.setEditable(false); + tipLabel.setText(title); + tipLabel.setLineWrap(true); + tipLabel.setWrapStyleWord(true); + tipLabel.setOpaque(false); + tipLabel.setBackground(null); + return tipLabel; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/TabbedPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/TabbedPane.java new file mode 100644 index 0000000000..c1c8371674 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/TabbedPane.java @@ -0,0 +1,72 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.design.gui.ibutton.UITabGroup; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dimension; +import java.util.Arrays; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class TabbedPane extends JPanel { + protected UITabGroup buttonGroup; + public JPanel tabContentPane; + public CardLayout cardLayout; + private String[] names = new String[]{}; + private JComponent[] panes = new JComponent[]{}; + + public TabbedPane(String[] names, JComponent[] panes) { + setLayout(FRGUIPaneFactory.createBorderLayout()); + + for (JComponent pane :panes) { + pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + } + + int count = Math.min(names.length, panes.length); + if (count > 0) { + this.names = names.length > count ? Arrays.copyOf(names, count) : names; + this.panes = panes.length > count ? Arrays.copyOf(panes, count) : panes; + initializeTabPane(); + } + } + + private void initializeTabPane() { + buttonGroup = new UITabGroup(this.names) { + @Override + public void tabChanged(int index) { + super.tabChanged(index); + cardLayout.show(tabContentPane, names[buttonGroup.getSelectedIndex()]); + } + }; + buttonGroup.setDrawLine(true); + + cardLayout = new CardLayout(); + tabContentPane = new JPanel(cardLayout) { + @Override + public Dimension getPreferredSize() { + int selectedIndex = buttonGroup.getSelectedIndex(); + if (selectedIndex < 0) { + return super.getPreferredSize(); + } else { + return panes[selectedIndex].getPreferredSize(); + } + } + }; + for (int i = 0; i < this.names.length; i++) { + tabContentPane.add(panes[i], names[i]); + } + buttonGroup.setSelectedIndex(0); + cardLayout.show(tabContentPane, names[0]); + + add(buttonGroup, BorderLayout.NORTH); + add(tabContentPane, BorderLayout.CENTER); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartComponentPreviewPane.java new file mode 100644 index 0000000000..5c000749f8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartComponentPreviewPane.java @@ -0,0 +1,34 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.theme.FormTheme; + +import java.awt.Component; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ChartComponentPreviewPane extends ComponentPreviewPane implements ThemePreviewed { + private ChartPreviewPane contentPane; + + public ChartComponentPreviewPane(String title) { + super(title); + } + + @Override + protected Component createContentPane() { + contentPane = new ChartPreviewPane(); + return contentPane; + } + + @Override + public void refresh(FormTheme theme) { + super.refresh(theme); + contentPane.refresh(theme); + } + + public ChartPreviewPane getContentPane() { + return contentPane; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartPreviewPane.java new file mode 100644 index 0000000000..2029539aa8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartPreviewPane.java @@ -0,0 +1,80 @@ +package com.fr.design.mainframe.theme.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.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.gui.chart.MiddleChartComponent; +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 Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ChartPreviewPane extends MiddleChartComponent implements ThemePreviewed { + + private ChartCollection chartCollection; + + private CallbackEvent callbackEvent; + + public ChartPreviewPane() { + this.setBorder(BorderFactory.createEmptyBorder(0, 1, 2, 1)); + } + + public void setCallbackEvent(CallbackEvent callbackEvent) { + this.callbackEvent = callbackEvent; + } + + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + super.paintComponent(g); + if (chartCollection != null) { + drawChart(g2d); + } + drawChart(g2d); + } + + private void drawChart(Graphics2D g2d) { + Dimension d = getBounds().getSize(); + int chartWidth = d.width; + int chartHeight = d.height; + BaseChartPainter painter = chartCollection.createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), + WebChartIDInfo.createEmptyDesignerInfo(), chartWidth, chartHeight); + painter.paint(g2d, chartWidth, chartHeight, 0, null, callbackEvent); + } + + @Override + public void populate(BaseChartCollection cc) { + this.chartCollection = (ChartCollection) cc; + } + + @Override + public BaseChartCollection update() { + return this.chartCollection; + } + + @Override + public void reset() { + + } + + @Override + public void addStopEditingListener(PropertyChangeListener list) { + + } + + @Override + public void refresh(TemplateTheme style) { + chartCollection.onTemplateUsingThemeChange(style, TemplateThemeCompatible.NONE); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ComponentPreviewPane.java new file mode 100644 index 0000000000..cfd2781aa8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ComponentPreviewPane.java @@ -0,0 +1,221 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.BaseUtils; +import com.fr.base.Style; +import com.fr.base.background.ImageBackground; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.Label; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.WidgetValue; +import com.fr.general.Background; +import com.fr.general.act.BorderPacker; +import com.fr.general.act.TitlePacker; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.LineBorder; +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class ComponentPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + public static final int TITLE_HEIGHT = 46; + + private final JPanel container; + private TitleDemoPane titlePane; + private BorderPacker style = new LayoutBorderStyle(); + + public ComponentPreviewPane(){ + this(StringUtils.EMPTY); + } + + public ComponentPreviewPane(String title) { + container = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + setLayout(new BorderLayout()); + if (StringUtils.isNotEmpty(title)) { + titlePane = new TitleDemoPane(title); + titlePane.setPreferredSize(new Dimension(517, TITLE_HEIGHT)); + container.add(titlePane, BorderLayout.NORTH); + } + container.add(createContentPane(), BorderLayout.CENTER); + add(container, BorderLayout.CENTER); + } + + protected abstract Component createContentPane(); + + @Override + public void refresh(FormTheme theme) { + ThemedComponentStyle componentStyle = theme.getComponentStyle(); + + style = componentStyle.getStyle(); + if (style.getBorder() == 0) { + setBorder(null); + } else { + setBorder(new UIRoundedBorder(style.getBorder(), style.getColor(), style.getBorderRadius())); + } + + int paddingTop = componentStyle.getPaddingTop(); + int paddingBottom = componentStyle.getPaddingBottom(); + int paddingLeft = componentStyle.getPaddingLeft(); + int paddingRight = componentStyle.getPaddingRight(); + container.setBorder(BorderFactory.createEmptyBorder(paddingTop, paddingLeft, paddingBottom, paddingRight)); + if (titlePane != null) { + titlePane.refresh(componentStyle); + } + + } + + @Override + protected void paintBorder(Graphics g) { + super.paintBorder(g); + + paintSeparator((Graphics2D) g); + } + + private void paintSeparator(Graphics2D g2d) { + Border border = getBorder(); + if (border instanceof LineBorder && titlePane != null) { + Border containerBorder = container.getBorder(); + Insets insets = containerBorder.getBorderInsets(container); + int y = titlePane.getHeight() + insets.top; + + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Color lineColor = ((LineBorder) border).getLineColor(); + int thickness = ((LineBorder) border).getThickness(); + g2d.setColor(lineColor); + g2d.setStroke(new BasicStroke(thickness * 2)); + g2d.drawLine(0, y, getWidth(), y); + + g2d.setStroke(oldStroke); + g2d.setColor(oldColor); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + + Border border = getBorder(); + if (border instanceof UIRoundedBorder) { + UIRoundedBorder roundedBorder = (UIRoundedBorder) border; + Utils.clipByRoundBorder(g2d, getWidth(), getHeight(), roundedBorder.getRoundedCorner(), roundedBorder.getThickness()); + } + + Border containerBorder = container.getBorder(); + Insets insets = containerBorder.getBorderInsets(container); + int titleHeight = titlePane == null ? 0 : titlePane.getHeight() + insets.top; + //绘制标题背景 + if (titlePane != null) { + Label data = titlePane.getData(); + float opacity = data.getBackgroundOpacity(); + Background background = data.getBackground(); + if (background != null) { + Utils.paintBackground((Graphics2D) g, background, new Rectangle2D.Double(0, 0, getWidth(), titleHeight), opacity); + } + } + + //绘制主体背景 + Utils.paintBackground(g2d, style.getBackground(), new Rectangle2D.Double(0, titleHeight, getWidth(), getHeight() - titleHeight), style.getAlpha()); + + Utils.paintBackground(g2d, style.getBorderImage(), new Rectangle2D.Double(0, 0, getWidth(), getHeight()), style.getBorderImageOpacity()); + + super.paint(g); + } + + private static class TitleDemoPane extends UINoOpaquePanel { + private final Label data = new Label(); + private String title = StringUtils.EMPTY; + + public TitleDemoPane(String title){ + this.title = title; + } + + public void refresh(ThemedComponentStyle componentStyle) { + BorderPacker borderPacker = componentStyle.getStyle(); + TitlePacker titlePacker = componentStyle.getStyle().getTitle(); + + data.setColor(borderPacker.getColor()); + data.setWidgetValue(new WidgetValue(String.valueOf(titlePacker.getTextObject()))); + data.setFont(titlePacker.getFrFont()); + data.setTextalign(titlePacker.getPosition()); + data.setBackground(titlePacker.getBackground()); + data.setBackgroundOpacity(titlePacker.getBackgroundOpacity()); + + data.setInsetImage(titlePacker.getInsetImage()); + data.setInsetImagePadding(titlePacker.getInsetImagePadding()); + data.setInsetRelativeTextLeft(titlePacker.isInsetRelativeTextLeft()); + data.setInsetRelativeTextRight(titlePacker.isInsetRelativeTextRight()); + } + + public Label getData(){ + return data; + } + + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g.create(); + Background inset = data.getInsetImage(); + Image insetImage = inset instanceof ImageBackground ? ((ImageBackground) inset).getImage() : null; + + BaseUtils.drawStringStyleInRotation(g2d, + getWidth(), getHeight(), + title, + Style.getInstance(data.getFont()) + .deriveHorizontalAlignment(data.getTextalign()) + .deriveVerticalAlignment(data.isVerticalCenter() ? SwingConstants.CENTER : SwingConstants.TOP) + .deriveTextStyle(data.isWrap() ? Style.TEXTSTYLE_WRAPTEXT : Style.TEXTSTYLE_SINGLELINE), + insetImage, data.getInsetImagePadding(), data.isInsetRelativeTextLeft(), data.isInsetRelativeTextRight(), + Constants.FR_PAINT_RESOLUTION); + } + + } + + + private static class Utils { + private static void paintBackground(Graphics2D g2d, Background background, Shape shape, float opacity) { + if (background != null) { + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, opacity)); + background.paint(g2d, shape); + g2d.setComposite(oldComposite); + } + } + + private static void clipByRoundBorder(Graphics2D g2d, int width, int height, int radius, int borderThickness) { + int currentClipRadius = Math.max(radius - borderThickness, 0); + g2d.clip(new RoundRectangle2D.Double(0, 0, width, height, currentClipRadius, currentClipRadius)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java new file mode 100644 index 0000000000..25a1daee92 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java @@ -0,0 +1,204 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.BaseFormula; +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.FormTheme; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartattr.Title; +import com.fr.chart.chartdata.NormalChartData; +import com.fr.chart.charttypes.ChartTypeManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ecpreview.ECComponentPreviewPane; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.PiePlot4VanChart; +import com.fr.plugin.chart.attr.VanChartLegend; +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.type.GradientType; +import com.fr.plugin.chart.type.RadiusType; +import com.fr.plugin.chart.vanchart.VanChart; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.JPanel; +import java.awt.AlphaComposite; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import static com.fr.design.i18n.Toolkit.i18nText; +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class FormThemePreviewPane extends TemplateThemePreviewPane { + private ECComponentPreviewPane elementCasePane; + private Background background; + private ChartComponentPreviewPane columnChartPreviewPane; + private ChartComponentPreviewPane pieChartPreviewPane; + private float alpha = 1.0F; + + public FormThemePreviewPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel content = new UINoOpaquePanel(); + content.setLayout(new BorderLayout()); + content.add(createChartContent(), BorderLayout.CENTER); + content.add(elementCasePane = new ECComponentPreviewPane(), BorderLayout.SOUTH); + add(content, BorderLayout.CENTER); + } + + private JPanel createChartContent() { + JPanel chartContent = new UINoOpaquePanel(); + chartContent.setLayout(new BorderLayout()); + JPanel columnChartPanel = new UINoOpaquePanel() { + public Dimension getPreferredSize() { + return new Dimension(379, 314); + } + }; + columnChartPanel.setLayout(new BorderLayout()); + columnChartPreviewPane = createChartPreviewPane(initColumnChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Comp_Title1")); + columnChartPanel.add(columnChartPreviewPane, BorderLayout.CENTER); + + JPanel pieChartPanel = new UINoOpaquePanel() { + public Dimension getPreferredSize() { + return new Dimension(236, 314); + } + }; + pieChartPanel.setLayout(new BorderLayout()); + pieChartPreviewPane = createChartPreviewPane(initPieChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Comp_Title2")); + pieChartPanel.add(pieChartPreviewPane, BorderLayout.CENTER); + chartContent.add(columnChartPanel, BorderLayout.CENTER); + chartContent.add(pieChartPanel, BorderLayout.EAST); + return chartContent; + } + + private ChartComponentPreviewPane createChartPreviewPane(ChartCollection chartCollection, String title) { + ChartComponentPreviewPane chartComponentPreviewPane = new ChartComponentPreviewPane(title); + chartComponentPreviewPane.getContentPane().populate(chartCollection); + chartComponentPreviewPane.getContentPane().setCallbackEvent(this); + return chartComponentPreviewPane; + } + + @Override + public void refresh(FormTheme theme) { + background = theme.getBodyStyle().getStyle().getBackground(); + alpha = theme.getBodyStyle().getStyle().getAlpha(); + elementCasePane.refresh(theme); + columnChartPreviewPane.refresh(theme); + pieChartPreviewPane.refresh(theme); + repaint(); + } + + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + g2d.setComposite(oldComposite); + } + + //柱形图 + private ChartCollection initColumnChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID)[0].clone(); + chart.getTitle().setTitleVisible(false); + 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().setPosition(Constants.TOP); + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setSeriesOverlapPercent(30); + plot.setCategoryIntervalPercent(30); + + VanChartAxis defaultYAxis = plot.getDefaultYAxis(); + Title title = new Title(); + title.setTextObject(Toolkit.i18nText("Fine-Design_Chart_Axis_Title")); + title.getTextAttr().setRotation(-90); + title.getTextAttr().setThemed(true); + defaultYAxis.setTitle(title); + defaultYAxis.setShowAxisTitle(true); + defaultYAxis.setCustomMaxValue(true); + defaultYAxis.setCustomMinValue(true); + defaultYAxis.setCustomMainUnit(true); + defaultYAxis.setMaxValue(BaseFormula.createFormulaBuilder().build("=600")); + defaultYAxis.setMinValue(BaseFormula.createFormulaBuilder().build("=0")); + defaultYAxis.setMainUnit(BaseFormula.createFormulaBuilder().build("=200")); + + Object[] category = { + Toolkit.i18nText("Fine-Design_Chart_Category") + "1", + Toolkit.i18nText("Fine-Design_Chart_Category") + "2", + Toolkit.i18nText("Fine-Design_Chart_Category") + "3", + Toolkit.i18nText("Fine-Design_Chart_Category") + "4" + }; + Object[] series = { + Toolkit.i18nText("Fine-Design_Chart_Series") + "1", + Toolkit.i18nText("Fine-Design_Chart_Series") + "2" + }; + Object[][] value = { + {"250", "540", "300", "410"}, + {"180", "190", "170", "100"}, + }; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } + + //饼图 + private ChartCollection initPieChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(PiePlot4VanChart.VAN_CHART_PIE_PLOT)[0].clone(); + chart.getTitle().setTitleVisible(false); + VanChartTools vanChartTools = chart.getVanChartTools(); + vanChartTools.setSort(false); + vanChartTools.setExport(false); + vanChartTools.setFullScreen(false); + + PiePlot4VanChart plot = chart.getPlot(); + VanChartLegend legend = (VanChartLegend) plot.getLegend(); + legend.setPosition(Constants.BOTTOM); + legend.setCustomSize(true); + legend.setMaxHeight(28); + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setInnerRadiusPercent(75); + plot.getRadius().setRadiusType(RadiusType.FIXED); + plot.getRadius().setRadius(70); + + Object[] category = {StringUtils.EMPTY}; + Object[] series = {"A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"}; + Object[][] value = {{45}, {24}, {12}, {8}, {5}, {3}, {2}, {1},}; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ReportThemePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ReportThemePreviewPane.java new file mode 100644 index 0000000000..103b6ca6e0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ReportThemePreviewPane.java @@ -0,0 +1,129 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.BaseFormula; +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.ReportTheme; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartattr.Title; +import com.fr.chart.chartdata.NormalChartData; +import com.fr.chart.charttypes.ChartTypeManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ecpreview.ECReportPreviewPane; +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.type.GradientType; +import com.fr.plugin.chart.vanchart.VanChart; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ReportThemePreviewPane extends TemplateThemePreviewPane { + private Background background; + + private final ECReportPreviewPane reportPreviewPane; + + private final ChartPreviewPane chartPreviewPane; + + public ReportThemePreviewPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + chartPreviewPane = new ChartPreviewPane(); + chartPreviewPane.setPreferredSize(new Dimension(615, 207)); + chartPreviewPane.populate(initColumnChart()); + chartPreviewPane.setCallbackEvent(this); + reportPreviewPane = new ECReportPreviewPane(); + reportPreviewPane.setPreferredSize(new Dimension(615, 297)); + this.add(reportPreviewPane, BorderLayout.NORTH); + this.add(chartPreviewPane, BorderLayout.CENTER); + } + + @Override + public void refresh(ReportTheme theme) { + background = theme.getBodyStyle().getBackground(); + reportPreviewPane.refresh(theme); + chartPreviewPane.refresh(theme); + repaint(); + } + + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + } + + + //柱形图 + private ChartCollection initColumnChart() { + 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.getGradientStyle().setGradientType(GradientType.NONE); + plot.setSeriesOverlapPercent(30); + plot.setCategoryIntervalPercent(30); + + VanChartAxis defaultYAxis = plot.getDefaultYAxis(); + Title title = new Title(); + title.setTextObject(Toolkit.i18nText("Fine-Design_Chart_Axis_Title")); + title.getTextAttr().setRotation(-90); + title.getTextAttr().setThemed(true); + defaultYAxis.setTitle(title); + defaultYAxis.setShowAxisTitle(true); + defaultYAxis.setCustomMaxValue(true); + defaultYAxis.setCustomMinValue(true); + defaultYAxis.setCustomMainUnit(true); + defaultYAxis.setMaxValue(BaseFormula.createFormulaBuilder().build("=600")); + defaultYAxis.setMinValue(BaseFormula.createFormulaBuilder().build("=0")); + defaultYAxis.setMainUnit(BaseFormula.createFormulaBuilder().build("=200")); + + Object[] category = { + Toolkit.i18nText("Fine-Design_Chart_Category") + "1", + Toolkit.i18nText("Fine-Design_Chart_Category") + "2", + Toolkit.i18nText("Fine-Design_Chart_Category") + "3", + Toolkit.i18nText("Fine-Design_Chart_Category") + "4" + }; + Object[] series = { + Toolkit.i18nText("Fine-Design_Chart_Series") + "1", + Toolkit.i18nText("Fine-Design_Chart_Series") + "2", + Toolkit.i18nText("Fine-Design_Chart_Series") + "3" + }; + Object[][] value = { + {"340", "510", "300", "250"}, + {"180", "360", "170", "100"}, + {"210", "205", "405", "190"} + }; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ThemePreviewed.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ThemePreviewed.java new file mode 100644 index 0000000000..bb2aa05c22 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ThemePreviewed.java @@ -0,0 +1,10 @@ +package com.fr.design.mainframe.theme.preview; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public interface ThemePreviewed { + void refresh(T style); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/UINoOpaquePanel.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/UINoOpaquePanel.java new file mode 100644 index 0000000000..16eb2d55e0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/UINoOpaquePanel.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.theme.preview; + +import javax.swing.JPanel; +import java.awt.LayoutManager; + +public class UINoOpaquePanel extends JPanel { + + public UINoOpaquePanel(){ + super(); + this.setOpaque(false); + this.setBackground(null); + } + + public UINoOpaquePanel(LayoutManager layout) { + super(layout, true); + this.setOpaque(false); + this.setBackground(null); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/AbstractECPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/AbstractECPreviewPane.java new file mode 100644 index 0000000000..da818cb7af --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/AbstractECPreviewPane.java @@ -0,0 +1,39 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.CellBorderStyle; +import com.fr.base.Style; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; + +import java.util.List; + +public abstract class AbstractECPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + private Style getCellStyle(ThemedCellStyle themedCellStyle) { + if (themedCellStyle == null) { + return Style.DEFAULT_STYLE; + } + Style style = themedCellStyle.getStyle(); + return style != null ? style : Style.DEFAULT_STYLE; + } + + private CellBorderStyle getCellBorderStyle(ThemedCellStyle themedCellStyle) { + if (themedCellStyle == null) { + return null; + } + return themedCellStyle.getCellBorderStyle(); + } + + protected void refresh(List list, ThemedCellStyle themedCellStyle) { + Style style = getCellStyle(themedCellStyle); + CellBorderStyle borderStyle = getCellBorderStyle(themedCellStyle); + + for (AbstractPreviewCell cell : list) { + cell.refresh(style, borderStyle); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECComponentPreviewPane.java new file mode 100644 index 0000000000..427b92cd57 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECComponentPreviewPane.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.theme.FormTheme; +import com.fr.design.mainframe.theme.preview.ComponentPreviewPane; + +import java.awt.Component; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ECComponentPreviewPane extends ComponentPreviewPane { + private ECPreviewPane contentPane; + + public ECComponentPreviewPane(){ + super(i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Title")); + } + + @Override + protected Component createContentPane() { + contentPane = new ECPreviewPane(); + return contentPane; + } + + @Override + public void refresh(FormTheme theme) { + super.refresh(theme); + contentPane.refresh(theme); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java new file mode 100644 index 0000000000..2ac59af941 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java @@ -0,0 +1,115 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.CellBorderSourceFlag; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ECPreviewPane extends AbstractECPreviewPane { + private final List headerCellList = new ArrayList<>(); + private final List contentCellList = new ArrayList<>(); + private final List highLightCellList = new ArrayList<>(); + private final List assistCellList = new ArrayList<>(); + private static final int COL_COUNT = 5; + private static final int CONTENT_ROW_COUNT = 2; + + public ECPreviewPane() { + this.setPreferredSize(new Dimension(517, 158)); + this.setBorder(BorderFactory.createEmptyBorder(0, 1, 2, 1)); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel titlePane = new UINoOpaquePanel(new GridLayout()); + JPanel extCenterPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + this.add(extCenterPane, BorderLayout.CENTER); + extCenterPane.add(titlePane, BorderLayout.NORTH); + for (int c = 0; c < COL_COUNT; c++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(103, 36)); + titlePane.add(cell); + headerCellList.add(cell); + } + JPanel contentPane = new UINoOpaquePanel(new GridLayout(2, 5, 0, 0)); + extCenterPane.add(contentPane, BorderLayout.CENTER); + for (int i = 0; i < COL_COUNT * CONTENT_ROW_COUNT; i++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text")); + int r = i / COL_COUNT; + int c = i % COL_COUNT; + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r > 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r < CONTENT_ROW_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(103, 30)); + contentPane.add(cell); + contentCellList.add(cell); + } + + JPanel endPane = new UINoOpaquePanel(new GridLayout()); + extCenterPane.add(endPane, BorderLayout.SOUTH); + for (int c = 0; c < COL_COUNT; c++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(103, 30)); + endPane.add(cell); + highLightCellList.add(cell); + } + + JPanel extSouthPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + PreviewCell assistCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Assist_Text")); + assistCell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + assistCell.setPreferredSize(new Dimension(123, 30)); + assistCellList.add(assistCell); + extSouthPane.add(assistCell); + this.add(extSouthPane, BorderLayout.SOUTH); + } + + @Override + public void refresh(TemplateTheme theme) { + ThemedCellStyleList cellStyleConfig = theme.getCellStyleList(); + refresh(headerCellList, cellStyleConfig.getUse4Header()); + refresh(contentCellList, cellStyleConfig.getUse4MainText()); + refresh(highLightCellList, cellStyleConfig.getUse4HighlightText()); + refresh(assistCellList, cellStyleConfig.getUse4SupportInfo()); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java new file mode 100644 index 0000000000..98f75538f1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java @@ -0,0 +1,194 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.CellBorderSourceFlag; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.CornerPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +public class ECReportPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + private final List headerTitleCellList = new ArrayList<>(); // 大标题样式单元格 + private final List headerCellList = new ArrayList<>(); // 表头样式单元格 + private final List titleCellList = new ArrayList<>(); // 小标题样式单元格 + private final List contentCellList = new ArrayList<>(); // 正文样式单元格 + private final List highLightCellList = new ArrayList<>(); // 高亮文本样式单元格 + private final List assistCellList = new ArrayList<>(); // 辅助信息样式单元格 + private static final int CONTENT_ROW_COUNT = 3; + private static final int COL_COUNT = 5; + + private final PreviewPane previewPane; + + public ECReportPreviewPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + previewPane = new PreviewPane(); + this.add(previewPane, BorderLayout.CENTER); + } + + @Override + public void refresh(ReportTheme theme) { + previewPane.refresh(theme); + } + + + class PreviewPane extends AbstractECPreviewPane { + + + public PreviewPane() { + this.setPreferredSize(new Dimension(517, 270)); + this.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel northPane = createNorthPane(); + JPanel centerPane = createCenterPane(); + JPanel southPane = createSouthPane(); + this.add(northPane, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.CENTER); + this.add(southPane, BorderLayout.SOUTH); + } + + private JPanel createNorthPane() { + JPanel northPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + AbstractPreviewCell bigTitleCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Cell_Style_Big_Title")); + bigTitleCell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + bigTitleCell.setPreferredSize(new Dimension(615, 46)); + headerTitleCellList.add(bigTitleCell); + northPane.add(bigTitleCell, BorderLayout.NORTH); + CornerPreviewCell cornerCell = new CornerPreviewCell(new String[]{Toolkit.i18nText("Fine-Design_Basic_Column_Name"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Data"), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Row_Name")}, + new Point2D[]{new Point(159, 71), new Point(225, 49)}); + cornerCell.setBorderSourceFlag(CellBorderSourceFlag.INVALID_BORDER_SOURCE); + cornerCell.setPreferredSize(new Dimension(225, 71)); + titleCellList.add(cornerCell); + northPane.add(cornerCell, BorderLayout.WEST); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + northPane.add(centerPane, BorderLayout.CENTER); + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Small_Title")); + cell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + titleCellList.add(cell); + cell.setPreferredSize(new Dimension(308, 38)); + centerPane.add(cell, BorderLayout.NORTH); + JPanel eastSouthPane = new UINoOpaquePanel(new GridLayout()); + for (int c = 0; c < CONTENT_ROW_COUNT; c++) { + PreviewCell headerCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < CONTENT_ROW_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + headerCell.setBorderSourceFlag(flag); + headerCellList.add(headerCell); + eastSouthPane.add(headerCell); + } + centerPane.add(eastSouthPane, BorderLayout.CENTER); + return northPane; + } + + private JPanel createCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + JPanel westPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + centerPane.add(westPane, BorderLayout.WEST); + PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Small_Title")); + titleCellList.add(cell1); + cell1.setPreferredSize(new Dimension(112, 153)); + westPane.add(cell1, BorderLayout.WEST); + JPanel gridPane = new UINoOpaquePanel(new GridLayout(5, 1)); + for (int r = 0; r < COL_COUNT; r++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r > 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(113, 31)); + headerCellList.add(cell); + gridPane.add(cell); + } + westPane.add(gridPane, BorderLayout.CENTER); + + JPanel innerCenterPane = new UINoOpaquePanel(new GridLayout(5, 3)); + centerPane.add(innerCenterPane, BorderLayout.CENTER); + for (int i = 0; i < COL_COUNT * CONTENT_ROW_COUNT; i++) { + PreviewCell cell ; + int r = i / CONTENT_ROW_COUNT; + int c = i % CONTENT_ROW_COUNT; + if (c == CONTENT_ROW_COUNT - 1) { + cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r != 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r != COL_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + highLightCellList.add(cell); + } else { + cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r > 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < CONTENT_ROW_COUNT - 2) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + + contentCellList.add(cell); + } + cell.setPreferredSize(new Dimension(123, 31)); + innerCenterPane.add(cell); + } + + + return centerPane; + } + + private JPanel createSouthPane(){ + JPanel southPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + PreviewCell assistCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Assist_Text")); + assistCell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + assistCell.setPreferredSize(new Dimension(123, 30)); + assistCellList.add(assistCell); + southPane.add(assistCell, BorderLayout.CENTER); + return southPane; + } + + @Override + public void refresh(TemplateTheme theme) { + ThemedCellStyleList cellStyleConfig = theme.getCellStyleList(); + refresh(headerTitleCellList, cellStyleConfig.getUse4BigTitle()); + refresh(headerCellList, cellStyleConfig.getUse4Header()); + refresh(contentCellList, cellStyleConfig.getUse4MainText()); + refresh(titleCellList, cellStyleConfig.getUse4SmallTitle()); + refresh(highLightCellList, cellStyleConfig.getUse4HighlightText()); + refresh(assistCellList, cellStyleConfig.getUse4SupportInfo()); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/AbstractPreviewCell.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/AbstractPreviewCell.java new file mode 100644 index 0000000000..cfecccd61a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/AbstractPreviewCell.java @@ -0,0 +1,53 @@ +package com.fr.design.mainframe.theme.preview.ecpreview.cell; + +import com.fr.base.CellBorderSourceFlag; +import com.fr.base.CellBorderStyle; +import com.fr.base.Style; +import com.fr.stable.Constants; + +import javax.swing.JComponent; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; + +public abstract class AbstractPreviewCell extends JComponent { + private static final double BORDER_INSET = 0.5D; + protected Style style = Style.DEFAULT_STYLE; + private static final int NO_SCALE_RESOLUTION = 100; + private int borderSourceFlag = CellBorderSourceFlag.INVALID_BORDER_SOURCE; + + public void setBorderSourceFlag(int borderSourceFlag) { + this.borderSourceFlag = borderSourceFlag; + } + + public void refresh(Style style, CellBorderStyle borderStyle) { + this.style = CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, borderSourceFlag); + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Style.paintBackground(g2d, style, getWidth(), getHeight()); + paintContent(g2d, NO_SCALE_RESOLUTION); + paintBorder(g2d); + } + + private void paintBorder(Graphics2D g2d) { + double width = getWidth(); + double height = getHeight(); + if (style.getBorderLeft() == Constants.LINE_SLIM || style.getBorderRight() == Constants.LINE_SLIM) { + width -= BORDER_INSET; + } + if (style.getBorderBottom() == Constants.LINE_SLIM || style.getBorderTop() == Constants.LINE_SLIM) { + height -= BORDER_INSET; + } + g2d.setClip(null); + Style.paintBorder(g2d, style, width, height); + } + + protected abstract void paintContent(Graphics2D g2d, int resolution); + + @Override + public Dimension getMinimumSize() { + return new Dimension(125, 30); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/CornerPreviewCell.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/CornerPreviewCell.java new file mode 100644 index 0000000000..c82ea9fa9c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/CornerPreviewCell.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe.theme.preview.ecpreview.cell; + +import com.fr.general.FRFont; +import com.fr.stable.GraphDrawHelper; + +import java.awt.Graphics2D; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; + +public class CornerPreviewCell extends AbstractPreviewCell { + private final String[] values; + private final Point2D[] point2DS; + + public CornerPreviewCell(String[] values, Point2D[] point2DS) { + this.values = values; + this.point2DS = point2DS; + } + + @Override + protected void paintContent(Graphics2D g2d, int resolution) { + FRFont frFont = style.getFRFont(); + g2d.setPaint(frFont.getForeground()); + g2d.drawString(values[0], 23, 53); + GraphDrawHelper.drawRotatedString(g2d, values[1], 128, 50, 30); + g2d.drawString(values[2], 150, 23); + //画分割线 + for (int i = 0; i < point2DS.length; i++) { + g2d.draw(new Line2D.Double(0, 0, point2DS[i].getX(), point2DS[i].getY())); //画线 + } + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/PreviewCell.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/PreviewCell.java new file mode 100644 index 0000000000..a6a5836dba --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/PreviewCell.java @@ -0,0 +1,25 @@ +package com.fr.design.mainframe.theme.preview.ecpreview.cell; + +import com.fr.base.Style; + +import java.awt.Dimension; +import java.awt.Graphics2D; + +public class PreviewCell extends AbstractPreviewCell { + + private final String value; + + public PreviewCell(String value) { + this.value = value; + } + + @Override + protected void paintContent(Graphics2D g2d, int resolution) { + Style.paintContent(g2d, value, style, getWidth() - 3, getHeight() - 3, resolution); + } + + @Override + public Dimension getMinimumSize() { + return new Dimension(125, 30); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeManageActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeManageActionProvider.java new file mode 100644 index 0000000000..6d9744693c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeManageActionProvider.java @@ -0,0 +1,23 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +@API(level = ThemeManageActionProvider.CURRENT_LEVEL) +public abstract class AbstractThemeManageActionProvider extends AbstractProvider implements ThemeManageActionProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeProfileActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeProfileActionProvider.java new file mode 100644 index 0000000000..0ff446e800 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeProfileActionProvider.java @@ -0,0 +1,23 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +@API(level = ThemeProfileActionProvider.CURRENT_LEVEL) +public abstract class AbstractThemeProfileActionProvider extends AbstractProvider implements ThemeProfileActionProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeManageActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeManageActionProvider.java new file mode 100644 index 0000000000..fd9f452f56 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeManageActionProvider.java @@ -0,0 +1,28 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.theme.dialog.TemplateThemeDialog; +import com.fr.stable.fun.mark.Mutable; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +public interface ThemeManageActionProvider extends Mutable { + + String MARK_STRING = "ThemeManageActionProvider"; + + int CURRENT_LEVEL = 1; + + UIButton createButton(ThemeManageActionContext context); + + interface ThemeManageActionContext { + + TemplateThemeDialog getDialog(); + + TemplateThemeConfig getConfig(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeProfileActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeProfileActionProvider.java new file mode 100644 index 0000000000..cabf0a13a3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeProfileActionProvider.java @@ -0,0 +1,27 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.theme.TemplateThemeProfilePane; +import com.fr.design.mainframe.theme.dialog.TemplateThemeDialog; +import com.fr.stable.fun.mark.Mutable; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +public interface ThemeProfileActionProvider extends Mutable { + + String MARK_STRING = "ThemeProfileActionProvider"; + + int CURRENT_LEVEL = 1; + + UIButton createButton(ThemeProfileActionContext context); + + interface ThemeProfileActionContext { + TemplateThemeDialog getDialog(); + + TemplateThemeProfilePane getProfilePane(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/AutoCheckTextField.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/AutoCheckTextField.java new file mode 100644 index 0000000000..9ce5a3d5d3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/AutoCheckTextField.java @@ -0,0 +1,100 @@ +package com.fr.design.mainframe.theme.ui; + +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.stable.StringUtils; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/18 + */ +public class AutoCheckTextField extends UITextField implements DocumentListener, FocusListener { + private DuplicateChecker duplicatedChecker; + private CheckListener checkListener; + + public AutoCheckTextField() { + getDocument().addDocumentListener(this); + addFocusListener(this); + } + + public void setDuplicatedChecker(DuplicateChecker checker) { + this.duplicatedChecker = checker; + } + public void setNameCheckListener(CheckListener checkListener) { + this.checkListener = checkListener; + } + + private boolean isEmpty(String name) { + return StringUtils.isEmpty(name); + } + private boolean isDuplicated(String name) { + if (duplicatedChecker != null) { + return duplicatedChecker.isDuplicated(name); + } + return false; + } + private boolean checkValid(boolean notifyEmptyTip) { + String name = getText(); + + String error = StringUtils.EMPTY; + boolean valid = true; + if (isEditable()) { + if (isEmpty(name)) { + valid = false; + if (notifyEmptyTip) { + error = Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Empty_Name_Error_Tip"); + } + } else if (isDuplicated(name)) { + valid = false; + error = Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Duplicated_Name_Error_Tip"); + } + } + + if (checkListener != null) { + checkListener.onChecked(error, valid); + } + + return valid; + } + public boolean checkValid() { + return checkValid(true); + } + + @Override + public void insertUpdate(DocumentEvent e) { + checkValid(false); + } + + @Override + public void removeUpdate(DocumentEvent e) { + checkValid(false); + } + + @Override + public void changedUpdate(DocumentEvent e) { + + } + + @Override + public void focusGained(FocusEvent e) { + checkValid(false); + } + + @Override + public void focusLost(FocusEvent e) { + checkValid(true); + } + + public interface CheckListener { + void onChecked(String error, boolean valid); + } + public interface DuplicateChecker { + boolean isDuplicated(String name); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/AutoCheckThemeNameTextField.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/AutoCheckThemeNameTextField.java new file mode 100644 index 0000000000..804c8493d2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/AutoCheckThemeNameTextField.java @@ -0,0 +1,26 @@ +package com.fr.design.mainframe.theme.ui; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/18 + */ +public class AutoCheckThemeNameTextField extends AutoCheckTextField { + private TemplateThemeConfig config; + + public AutoCheckThemeNameTextField() { + setDuplicatedChecker(new DuplicateChecker() { + @Override + public boolean isDuplicated(String name) { + return config != null && config.contains(name); + } + }); + } + + public void setThemeConfig(TemplateThemeConfig config) { + this.config = config; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BorderUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BorderUtils.java new file mode 100644 index 0000000000..3b7a8b6c0e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BorderUtils.java @@ -0,0 +1,30 @@ +package com.fr.design.mainframe.theme.ui; + +import com.fr.design.border.UIRoundedBorder; +import com.fr.general.FRFont; + +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import java.awt.Color; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/15 + */ +public class BorderUtils { + public static Border createTitleBorder(String title) { + return createTitleBorder(title, 12); + } + public static Border createTitleBorder(String title, int size) { + return new NoEdgeTitleBorder( + new UIRoundedBorder(new Color(0XE0E0E1), 1, 1), + title, + TitledBorder.LEADING, + TitledBorder.TOP, + FRFont.getInstance().applySize(size), + new Color(47, 142, 241) + ); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BreadcrumbBar.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BreadcrumbBar.java new file mode 100644 index 0000000000..bc466972ef --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BreadcrumbBar.java @@ -0,0 +1,114 @@ +package com.fr.design.mainframe.theme.ui; + +import com.fr.design.gui.ilable.UILabel; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/10/9 + */ +public class BreadcrumbBar extends JPanel { + private JButton currentCrumb; + + public BreadcrumbBar() { + setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + } + + public void addCrumb(final String text, final BreadcrumbBackListener backListener) { + if (currentCrumb != null) { + currentCrumb.setSelected(false); + add(createSeparator()); + } + final JButton breadcrumb = createBreadcrumb(text); + breadcrumb.setSelected(true); + add(breadcrumb); + currentCrumb = breadcrumb; + + final int index = getComponentCount() - 1; + breadcrumb.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + removeTailCrumbs(index + 1); + + breadcrumb.setSelected(true); + currentCrumb = breadcrumb; + if (backListener != null) { + backListener.onBreadcrumbBack(text); + } + } + }); + } + + private void removeTailCrumbs(int from) { + Component[] components = getComponents(); + for (int i = from; i < components.length; i++) { + remove(components[i]); + } + revalidate(); + repaint(); + } + + public void clear() { + removeAll(); + currentCrumb = null; + } + + protected Component createSeparator() { + UILabel separator = new UILabel("/"); + separator.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + separator.setPreferredSize(new Dimension(separator.getPreferredSize().width, 17)); + + return separator; + } + + protected JButton createBreadcrumb(String text) { + JButton button = new BreadcrumbButton(text); + button.setPreferredSize(new Dimension(button.getPreferredSize().width, 17)); + return button; + } + + public static class BreadcrumbButton extends JButton { + + public BreadcrumbButton(String text) { + super(text); + setMargin(new Insets(0, 0, 0, 0)); + setBorder(BorderFactory.createEmptyBorder()); + setUI(new BasicButtonUI()); + setBorderPainted(false); + setOpaque(false); + setBackground(null); + } + + @Override + public Insets getMargin() { + Insets insets = super.getMargin(); + if (insets != null) { + insets.set(0, 0, 0, 0); + } + return insets; + } + + @Override + public void setSelected(boolean b) { + super.setSelected(b); + setForeground(b ? new Color(0x419BF9) : new Color(0x838384)); + repaint(); + } + } + + public interface BreadcrumbBackListener { + void onBreadcrumbBack(String text); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/NoEdgeTitleBorder.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/NoEdgeTitleBorder.java new file mode 100644 index 0000000000..bf532b00f5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/NoEdgeTitleBorder.java @@ -0,0 +1,320 @@ +package com.fr.design.mainframe.theme.ui; + +import javax.swing.JLabel; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.plaf.basic.BasicHTML; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.geom.Path2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/16 + * 修正TitleBorder默认的行为,使得组件有多大,边框就有多大 + */ +public class NoEdgeTitleBorder extends TitledBorder { + + private final JLabel label; + + public NoEdgeTitleBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont, Color titleColor) { + super(border, title, titleJustification, titlePosition, titleFont, titleColor); + + this.label = new JLabel(); + this.label.setOpaque(false); + this.label.putClientProperty(BasicHTML.propertyKey, null); + } + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Border border = getBorder(); + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = 0; //(border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0)); + + int borderX = x + edge; + int borderY = y + edge; + int borderW = width - edge - edge; + int borderH = height - edge - edge; + + int labelY = y; + int labelH = size.height; + int position = getPosition(); + switch (position) { + case ABOVE_TOP: + insets.left = 0; + insets.right = 0; + borderY += labelH - edge; + borderH -= labelH - edge; + break; + case TOP: + insets.top = edge + insets.top/2 - labelH/2; + if (insets.top < edge) { + borderY -= insets.top; + borderH += insets.top; + } + else { + labelY += insets.top; + } + break; + case BELOW_TOP: + labelY += insets.top + edge; + break; + case ABOVE_BOTTOM: + labelY += height - labelH - insets.bottom - edge; + break; + case BOTTOM: + labelY += height - labelH; + insets.bottom = edge + (insets.bottom - labelH) / 2; + if (insets.bottom < edge) { + borderH += insets.bottom; + } + else { + labelY -= insets.bottom; + } + break; + case BELOW_BOTTOM: + insets.left = 0; + insets.right = 0; + labelY += height - labelH; + borderH -= labelH - edge; + break; + } + insets.left += edge + TEXT_INSET_H; + insets.right += edge + TEXT_INSET_H; + + int labelX = x; + int labelW = width - insets.left - insets.right; + if (labelW > size.width) { + labelW = size.width; + } + switch (getJustification(c)) { + case LEFT: + labelX += insets.left; + break; + case RIGHT: + labelX += width - insets.right - labelW; + break; + case CENTER: + labelX += (width - labelW) / 2; + break; + } + + if (border != null) { + if ((position != TOP) && (position != BOTTOM)) { + border.paintBorder(c, g, borderX, borderY, borderW, borderH); + } + else { + Graphics g2 = g.create(); + if (g2 instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) g2; + Path2D path = new Path2D.Float(); + path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false); + path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false); + path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY, borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false); + path.append(new Rectangle(borderX, labelY + labelH, borderW, borderY - labelY + borderH - labelH), false); + g2d.clip(path); + } + border.paintBorder(c, g2, borderX, borderY, borderW, borderH); + g2.dispose(); + } + } + g.translate(labelX, labelY); + label.setSize(labelW, labelH); + label.paint(g); + g.translate(-labelX, -labelY); + } + else if (border != null) { + border.paintBorder(c, g, x, y, width, height); + } + } + + /** + * Reinitialize the insets parameter with this Border's current Insets. + * @param c the component for which this border insets value applies + * @param insets the object to be reinitialized + */ + public Insets getBorderInsets(Component c, Insets insets) { + Border border = getBorder(); + insets = getBorderInsets(border, c, insets); + + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = 0; //(border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + + switch (getPosition()) { + case ABOVE_TOP: + insets.top += size.height - edge; + break; + case TOP: { + if (insets.top < size.height) { + insets.top = size.height - edge; + } + break; + } + case BELOW_TOP: + insets.top += size.height; + break; + case ABOVE_BOTTOM: + insets.bottom += size.height; + break; + case BOTTOM: { + if (insets.bottom < size.height) { + insets.bottom = size.height - edge; + } + break; + } + case BELOW_BOTTOM: + insets.bottom += size.height - edge; + break; + } + insets.top += edge; //TEXT_SPACING; + insets.left += edge; //TEXT_SPACING; + insets.right += edge; //TEXT_SPACING; + insets.bottom += edge; //TEXT_SPACING; + } + return insets; + } + + public int getBaseline(Component c, int width, int height) { + if (c == null) { + throw new NullPointerException("Must supply non-null component"); + } + if (width < 0) { + throw new IllegalArgumentException("Width must be >= 0"); + } + if (height < 0) { + throw new IllegalArgumentException("Height must be >= 0"); + } + Border border = getBorder(); + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = 0; //(border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0)); + + int baseline = label.getBaseline(size.width, size.height); + switch (getPosition()) { + case ABOVE_TOP: + return baseline; + case TOP: + insets.top = edge + (insets.top - size.height) / 2; + return (insets.top < edge) + ? baseline + : baseline + insets.top; + case BELOW_TOP: + return baseline + insets.top + edge; + case ABOVE_BOTTOM: + return baseline + height - size.height - insets.bottom - edge; + case BOTTOM: + insets.bottom = edge + (insets.bottom - size.height) / 2; + return (insets.bottom < edge) + ? baseline + height - size.height + : baseline + height - size.height + insets.bottom; + case BELOW_BOTTOM: + return baseline + height - size.height; + } + } + return -1; + } + + private int getPosition() { + int position = getTitlePosition(); + if (position != DEFAULT_POSITION) { + return position; + } + Object value = UIManager.get("TitledBorder.position"); + if (value instanceof Integer) { + int i = (Integer) value; + if ((0 < i) && (i <= 6)) { + return i; + } + } + else if (value instanceof String) { + String s = (String) value; + if (s.equalsIgnoreCase("ABOVE_TOP")) { + return ABOVE_TOP; + } + if (s.equalsIgnoreCase("TOP")) { + return TOP; + } + if (s.equalsIgnoreCase("BELOW_TOP")) { + return BELOW_TOP; + } + if (s.equalsIgnoreCase("ABOVE_BOTTOM")) { + return ABOVE_BOTTOM; + } + if (s.equalsIgnoreCase("BOTTOM")) { + return BOTTOM; + } + if (s.equalsIgnoreCase("BELOW_BOTTOM")) { + return BELOW_BOTTOM; + } + } + return TOP; + } + + private int getJustification(Component c) { + int justification = getTitleJustification(); + if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) { + return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT; + } + if (justification == TRAILING) { + return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT; + } + return justification; + } + + private Color getColor(Component c) { + Color color = getTitleColor(); + if (color != null) { + return color; + } + return (c != null) + ? c.getForeground() + : null; + } + + private JLabel getLabel(Component c) { + this.label.setText(getTitle()); + Font font = getFont(c); + this.label.setFont(font); + this.label.setForeground(getColor(c)); + this.label.setComponentOrientation(c.getComponentOrientation()); + this.label.setEnabled(c.isEnabled()); + Dimension dimension = this.label.getPreferredSize(); + dimension.height = font.getSize(); + this.label.setPreferredSize(dimension); + return this.label; + } + + private static Insets getBorderInsets(Border border, Component c, Insets insets) { + if (border == null) { + insets.set(0, 0, 0, 0); + } + else if (border instanceof AbstractBorder) { + AbstractBorder ab = (AbstractBorder) border; + insets = ab.getBorderInsets(c, insets); + } + else { + Insets i = border.getBorderInsets(c); + insets.set(i.top, i.left, i.bottom, i.right); + } + return insets; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedFloatElement.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedFloatElement.java new file mode 100644 index 0000000000..e1e2e4c155 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedFloatElement.java @@ -0,0 +1,41 @@ +package com.fr.design.mainframe.theme.utils; + +import com.fr.base.NameStyle; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.report.cell.FloatElement; +import com.fr.stable.unit.UNIT; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/9 + */ +public class DefaultThemedFloatElement { + public static FloatElement createInstance() { + return themingFloatElement(new FloatElement()); + } + + public static FloatElement createInstance(Object value) { + return themingFloatElement(new FloatElement(value)); + } + + public static FloatElement createInstance(UNIT leftDistance, UNIT topDistance, UNIT width, UNIT height, Object value) { + return themingFloatElement(new FloatElement(leftDistance, topDistance, width, height, value)); + } + + private static FloatElement themingFloatElement(FloatElement floatElement) { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + ThemedCellStyle themedCellStyle = theme.getCellStyleList().getUse4Default(); + if (themedCellStyle != null) { + NameStyle nameStyle = NameStyle.getPassiveInstance(themedCellStyle.getName(), themedCellStyle.getStyle()); + floatElement.setStyle(nameStyle); + } + } + return floatElement; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedTemplateCellElementCase.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedTemplateCellElementCase.java new file mode 100644 index 0000000000..67be5cc9aa --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedTemplateCellElementCase.java @@ -0,0 +1,45 @@ +package com.fr.design.mainframe.theme.utils; + +import com.fr.base.NameStyle; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.report.cell.DefaultTemplateCellElement; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/31 + */ +public class DefaultThemedTemplateCellElementCase { + + public static DefaultTemplateCellElement createInstance() { + return themingCellElement(new DefaultTemplateCellElement()); + } + + public static DefaultTemplateCellElement createInstance(int column, int row) { + return themingCellElement(new DefaultTemplateCellElement(column, row)); + } + + public static DefaultTemplateCellElement createInstance(int column, int row, Object value) { + return themingCellElement(new DefaultTemplateCellElement(column, row, value)); + } + + public static DefaultTemplateCellElement createInstance(int column, int row, int columnSpan, int rowSpan, Object value) { + return themingCellElement(new DefaultTemplateCellElement(column, row, columnSpan, rowSpan, value)); + } + + private static DefaultTemplateCellElement themingCellElement(DefaultTemplateCellElement cellElement) { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + ThemedCellStyle themedCellStyle = theme.getCellStyleList().getUse4Default(); + if (themedCellStyle != null) { + NameStyle nameStyle = NameStyle.getPassiveInstance(themedCellStyle.getName(), themedCellStyle.getStyle()); + cellElement.setStyle(nameStyle); + } + } + return cellElement; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java b/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java index 4e69c34c56..fc326c60e6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java @@ -6,17 +6,17 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.stable.Constants; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.Window; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.SwingConstants; import java.awt.BorderLayout; +import java.awt.Dialog; import java.awt.Dimension; import java.awt.Font; +import java.awt.Frame; +import java.awt.Window; /** * Created by kerry on 5/6/21 @@ -31,6 +31,13 @@ public class DesignerToastMsgUtil { } + public static ToastMsgDialog createPromptDialog(String text) { + return createDialog(PROMPT_ICON, toastPane(text), DesignerContext.getDesignerFrame()); + } + + public static ToastMsgDialog createPromptDialog(JPanel contentPane) { + return createDialog(PROMPT_ICON, contentPane, DesignerContext.getDesignerFrame()); + } public static void toastPrompt(JPanel contendPane) { toastPane(PROMPT_ICON, contendPane, DesignerContext.getDesignerFrame()); @@ -69,6 +76,11 @@ public class DesignerToastMsgUtil { } private static void toastPane(Icon icon, JPanel contendPane, Window parent) { + ToastMsgDialog dialog = createDialog(icon, contendPane, parent); + dialog.setVisible(true); + } + + private static ToastMsgDialog createDialog(Icon icon, JPanel contendPane, Window parent) { JPanel pane = FRGUIPaneFactory.createBorderLayout_S_Pane(); UILabel uiLabel = new UILabel(icon); uiLabel.setVerticalAlignment(SwingConstants.TOP); @@ -83,7 +95,7 @@ public class DesignerToastMsgUtil { } else { dialog = new ToastMsgDialog((Frame) parent, pane); } - dialog.setVisible(true); + return dialog; } @@ -118,4 +130,4 @@ public class DesignerToastMsgUtil { .toString(); } -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java index 00f4f95ead..83cd84e9cc 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java @@ -3,10 +3,11 @@ package com.fr.design.mainframe.toast; import com.fr.concurrent.NamedThreadFactory; import com.fr.design.dialog.UIDialog; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; import com.fr.module.ModuleContext; -import java.awt.Dialog; import javax.swing.JPanel; +import java.awt.Dialog; import java.awt.Dimension; import java.awt.Frame; import java.awt.Point; @@ -24,6 +25,7 @@ public class ToastMsgDialog extends UIDialog { private ScheduledExecutorService TIMER; private int hide_height = 0; private JPanel contentPane; + private boolean show = false; public ToastMsgDialog(Frame parent, JPanel panel) { super(parent); @@ -50,12 +52,16 @@ public class ToastMsgDialog extends UIDialog { hide_height = dimension.height; setSize(new Dimension(dimension.width, 0)); contentPane.setSize(dimension); - setLocationRelativeTo(DesignerContext.getDesignerFrame().getContentFrame()); - int positionY = DesignerContext.getDesignerFrame().getContentFrame().getLocationOnScreen().y + 10; - setLocation((DesignerContext.getDesignerFrame().getWidth() - dimension.width) / 2, positionY); + setRelativeLocation(dimension); addMouseEvent(contentPane); } + private void setRelativeLocation(Dimension dimension) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + int positionX = designerFrame.getLocationOnScreen().x + (designerFrame.getWidth() - dimension.width) / 2; + int positionY = designerFrame.getContentFrame().getLocationOnScreen().y + 10; + this.setLocation(positionX, positionY); + } private Dimension calculatePreferSize() { Dimension contentDimension = contentPane.getPreferredSize(); @@ -65,6 +71,7 @@ public class ToastMsgDialog extends UIDialog { public void display(JPanel outerJPanel) { + show = true; outerJPanel.setLocation(0, -hide_height); ScheduledExecutorService TIP_TOOL_TIMER = createToastScheduleExecutorService(); TIP_TOOL_TIMER.scheduleAtFixedRate(new Runnable() { @@ -98,12 +105,13 @@ public class ToastMsgDialog extends UIDialog { TIP_TOOL_TIMER.shutdown(); ToastMsgDialog.this.setVisible(false); ToastMsgDialog.this.dispose(); + ToastMsgDialog.this.show = false; } outerJPanel.setLocation(point.x, point.y - 5); Dimension dimension = ToastMsgDialog.this.getSize(); ToastMsgDialog.this.setSize(new Dimension(dimension.width, dimension.height - 5)); } - }, 0,50, TimeUnit.MILLISECONDS); + }, 0, 50, TimeUnit.MILLISECONDS); } }, 5000, TimeUnit.MILLISECONDS); @@ -159,5 +167,7 @@ public class ToastMsgDialog extends UIDialog { super.dispose(); } - -} + public boolean isShow() { + return show; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java index 5043e8307b..ba9aadcc5e 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java @@ -470,6 +470,10 @@ public abstract class ToolBarMenuDock { return new UILabel(); } + public Component createGuideEntryPane() { + return new UILabel(); + } + public Component createNotificationCenterPane(){ return new UILabel(); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java index 8229c9f8d8..0ec5b9c4f5 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java @@ -1,5 +1,6 @@ package com.fr.design.mainframe.vcs.common; + import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.file.HistoryTemplateListCache; diff --git a/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java b/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java index d94da0c887..ae83a0bb91 100644 --- a/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java +++ b/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java @@ -12,7 +12,13 @@ public abstract class SnapChatAllTypes { /** * 社区按钮 */ - BBS("BBS"); + BBS("BBS"), + + /** + * 服务器按钮 + */ + SERVER("SERVER"); + private static final String SIGN = "0001"; @@ -35,4 +41,32 @@ public abstract class SnapChatAllTypes { } } + public enum UpdateAction implements SnapChatKey { + + /** + * 服务器模版主题管理 + */ + TEMPLATE_THEMES_MANAGER("TEMPLATE_THEMES_MANAGER"); + + private static final String SIGN = "0002"; + + private String key; + + UpdateAction(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + @Override + public String calc() { + + return CommonUtils.join( + new String[]{SIGN, getKey()}, "-" + ); + } + } + } diff --git a/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java b/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java index 057b561fa0..115b9617ce 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java @@ -1,18 +1,8 @@ package com.fr.design.os.impl; -import com.fr.design.data.datapane.connect.ConnectionManagerPane; -import com.fr.design.dialog.BasicDialog; -import com.fr.design.dialog.DialogActionAdapter; -import com.fr.design.editlock.EditLockUtils; +import com.fr.design.data.datapane.connect.ConnectionListPane; import com.fr.design.mainframe.DesignerContext; -import com.fr.design.mainframe.DesignerFrame; -import com.fr.file.ConnectionConfig; import com.fr.stable.os.support.OSBasedAction; -import com.fr.transaction.CallBackAdaptor; -import com.fr.transaction.Configurations; -import com.fr.transaction.WorkerFacade; -import com.fr.report.LockItem; -import static com.fr.design.actions.server.ConnectionListAction.doWithDatasourceManager; /** * 数据连接窗口 @@ -33,54 +23,7 @@ public class DatabaseDialogAction implements OSBasedAction { } private void openDesignDatabaseManager() { - DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); - final ConnectionConfig datasourceManager = ConnectionConfig.getInstance(); - final ConnectionManagerPane databaseManagerPane = new ConnectionManagerPane() { - public void complete() { - ConnectionConfig connectionConfig = datasourceManager.mirror(); - populate(connectionConfig); - } - - protected void renameConnection(String oldName, String newName) { - datasourceManager.renameConnection(oldName, newName); - } - }; - final BasicDialog databaseListDialog = databaseManagerPane.showLargeWindow(designerFrame, null); - databaseListDialog.addDialogActionListener(new DialogActionAdapter() { - public void doOk() { - if (!databaseManagerPane.isNamePermitted()) { - databaseListDialog.setDoOKSucceed(false); - return; - } - Configurations.modify(new WorkerFacade(ConnectionConfig.class) { - @Override - public void run() { - databaseManagerPane.update(datasourceManager); - } - }.addCallBack(new CallBackAdaptor() { - @Override - public boolean beforeCommit() { - //如果更新失败,则不关闭对话框,也不写xml文件,并且将对话框定位在请重命名的那个对象页面 - return doWithDatasourceManager(datasourceManager, databaseManagerPane, databaseListDialog); - } - - @Override - public void afterCommit() { - DesignerContext.getDesignerBean("databasename").refreshBeanElement(); - // 定义数据连接弹窗关闭后,解锁 - EditLockUtils.unlock(LockItem.CONNECTION); - } - })); - } - - @Override - public void doCancel() { - super.doCancel(); - // 定义数据连接弹窗关闭后,解锁 - EditLockUtils.unlock(LockItem.CONNECTION); - } - }); - databaseListDialog.setVisible(true); + ConnectionListPane.showDialog(DesignerContext.getDesignerFrame()); } diff --git a/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java b/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java index 3ec67200d5..5751c3ecb9 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java @@ -1,6 +1,7 @@ package com.fr.design.os.impl; import com.fr.base.FRContext; +import com.fr.design.config.DesignerProperties; import com.fr.design.jdk.JdkVersion; import com.fr.general.CloudCenter; import com.fr.general.GeneralContext; @@ -27,11 +28,11 @@ import java.util.Scanner; public enum SupportOSImpl implements SupportOS { /** - * ARM下屏蔽登录 + * 屏蔽登录入口 */ - USERINFOPANE{ + BBS_USER_LOGIN_PANE { public boolean support(){ - return Arch.getArch() != Arch.ARM; + return Arch.getArch() != Arch.ARM && DesignerProperties.getInstance().isSupportLoginEntry(); } }, /** diff --git a/designer-base/src/main/java/com/fr/design/parameter/ParameterArrayPane.java b/designer-base/src/main/java/com/fr/design/parameter/ParameterArrayPane.java index 2703a2a2b8..22211acff1 100644 --- a/designer-base/src/main/java/com/fr/design/parameter/ParameterArrayPane.java +++ b/designer-base/src/main/java/com/fr/design/parameter/ParameterArrayPane.java @@ -2,20 +2,16 @@ package com.fr.design.parameter; import com.fr.base.Parameter; import com.fr.base.ParameterConfig; -import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.controlpane.JListControlPane; import com.fr.design.gui.controlpane.NameableCreator; import com.fr.design.gui.controlpane.NameableSelfCreator; import com.fr.design.gui.controlpane.UnrepeatedNameHelper; import com.fr.design.i18n.Toolkit; -import com.fr.general.ComparatorUtils; import com.fr.stable.Nameable; -import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; -import javax.swing.*; import java.util.Arrays; -import java.util.List; +import java.util.Collection; public class ParameterArrayPane extends JListControlPane { @@ -29,27 +25,25 @@ public class ParameterArrayPane extends JListControlPane { this.addModNameActionListener((index, oldName, newName) -> populateSelectedValue()); this.addEditingListener(new PropertyChangeAdapter() { public void propertyChange() { - Parameter[] parameters = ParameterConfig.getInstance().getGlobalParameters(); - String[] allListNames = nameableList.getAllNames(); - allListNames[editingIndex] = StringUtils.EMPTY; - String tempName = getEditingName(); - if (StringUtils.isEmpty(tempName)) { - nameableList.stopEditing(); - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ParameterArrayPane.this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Empty_Parameter_Name")); - setIllegalIndex(editingIndex); - return; - } - if (!ComparatorUtils.equals(tempName, selectedName) - && isNameRepeated(new List[]{Arrays.asList(parameters), Arrays.asList(allListNames)}, tempName)) { - nameableList.stopEditing(); - FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ParameterArrayPane.this), - Toolkit.i18nText("Fine-Design_Basic_Duplicate_Parameter_Name")); - setIllegalIndex(editingIndex); - } + checkName(); } }); } + @Override + public String getEmptyNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Empty_Parameter_Name"); + } + + @Override + public String getDuplicatedNameTip() { + return Toolkit.i18nText("Fine-Design_Basic_Duplicate_Parameter_Name"); + } + + @Override + public Collection getExtraItemsToCheckNameRepeat() { + return Arrays.asList(ParameterConfig.getInstance().getGlobalParameters()); + } @Override protected String title4PopupWindow() { diff --git a/designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java b/designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java similarity index 50% rename from designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java rename to designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java index 96e90d5a22..04fd6623c8 100644 --- a/designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java +++ b/designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java @@ -1,40 +1,41 @@ package com.fr.design.preview; -import com.fr.base.io.IOFile; import com.fr.design.fun.impl.AbstractPreviewProvider; - +import com.fr.general.web.ParameterConstants; +import com.fr.locale.InterProviderFactory; import java.util.HashMap; import java.util.Map; -/** - * Created by loy on 2017/7/7. - */ -public class WriteEnhancePreview extends AbstractPreviewProvider { +import static com.fr.nx.app.web.v9.PagePlusActor.TYPE; + +public class PagePlusPreview extends AbstractPreviewProvider { + private static final int CODE = 100; + @Override public String nameForPopupItem() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Enhance_Preview"); + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Page-Plus"); } @Override public String iconPathForPopupItem() { - return "com/fr/design/images/buttonicon/writes.png"; + return "com/fr/design/images/buttonicon/pages.png"; } @Override public String iconPathForLarge() { - return "com/fr/design/images/buttonicon/writeb24.png"; + return "com/fr/design/images/buttonicon/pageb24.png"; } @Override public int previewTypeCode() { - return IOFile.WRITE_ENHANCE_PREVIEW_TYPE; + return CODE; } @Override public Map parametersForPreview() { Map map = new HashMap(); - map.put("op", "write_plus"); + map.put(ParameterConstants.OP, TYPE); return map; } } diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java b/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java index 26fc0c28a2..da5817b853 100644 --- a/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java +++ b/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java @@ -38,7 +38,7 @@ public class AuthorityEditorPane extends BasicBeanPane { ) ) ); - IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class", ".frm", ".form"}); + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cptx", ".cpt", ".class", ".frm", ".form"}); tree.setDigIn(true); tree.setFileNodeFilter(filter); UIScrollPane scrollPane = new UIScrollPane(tree); diff --git a/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java b/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java index 588e4601d0..48e988a826 100644 --- a/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java +++ b/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java @@ -163,7 +163,7 @@ public class WatermarkPane extends BasicPane { tipsJp.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Direction_Vertical"), SwingConstants.CENTER)); watermarkGapTipsPane.add(tipsJp, BorderLayout.CENTER); - colorPane = new NewColorSelectPane(); + colorPane = new NewColorSelectPane(false); JPanel colorLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); colorLabelPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Text_Color")), BorderLayout.NORTH); 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 new file mode 100644 index 0000000000..9e60c6cc84 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/AdaptiveFrmFitAttrModel.java @@ -0,0 +1,55 @@ +package com.fr.design.report.fit; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.report.fit.provider.AbstractFitAttrModelProvider; + +import com.fr.form.fit.common.LightTool; +import com.fr.form.fit.config.FormFitConfig; +import com.fr.form.main.Form; +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 + }; + } + + public String getFitName() { + return Toolkit.i18nText("Fine-Designer_Fit_Report_Scale_Method"); + } + + @Override + public String getModelName() { + return Toolkit.i18nText("Fine-Design_Basic_Decision_Report"); + } + + @Override + public ReportFitAttr getGlobalReportFitAttr() { + return FormFitConfig.getInstance().getNewFitAttr(); + } + + @Override + public void setGlobalReportFitAttr(ReportFitAttr reportFitAttr) { + FormFitConfig.getInstance().setNewFitAttr(reportFitAttr); + } + + @Override + public int getPriority() { + return 2; + } + + @Override + public boolean isAvailable(JTemplate jTemplate) { + if (jTemplate.getTarget() instanceof Form) { + return LightTool.containNewFormFlag((Form) jTemplate.getTarget()); + } + return false; + } + +} \ No newline at end of file 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 7a2e0e4729..2c38d597c4 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 @@ -16,7 +16,6 @@ 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; @@ -52,6 +51,7 @@ public abstract class BaseFitAttrPane extends BasicBeanPane { private void initFitAttrModel() { fitAttrModelList.add(new FrmFitAttrModel()); fitAttrModelList.add(new CptFitAttrModel()); + fitAttrModelList.add(new AdaptiveFrmFitAttrModel()); Set fitAttrModelProviders = ExtraDesignClassManager.getInstance().getArray(FitAttrModelProvider.XML_TAG); 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 258dfbf49c..c4bdaf6de2 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 @@ -12,7 +12,7 @@ public class FrmFitAttrModel implements FitAttrModel { @Override public String getModelName() { - return Toolkit.i18nText("Fine-Design_Basic_Decision_Report"); + return Toolkit.i18nText("Fine-Design_Old_Decision_Report"); } @Override diff --git a/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java b/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java index c1dd3afd6e..ba37ea18b7 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java @@ -70,11 +70,15 @@ public class ReportFitAttrAction extends JTemplateAction { UIDialog dialog = attrPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { @Override public void doOk() { - wbTpl.setReportFitAttr(attrPane.updateBean()); - jwb.fireTargetModified(); + fireEditingOk(jwb, wbTpl, attrPane.updateBean(), fitAttr); } }, DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.templatePane.dialog")); 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-base/src/main/java/com/fr/design/style/AbstractSelectBox.java b/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java index 4e82d38051..e59ddfa579 100644 --- a/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java @@ -43,7 +43,6 @@ public abstract class AbstractSelectBox extends AbstractPopBox implements Mou displayComponent = new BackgroundJComponent(); displayComponent.setEmptyBackground(); - displayComponent.setBorder(new TriggleLineBorder()); triggleButton = new UIButton(UIConstants.ARROW_DOWN_ICON) { public boolean shouldResponseChangeListener() { return false; diff --git a/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java b/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java index 136de486a6..22f60b185c 100644 --- a/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java +++ b/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java @@ -5,6 +5,7 @@ package com.fr.design.style; import com.fr.base.BaseUtils; import com.fr.base.Style; +import com.fr.design.border.UITitledBorder; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.icheckbox.UICheckBox; @@ -86,7 +87,7 @@ public class AlignmentPane extends BasicPane { //richer:文本控制和图片布局 JPanel textDirectionPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); contentPane.add(textDirectionPanel); - textDirectionPanel.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation"), null)); + textDirectionPanel.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation"))); JPanel isVerticalTextPanel = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); textDirectionPanel.add(isVerticalTextPanel); initVerticalPane(isVerticalTextPanel); @@ -131,7 +132,7 @@ public class AlignmentPane extends BasicPane { private void initSpacingPane (JPanel spacingPane) { spacingPane.setLayout(new GridLayout(1, 3)); - spacingPane.setBorder(BorderFactory.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing") + ":")); + spacingPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing") + ":")); spacingBeforeSpinner = new UIBasicSpinner(new SpinnerNumberModel(new Integer(0), new Integer(0), null, new Integer(1))); spacingBeforeSpinner.addChangeListener(changeListener); @@ -153,7 +154,7 @@ public class AlignmentPane extends BasicPane { private JPanel getIndentPane() { JPanel indentPane = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); - indentPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sytle_Indentation"), null)); + indentPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sytle_Indentation"))); Comparable maximum = null; leftIndentSpinner = new UIBasicSpinner(new SpinnerNumberModel(new Integer(0), new Integer(0), maximum, new Integer(1))); leftIndentSpinner.addChangeListener(changeListener); diff --git a/designer-base/src/main/java/com/fr/design/style/BorderPane.java b/designer-base/src/main/java/com/fr/design/style/BorderPane.java index 442f301894..c9dff2c3d2 100644 --- a/designer-base/src/main/java/com/fr/design/style/BorderPane.java +++ b/designer-base/src/main/java/com/fr/design/style/BorderPane.java @@ -7,6 +7,7 @@ import com.fr.base.BaseUtils; import com.fr.base.CellBorderStyle; import com.fr.base.GraphHelper; import com.fr.base.Style; +import com.fr.design.border.UITitledBorder; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icombobox.LineComboBox; @@ -96,7 +97,7 @@ public class BorderPane extends BasicPane { JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - centerPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"), null)); + centerPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"))); JPanel borderAllControlPane = FRGUIPaneFactory.createCenterFlowInnerContainer_S_Pane(); centerPane.add(borderAllControlPane, BorderLayout.NORTH); borderAllControlPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); @@ -147,7 +148,7 @@ public class BorderPane extends BasicPane { JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - northPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Line"), null)); + northPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Line"))); JPanel rightTopPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); northPane.add(rightTopPane, BorderLayout.NORTH); JPanel first = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); diff --git a/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java b/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java index cffe363737..3b8e1daa23 100644 --- a/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java @@ -11,7 +11,7 @@ import javax.swing.event.ChangeListener; import com.fr.base.background.ColorBackground; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.style.background.BackgroundCustomJComponent; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; /** @@ -40,11 +40,11 @@ public class CustomSelectBox extends AbstractPopBox { @Override public JPanel initWindowPane(double preferredWidth) { - ColorSelectPane colorPane = new ColorSelectPane(); + NewColorSelectPane colorPane = new NewColorSelectPane(); colorPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { - ColorSelectPane source = (ColorSelectPane)e.getSource(); + NewColorSelectPane source = (NewColorSelectPane)e.getSource(); setSelectObject(source.getColor()); hidePopupMenu(); } diff --git a/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java b/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java index 9d3c31bd46..611953a20b 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java +++ b/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java @@ -1,10 +1,12 @@ package com.fr.design.style.background; +import java.awt.Color; import java.awt.Graphics; +import java.awt.Insets; import java.awt.geom.Rectangle2D; import javax.swing.JComponent; - +import com.fr.design.border.UIRoundedBorder; import com.fr.general.Background; /** @@ -18,7 +20,7 @@ public class BackgroundJComponent extends JComponent { protected Background background ; public BackgroundJComponent() { - + this.setBorder(new UIRoundedBorder(Color.decode("#999999"), 2, 2)); } public BackgroundJComponent(Background background) { @@ -29,16 +31,23 @@ public class BackgroundJComponent extends JComponent { super.paint(g); if(background != null && this.getSize().getWidth() > 0 && this.getSize().getHeight() > 0) { - background.paint(g, new Rectangle2D.Double(1, 1, this.getSize().getWidth() - 2, - this.getSize().getHeight() - 2)); - } + background.paint(g, new Rectangle2D.Double(2, 2, this.getSize().getWidth() - 4, + this.getSize().getHeight() - 4)); + } + } - - public void setEmptyBackground() { + + + public void setEmptyBackground() { this.background = null; } public void setSelfBackground(Background background) { this.background = background; } + + @Override + public Insets getInsets() { + return new Insets(0,0,0,0); + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java b/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java index 593250ca8c..ebaf04e32a 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java +++ b/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java @@ -8,6 +8,7 @@ import java.awt.Dimension; import java.util.HashMap; import java.util.Map; +import com.fr.base.background.ColorBackground; import com.fr.design.gui.frpane.UITabbedPane; import javax.swing.event.ChangeEvent; @@ -16,6 +17,9 @@ import javax.swing.event.EventListenerList; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.dialog.BasicPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.style.background.impl.ColorBackgroundPane; +import com.fr.design.style.background.impl.ColorNoThemeBackgroundPane; import com.fr.general.Background; import com.fr.log.FineLoggerFactory; @@ -27,14 +31,15 @@ public class BackgroundPane extends BasicPane { private EventListenerList eventChangeList = new EventListenerList(); protected Map cacheMap = new HashMap<>(); - + //需求说: 如果是浏览器背景, 隐藏掉几个button public BackgroundPane() { + BackgroundFactory.getWrapper(ColorBackground.class).setType( + DesignerContext.getDesignerFrame().isServerConfig() ? ColorNoThemeBackgroundPane.class : ColorBackgroundPane.class); this.initComponents(); this.setPreferredSize(new Dimension(400, 300)); } - protected void initComponents() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/AbstractComponentPopBox.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/AbstractComponentPopBox.java new file mode 100644 index 0000000000..ef647f2bde --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/AbstractComponentPopBox.java @@ -0,0 +1,243 @@ +package com.fr.design.style.background.gradient; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.style.background.BackgroundJComponent; +import com.fr.general.Background; + +import javax.swing.JComponent; +import javax.swing.JPanel; +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; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.AWTEventListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-24 + */ +public abstract class AbstractComponentPopBox extends JComponent { + + protected BackgroundJComponent displayComponent; + + private JWindow selectPopupWindow; + private boolean isWindowEventInit = false; + private static int GAP = 2; + private static int GAP2 = 20; + + private List changeListenerList = new ArrayList(); + + MouseAdapter mouseListener = new MouseAdapter() { + public void mousePressed(MouseEvent evt) { + showPopupMenu(); + } + + + }; + + AWTEventListener awt = new AWTEventListener() { + public void eventDispatched(AWTEvent event) { + if (event instanceof MouseEvent) { + MouseEvent evt = (MouseEvent) event; + if (evt.getClickCount() > 0) { + mouseClick(evt); + } + } + } + }; + + protected void showPopupMenu() { + if (selectPopupWindow != null && selectPopupWindow.isVisible()) { + hidePopupMenu(); + return; + } + + if (!this.isEnabled()) { + return; + } + Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + + selectPopupWindow = this.getControlWindow(); + + Point convertPoint = new Point(0, 0); + + // e: 将点(0,0)从ColorSelectionPane的坐标系统转换到屏幕坐标. + SwingUtilities.convertPointToScreen(convertPoint, this); + int y = convertPoint.y + this.getSize().height; + int x = convertPoint.x; + int h = y + selectPopupWindow.getHeight(); + int width = x + selectPopupWindow.getWidth(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + if (h > screenSize.height) { + y = y - selectPopupWindow.getHeight() - GAP2;// 超过屏幕高度了 + } + + if (width > screenSize.width) { + x = screenSize.width - selectPopupWindow.getWidth(); + } + selectPopupWindow.setLocation(x, y); + + selectPopupWindow.setVisible(true); + + //wei : 为了点击别的地方下拉颜色窗口消失 + MouseAdapter parentMouseListener = new MouseAdapter() { + public void mousePressed(MouseEvent evt) { + mouseClick(evt); + } + }; + if (!this.isWindowEventInit && SwingUtilities.getAncestorOfClass(GradientBackgroundPane.class, this) != null) { + SwingUtilities.getAncestorOfClass(GradientBackgroundPane.class, this).addMouseListener(parentMouseListener); + this.isWindowEventInit = true; + } + } + + private void mouseClick(MouseEvent evt) { + Point point = new Point((int) (evt.getLocationOnScreen().getX()), (int) evt.getLocationOnScreen().getY()); + Dimension popBoxD = AbstractComponentPopBox.this.getSize(); + try { + Point popBoxP = AbstractComponentPopBox.this.getLocationOnScreen(); + Dimension popMenuD = this.getControlWindow().getSize(); + Point popMenuP = this.getControlWindow().getLocation(); + Rectangle popBoxRect = new Rectangle(popBoxP, popBoxD); + Rectangle popMenuRect = new Rectangle(popMenuP, popMenuD); + if (!popBoxRect.contains(point) && !popMenuRect.contains(point)) { + this.hidePopupMenu(); + } + } catch (Exception ignore) { + this.hidePopupMenu(); + } + } + + protected void hidePopupMenu() { + if (selectPopupWindow != null) { + selectPopupWindow.setVisible(false); + } + + selectPopupWindow = null; + Toolkit.getDefaultToolkit().removeAWTEventListener(awt); + } + + protected JWindow getControlWindow() { + //find parent. + if (this.selectPopupWindow == null) { + Window parentWindow = SwingUtilities.windowForComponent(this); + if (parentWindow != null) { + this.selectPopupWindow = new AbstractComponentPopBox.SelectControlWindow(parentWindow); + } + + selectPopupWindow.addMouseListener(new MouseAdapter() { + public void mouseExited(MouseEvent evt) { + int x = evt.getLocationOnScreen().x; + int y = evt.getLocationOnScreen().y; + + if (selectPopupWindow != null) { + double desValue = 2; + Rectangle rectangle = selectPopupWindow.getBounds(); + boolean b1 = x < rectangle.x + desValue || x >= rectangle.x + rectangle.width - desValue; + boolean b2 = y > rectangle.y + rectangle.height - desValue;//避免了鼠标下移刚进入selectPopupWindow的过程中弹出框隐藏,上移移出后由AbstractPopBox的mouseListener处理 + if (b1 || b2) { + hidePopupMenu(); + } + } + } + }); + } + + return selectPopupWindow; + } + + /** + * 添加事件 + * + * @param changeListener 事件 + */ + public void addSelectChangeListener(ChangeListener changeListener) { + this.changeListenerList.add(changeListener); + } + + /** + * 删除事件 + * + * @param changeListener 事件 + */ + public void removeSelectChangeListener(ChangeListener changeListener) { + this.changeListenerList.remove(changeListener); + } + + /** + * 响应事件 + */ + public void fireChangeListener() { + if (!changeListenerList.isEmpty()) { + ChangeEvent evt = new ChangeEvent(this); + for (int i = 0; i < changeListenerList.size(); i++) { + this.changeListenerList.get(i).stateChanged(evt); + } + } + } + + /** + * 待说明 + * + * @param background 背景 + */ + public void fireDisplayComponent(Background background) { + if (displayComponent != null) { + displayComponent.setSelfBackground(background); + } + fireChangeListener(); + this.repaint(); + } + + /** + * 初始化弹出框的面板 + * + * @param preWidth 宽度 + * @return 弹出面板 + */ + public abstract JPanel initWindowPane(double preWidth); + + private class SelectControlWindow extends JWindow { + private static final long serialVersionUID = -5776589767069105911L; + + public SelectControlWindow(Window paranet) { + super(paranet); + this.initComponents(); + } + + public void initComponents() { + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.setContentPane(defaultPane); + +// defaultPane.setBorder(UIManager.getBorder("PopupMenu.border")); + + if (displayComponent != null) { + defaultPane.add(initWindowPane(displayComponent.getPreferredSize().getWidth())); + } else { + defaultPane.add(initWindowPane(20)); + } + this.pack(); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + AbstractComponentPopBox.this.repaint(); + } + } + + protected boolean isPopupVisible() { + return selectPopupWindow == null ? false : selectPopupWindow.isVisible(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBar.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBar.java index 8c502114bf..06a217f230 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBar.java +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBar.java @@ -14,6 +14,12 @@ public class FixedGradientBar extends GradientBar { super(minvalue, maxvalue); } + @Override + protected void clickButton(int select) { + setColor(getList().get(select).getColorInner()); + super.clickButton(select); + } + @Override protected void addMouseDragListener() { //不添加拖拽事件 diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBarNoTheme.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBarNoTheme.java new file mode 100644 index 0000000000..d45bd62f79 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBarNoTheme.java @@ -0,0 +1,39 @@ +package com.fr.design.style.background.gradient; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.style.color.ColorSelectDetailPane; +import com.fr.design.style.color.ColorSelectDialog; + +import javax.swing.JPanel; +import java.awt.Color; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-19 + */ +public class FixedGradientBarNoTheme extends FixedGradientBar { + + + public FixedGradientBarNoTheme(int minvalue, int maxvalue) { + super(minvalue, maxvalue); + } + + protected void clickButton(int select) { + ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); + Color selectColor = getList().get(select).getColorInner() == null ? Color.WHITE : getList().get(select).getColorInner(); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, selectColor, FixedGradientBarNoTheme.this, true); + Color color = FixedGradientBarNoTheme.this.getColor(); + if (color != null) { + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + getList().get(select).setColorInner(color); + stateChanged(); + FixedGradientBarNoTheme.this.repaint(); + } + } + + public JPanel initWindowPane(double preWidth) { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java index b088864c0f..97a19f4643 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java @@ -1,18 +1,16 @@ package com.fr.design.style.background.gradient; -import com.fr.design.DesignerEnvManager; +import com.fr.base.background.ColorBackground; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import com.fr.design.gui.itextfield.UINumberField; -import com.fr.design.mainframe.DesignerContext; import com.fr.design.style.color.ColorCell; -import com.fr.design.style.color.ColorSelectDetailPane; -import com.fr.design.style.color.ColorSelectDialog; import com.fr.design.style.color.ColorSelectable; +import com.fr.design.style.color.NewColorSelectPane; import com.fr.stable.AssistUtils; - import com.fr.stable.os.OperatingSystem; -import javax.swing.JComponent; + +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; @@ -33,8 +31,8 @@ import java.awt.geom.Point2D; /** * TODO:面板缩放的功能没有考虑(就是尾值过大,导致超过界面显示的情况),原来的那个实现完全是个BUG。要缩放的情况也比较少,就干脆以后弄吧 */ -public class GradientBar extends JComponent implements UIObserver, ColorSelectable { - +public class GradientBar extends AbstractComponentPopBox implements UIObserver, ColorSelectable { + private NewColorSelectPane colorPane; /** * */ @@ -88,6 +86,22 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab iniListener(); } + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + public void updateColor(Color begin, Color end) { p1.setColorInner(begin); p2.setColorInner(end); @@ -106,15 +120,7 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab } if (select >= 0) { - ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); - ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, Color.WHITE, GradientBar.this); - Color color = GradientBar.this.getColor(); - if (color != null) { - DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); - list.get(select).setColorInner(color); - stateChanged(); - GradientBar.this.repaint(); - } + clickButton(select); } GradientBar.this.repaint(); } @@ -122,6 +128,37 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab }); } + protected void clickButton(int select) { + setIndex(select); + showPopupMenu(); + } + + public JPanel initWindowPane(double preferredWidth) { + // 下拉的时候重新生成面板,刷新最近使用颜色 + colorPane = new NewColorSelectPane(false) { + @Override + public void setVisible(boolean b) { + super.setVisible(b); + } + + @Override + protected boolean selectRealTime() { + return false; + } + }; + colorPane.setColor(getColor()); + colorPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + hidePopupMenu(); + setColor(((NewColorSelectPane) e.getSource()).getColor()); + getList().get(getIndex()).setColorInner(getColor()); + fireDisplayComponent(ColorBackground.getInstance(getColor())); + GradientBar.this.stateChanged(); + } + }); + return colorPane; + } + protected void addMouseDragListener() { this.addMouseMotionListener(new MouseAdapter() { public void mouseDragged(MouseEvent e) { @@ -132,10 +169,10 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab break; } } - if(OperatingSystem.isLinux() && AssistUtils.equals(oldIndex,index)){ - if(Math.abs(p1.getX() - e.getX()) > Math.abs(p2.getX() - e.getX())){ + if (OperatingSystem.isLinux() && AssistUtils.equals(oldIndex, index)) { + if (Math.abs(p1.getX() - e.getX()) > Math.abs(p2.getX() - e.getX())) { index = 1; - }else{ + } else { index = 0; } } diff --git a/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java index 62a08a948a..37fef6e613 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java +++ b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java @@ -19,10 +19,14 @@ public class ColorBackgroundPane extends BackgroundDetailPane { public ColorBackgroundPane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - detailColorSelectPane = new DetailColorSelectPane(); + detailColorSelectPane = createColorSelectPane(); this.add(detailColorSelectPane, BorderLayout.CENTER); } + protected DetailColorSelectPane createColorSelectPane(){ + return new DetailColorSelectPane(); + } + public void populate(Background background) { if (background instanceof ColorBackground) { ColorBackground colorBackgroud = (ColorBackground) background; diff --git a/designer-base/src/main/java/com/fr/design/style/background/impl/ColorNoThemeBackgroundPane.java b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorNoThemeBackgroundPane.java new file mode 100644 index 0000000000..01ee19a67e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorNoThemeBackgroundPane.java @@ -0,0 +1,10 @@ +package com.fr.design.style.background.impl; + +import com.fr.design.style.color.DetailColorSelectPane; + +public class ColorNoThemeBackgroundPane extends ColorBackgroundPane{ + + protected DetailColorSelectPane createColorSelectPane(){ + return new DetailColorSelectPane(false); + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java b/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java index fcdc594b5f..ad99b90835 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java @@ -1,13 +1,14 @@ package com.fr.design.style.color; import com.fr.base.BaseUtils; -import com.fr.base.background.ColorBackground; +import com.fr.design.DesignerEnvManager; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.VerticalFlowLayout; -import com.fr.design.style.AbstractSelectBox; +import com.fr.design.mainframe.DesignerContext; +import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -75,7 +76,7 @@ public class ColorAdjustPane extends JPanel implements UIObserver { int size = colorButtons.size(); Color[] colors = new Color[size]; for (int i = 0; i < size; i++) { - colors[i] = colorButtons.get(i).getSelectObject(); + colors[i] = colorButtons.get(i).getColor(); } return colors; } @@ -169,7 +170,7 @@ public class ColorAdjustPane extends JPanel implements UIObserver { } - private class AddColorButton extends AbstractSelectBox { + private class AddColorButton extends JComponent implements ColorSelectable { BufferedImage image = BaseUtils.readImageWithCache("/com/fr/design/images/buttonicon/add.png"); @@ -195,43 +196,38 @@ public class ColorAdjustPane extends JPanel implements UIObserver { return new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - showPopupMenu(); + //打开颜色选择面板 + showDialog(); } }; } - public JPanel initWindowPane(double preferredWidth) { - // 下拉的时候重新生成面板,刷新最近使用颜色 - ColorSelectPane colorPane = new ColorSelectPane(false) { - public void setVisible(boolean b) { - super.setVisible(b); - } + private void showDialog() { + ColorSelectDetailPane pane = new ColorSelectDetailPane(getColor()); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, getColor(), this, true); + Color color = this.getColor(); + if (color != null) { + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + } + } - protected boolean selectRealTime() { - return false; - } - }; - colorPane.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - hidePopupMenu(); - Color color = ((ColorSelectPane) e.getSource()).getColor(); - fireDisplayComponent(ColorBackground.getInstance(color)); - if(colorButtons.size() < MAX_BUTTON) { - colorButtons.add(createColorButton(color)); - } - ColorAdjustPane.this.stateChanged(); - relayout(); - } - }); - return colorPane; + @Override + public void setColor(Color color) { + if (colorButtons.size() < MAX_BUTTON) { + colorButtons.add(createColorButton(color)); + } + ColorAdjustPane.this.stateChanged(); + relayout(); } - public Color getSelectObject() { - return null; + @Override + public Color getColor() { + return Color.WHITE; } - public void setSelectObject(Color color) { + @Override + public void colorSetted(ColorCell colorCell) { } } -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java b/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java index a052f99f13..5ad794c79c 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java @@ -1,11 +1,10 @@ package com.fr.design.style.color; import com.fr.base.BaseUtils; -import com.fr.base.background.ColorBackground; -import com.fr.design.style.AbstractSelectBox; +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.DesignerContext; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; +import javax.swing.JComponent; import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.Dimension; @@ -22,7 +21,7 @@ import java.awt.image.BufferedImage; * @version 10.0 * Created by Bjorn on 2020-03-06 */ -public class ColorButton extends AbstractSelectBox { +public class ColorButton extends JComponent implements ColorSelectable { private static final double DEL_WIDTH = 7; @@ -34,8 +33,6 @@ public class ColorButton extends AbstractSelectBox { private boolean isMoveOn = false; - private ColorSelectPane colorPane; - private boolean lastButton; private ChangeListener changeListener; @@ -111,40 +108,24 @@ public class ColorButton extends AbstractSelectBox { } if (e.getX() >= bounds.getWidth() - DEL_WIDTH && e.getY() <= DEL_WIDTH) { deleteButton(); - hidePopupMenu(); return; } } //打开颜色选择面板 - showPopupMenu(); + showDialog(); } - public JPanel initWindowPane(double preferredWidth) { - // 下拉的时候重新生成面板,刷新最近使用颜色 - colorPane = new ColorSelectPane(false) { - @Override - public void setVisible(boolean b) { - super.setVisible(b); - } - - @Override - protected boolean selectRealTime() { - return false; - } - }; - colorPane.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - hidePopupMenu(); - color = ((ColorSelectPane) e.getSource()).getColor(); - fireDisplayComponent(ColorBackground.getInstance(color)); - ColorButton.this.stateChanged(); - } - }); - return colorPane; + private void showDialog() { + ColorSelectDetailPane pane = new ColorSelectDetailPane(getColor()); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, getColor(), this, true); + Color color = this.getColor(); + if (color != null) { + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + } } public void stateChanged() { - if (changeListener != null) { + if (changeListener != null) { changeListener.stateChanged(null); } } @@ -153,26 +134,18 @@ public class ColorButton extends AbstractSelectBox { this.changeListener = changeListener; } + @Override + public void setColor(Color color) { + this.color = color; + this.stateChanged(); + } - /** - * 获取当前选中的颜色 - * - * @return 当前选中的颜色 - */ - public Color getSelectObject() { + @Override + public Color getColor() { return this.color; } - /** - * 设置选中的颜色 - * - * @param color 颜色 - */ - public void setSelectObject(Color color) { - this.color = color; - colorPane.setColor(color); - - fireDisplayComponent(ColorBackground.getInstance(color)); + @Override + public void colorSetted(ColorCell colorCell) { } - -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java b/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java index 06cca51d03..4cc3e41cea 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java @@ -10,6 +10,7 @@ import java.awt.event.MouseEvent; import javax.swing.JComponent; +import com.fr.design.DesignerEnvManager; import com.fr.design.constants.UIConstants; import com.fr.general.ComparatorUtils; @@ -76,17 +77,21 @@ public class ColorCell extends JComponent implements ColorSelectable { g.fillRect(b.left, b.top, right, bottom); } - if (colorSelectable.getColor() != null - && ComparatorUtils.equals(colorSelectable.getColor(), this.getColor())) { + if (isColorSelected(colorSelectable)) { g.setColor(UIConstants.LINE_COLOR); g.drawRect(b.left, b.top, right - 1, bottom - 1); } } + protected boolean isColorSelected(ColorSelectable colorSelectable){ + return colorSelectable.getColor() != null + && ComparatorUtils.equals(colorSelectable.getColor(), this.getColor()); + } + /** * 鼠标事件处理 - * @param 鼠标事件 + * @param e 鼠标事件 */ public void processMouseEvent(MouseEvent e) { if (!isEnabled()) { @@ -96,6 +101,10 @@ public class ColorCell extends JComponent implements ColorSelectable { if (e == null || e.getID() == MouseEvent.MOUSE_RELEASED) { colorSelectable.setColor(this.getColor()); colorSelectable.colorSetted(this); + if (this.getColor() != null) { + int rgb = this.getColor().getRGB(); + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(new Color(rgb)); + } } if (e != null) { diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java index 4ee3a119ea..b84173f1db 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java @@ -38,6 +38,10 @@ public abstract class ColorControlWindow extends JPopupMenu { return selectionPopupPane.getColor(); } + public void setColor(Color color) { + selectionPopupPane.setColor(color); + } + public PopupHider getPopupHider() { return popupHider; } @@ -58,15 +62,28 @@ public abstract class ColorControlWindow extends JPopupMenu { } protected void initSelectionPopupPane(boolean isSupportTransparent) { - selectionPopupPane = new ColorSelectionPopupPane(isSupportTransparent); + selectionPopupPane = createColorSelectionPopupPane(isSupportTransparent); this.add(selectionPopupPane, BorderLayout.CENTER); } - class ColorSelectionPopupPane extends NewColorSelectPane { + protected ColorSelectionPopupPane createColorSelectionPopupPane(boolean isSupportTransparent) { + return new ColorSelectionPopupPane(isSupportTransparent, supportThemeColor()); + } + + protected boolean supportThemeColor(){ + return true; + } + + protected class ColorSelectionPopupPane extends NewColorSelectPane { private static final long serialVersionUID = 7822856562329146354L; - public ColorSelectionPopupPane(boolean isSupportTransparent) { - super(isSupportTransparent); + public ColorSelectionPopupPane(boolean isSupportTransparent, boolean isSupportThemeColor) { + this(isSupportTransparent, isSupportThemeColor, null); + } + + public ColorSelectionPopupPane(boolean isSupportTransparent, boolean isSupportThemeColor, Color color) { + super(isSupportTransparent, isSupportThemeColor); + this.setColor(color); this.addChangeListener(new ChangeListener() { @Override @@ -77,7 +94,7 @@ public abstract class ColorControlWindow extends JPopupMenu { } @Override - protected void doTransparent() { + public void doTransparent() { popupHider.hidePopupMenu(); super.doTransparent(); } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java index cbb0e97eaa..01351bfedb 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java @@ -39,6 +39,11 @@ public abstract class ColorControlWindowWithAuto extends ColorControlWindow { return selectionPopupPaneWithAuto.getColor(); } + public void setColor(Color color) { + selectionPopupPaneWithAuto.setColor(color); + } + + protected void initSelectionPopupPane(boolean isSupportTransparent) { selectionPopupPaneWithAuto = new ColorSelectionPopupPaneWithAuto(isSupportTransparent); this.add(selectionPopupPaneWithAuto, BorderLayout.CENTER); @@ -61,7 +66,7 @@ public abstract class ColorControlWindowWithAuto extends ColorControlWindow { }); } - protected void doTransparent() { + public void doTransparent() { getPopupHider().hidePopupMenu(); setColor(null); } @@ -114,11 +119,10 @@ public abstract class ColorControlWindowWithAuto extends ColorControlWindow { } } + @Override public Dimension getPreferredSize() { - if (isSupportTransparent()) { - return new Dimension(super.getPreferredSize().width, TRANSPARENT_WINDOW_HEIGHT + BUTTON_HEIGHT); - } - return new Dimension(super.getPreferredSize().width, WINDOW_HEIGHT + BUTTON_HEIGHT); + Dimension dimension = super.getPreferredSize(); + return new Dimension(dimension.width, dimension.height + BUTTON_HEIGHT); } } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java b/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java index b22104f283..0ab0d8f381 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java @@ -3,7 +3,7 @@ package com.fr.design.style.color; import java.awt.Color; public interface ColorFactory { - + public static final Color MenuColors[] = { Color.black, new Color(153, 51, 0), @@ -71,5 +71,18 @@ public interface ColorFactory { new Color(0, 0, 255) }; - -} \ No newline at end of file + public static final Color STANDARD_COLORS[] = { + new Color(234, 68, 49), + new Color(179, 96, 36), + new Color(232, 147, 37), + new Color(109, 214, 50), + new Color(51, 147, 219), + new Color(56, 54, 179), + new Color(93, 54, 179), + new Color(154, 54, 179), + new Color(127, 76, 217), + new Color(179, 36, 102) + }; + + +} diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java index d2a8245445..3ec124b135 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java @@ -17,7 +17,7 @@ public class ColorSelectBox extends AbstractSelectBox implements UIObserv private static final long serialVersionUID = 2782150678943960557L; private Color color; - private ColorSelectPane colorPane; + private NewColorSelectPane colorPane; private UIObserverListener uiObserverListener; public ColorSelectBox(int preferredWidth) { @@ -40,12 +40,8 @@ public class ColorSelectBox extends AbstractSelectBox implements UIObserv } } - protected ColorSelectPane getColorSelectPane(){ - return new ColorSelectPane() { - public void setVisible(boolean b) { - super.setVisible(b); - } - }; + protected NewColorSelectPane getColorSelectPane(){ + return new NewColorSelectPane(); } /** @@ -56,14 +52,14 @@ public class ColorSelectBox extends AbstractSelectBox implements UIObserv public JPanel initWindowPane(double preferredWidth) { // 下拉的时候重新生成面板,刷新最近使用颜色 colorPane = getColorSelectPane(); + colorPane.setColor(color); colorPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { hidePopupMenu(); - color = ((ColorSelectPane) e.getSource()).getColor(); + color = ((NewColorSelectPane) e.getSource()).getColor(); fireDisplayComponent(ColorBackground.getInstance(color)); } }); - colorPane.setColor(color); return colorPane; } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java index 13d8998222..3756fc627e 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java @@ -36,6 +36,10 @@ public class ColorSelectDetailPane extends BasicPane { return selectedPanel; } + private SwatchChooserPanel swatchChooserPanel; + + private CustomChooserPanel customChooserPanel; + public void setSelectedPanel(JColorChooser selectedPanel) { this.selectedPanel = selectedPanel; } @@ -69,9 +73,9 @@ public class ColorSelectDetailPane extends BasicPane { selectedPanel.setPreferredSize(new Dimension(selectedPanel.getWidth(), SELECT_PANEL_HEIGHT)); selectedPanel.setPreviewPanel(new JPanel()); - AbstractColorChooserPanel swatchChooserPanel = new SwatchChooserPanel(); - AbstractColorChooserPanel customChooserPanel = new CustomChooserPanel(); - selectedPanel.setChooserPanels(new AbstractColorChooserPanel[]{swatchChooserPanel, customChooserPanel}); + swatchChooserPanel = new SwatchChooserPanel(); + customChooserPanel = new CustomChooserPanel(); + selectedPanel.setChooserPanels(new AbstractColorChooserPanel[]{customChooserPanel, swatchChooserPanel}); this.add(selectedPanel, BorderLayout.NORTH); // 最近使用面板 @@ -98,4 +102,8 @@ public class ColorSelectDetailPane extends BasicPane { previewPanel.add(colorChooserPreview); this.add(previewPanel, BorderLayout.SOUTH); } + + public void populate(Color color){ + customChooserPanel.setColor(color); + } } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java index 33eb6dbf15..23dcf8cc36 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java @@ -1,6 +1,7 @@ package com.fr.design.style.color; import com.fr.base.chart.BaseChartCollection; +import com.fr.design.DesignerEnvManager; import com.fr.design.gui.chart.MiddleChartDialog; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.utils.gui.GUICoreUtils; @@ -77,6 +78,7 @@ public class ColorSelectDialog extends MiddleChartDialog{ this.okListener = (ColorTracker) okListener; this.seletePane = seletePane; initComponent(); + this.pane.populate(initialColor); } private void initComponent() { @@ -100,7 +102,9 @@ public class ColorSelectDialog extends MiddleChartDialog{ ok.setActionCommand("OK"); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - seletePane.setColor(okListener.getColor()); + Color color = okListener.getColor(); + seletePane.setColor(color); + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); doOK(); } }); diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java index 68c1b2b992..452c5fe30a 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java @@ -30,6 +30,7 @@ import java.awt.event.MouseEvent; /** * The pane used to select color */ +@Deprecated public class ColorSelectPane extends TransparentPane implements ColorSelectable { private static final long serialVersionUID = -8634152305687249392L; diff --git a/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java b/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java index 4245c1293b..5d7e81487e 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java @@ -29,10 +29,14 @@ import com.fr.design.dialog.BasicPane; * Often used for foreground selection. */ public class DetailColorSelectPane extends BasicPane { - private ColorSelectPane colorSelectPane; + private NewColorSelectPane colorSelectPane; private UILabel colorPreviewLabel; - public DetailColorSelectPane() { + public DetailColorSelectPane(){ + this(true); + } + + public DetailColorSelectPane(boolean supportTheme) { this.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4)); this.setLayout(FRGUIPaneFactory.createBorderLayout()); @@ -44,7 +48,7 @@ public class DetailColorSelectPane extends BasicPane { defaultPane.add(Box.createHorizontalStrut(4)); JPanel colorSelectContainPane =FRGUIPaneFactory.createBorderLayout_L_Pane(); defaultPane.add(colorSelectContainPane); - colorSelectPane = new ColorSelectPane(); + colorSelectPane = NewColorSelectPane.createColorSelectPaneWithTheme(supportTheme); colorSelectContainPane.add(colorSelectPane, BorderLayout.NORTH); defaultPane.add(Box.createHorizontalStrut(8)); diff --git a/designer-base/src/main/java/com/fr/design/style/color/FineColorCell.java b/designer-base/src/main/java/com/fr/design/style/color/FineColorCell.java new file mode 100644 index 0000000000..1007b3f849 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/color/FineColorCell.java @@ -0,0 +1,38 @@ +package com.fr.design.style.color; + +import com.fr.base.FineColor; +import com.fr.general.ComparatorUtils; + +import java.awt.Color; + +public class FineColorCell extends ColorCell { + private final int x; + private final int y; + + public FineColorCell(Color color, ColorSelectable colorSelectable) { + this(color, colorSelectable, -1, -1); + } + + public FineColorCell(Color color, ColorSelectable colorSelectable, int x, int y) { + super(color, colorSelectable); + this.x = x; + this.y = y; + } + + public Color getColor() { + Color color = super.getColor(); + FineColor fineColor = new FineColor(x, y, color); + return fineColor; + } + + + protected boolean isColorSelected(ColorSelectable colorSelectable) { + Color color = colorSelectable.getColor(); + if (color instanceof FineColor) { + return super.isColorSelected(colorSelectable) && (x == ((FineColor) color).getHor()) && (y == ((FineColor) color).getVer()); + } + return super.isColorSelected(colorSelectable); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java index 4f291c6398..04d368e6bc 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java @@ -20,7 +20,7 @@ public class NewColorSelectBox extends AbstractSelectBox implements UIObs private static final long serialVersionUID = 2782150678943960557L; private Color color; - private NewColorSelectPane colorPane = new NewColorSelectPane(); + private NewColorSelectPane colorPane = new NewColorSelectPane(false); private UIObserverListener uiObserverListener; private String newColorSelectBoxName = ""; private GlobalNameListener globalNameListener = null; @@ -58,7 +58,8 @@ public class NewColorSelectBox extends AbstractSelectBox implements UIObs */ public JPanel initWindowPane(double preferredWidth) { // 下拉的时候重新生成面板,以刷新最近使用颜色 - colorPane = new NewColorSelectPane(); + colorPane = new NewColorSelectPane(false); + colorPane.setColor(this.getSelectObject()); colorPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { hidePopupMenu(); diff --git a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java index 6c21c10cba..22be3f4dcf 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java @@ -1,16 +1,23 @@ package com.fr.design.style.color; +import com.fr.base.FineColor; +import com.fr.base.theme.FineColorDeriveState; +import com.fr.base.theme.TemplateTheme; import com.fr.design.DesignerEnvManager; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicPane; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; import javax.swing.BorderFactory; -import javax.swing.Box; +import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -19,11 +26,10 @@ import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.List; /** @@ -33,56 +39,78 @@ import java.util.ArrayList; public class NewColorSelectPane extends BasicPane implements ColorSelectable { private static final long serialVersionUID = -8634152305687249392L; - private Color color = null; // color + private static final int WIDTH = 216; + private static final int HEIGHT = 230; + + private static final int DEFAULT_COLOR_HOR_INTERVAL = 4; + //颜色衍生的数量 + private static final int DEFAULT_DERIVE_COUNT = 5; + + private FineColor color = null; // color // color setting action. - private ArrayList colorChangeListenerList = new ArrayList(); + private final ArrayList colorChangeListenerList = new ArrayList<>(); // 是否支持透明 private boolean isSupportTransparent; - public final static int TRANSPARENT_WINDOW_HEIGHT = 165; - public final static int WINDOW_HEIGHT = 150; + private boolean isSupportThemeColor; // 最近使用颜色 - private UsedColorPane usedColorPane; + private final NewUsedColorPane usedColorPane; + private final JPanel menuColorPane; + private ColorCell[][] themeColorCellGrid; + + public static NewColorSelectPane createColorSelectPaneWithTheme(boolean supportTheme) { + return new NewColorSelectPane(true, supportTheme); + } /** * Constructor. */ public NewColorSelectPane() { - this(false); + this(true); + } + + public NewColorSelectPane(boolean isSupportTransparent) { + this(isSupportTransparent, true); } /** * Constructor. */ - NewColorSelectPane(boolean isSupportTransparent) { + public NewColorSelectPane(boolean isSupportTransparent, boolean isSupportThemeColor) { + this.isSupportThemeColor = isSupportThemeColor; initSelectButton(isSupportTransparent); - // center JPanel centerPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + centerPane.setBorder(BorderFactory.createEmptyBorder(10, 6, 0, 6)); this.add(centerPane, BorderLayout.CENTER); - // 第一行 - JPanel row1Pane = new JPanel(FRGUIPaneFactory.createBorderLayout()); - row1Pane.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 0)); - row1Pane.setPreferredSize(new Dimension(135, 16)); // 宽度为 16 * 8 + 7 - centerPane.add(row1Pane); - // 最近使用 - usedColorPane = new UsedColorPane(1, 8, 1, this, true, false); - usedColorPane.getPane().setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 8)); - row1Pane.add(usedColorPane.getPane()); + menuColorPane = getMenuColorPane(); - JPanel menuColorPane1 = new JPanel(); - centerPane.add(menuColorPane1); - - menuColorPane1.setLayout(new GridLayout(5, 8, 1, 1)); - menuColorPane1.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8)); - for (int i = 0; i < ColorFactory.MenuColors.length; i++) { - menuColorPane1.add(new ColorCell(ColorFactory.MenuColors[i], this)); + if (isSupportThemeColor) { + JPanel themePane = initThemeColorPane(); + centerPane.add(themePane); + } else { + centerPane.add(menuColorPane); + initMenuColorPane(); } - centerPane.add(Box.createVerticalStrut(1)); + JPanel standardColorPane = new JPanel(new BorderLayout(0, 5)); + standardColorPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + standardColorPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Standard_Color")), BorderLayout.CENTER); + centerPane.add(standardColorPane); + JPanel colorSelectPane = createStandardColorPane(); + standardColorPane.add(colorSelectPane, BorderLayout.SOUTH); + + // 增加最近使用 pane + JPanel row1Pane = new JPanel(new BorderLayout(0, 5)); + row1Pane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + row1Pane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Used")), BorderLayout.CENTER); + centerPane.add(row1Pane); + // 最近使用 + usedColorPane = new NewUsedColorPane(9, this, selectRealTime()); + row1Pane.add(usedColorPane.getPane(), BorderLayout.SOUTH); // mod by anchore 16/11/16 final UIButton customButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_More_Color")); @@ -99,12 +127,123 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { }); customButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - JPanel centerPane1 = FRGUIPaneFactory.createBorderLayout_S_Pane(); - centerPane1.setBorder(BorderFactory.createEmptyBorder(2, 8, 0, 8)); - centerPane1.add(customButton, BorderLayout.NORTH); + JPanel centerPane1 = new JPanel(new BorderLayout(0, 0)); + centerPane1.setBorder(BorderFactory.createEmptyBorder(8, 0, 9, 0)); + centerPane1.add(customButton, BorderLayout.CENTER); + customButton.setPreferredSize(new Dimension(197, 20)); centerPane.add(centerPane1); } + private JPanel createStandardColorPane() { + JPanel jPanel = new JPanel(new GridLayout(1, 10, DEFAULT_COLOR_HOR_INTERVAL, 0)); + Color[] colorArray = ColorFactory.STANDARD_COLORS; + for (int i = 0; i < colorArray.length; i++) { + jPanel.add(new ColorCell(colorArray[i], this)); + } + return jPanel; + } + + private JPanel initThemeColorPane() { + menuColorPane.removeAll(); + JPanel themeColorPane = new JPanel(new BorderLayout(0, 5)); + themeColorPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + themeColorPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Theme_Color")), BorderLayout.CENTER); + + themeColorPane.add(menuColorPane, BorderLayout.SOUTH); + + menuColorPane.setLayout(new BorderLayout(0, 10)); + JPanel northPane = new JPanel(new GridLayout(1, 8, DEFAULT_COLOR_HOR_INTERVAL, 0)); + JPanel centerPane = new JPanel(new GridLayout(1, 8, DEFAULT_COLOR_HOR_INTERVAL, 0)); + menuColorPane.add(northPane, BorderLayout.NORTH); + menuColorPane.add(centerPane, BorderLayout.CENTER); + + Color[] colorArray = new Color[]{ + // 8列主题色 + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + + // 2列灰度色 + Color.decode("#000000"), + Color.decode("#FFFFFF"), + }; + + if (themeColorCellGrid == null) { + themeColorCellGrid = new ColorCell[colorArray.length][DEFAULT_DERIVE_COUNT]; + for (int i = 0; i < colorArray.length; i++) { + ColorCell[] colorCellColumn = new ColorCell[DEFAULT_DERIVE_COUNT]; + boolean isDefaultColor = (i == colorArray.length - 1 || i == colorArray.length - 2); + Color color = colorArray[i]; + Color[] deriveColorArr = FineColorDeriveState.getDeriveColorArr(color, isDefaultColor, DEFAULT_DERIVE_COUNT); + for (int j = 0; j < deriveColorArr.length; j++) { + colorCellColumn[j] = createFineColorCell(deriveColorArr[j], isDefaultColor, i, j); + } + themeColorCellGrid[i] = colorCellColumn; + } + } + + for (int i = 0; i < colorArray.length; i++) { + northPane.add(themeColorCellGrid[i][0]); + } + for (int i = 0; i < colorArray.length; i++) { + JPanel columnPane = new JPanel(new GridLayout(DEFAULT_DERIVE_COUNT - 1, 1, 0, 0)); + for (int j = 1; j < DEFAULT_DERIVE_COUNT; j++) { + columnPane.add(themeColorCellGrid[i][j]); + } + centerPane.add(columnPane); + } + + refreshThemeMenuColorPane(); + return themeColorPane; + } + + private void refreshThemeMenuColorPane() { + List standardColors = null; + if (TemplateThemeProfileDialog.isEditingTheme()) { + standardColors = TemplateThemeProfileDialog.getEditingColorScheme(); + } else { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + if (theme != null) { + standardColors = theme.getColorScheme().getColors(); + } + } + } + if (standardColors == null || standardColors.size() < 8) { + return; + } + + for (int i = 0; i < themeColorCellGrid.length - 2; i++) { + Color color = standardColors.get(i); + Color[] deriveColorArr = FineColorDeriveState.getDeriveColorArr(color, false, DEFAULT_DERIVE_COUNT); + for (int j = 0; j < deriveColorArr.length; j++) { + themeColorCellGrid[i][j].setColor(deriveColorArr[j]); + } + } + } + + + private FineColorCell createFineColorCell(Color color, boolean isDefaultColor, int x, int y) { + return isDefaultColor ? new FineColorCell(color, this) : new FineColorCell(color, this, x, y); + } + + + private void initMenuColorPane() { + menuColorPane.setLayout(new GridLayout(5, 8, DEFAULT_COLOR_HOR_INTERVAL, 0)); + Color[] colorArray = this.getColorArray(); + for (int i = 0; i < colorArray.length; i++) { + Color color = colorArray[i] == null ? UsedColorPane.DEFAULT_COLOR : colorArray[i]; + menuColorPane.add(new ColorCell(color, this)); + } + + } + public boolean isSupportTransparent() { return isSupportTransparent; } @@ -113,20 +252,18 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { isSupportTransparent = supportTransparent; } - protected void initSelectButton(boolean isSupportTransparent){ + protected boolean selectRealTime() { + return true; + } + + protected void initSelectButton(boolean isSupportTransparent) { this.isSupportTransparent = isSupportTransparent; this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setBorder(new UIRoundedBorder(UIConstants.TOOLBAR_BORDER_COLOR, 1, 5)); if (isSupportTransparent) { UIButton transparentButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_ChartF_Transparency")); this.add(transparentButton, BorderLayout.NORTH); - transparentButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - doTransparent(); - } - }); + transparentButton.addActionListener(e -> doTransparent()); } } @@ -134,7 +271,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { /** * 添加监听 * - * @param 监听列表 Add change listener. + * @param changeListener 监听 */ public void addChangeListener(ChangeListener changeListener) { this.colorChangeListenerList.add(changeListener); @@ -151,7 +288,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { * @return 颜色 * Return the color. */ - public Color getColor() { + public FineColor getColor() { return color; } @@ -163,7 +300,6 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { public Color getNotNoneColor() { if (color == null) { setColor(Color.WHITE); - return Color.WHITE; } return color; } @@ -175,27 +311,36 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { */ @Override public void setColor(Color color) { - this.color = color; + if (isSupportThemeColor) { + refreshThemeMenuColorPane(); + } + FineColor fineColor; + if (color == null) { + fineColor = null; + } else { + fineColor = color instanceof FineColor ? (FineColor) color : new FineColor(color); + } + setFineColor(fineColor); + } + + private void setFineColor(FineColor fineColor) { + this.color = fineColor; // fire color change. if (!colorChangeListenerList.isEmpty()) { ChangeEvent evt = new ChangeEvent(this); - for (int i = 0; i < colorChangeListenerList.size(); i++) { - this.colorChangeListenerList.get(i).stateChanged(evt); + for (ChangeListener changeListener : colorChangeListenerList) { + changeListener.stateChanged(evt); } } - DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + this.repaint(); } - /** - * 设置颜色 - * - * @param 颜色位置 - */ @Override public void colorSetted(ColorCell colorCell) { + this.updateUsedColor(); colorCell.repaint(); } @@ -203,18 +348,32 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { setColor(null); } + protected Color[] getColorArray() { + return ColorFactory.MenuColors; + } + + protected JPanel getMenuColorPane() { + return new JPanel(); + } + + protected void customButtonPressed() { // 颜色选择器 ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); - ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, Color.WHITE, this); + Color color = getColor() == null ? Color.WHITE : getColor().getColor(); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, color, this); } @Override public Dimension getPreferredSize() { + int height = HEIGHT; if (isSupportTransparent) { - return new Dimension(super.getPreferredSize().width, TRANSPARENT_WINDOW_HEIGHT); + height += 15; + } + if (isSupportThemeColor) { + height += 25; } - return new Dimension(super.getPreferredSize().width, WINDOW_HEIGHT); + return new Dimension(WIDTH, height); } /** @@ -224,5 +383,69 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { usedColorPane.updateUsedColor(); } + class NewUsedColorPane extends BasicPane { + + // 最近使用面板列数 + private int columns; + + // 最近使用面板 + private JPanel pane; + + private ColorSelectable selectable; + + private boolean setColorRealTime; + + public JPanel getPane() { + return this.pane; + } + + + public NewUsedColorPane(int columns, ColorSelectable selectable, boolean setColorRealTime) { + this.columns = columns; + this.selectable = selectable; + this.setColorRealTime = setColorRealTime; + initialComponents(); + } + + + private void initialComponents() { + int total = columns; + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(1, columns + 1, DEFAULT_COLOR_HOR_INTERVAL, 0)); + panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + //最近使用颜色 + Color[] colors = DesignerEnvManager.getEnvManager().getColorConfigManager().getColors(); + int size = colors.length; + for (int i = 0; i < total; i++) { + Color color = i < size ? colors[size - i - 1] : + UsedColorPane.DEFAULT_COLOR; + panel.add(new ColorCell(color == null ? UsedColorPane.DEFAULT_COLOR : color, selectable)); + } + // 取色按钮 + JButton pickColorButton = PickColorButtonFactory.getPickColorButton(selectable, PickColorButtonFactory.IconType.ICON16, setColorRealTime); + panel.add(pickColorButton); + this.pane = panel; + } + + /** + * 更新最近使用颜色 + */ + public void updateUsedColor() { + int total = columns; + Color[] colors = DesignerEnvManager.getEnvManager().getColorConfigManager().getColors(); + int size = colors.length; + for (int i = 0; i < total; i++) { + ColorCell cell = (ColorCell) this.pane.getComponent(i); + Color color = i < size ? colors[size - i - 1] : UsedColorPane.DEFAULT_COLOR; + cell.setColor(color == null ? UsedColorPane.DEFAULT_COLOR : color); + } + } + + @Override + protected String title4PopupWindow() { + return null; + } + } + } diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java index 6214f1cfa9..425f164543 100644 --- a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java +++ b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java @@ -60,7 +60,7 @@ public class DesignerPushUpdateManager { private String getFullLatestVersion() { try { - String url = CloudCenter.getInstance().acquireUrlByKind("jar10.update"); + String url = CloudCenter.getInstance().acquireUrlByKind("jar11.update"); if(StringUtils.isBlank(url)){ return StringUtils.EMPTY; } diff --git a/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java b/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java index 3c91ebf145..9a849ad4e9 100644 --- a/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java +++ b/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java @@ -350,7 +350,7 @@ public class UpdateMainDialog extends UIDialog { new SwingWorker() { @Override protected JSONObject doInBackground() throws Exception { - return new JSONObject(HttpToolbox.get(CloudCenter.getInstance().acquireUrlByKind("jar10.update"))); + return new JSONObject(HttpToolbox.get(CloudCenter.getInstance().acquireUrlByKind("jar11.update"))); } @Override diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java b/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java index e97a5826a1..3d8252b759 100644 --- a/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java +++ b/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java @@ -37,7 +37,7 @@ public class UpmUtils { } private static String fetchLatestVersion() { - String version = CloudCenter.getInstance().acquireUrlByKind("upm.script.version"); + String version = CloudCenter.getInstance().acquireUrlByKind("upm.script.version.v11"); if (StringUtils.isBlank(version)) { version = "1.0"; } diff --git a/designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java b/designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java index 1d93611386..24134dce18 100644 --- a/designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java @@ -1,11 +1,13 @@ package com.fr.design.utils; import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; import javax.swing.*; import java.awt.*; import java.awt.geom.Rectangle2D; import java.util.ArrayList; +import java.util.List; /** * 工具类,提供常用的工具方法 @@ -151,4 +153,62 @@ public class ComponentUtils { } return false; } + + public static Component findComponentByName(Component container, String componentName) { + Component target = null; + if (container instanceof Container) { + for (Component component: ((Container)container).getComponents()) { + if (componentName.equals(component.getName())) { + return component; + } + if (component instanceof JRootPane) { + JRootPane nestedJRootPane = (JRootPane)component; + target = findComponentByName(nestedJRootPane.getContentPane(), componentName); + } else if (component instanceof Container){ + target = findComponentByName( component, componentName); + } + if (target != null) { + return target; + } + } + } + return null; + } + + public static Component findComponentByClass(Component container, Class clazz) { + Component target = null; + if (container instanceof Container) { + for (Component component: ((Container)container).getComponents()) { + if (clazz.isInstance(component)) { + return component; + } + if (component instanceof JRootPane) { + JRootPane nestedJRootPane = (JRootPane)component; + target = findComponentByClass(nestedJRootPane.getContentPane(), clazz); + } else if (component instanceof Container){ + target = findComponentByClass(component, clazz); + } + if (target != null) { + return target; + } + } + } + return null; + } + + public static List findComponentsByClass(Component container, Class clazz) { + List components= new ArrayList<>(); + if (container instanceof Container) { + for (Component component: ((Container)container).getComponents()) { + if (clazz.isInstance(component)) { + components.add(component); + continue; + } + if (component instanceof Container){ + components.addAll(findComponentsByClass(component, clazz)); + } + } + } + return components; + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/OpenLoadingPane.java b/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java similarity index 78% rename from designer-base/src/main/java/com/fr/design/mainframe/OpenLoadingPane.java rename to designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java index adc30b2bff..d464dec796 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/OpenLoadingPane.java +++ b/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java @@ -1,35 +1,29 @@ -package com.fr.design.mainframe; +package com.fr.design.utils; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.general.IOUtils; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; -import javax.swing.ImageIcon; -import javax.swing.JPanel; - -/** - * @author hades - * @version 10.0 - * Created by hades on 2021/4/9 - */ -public class OpenLoadingPane extends JPanel { - private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/openloading.png")); +public class LoadingUtils { + private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/loading.png")); private static final Color TIP_COLOR = new Color(108, 174, 235); private static final int Y_GAP = 50; private static final int X_GAP = 10; - private UILabel loadingLabel; - private UILabel tipLabel; - - public OpenLoadingPane() { - - setLayout(new LayoutManager() { - + 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")); + tipLabel.setForeground(TIP_COLOR); + jPanel.setLayout(new LayoutManager() { @Override public void removeLayoutComponent(Component comp) { } @@ -64,12 +58,10 @@ public class OpenLoadingPane extends JPanel { public void addLayoutComponent(String name, Component comp) { } }); - setBackground(Color.WHITE); - loadingLabel = new UILabel(LOADING_ICON); - tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Open_Template_Loading")); - tipLabel.setForeground(TIP_COLOR); - add(loadingLabel); - add(tipLabel); + jPanel.setBackground(Color.WHITE); + jPanel.add(loadingLabel); + jPanel.add(tipLabel); + return jPanel; } } diff --git a/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java b/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java new file mode 100644 index 0000000000..2fac1e903e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java @@ -0,0 +1,135 @@ +package com.fr.design.utils; + +import com.fr.base.extension.FileExtension; +import com.fr.base.io.BaseBook; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.TemplateTreePane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.worker.save.SaveFailureHandler; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ArrayUtils; +import com.fr.stable.CoreConstants; +import com.fr.stable.ProductConstants; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.lock.TplOperator; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import javax.swing.SwingWorker; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/12/5 + */ +public class TemplateUtils { + + public static void createAndOpenTemplate(String prefix, FILE file, boolean needOpen) { + String fileName = file.getName(); + String oldPath = file.getPath(); + int indexOfLastDot = fileName.lastIndexOf(CoreConstants.DOT); + if (indexOfLastDot < 0) { + return; + } + String suffix = fileName.substring(indexOfLastDot + 1); + FILEChooserPane fileChooserPane = FILEChooserPane.getInstance(true, true); + fileChooserPane.setFileNameTextField(prefix + fileName, suffix); + FileExtension fileExtension = FileExtension.parse(suffix); + fileChooserPane.addChooseFILEFilter(new ChooseFileFilter(fileExtension, ProductConstants.APP_NAME + Toolkit.i18nText("Fine-Design_Report_Template_File"))); + fileChooserPane.disableFileNameTextFiled(); + int result = fileChooserPane.showSaveDialog(DesignerContext.getDesignerFrame(), suffix); + fileChooserPane.enableFileNameTextFiled(); + + if (isCancel(result)) { + return; + } + + if (isOk(result)) { + file = fileChooserPane.getSelectedFILE(); + _createAndOpenTemplate(file, oldPath, needOpen); + } + + } + + + private static void _createAndOpenTemplate(FILE file, String oldPath, boolean needOpen){ + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + byte[] content = new byte[0]; + if (!needOpen) { + // 从当前编辑模板中生成备份文件 + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BaseBook target = template.getTarget(); + if (target != null) { + target.export(outputStream); + content = outputStream.toByteArray(); + } + } else { + content = WorkContext.getWorkResource().readFully(oldPath); + } + if (ArrayUtils.isEmpty(content)) { + throw new Exception(oldPath + " content is empty" ); + } + OutputStream out = null; + try { + // 加锁 + WorkContext.getCurrent().get(TplOperator.class).saveAs(file.getPath()); + out = file.asOutputStream(); + out.write(content); + } finally { + try { + if (out != null) { + out.close(); + } + } finally { + // 解锁 + WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(file.getPath()); + } + + } + return null; + } + + @Override + protected void done() { + try { + get(); + if (needOpen) { + DesignerContext.getDesignerFrame().openTemplate(file); + } + // 备份成功刷新下目录树 展示出来备份的模板 + TemplateTreePane.getInstance().refresh(); + } catch (Exception e) { + SaveFailureHandler.getInstance().process(e); + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + }.execute(); + + } + + private static boolean isCancel(int result) { + return result == FILEChooserPane.CANCEL_OPTION || + result == FILEChooserPane.JOPTIONPANE_CANCEL_OPTION; + } + + private static boolean isOk(int result) { + return result == FILEChooserPane.JOPTIONPANE_OK_OPTION || + result == FILEChooserPane.OK_OPTION; + } + + public static String createLockeTemplatedName(JTemplate template, String name) { + int index = name.lastIndexOf(CoreConstants.DOT); + if (index < 0 || !template.isForbidden()) { + return name; + } + return name.substring(0, index) + Toolkit.i18nText("Fine_Design_Template_Has_Been_Locked") + name.substring(index); + } +} diff --git a/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java b/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java index bfa742f9b1..c3c087b4db 100644 --- a/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java @@ -65,4 +65,15 @@ public class AdjustWorkBookDefaultStyleUtils { return DesignModeContext.isDuchampMode() ? getCurrentStoryBack() : color; } + /** + * cpt模板是否支持跟随主题选项 + * 单元格样式 + * 悬浮元素样式 + * 纸张背景入口大屏模板屏蔽掉了 忽略 + * @return 大屏模板中cpt组件不支持 + */ + public static boolean supportTheme() { + return !DesignModeContext.isDuchampMode(); + } + } diff --git a/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java b/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java index 40e6683eb5..b070b7f078 100644 --- a/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java +++ b/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java @@ -3,18 +3,23 @@ package com.fr.design.worker.open; import com.fr.base.chart.exception.ChartNotFoundException; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.file.TemplateTreePane; import com.fr.design.i18n.Toolkit; +import com.fr.design.lock.LockInfoDialog; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.JTemplate; import com.fr.design.utils.DesignUtils; import com.fr.design.worker.WorkerManager; import com.fr.exception.DecryptTemplateException; +import com.fr.exception.TplLockedException; import com.fr.file.FILE; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; +import java.util.UUID; import javax.swing.JOptionPane; import javax.swing.SwingWorker; import javax.swing.UIManager; @@ -81,6 +86,11 @@ public class OpenWorker extends SwingWorker { JOptionPane.ERROR_MESSAGE, UIManager.getIcon("OptionPane.errorIcon")); } + if (cause.getCause() instanceof TplLockedException) { + MutilTempalteTabPane.getInstance().closeCurrentTpl(); + TemplateTreePane.getInstance().getFileNode().setLock(UUID.randomUUID().toString()); + LockInfoDialog.show(null); + } FineLoggerFactory.getLogger().error(t.getMessage(), t); return; } diff --git a/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java b/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java index f8a0f5d4fa..ed2597f1d7 100644 --- a/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java +++ b/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java @@ -63,6 +63,15 @@ public class CallbackSaveWorker extends SaveWorker { } } + public void addSuccessCallbackBeforeLast(Runnable successRunnable) { + if (successRunnableList == null) { + successRunnableList = new LinkedList<>(); + } + if (successRunnable != null) { + successRunnableList.add(successRunnableList.size() - 1, successRunnable); + } + } + public void addFailCallback(Runnable failRunnable) { if (failRunnableList == null) { failRunnableList = new LinkedList<>(); diff --git a/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java b/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java new file mode 100644 index 0000000000..5d7beb36ae --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java @@ -0,0 +1,122 @@ +package com.fr.design.worker.save; + +import com.fr.common.exception.ThrowableHandler; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.ui.util.UIUtil; +import com.fr.design.utils.TemplateUtils; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.IOUtils; +import com.fr.report.UnLockedException; +import com.fr.workspace.exception.DiskSpaceFullException; +import com.fr.report.InconsistentLockException; +import java.awt.Frame; +import javax.swing.JOptionPane; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2021/12/7 + */ +public class SaveFailureHandler implements ThrowableHandler { + + private static final SaveFailureHandler INSTANCE = new SaveFailureHandler(); + + public static SaveFailureHandler getInstance() { + return INSTANCE; + } + + @Override + public boolean process(Throwable e) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + for (Handler handler : Handler.values()) { + try { + if (handler.process(e)) { + break; + } + } catch (Exception ignored) { + } + } + } + }); + return true; + } + + public enum Handler implements ThrowableHandler { + + FullDisk { + @Override + public boolean process(Throwable e) { + if (e.getCause() instanceof DiskSpaceFullException + || e instanceof DiskSpaceFullException + || e.getCause().getCause() instanceof DiskSpaceFullException) { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine_Design_Template_Save_Failed_By_Full_Disk"), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE, + IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png")); + return true; + } + return false; + } + }, + UnLocked { + @Override + public boolean process(Throwable e) { + if (e.getCause() instanceof UnLockedException || e instanceof UnLockedException) { + processByBack(Toolkit.i18nText("Fine_Design_Template_Has_Been_UnLocked")); + return true; + } + return false; + } + }, + + InconsistentLock { + @Override + public boolean process(Throwable e) { + if (e.getCause() instanceof InconsistentLockException || e instanceof InconsistentLockException) { + processByBack(Toolkit.i18nText("Fine_Design_Template_Save_Failed_By_Lock_Inconsistency")); + return true; + } + return false; + } + }, + + Other { + @Override + public boolean process(Throwable e) { + boolean minimized = (DesignerContext.getDesignerFrame().getExtendedState() & Frame.ICONIFIED ) != 0; + FineJOptionPane.showMessageDialog( + minimized ? null : DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design-Basic_Save_Failure"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.ERROR_MESSAGE); + return true; + } + }; + + + protected void processByBack(String tip) { + int option = FineJOptionPane.showOptionDialog(DesignerContext.getDesignerFrame(), + tip, + Toolkit.i18nText("Fine-Design_Basic_Alert"), + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE, + IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"), + new Object[] {Toolkit.i18nText("Fine_Design_Template_SaveAs_Backup"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null); + if (option == JOptionPane.YES_OPTION) { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateUtils.createAndOpenTemplate(Toolkit.i18nText("Fine_Design_Template_Backup"), new FileNodeFILE(new FileNode(template.getPath(), false)), false); + } + } + } + + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java b/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java index f47a4f88e7..60d797c3e9 100644 --- a/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java +++ b/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java @@ -1,8 +1,6 @@ package com.fr.design.worker.save; -import com.fr.design.dialog.FineJOptionPane; import com.fr.design.file.HistoryTemplateListCache; -import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.EastRegionContainerPane; @@ -10,11 +8,9 @@ import com.fr.design.mainframe.JTemplate; import com.fr.design.worker.WorkerManager; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; -import java.awt.Frame; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import javax.swing.JOptionPane; import javax.swing.SwingWorker; /** @@ -55,12 +51,7 @@ public class SaveWorker extends SwingWorker { } catch (Exception e) { processResult(); FineLoggerFactory.getLogger().error(e.getMessage(), e); - boolean minimized = (DesignerContext.getDesignerFrame().getExtendedState() & Frame.ICONIFIED ) != 0; - FineJOptionPane.showMessageDialog( - minimized ? null : DesignerContext.getDesignerFrame(), - Toolkit.i18nText("Fine-Design-Basic_Save_Failure"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), - JOptionPane.ERROR_MESSAGE); + SaveFailureHandler.getInstance().process(e); return; } processResult(); @@ -70,7 +61,6 @@ public class SaveWorker extends SwingWorker { this.template.setSaving(false); // 恢复界面 if (slowly && ComparatorUtils.equals(this.template.getName(), HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getName())) { - DesignerContext.getDesignerFrame().refreshUIToolBar(); DesignerContext.getDesignerFrame().getCenterTemplateCardPane().hideCover(); } DesignerFrameFileDealerPane.getInstance().stateChange(); diff --git a/designer-base/src/main/java/com/fr/env/HelpLink.java b/designer-base/src/main/java/com/fr/env/HelpLink.java index 133a234900..c717ce6ea6 100644 --- a/designer-base/src/main/java/com/fr/env/HelpLink.java +++ b/designer-base/src/main/java/com/fr/env/HelpLink.java @@ -1,7 +1,7 @@ package com.fr.env; - -import com.fr.i18n.UrlI18nManager; +import com.fr.general.locale.LocaleCenter; +import com.fr.general.locale.LocaleMark; import com.fr.locale.InterProviderFactory; import com.fr.stable.StringUtils; import java.util.HashMap; @@ -18,7 +18,8 @@ public class HelpLink { public static String getLink(String solution) { Map map = new HashMap<>(); - String link = UrlI18nManager.getInstance().getI18nUrl("help.remote.design"); + LocaleMark linkMark = LocaleCenter.getMark(RemoteDesignLocaleMark.class); + String link = linkMark.getValue(); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Change_PassWord"), StringUtils.EMPTY); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Cert_Error_Solution"), link); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Connection_Unknown_Error_Solution"), link); 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 ce08662cae..426fd18e26 100644 --- a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java +++ b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java @@ -648,7 +648,7 @@ public class FILEChooserPane extends BasicPane { this.suffix = suffix; if (!text.endsWith(suffix)) { - text = text + suffix; + text = removeSuffix(text) + suffix; } fileNameTextField.removeDocumentListener(); fileNameTextField.setText(text); @@ -664,6 +664,24 @@ public class FILEChooserPane extends BasicPane { fileNameTextField.setFilter(new DefaultCompletionFilter(names)); } + public void disableFileNameTextFiled() { + fileNameTextField.setEditable(false); + fileNameTextField.setEnabled(false); + } + + public void enableFileNameTextFiled() { + fileNameTextField.setEditable(true); + fileNameTextField.setEnabled(true); + } + + /** + * 移除文件后缀的方法 + * 解决cptx文件的另存为操作默认会出现双后缀的bug(xxx.cptx.cpt) + **/ + private String removeSuffix(String text){ + return FileExtension.CPTX.matchExtension(text) ? text.substring(0, text.length() - FileExtension.CPTX.getSuffix().length()) : text; + } + /** * 打开对话框 @@ -774,6 +792,7 @@ public class FILEChooserPane extends BasicPane { // ben:filefilter设置初值为cpt过滤 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); + this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); // richer:form文件 daniel 改成三个字 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.FRM, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java b/designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java new file mode 100644 index 0000000000..cfb7c44955 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java @@ -0,0 +1,35 @@ +package com.fr.nx.app.designer.cptx.io; + +import com.fr.common.annotations.Negative; +import com.fr.file.FILE; +import com.fr.nx.cptx.io.handle.impl.CompileToPathCptxIOProvider; +import com.fr.nx.cptx.pack.util.CompiledReportOutputStream; +import com.fr.nx.cptx.utils.CptxFileUtils; + +/** + * 用于设计器保存编译后的结果并缓存可web预览模版 + * 没有可观的内存实现,内存实现方式复杂,赶发布,先提供简单的内存实现方式 + * + * @author: Maksim + * @Date: Created in 2020/4/10 + * @Description: 用于cptx写操作的Provider + */ +@Negative(until = "2020-05-10") +public class DesignReadWritableProvider extends CompileToPathCptxIOProvider { + /** + * 原文件 + */ + private final FILE file; + + public DesignReadWritableProvider(FILE file) { + super(CptxFileUtils.getFormatPath(file.getPath())); + this.file = file; + } + + + @Override + public CompiledReportOutputStream outputOpen() throws Exception { + return new CompiledReportOutputStream(file.asOutputStream(), getCompilePath()); + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java b/designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java new file mode 100644 index 0000000000..0644bd5113 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java @@ -0,0 +1,97 @@ +package com.fr.nx.app.designer.monitor; + +import com.fr.design.mainframe.errorinfo.ErrorInfo; +import com.fr.intelli.record.MetricRegistry; +import com.fr.json.JSON; +import com.fr.json.JSONFactory; +import com.fr.json.JSONObject; +import com.fr.message.ErrorMessage; +import com.fr.nx.app.designer.toolbar.TransformResult; + +/** + * Created by loy on 2021/1/18. + * + *

设计器埋点记录相关 + */ +public class DesignerMetricRecorder { + + private static final String ATTR_TEMPLATE_ID = "templateid"; + private static final String ATTR_USERNAME = "username"; + private static final String ATTR_UUID = "uuid"; + private static final String ATTR_ACTIVE_KEY = "activekey"; + private static final String ATTR_TEST_LOG = "testlog"; + private static final String ATTR_REPORT_CONTENT = "reportcontent"; + private static final String ATTR_ERROR_STACK = "errorstack"; + private static final String IDENTIFICATION = "view_plus"; + + private DesignerMetricRecorder() { + } + + /** + * 模板转换失败的埋点 + */ + public static void submitFailedTransform(TransformResult result, String templateID, String name, Exception e) { + if (isPressureTesting()) { + return; + } + saveAsJSON(result, templateID, name, e); + } + + /** + * 记录在设计器的错误信息收集中 + */ + private static void saveToErrorInfo(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) { + JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); + jo.put(ATTR_USERNAME, IDENTIFICATION); + jo.put(ATTR_UUID, IDENTIFICATION); + jo.put(ATTR_ACTIVE_KEY, IDENTIFICATION); + jo.put(ATTR_TEMPLATE_ID, templateID); + jo.put(ATTR_REPORT_CONTENT, name); + if (result == TransformResult.FAILED) { + jo.put(ATTR_TEST_LOG, e); + jo.put(ATTR_ERROR_STACK, e.getMessage()); + } else { + jo.put(ATTR_TEST_LOG, unsupportMessage); + } + new ErrorInfo().saveFileToCache(jo); + } + + /** + * 记录在fine_record_error表中 + */ + private static void saveToErrorMessage(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) { + String errorMessage = unsupportMessage; + if (result == TransformResult.FAILED) { + errorMessage = e.getStackTrace()[0].toString(); + } + ErrorMessage message = ErrorMessage.build(e == null ? errorMessage : e.getMessage(), errorMessage); + message.setTname(name); + message.setDisplayName(name); + MetricRegistry.getMetric().submit(message); + } + + private static void saveAsJSON(TransformResult result, String templateID, String name, Exception e) { + saveToErrorInfo(result, templateID, name, e, null); + saveToErrorMessage(result, templateID, name, e, null); + } + + /** + * 预编译中不支持的功能的埋点 + */ + public static void submitUnSupportTransform(TransformResult result, String templateID, String name, String unsupportMessage) { + if (isPressureTesting()) { + return; + } + saveToErrorInfo(result, templateID, name, null, unsupportMessage); + saveToErrorMessage(result, templateID, name, null, unsupportMessage); + } + + /** + * 埋点对压测性能的影响控制参数 + * + * @return 是否压测 + */ + public static boolean isPressureTesting() { + return Boolean.parseBoolean(System.getProperty("monitorDebug")); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java new file mode 100644 index 0000000000..4496ecd9af --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java @@ -0,0 +1,116 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.extension.FileExtension; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.general.IOUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.utils.CompileTransformUtil; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog; +import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; +import static javax.swing.JOptionPane.OK_CANCEL_OPTION; +import static javax.swing.JOptionPane.OK_OPTION; +import static javax.swing.JOptionPane.WARNING_MESSAGE; + +/** + * Created by kerry on 2019-10-14 + */ +public class CompileAction extends UpdateAction { + public static final Icon TRANS_ICON = IOUtils.readIcon("/com/fr/nx/app/designer/transform.png"); + + private static final MenuKeySet COMPILE_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip"); + } + + @Override + public KeyStroke getKeyStroke() { + return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER); + } + }; + + public CompileAction() { + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(COMPILE_ATTR); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(TRANS_ICON); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public void actionPerformed(ActionEvent e) { + JTemplate jtemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate(); + if (jtemplate == null || jtemplate.getEditingFILE() == null) { + return; + } + FILE currentTemplate = jtemplate.getEditingFILE(); + if(currentTemplate instanceof FileNodeFILE){ + transformAndDisplay(jtemplate); + }else { + //模板不在报表环境下,提示保存 + int selVal = showConfirmDialog( + DesignerContext.getDesignerFrame(), + InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Preview_Message"), + InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Transformer_Tips"), + OK_CANCEL_OPTION, + WARNING_MESSAGE); + + if (OK_OPTION == selVal) { + //保存成功才会执行编译 + if (jtemplate.saveAsTemplate2Env()) { + transformAndDisplay(jtemplate); + } + } + } + + } + + //编译模板并展示 + private void transformAndDisplay(JTemplate jtemplate){ + String path = jtemplate.getEditingFILE().getPath(); + TemplateTransformer transformer = TemplateTransformer.parse(path); + FILE targetFile = CompileTransformUtil.getTargetFile(jtemplate, transformer); + TransformResult result = transformer.transform(jtemplate, targetFile); + jtemplate.fireJTemplateSaved(); + result.display(); + } + + @Override + public boolean isEnabled() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String path = jt.getEditingFILE().getPath(); + return FileExtension.CPTX.matchExtension(path) || FileExtension.CPT.matchExtension(path); + } + + @Override + public JComponent createToolBarComponent() { + UIButton transBtn = (UIButton) super.createToolBarComponent(); + transBtn.set4ToolbarButton(); + transBtn.setToolTipText(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip")); + return transBtn; + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java new file mode 100644 index 0000000000..42490fe7d5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java @@ -0,0 +1,220 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.extension.FileExtension; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.app.designer.monitor.DesignerMetricRecorder; +import com.fr.nx.compile.CompileStatus; +import com.fr.nx.compile.ReportCompiler; +import com.fr.nx.compile.adapter.LegacyWorkBookAdapter; +import com.fr.nx.compile.util.ReportCompileUtils; +import com.fr.nx.cptx.CptxIOManager; +import com.fr.nx.cptx.cache.CptxTemplatePool; +import com.fr.nx.cptx.entry.CptxTemplate; +import com.fr.nx.cptx.io.handle.CptxTemplateHandle; +import com.fr.nx.app.designer.cptx.io.DesignReadWritableProvider; +import com.fr.nx.cptx.monitor.CompileMonitorHandler; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.nx.data.layer.LayerItem; +import com.fr.nx.data.layer.LayerProps; +import com.fr.nx.template.compile.CompiledReport; +import com.fr.stable.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.io.OutputStream; + +import static com.fr.base.extension.FileExtension.ALL; +import static com.fr.base.extension.FileExtension.CPT; +import static com.fr.base.extension.FileExtension.CPTX; + +/** + * 模板转换器, 可以把cptx模板转为cpt, 或者cpt模板转为cptx. + * 以后可以扩展支持frm frmx互相转换 + */ + +public enum TemplateTransformer { + + TO_CPTX(CPT) { + @Override + public TransformResult transform(JTemplate jtemplate, FILE file) { + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + TransformResultInfo resultInfo = compileCPTX(workbook, file); + if (needDoAfterTransformed(resultInfo.getResult())) { + doAfterTransformed(file, jtemplate); + } + return resultInfo.getResult(); + } + }, + TO_CPT(CPTX) { + @Override + public TransformResult transform(JTemplate jtemplate, FILE file) { + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + try { + workbook.export(file.asOutputStream()); + doAfterTransformed(file, jtemplate); + return TransformResult.SUCCESS; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResult.FAILED; + } + } + }, + OTHER(ALL); + private FileExtension extension; + + TemplateTransformer(FileExtension extension) { + this.extension = extension; + } + + public TransformResult transform(JTemplate jtemplate) { + return transform(jtemplate, jtemplate.getEditingFILE()); + } + + public TransformResult transform(JTemplate jtemplate, FILE newFile) { + return TransformResult.UNSUPPORT; + } + + public static TemplateTransformer parse(String path) { + for (TemplateTransformer transformer : values()) { + if (transformer.extension.matchExtension(path)) { + return transformer; + } + } + return OTHER; + } + + private static boolean needDoAfterTransformed(TransformResult result) { + return ComparatorUtils.equals(TransformResult.SUCCESS, result) + || ComparatorUtils.equals(TransformResult.UNSUPPORT, result); + } + + private static void doAfterTransformed(FILE file, JTemplate jtemplate) { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (ComparatorUtils.equals(file.getPath(), jt.getPath())) { + HistoryTemplateListCache.getInstance().closeSelectedReport(jt); + DesignerContext.getDesignerFrame().openTemplate(file); + return; + } + MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); + MutilTempalteTabPane.getInstance().closeFormat(jt); + MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt); + DesignerContext.getDesignerFrame().openTemplate(file); + } + + + public static FILE createOutputFile(String oldPath, String oldSuffix, String newSuffix) { + String newPath = generateNewPath(oldPath, oldSuffix, newSuffix); + return new FileNodeFILE(new FileNode(newPath, false)); + } + + private static String generateNewPath(String oldPath, String oldSuffix, String newSuffix) { + if (StringUtils.isEmpty(oldPath) || StringUtils.isEmpty(oldSuffix) || StringUtils.isEmpty(newSuffix)) { + return oldPath; + } + + if (oldPath.endsWith(oldSuffix)) { + return StringUtils.cutStringEndWith(oldPath, oldSuffix) + newSuffix; + } + return oldPath; + } + + /** + * 编译和保存 + * + * @param workbook work + * @param file file + * @return 编译保存结果 + */ + @NotNull + public static TransformResultInfo compileCPTX(WorkBook workbook, FILE file) { + //对于非工作目录的cptx,修改无需执行编译 + if (!(file instanceof FileNodeFILE)) { + try { + OutputStream outputStream = file.asOutputStream(); + workbook.export(outputStream); + return TransformResultInfo.generateResult(TransformResult.SUCCESS).saved(true); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResultInfo.generateResult(TransformResult.FAILED).saved(false); + } + } + boolean saved; + CompiledReport report = null; + CompileStatus compileStatus = CompileStatus.SUCCEED; + if (workbook == null || file == null) { + return TransformResultInfo + .generateResult(TransformResult.FAILED, "work and file must not be null") + .saved(false); + } + String failMessage = null; + // 编译 + ReportCompiler compiler; + try { + compiler = new ReportCompiler(new LegacyWorkBookAdapter(workbook)); + long startTime = System.currentTimeMillis(); + compiler.compile(); + report = compiler.getCompiledReport(); + // 折叠树埋点 + LayerProps props = ReportCompileUtils.getLayerProps(report); + LayerItem[] items; + if (props != null && (items = props.getLayerItems()) != null) { + CompileMonitorHandler.submitTreeCompileFocusPoint( + startTime, file.getPath(), items.length, + props.getExpandLayer(), true + ); + } + compileStatus = compiler.getStatus(); + failMessage = compiler.getFailMessage(); + long endTime = System.currentTimeMillis(); + CompileMonitorHandler.submitCompileMessage(startTime, endTime, file.getPath(), ""); + if (compileStatus != CompileStatus.SUCCEED) { + DesignerMetricRecorder.submitUnSupportTransform( + TransformResult.UNSUPPORT, + workbook.getTemplateID(), + file.getName(), + compileStatus == CompileStatus.FAILED_UNSUPPORT ? failMessage : null + ); + } + } catch (Exception exception) { + String templateID = workbook.getTemplateID(); + String fileName = file.getName(); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, templateID, fileName, exception); + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + } + + // 构建编译结果,当前的 cptx template 是未经反序列化钩子处理过的 cptx 模版对象,不能直接用于模版预览 + CptxTemplate template = CptxIOManager.createCptxTemplate(workbook, report, compileStatus, failMessage); + // 保存 + DesignReadWritableProvider cptx = new DesignReadWritableProvider(file); + CptxTemplateHandle handle = CptxIOManager.create(template, cptx); + try { + saved = handle.save(); + } catch (Exception exception) { + // 存储cptx格式报错或者失败 + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, workbook.getTemplateID(), file.getName(), exception); + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(false); + } + // 读取可 web 预览模版并缓存 + try { + // todo 是否考虑异步 + CptxTemplate previewCptxTemplate = CptxIOManager.open(cptx).getTemplate(); + CptxTemplatePool.getInstance().addCptxTemplate(CptxFileUtils.getFormatPath(file.getPath()), previewCptxTemplate); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (report == null) { + // 编译报错或者失败 + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(saved); + } + return TransformResultInfo.generateResult(TransformResult.parse(compileStatus), failMessage).saved(saved); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java new file mode 100644 index 0000000000..9668ec8055 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java @@ -0,0 +1,55 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.design.file.TemplateTreePane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.compile.CompileStatus; + +import javax.swing.JOptionPane; + +public enum TransformResult { + + SUCCESS(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Success")) { + @Override + public void display() { + // 转换成功后, 刷新下目录树 + TemplateTreePane.getInstance().refresh(); + super.display(); + } + }, + FAILED(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Failed")), + UNSUPPORT(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Unsupport")){ + @Override + public void display() { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), TransformResult.SUCCESS.toString()); + } + }; + + private String msg; + + private TransformResult(String msg) { + this.msg = msg; + } + + // 展示结果 + public void display() { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), this.toString()); + } + + @Override + public String toString() { + return this.msg; + } + + public static TransformResult parse(CompileStatus status) { + switch (status) { + case SUCCEED: + return TransformResult.SUCCESS; + case FAILED_UNSUPPORT: + return TransformResult.UNSUPPORT; + default: + return TransformResult.FAILED; + } + + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java new file mode 100644 index 0000000000..15e3c8bf90 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java @@ -0,0 +1,64 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.locale.InterProviderFactory; +import com.fr.stable.StringUtils; + +/** + * Created by kerry on 2020-01-15 + */ +public class TransformResultInfo { + + private boolean saved; + private TransformResult result; + private final String transformLog; + + public static TransformResultInfo generateResult(TransformResult result, String transformLog) { + return new TransformResultInfo(result, transformLog); + } + + public static TransformResultInfo generateResult(TransformResult result) { + return new TransformResultInfo(result, StringUtils.EMPTY); + } + + + private TransformResultInfo(TransformResult result, String transformLog) { + this.result = result; + this.transformLog = transformLog; + this.saved = false; + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public TransformResultInfo saved(boolean saved) { + setSaved(saved); + return this; + } + + public TransformResult getResult() { + return result; + } + + public void setResult(TransformResult result) { + this.result = result; + } + + public String getTransformLog() { + switch (this.result) { + case FAILED: + return transformLog + "\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"); + case SUCCESS: + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"); + case UNSUPPORT: + return transformLog + "\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_X_Unsupport_Tip"); + } + return transformLog; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java new file mode 100644 index 0000000000..7b11cd34c5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java @@ -0,0 +1,25 @@ +package com.fr.nx.app.designer.transform; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformProgress { + private double progress = 0.0D; + private int total = 0; + private int complete = 0; + + public BatchTransformProgress(int total) { + this.total = total; + } + + + public double getProgress() { + return this.progress; + } + + + public void updateProgress() { + this.complete++; + this.progress = this.complete * 1D / this.total; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java new file mode 100644 index 0000000000..aef4eed21f --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java @@ -0,0 +1,25 @@ +package com.fr.nx.app.designer.transform; + +import com.fr.file.filetree.FileNode; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-02-14 + */ +public class BatchTransformUtil { + private BatchTransformUtil() { + + } + + public static FileNode[] filterTransformedFile(FileNode[] fileNodes, List transformedList){ + List list = new ArrayList(); + for (FileNode fileNode : fileNodes) { + if (!transformedList.contains(fileNode)) { + list.add(fileNode); + } + } + return list.toArray(new FileNode[list.size()]); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java new file mode 100644 index 0000000000..8dee1ca309 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java @@ -0,0 +1,71 @@ +package com.fr.nx.app.designer.transform; + +import com.fr.design.utils.concurrent.ThreadFactoryBuilder; +import com.fr.file.filetree.FileNode; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.nx.app.designer.utils.CompileTransformUtil; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformer { + private BatchTransformProgress progress = new BatchTransformProgress(0); + private Map transformResults = new ConcurrentHashMap(); + private UpdateCallBack updateCallBack; + private static final int MAXPOOLSIZE = 5; + private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s"; + private ExecutorService threadPoolExecutor = + Executors.newFixedThreadPool(MAXPOOLSIZE, + new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); + + public BatchTransformer(UpdateCallBack updateCallBack) { + this.updateCallBack = updateCallBack; + } + + + public void batchTransform(List fileNodes) { + //先清理下 + transformResults.clear(); + progress = new BatchTransformProgress(fileNodes.size()); + for (FileNode fileNode : fileNodes) { + transform(fileNode); + } + } + + private void transform(final FileNode fileNode) { + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + TransformResultInfo transformResult = CompileTransformUtil.compileFile(fileNode); + transformResults.put(fileNode, transformResult); + updateTransformProgress(); + } + }); + } + + private synchronized void updateTransformProgress() { + progress.updateProgress(); + updateCallBack.updateProgress(progress.getProgress()); + } + + public void shutDown() { + if (threadPoolExecutor != null) { + threadPoolExecutor.shutdownNow(); + } + threadPoolExecutor = Executors.newFixedThreadPool(MAXPOOLSIZE, + new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); + updateCallBack.shutDown(); + } + + public Map getResults() { + return transformResults; + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java new file mode 100644 index 0000000000..85e1a11517 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java @@ -0,0 +1,22 @@ +package com.fr.nx.app.designer.transform; + +/** + * Created by kerry on 2019-12-10 + */ +public interface UpdateCallBack { + /** + * 更新进度 + * @param progress 进度 + */ + void updateProgress(double progress); + + /** + * 进度中断 + */ + void shutDown(); + + /** + * 进度重置 + */ + void reset(); +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java new file mode 100644 index 0000000000..75b32cb270 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java @@ -0,0 +1,61 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.locale.InterProviderFactory; + +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by kerry on 2019-12-19 + */ +public class BatchTransformDialog extends JDialog implements ActionListener { + private UIButton closeBtn; + + public BatchTransformDialog(Frame parent, JPanel contentPane) { + super(parent, true); + + this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform")); + this.setResizable(false); + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + closeBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Close")); + closeBtn.addActionListener(this); + JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(closeBtn); + + defaultPane.add(contentPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(closeBtn); + + this.setSize(new Dimension(900, 600)); + GUICoreUtils.centerWindow(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + dialogExit(); + } + + + private void dialogExit() { + this.dispose(); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java new file mode 100644 index 0000000000..c11e4e4adf --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java @@ -0,0 +1,223 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.extension.FileExtension; +import com.fr.design.dialog.BasicPane; +import com.fr.design.file.NodeAuthProcessor; +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.itextfield.UITextField; +import com.fr.design.gui.itree.filetree.FileNodeComparator; +import com.fr.design.gui.itree.filetree.FileNodeConstants; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.file.filetree.FileNode; +import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.tree.DefaultTreeModel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dialog; +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.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformPane extends BasicPane { + private UITextField searchField; + private TransformFileTree tree; + private Dialog showDialog; + private TransformPreparePane preparePane; + private TransformResultPane resultPane; + + + public BatchTransformPane() { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + this.showDialog = new BatchTransformDialog(designerFrame, this); + initPane(); + } + + private void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initNorthPane(); + initSouthPane(); + } + + private void initNorthPane() { + UILabel northTip = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Tip")); + northTip.setForeground(Color.decode("#8F8F92")); + northTip.setBorder(BorderFactory.createEmptyBorder(0, 550, 10, 10)); + this.add(northTip, BorderLayout.NORTH); + } + + private void initSouthPane() { + preparePane = new TransformPreparePane(this.showDialog, this); + tree = new TransformFileTree(preparePane); + this.add(preparePane, BorderLayout.CENTER); + initLeftPane(); + initRightPane(); + } + + private void initLeftPane() { + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{FileExtension.CPT.getSuffix()}); + tree.setDigIn(true); + tree.setFileNodeFilter(filter); + UIScrollPane scrollPane = new UIScrollPane(tree); + scrollPane.setPreferredSize(new Dimension(320, 442)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(12, 0, 0, 0)); + tree.refreshEnv(); + JPanel selectPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Select_Template")); + JPanel searchPane = initSearchPane(); + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + jPanel.add(searchPane, BorderLayout.NORTH); + jPanel.add(scrollPane, BorderLayout.WEST); + jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + selectPane.add(jPanel); + selectPane.setPreferredSize(new Dimension(330, 501)); + this.add(selectPane, BorderLayout.WEST); + } + + + private void initRightPane() { + resultPane = new TransformResultPane(); + this.add(resultPane, BorderLayout.EAST); + } + + private JPanel initSearchPane() { + JPanel jPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + jPanel.setBorder(BorderFactory.createEmptyBorder()); + searchField = new UITextField(); + searchField.requestFocus(); + searchField.addKeyListener(keyFieldKeyListener); + searchField.setPreferredSize(new Dimension(261, 20)); + jPanel.add(searchField); + UIButton searchBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Search")); + searchBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + search(); + } + }); + searchBtn.setPreferredSize(new Dimension(44, 20)); + jPanel.add(searchBtn); + return jPanel; + } + + + private KeyAdapter keyFieldKeyListener = new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + search(); + e.consume(); + } + } + }; + + + + private void search() { + //重新构建TreeModel + filter(searchField.getText()); + ExpandMutableTreeNode rootNode = (ExpandMutableTreeNode) tree.getModel().getRoot(); + ((DefaultTreeModel) tree.getModel()).reload(rootNode); + // 展开所有isExpanded为true的TreeNode + rootNode.expandCurrentTreeNode(tree); + } + + public void filter(String filterString) { + NodeAuthProcessor.getInstance().refresh(); + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel(); + ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); + NodeAuthProcessor.getInstance().fixTreeNodeAuth(rootTreeNode); + filter(rootTreeNode, filterString); + defaultTreeModel.reload(rootTreeNode); + } + + private void filter(ExpandMutableTreeNode rootTreeNode, String filterString) { + rootTreeNode.removeAllChildren(); + + FileNode[] fns; + fns = listFileNodes(rootTreeNode); + + ExpandMutableTreeNode[] subTreeNodes = NodeAuthProcessor.getInstance().parser2TreeNodeArray(fns); + + for (ExpandMutableTreeNode node : subTreeNodes) { + filter(node, filterString); + if (node.getChildCount() > 0 || (node.getChildCount() == 0 && node.toString().contains(filterString))) { + node.setExpanded(true); + rootTreeNode.add(node); + } + } + + } + + private FileNode[] listFileNodes(ExpandMutableTreeNode rootTreeNode) { + if (rootTreeNode == null) { + return new FileNode[0]; + } + + Object object = rootTreeNode.getUserObject(); + if (!(object instanceof FileNode)) { + return new FileNode[0]; + } + + FileNode[] fileNodes = null; + try { + fileNodes = tree.listFile(((FileNode) object).getEnvPath()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (fileNodes == null) { + fileNodes = new FileNode[0]; + } + Arrays.sort(fileNodes, new FileNodeComparator(FileNodeConstants.getSupportFileTypes())); + return fileNodes; + } + + public void resetFilePaths(Map resultMap) { + this.tree.resetSelectedPaths(); + Iterator iterator = resultMap.keySet().iterator(); + List list = new ArrayList(); + while (iterator.hasNext()){ + FileNode node = iterator.next(); + list.add(node); + } + this.tree.addTransformedList(list); + this.tree.refresh(); + resultPane.populate(resultMap); + } + + public void removeSelectedNode(FileNode fileNode) { + String path = fileNode.getEnvPath(); + this.tree.removeSelectedPath(path); + } + + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); + } + + public Dialog showDialog() { + return this.showDialog; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java new file mode 100644 index 0000000000..22d6afcfd0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java @@ -0,0 +1,79 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itree.filetree.FileTreeIcon; +import com.fr.file.filetree.FileNode; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + * Created by kerry on 2020-01-13 + */ +public class PrepareTransformFileList extends UIList { + private TransformPreparePane transformingPane; + private static final int DELETE_RANGE = 20; + + + public PrepareTransformFileList(final TransformPreparePane transformingPane) { + super(); + this.transformingPane = transformingPane; + this.setBackground(UIConstants.TREE_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + DefaultListModel listModel = new DefaultListModel(); + this.setModel(listModel); + this.setCellRenderer(new UIListControlCellRenderer() { + @Override + protected Icon getLeftLabelIcon(Object value) { + if (value instanceof FileNode) { + return FileTreeIcon.getIcon((FileNode) value); + } + return null; + } + + @Override + protected Icon getRightLabelIcon(Object value) { + return BaseUtils.readIcon("/com/fr/nx/app/designer/transform/tab_close.png"); + } + }); + this.addMouseListener(getListMouseListener()); + } + + + private MouseListener getListMouseListener() { + return new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent evt) { + JList list = (JList) evt.getSource(); + int selectedIndex = list.getSelectedIndex(); + Rectangle rectangle = list.getCellBounds(selectedIndex, selectedIndex); + if (SwingUtilities.isLeftMouseButton(evt) + && pointInSelected(rectangle, evt.getX(), evt.getY())) { + Object value = PrepareTransformFileList.this.getSelectedValue(); + if (value != null) { + transformingPane.removeSelectedNode((FileNode) value); + } + } + } + }; + } + + private boolean pointInSelected(Rectangle rectangle, int x, int y) { + if (rectangle == null) { + return false; + } + return x >= rectangle.x + rectangle.width - DELETE_RANGE && + x <= rectangle.x + rectangle.width && + y >= rectangle.y && y <= rectangle.y + rectangle.height; + } +} + diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java new file mode 100644 index 0000000000..cbfcd253fc --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java @@ -0,0 +1,204 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.FRContext; +import com.fr.base.extension.FileExtension; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTree; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeCellRenderer; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeSelectionModel; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.remote.ui.tree.FileAuthorityTree; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.nx.app.designer.transform.BatchTransformUtil; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import java.awt.AlphaComposite; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformFileTree extends FileAuthorityTree { + private TransformPreparePane preparePane; + private static final float CHECKBOX_ENABLE_OPACITY = 0.4f; + + private List transformedList = new ArrayList(); + + public TransformFileTree(TransformPreparePane preparePane) { + this.preparePane = preparePane; + } + + public void addTransformedList(List removeList) { + this.transformedList.addAll(removeList); + } + + @Override + protected CheckBoxTree.Handler createHandler() { + return new CheckBoxTree.Handler(this) { + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + TreePath treePath = this.getTreePathForMouseEvent(e); + if (treePath == null) { + return; + } + CheckBoxTreeSelectionModel selectionModel = _tree.getCheckBoxTreeSelectionModel(); + boolean selected = selectionModel.isPathSelected(treePath, selectionModel.isDigIn()); + ExpandMutableTreeNode lastPathComponent = (ExpandMutableTreeNode) treePath.getLastPathComponent(); + List selectedFileNodes = filterBatchFileNode(lastPathComponent); + preparePane.removeTransformNode(selectedFileNodes); + if (selected) { + preparePane.addTransformNode(selectedFileNodes); + } + + } + }; + } + + + private List filterBatchFileNode(ExpandMutableTreeNode treeNode) { + List fileNodeList = new ArrayList<>(); + int childCount = treeNode.getChildCount(); + if (childCount > 0) { + loadPendingChildTreeNode(treeNode); + int expandChildCount = treeNode.getChildCount(); + for (int i = 0; i < expandChildCount; i++) { + fileNodeList.addAll(filterBatchFileNode((ExpandMutableTreeNode) treeNode.getChildAt(i))); + } + } else { + FileNode fileNode = (FileNode) treeNode.getUserObject(); + boolean locked = fileNodeLocked(treeNode); + if (!fileNode.isDirectory() && !locked) { + fileNodeList.add((FileNode) treeNode.getUserObject()); + } + } + return fileNodeList; + } + + + private boolean fileNodeLocked(ExpandMutableTreeNode treeNode) { + Object userObj = treeNode.getUserObject(); + if (userObj instanceof FileNode) { + FileNode node = (FileNode) userObj; + String lock = node.getLock(); + if (lock != null && !node.getUserID().equals(lock)) { + return true; + } + } + return false; + } + + public void resetSelectedPaths() { + CheckBoxTreeSelectionModel selectionModel = this.getCheckBoxTreeSelectionModel(); + selectionModel.clearSelection(); + } + + @Override + public void selectCheckBoxPaths(String[] paths) { + if (paths == null || paths.length == 0) { + return; + } + + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot(); + List res = new ArrayList<>(); + for (String path : paths) { + TreePath treePath = getSelectedPath(treeNode, path); + if (treePath != null) { + res.add(treePath); + } + } + // 勾选中这些结点 + this.getCheckBoxTreeSelectionModel().setSelectionPaths(res.toArray(new TreePath[0])); + } + + private TreePath getSelectedPath(ExpandMutableTreeNode treeNode, String path) { + //可以只在选中的path中选择 + for (int i = 0, len = treeNode.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i); + if (childTreeNode.getChildCount() > 0) { + loadPendingChildTreeNode(childTreeNode); + TreePath treePath = getSelectedPath(childTreeNode, path); + if (treePath != null) { + return treePath; + } + } + if (!(childTreeNode.getUserObject() instanceof FileNode)) { + continue; + } + FileNode fileNode = (FileNode) childTreeNode.getUserObject(); + if (ComparatorUtils.equals(path, fileNode.getEnvPath())) { + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + return new TreePath(model.getPathToRoot(childTreeNode)); + } + } + return null; + } + + public void removeSelectedPath(String path) { + if (path == null) { + return; + } + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot(); + TreePath selectedPath = getSelectedPath(treeNode, path); + if (selectedPath != null) { + this.getCheckBoxTreeSelectionModel().removeSelectionPath(selectedPath); + + } + } + + + @Override + public FileNode[] listFile(String path) { + // 支持插件扩展, 先从env的filter拿, 再从插件拿 + Set supportTypes = new HashSet(); + for (String temp : this.filter.getSupportedTypes()) { + supportTypes.add(FileExtension.parse(temp)); + } + FileNode[] fileNodes = FRContext.getFileNodes().list( + path, + supportTypes.toArray(new FileExtension[supportTypes.size()]) + ); + return BatchTransformUtil.filterTransformedFile(fileNodes, transformedList); + } + + @Override + public boolean isCheckBoxEnabled(TreePath path) { + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) path.getLastPathComponent(); + return !fileNodeLocked(treeNode); + } + + @Override + protected CheckBoxTreeCellRenderer createCellRenderer(TreeCellRenderer renderer) { + final CheckBoxTreeCellRenderer checkBoxTreeCellRenderer = new CheckBoxTreeCellRenderer(renderer) { + @Override + public void paint(Graphics g) { + if (!_checkBox.isEnabled()) { + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, CHECKBOX_ENABLE_OPACITY); + ((Graphics2D) g).setComposite(composite); + } + super.paint(g); + } + }; + addPropertyChangeListener(CELL_RENDERER_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + checkBoxTreeCellRenderer.setActualTreeRenderer((TreeCellRenderer) evt.getNewValue()); + } + }); + return checkBoxTreeCellRenderer; + } + + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java new file mode 100644 index 0000000000..efbded1b00 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java @@ -0,0 +1,130 @@ +package com.fr.nx.app.designer.transform.ui; + +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.layout.FRGUIPaneFactory; +import com.fr.file.filetree.FileNode; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.nx.app.designer.transform.BatchTransformer; +import com.fr.nx.app.designer.transform.UpdateCallBack; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.DefaultListModel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformPreparePane extends JPanel { + private static final String INITIAL_DISPLAY_TEXT = "0"; + private PrepareTransformFileList fileList; + private List selectedFileNodes; + private UpdateProgressDialog dialog; + private BatchTransformer transformer; + private UpdateCallBack updateProgressPane; + private Dialog parentDialog; + private UILabel transCountLabel; + private BatchTransformPane batchTransformPane; + private UIButton startTransform; + + public TransformPreparePane(Dialog parentDialog, BatchTransformPane batchTransformPane) { + this.batchTransformPane = batchTransformPane; + this.parentDialog = parentDialog; + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + updateProgressPane = new UpdateProgressPane(this); + transformer = new BatchTransformer(updateProgressPane); + fileList = new PrepareTransformFileList(this); + selectedFileNodes = new ArrayList<>(); + initPane(); + } + + private void initPane() { + JPanel transformPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Template_To_Transform")); + transformPane.setPreferredSize(new Dimension(270, 501)); + startTransform = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Start")); + startTransform.setEnabled(false); + addStartTransformListener(startTransform); + transCountLabel = new UILabel(INITIAL_DISPLAY_TEXT); + JPanel northPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + northPane.add(startTransform); + northPane.add(Box.createHorizontalStrut(160)); + northPane.add(transCountLabel); + transformPane.add(northPane, BorderLayout.NORTH); + UIScrollPane scrollPane = new UIScrollPane(fileList); + scrollPane.setPreferredSize(new Dimension(260, 442)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + transformPane.add(scrollPane, BorderLayout.CENTER); + this.add(transformPane, BorderLayout.CENTER); + } + + private void addStartTransformListener(UIButton startTransform) { + startTransform.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + //开始转换 + transformer.batchTransform(selectedFileNodes); + displayProgressPane(); + } + + + private void displayProgressPane() { + dialog = new UpdateProgressDialog(transformer, parentDialog, (JPanel) updateProgressPane); + dialog.setVisible(true); + } + }); + } + + public void addTransformNode(List fileNodeList) { + selectedFileNodes.addAll(fileNodeList); + buildFileList(); + + } + + public void removeTransformNode(List fileNodeList) { + selectedFileNodes.removeAll(fileNodeList); + buildFileList(); + } + + public void removeSelectedNode(FileNode fileNode) { + selectedFileNodes.remove(fileNode); + buildFileList(); + this.batchTransformPane.removeSelectedNode(fileNode); + } + + private void buildFileList() { + DefaultListModel listModel = new DefaultListModel(); + int count = selectedFileNodes.size(); + for (int i = count - 1; i >= 0; i--) { + listModel.addElement(selectedFileNodes.get(i)); + } + this.fileList.setModel(listModel); + startTransform.setEnabled(selectedFileNodes.size() > 0); + transCountLabel.setText(String.valueOf(selectedFileNodes.size())); + } + + public void complete() { + dialog.dialogExit(); + updateProgressPane.reset(); + Map resultMap = transformer.getResults(); + resetFileNodeList(); + this.batchTransformPane.resetFilePaths(resultMap); + } + + private void resetFileNodeList(){ + this.selectedFileNodes.clear(); + buildFileList(); + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java new file mode 100644 index 0000000000..83eb534004 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java @@ -0,0 +1,70 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itree.filetree.FileTreeIcon; +import com.fr.file.filetree.FileNode; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ListSelectionModel; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformResultList extends UIList { + private Map resultMap; + private static final Icon FAILED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_failed.png"); + private static final Icon SUCCESS_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_success.png"); + private static final Icon UNSUPPORT_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_unsupport.png"); + + public TransformResultList() { + super(); + this.setBackground(UIConstants.TREE_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + DefaultListModel listModel = new DefaultListModel(); + this.setModel(listModel); + this.setCellRenderer(new UIListControlCellRenderer() { + @Override + protected Icon getLeftLabelIcon(Object value) { + if (value instanceof FileNode) { + return FileTreeIcon.getIcon((FileNode) value); + } + return null; + } + + @Override + protected Icon getRightLabelIcon(Object value) { + if (value != null) { + TransformResultInfo resultInfo = resultMap.get(value); + switch (resultInfo.getResult()) { + case FAILED: + return FAILED_ICON; + case SUCCESS: + return SUCCESS_ICON; + case UNSUPPORT: + return UNSUPPORT_ICON; + } + } + return null; + } + }); + } + + public void populate(Map resultMap) { + this.resultMap = resultMap; + DefaultListModel listModel = new DefaultListModel(); + Iterator> iterator = resultMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + FileNode key = entry.getKey(); + listModel.addElement(key); + } + this.setModel(listModel); + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java new file mode 100644 index 0000000000..6bed5aafc2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java @@ -0,0 +1,110 @@ +package com.fr.nx.app.designer.transform.ui; + +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.layout.FRGUIPaneFactory; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.toolbar.TransformResult; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by kerry on 2020-01-10 + */ +public class TransformResultPane extends JPanel { + private TransformResultList resultList; + private UITextArea resultInfo; + private Map resultMap; + private UILabel successTip; + + public TransformResultPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initPane(); + } + + private void initPane() { + JPanel resultPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Result")); + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + resultList = new TransformResultList(); + addValueChangeListener(); + UIScrollPane scrollPane = new UIScrollPane(resultList); + scrollPane.setPreferredSize(new Dimension(260, 260)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + successTip = new UILabel(""); + successTip.setBorder(BorderFactory.createEmptyBorder(5, 150, 5, 10)); + northPane.add(successTip, BorderLayout.NORTH); + northPane.add(scrollPane, BorderLayout.CENTER); + resultPane.add(northPane); + + JPanel resultInfoPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + resultInfoPane.setPreferredSize(new Dimension(270, 165)); + resultInfoPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5)); + UILabel transformLogLabel = new UILabel( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Logs")); + transformLogLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + resultInfoPane.add(transformLogLabel, BorderLayout.NORTH); + resultInfo = new UITextArea(); + resultInfo.setBackground(Color.white); + resultInfo.setLineWrap(true); + resultInfo.setWrapStyleWord(true); + resultInfo.setEditable(false); + UIScrollPane resultScrollPane = new UIScrollPane(resultInfo); + resultInfoPane.add(resultScrollPane, BorderLayout.CENTER); + this.add(resultPane, BorderLayout.NORTH); + this.add(resultInfoPane, BorderLayout.CENTER); + } + + private void addValueChangeListener() { + resultList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + FileNode selectedValue = (FileNode) resultList.getSelectedValue(); + if (resultInfo != null && selectedValue != null) { + TransformResultInfo result = resultMap.get(selectedValue); + resultInfo.setText(result.getTransformLog()); + } + } + }); + } + + public void populate(Map resultMap) { + int count = getSuccessCount(resultMap); + String tip = InterProviderFactory.getProvider().getLocText( + "Fine-Plugin_Engine_Transform_Result_Tip", String.valueOf(count)); + successTip.setText(tip); + this.resultMap = resultMap; + resultList.populate(resultMap); + if (resultList.getModel().getSize() > 0) { + resultList.setSelectedIndex(0); + FileNode firstResult = (FileNode) resultList.getModel().getElementAt(0); + resultInfo.setText(resultMap.get(firstResult).getTransformLog()); + } + } + + private int getSuccessCount(Map resultMap) { + int count = 0; + Iterator> iterator = resultMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + TransformResultInfo resultInfo = entry.getValue(); + if (ComparatorUtils.equals(TransformResult.SUCCESS, resultInfo.getResult())) { + count++; + } + } + return count; + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java new file mode 100644 index 0000000000..47f677238c --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java @@ -0,0 +1,86 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; +import sun.swing.DefaultLookup; + +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; + +/** + * Created by kerry on 2020-01-14 + */ +public class UIListControlCellRenderer extends JPanel implements ListCellRenderer { + private UILabel content; + private UILabel controlLabel; + private Color initialLabelForeground; + + public UIListControlCellRenderer() { + initPane(); + } + + private void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + content = new UILabel(); + initialLabelForeground = content.getForeground(); + controlLabel = new UILabel(); + controlLabel.setPreferredSize(new Dimension(16, 20)); + this.add(content, BorderLayout.CENTER); + this.add(controlLabel, BorderLayout.EAST); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + setComponentOrientation(list.getComponentOrientation()); + Color bg = null; + Color fg = null; + + JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground"); + fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground"); + + isSelected = true; + } + + if (isSelected) { + setBackground(bg == null ? list.getSelectionBackground() : bg); + setForeground(fg == null ? list.getSelectionForeground() : fg); + content.setForeground(Color.WHITE); + + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + content.setForeground(initialLabelForeground); + } + + content.setText((value == null) ? StringUtils.EMPTY : value.toString()); + Icon leftLabelIcon = getLeftLabelIcon(value); + if (leftLabelIcon != null) { + content.setIcon(leftLabelIcon); + } + Icon rightLabelIcon = getRightLabelIcon(value); + if (rightLabelIcon != null) { + controlLabel.setIcon(rightLabelIcon); + } + return this; + } + + protected Icon getLeftLabelIcon(Object value) { + return null; + } + + protected Icon getRightLabelIcon(Object value) { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java new file mode 100644 index 0000000000..6d9bb009b9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java @@ -0,0 +1,70 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.transform.BatchTransformer; + +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by kerry on 2019-12-19 + */ +public class UpdateProgressDialog extends JDialog implements ActionListener { + + private UIButton pauseBtn; + private BatchTransformer transformer; + + public UpdateProgressDialog(BatchTransformer transformer, Dialog parent, JPanel contentPane) { + super(parent, true); + this.transformer = transformer; + initPane(contentPane); + } + + private void initPane(JPanel contentPane) { + this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Format_Transform")); + this.setResizable(false); + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + pauseBtn = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend")); + pauseBtn.addActionListener(this); + JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(pauseBtn); + + defaultPane.add(contentPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + transformer.shutDown(); + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(pauseBtn); + + this.setSize(new Dimension(262, 122)); + GUICoreUtils.centerWindow(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + transformer.shutDown(); + dialogExit(); + } + + public void dialogExit() { + this.dispose(); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java new file mode 100644 index 0000000000..5fb57c369e --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java @@ -0,0 +1,72 @@ +package com.fr.nx.app.designer.transform.ui; + + +import com.fr.base.BaseUtils; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.transform.UpdateCallBack; +import com.sun.java.swing.plaf.motif.MotifProgressBarUI; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import java.awt.BorderLayout; +import java.awt.Dimension; + + +/** + * Created by kerry on 2019-12-11 + */ +public class UpdateProgressPane extends BasicPane implements UpdateCallBack { + private TransformPreparePane contentPane; + private JProgressBar progressBar; + + public UpdateProgressPane(TransformPreparePane contentPane) { + this.contentPane = contentPane; + initPane(); + } + + private void initPane() { + this.setPreferredSize(new Dimension(262, 60)); + UILabel icon = new UILabel(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transforming.png")); + icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); + this.add(icon, BorderLayout.WEST); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + UILabel title = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transforming")); + title.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); + centerPane.add(title, BorderLayout.NORTH); + progressBar = new JProgressBar(); + progressBar.setUI(new MotifProgressBarUI()); + progressBar.setForeground(UpdateConstants.BAR_COLOR); + centerPane.add(progressBar, BorderLayout.CENTER); + this.add(centerPane, BorderLayout.CENTER); + } + + + @Override + public void updateProgress(double progress) { + progressBar.setValue((int) (progress * 100)); + if (ComparatorUtils.equals(progress, 1D)) { + contentPane.complete(); + } + } + + @Override + public void shutDown() { + contentPane.complete(); + } + + @Override + public void reset() { + progressBar.setValue(0); + } + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend"); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java new file mode 100644 index 0000000000..3de788cd19 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java @@ -0,0 +1,55 @@ +package com.fr.nx.app.designer.utils; + +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.app.designer.toolbar.TemplateTransformer; +import com.fr.nx.app.designer.toolbar.TransformResult; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.workspace.WorkContext; + +import java.io.InputStream; + +import static com.fr.base.extension.FileExtension.CPT; +import static com.fr.base.extension.FileExtension.CPTX; + +/** + * Created by kerry on 2019-12-04 + */ +public class CompileTransformUtil { + + + public static TransformResultInfo compileFile(FileNode fileNode) { + long start = System.currentTimeMillis(); + InputStream in = WorkContext.getWorkResource().openStream(fileNode.getEnvPath()); + WorkBook workBook = new WorkBook(); + TransformResultInfo result = null; + try { + workBook.readStream(in); + FILE file = TemplateTransformer.createOutputFile(fileNode.getEnvPath(), CPT.getSuffix(), CPTX.getSuffix()); + result = TemplateTransformer.compileCPTX(workBook, file); + } catch (Exception ignore) { + result = TransformResultInfo.generateResult(TransformResult.FAILED); + } + long end = System.currentTimeMillis(); + FineLoggerFactory.getLogger().debug(fileNode.getName() + " compile cost : " + (end - start) +" ms "); + return result; + } + + + public static FILE getTargetFile(JTemplate jTemplate, TemplateTransformer transformer) { + FILE file = null; + if (ComparatorUtils.equals(TemplateTransformer.TO_CPTX, transformer)) { + file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(), + CPT.getSuffix(), CPTX.getSuffix()); + + } else if (ComparatorUtils.equals(TemplateTransformer.TO_CPT, transformer)) { + file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(), + CPTX.getSuffix(), CPT.getSuffix()); + } + return file; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/utils/CptAndCptxCompatibilityUtil.java b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CptAndCptxCompatibilityUtil.java new file mode 100644 index 0000000000..0b1a65657a --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CptAndCptxCompatibilityUtil.java @@ -0,0 +1,88 @@ +package com.fr.nx.app.designer.utils; + +import com.fr.base.extension.FileExtension; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.main.TemplateWorkBook; +import com.fr.report.report.Report; +import com.fr.report.stable.LayerReportAttr; +import com.fr.report.worksheet.WorkSheet; + +/** + * @author fly.li + * @version 10.0 + * Created on 2021/09/12 + */ +public class CptAndCptxCompatibilityUtil { + + /** + * 判断是否需要重新编译 + **/ + public static boolean needRecompile(String oldName, JTemplate jTemplate){ + FILE editingFILE = jTemplate.getEditingFILE(); + String path = editingFILE.getPath(); + //只有在旧文件是cptx文件并且新文件是cpt文件时才会改变报表引擎属性 + boolean isCptxConvertToCpt = FileExtension.CPTX.matchExtension(oldName) && FileExtension.CPT.matchExtension(path); + if (isCptxConvertToCpt && !setFrEngineAttr(jTemplate)){ + isCptxConvertToCpt = false; + } + return (isCptxConvertToCpt || isSaveAs(jTemplate, oldName, path)); + } + + /** + * 判断是不是cptx模板或者开启了的新引擎的cpt模板的另存为操作 + **/ + private static boolean isSaveAs(JTemplate jTemplate, String oldName, String newName){ + return isEngineXEnable(jTemplate.getTarget(), newName) && ((FileExtension.CPTX.matchExtension(oldName) && FileExtension.CPTX.matchExtension(newName)) || (FileExtension.CPT.matchExtension(oldName) && FileExtension.CPT.matchExtension(newName))); + } + + /** + * cptx另存为cpt需要修改报表引擎属性 + **/ + private static boolean setFrEngineAttr(JTemplate jTemplate){ + WorkSheet workSheet = gainWorkSheet(jTemplate.getTarget()); + if (workSheet == null){ + return false; + }else { + LayerReportAttr layerReportAttr = workSheet.getLayerReportAttr(); + if (layerReportAttr == null){ + layerReportAttr = new LayerReportAttr(); + workSheet.setLayerReportAttr(layerReportAttr); + } + layerReportAttr.setClientPaging(true); + layerReportAttr.setEngineState(0); + return true; + } + } + + /** + * 是否启用了新引擎的判断 + * cptx自动走新引擎(非兼容模式),cpt需要进行设置 + * */ + public static boolean isEngineXEnable(Object workBook, String fileName){ + WorkSheet workSheet = gainWorkSheet(workBook); + LayerReportAttr layerReportAttr = gainLayerReportAttr(workSheet); + return isEngineXEnable(layerReportAttr, fileName); + } + + private static LayerReportAttr gainLayerReportAttr(WorkSheet workSheet){ + if (workSheet != null){ + LayerReportAttr layerReportAttr = workSheet.getLayerReportAttr(); + return layerReportAttr; + } else { + return null; + } + } + + private static WorkSheet gainWorkSheet(Object workBook){ + if (workBook == null || !(workBook instanceof TemplateWorkBook)){ + return null; + } + Report report = ((TemplateWorkBook) workBook).getReport(0); + return report instanceof WorkSheet ? (WorkSheet)report : null; + } + + private static boolean isEngineXEnable(LayerReportAttr layerReportAttr, String fileName){ + return (layerReportAttr!= null && layerReportAttr.isClientPaging() && layerReportAttr.getEngineState() == LayerReportAttr.ENGINE_X) || FileExtension.CPTX.matchExtension(fileName); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/utils/CptCompileUtil.java b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CptCompileUtil.java new file mode 100644 index 0000000000..36c1846709 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CptCompileUtil.java @@ -0,0 +1,153 @@ +package com.fr.nx.app.designer.utils; + +import com.fr.base.extension.FileExtension; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.app.designer.cptx.io.DesignReadWritableProvider; +import com.fr.nx.app.designer.monitor.DesignerMetricRecorder; +import com.fr.nx.app.designer.toolbar.TransformResult; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.nx.compile.CompileStatus; +import com.fr.nx.compile.ReportCompiler; +import com.fr.nx.compile.adapter.LegacyWorkBookAdapter; +import com.fr.nx.compile.util.ReportCompileUtils; +import com.fr.nx.cptx.CptxIOManager; +import com.fr.nx.cptx.cache.CptxTemplatePool; +import com.fr.nx.cptx.entry.CptxTemplate; +import com.fr.nx.cptx.io.handle.CptxTemplateHandle; +import com.fr.nx.cptx.monitor.CompileMonitorHandler; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.nx.data.layer.LayerItem; +import com.fr.nx.data.layer.LayerProps; +import com.fr.nx.template.compile.CompiledReport; + +import java.io.OutputStream; + + +public class CptCompileUtil { + public static void compile(JTemplate jtemplate) { + if (jtemplate == null || jtemplate.getEditingFILE() == null) { + return; + } + FILE file = jtemplate.getEditingFILE(); + String path = file.getPath(); + Object target = jtemplate.getTarget(); + /* + * 如果是cpt并且引擎设置正确,执行预编译,如果是cptx文件也执行预编译。在JStreamWork中,保存和另存为流程都进行了重新编译。 + * 但是由于之前的DefaultTemplateResource.saveTemplate的原因导致JStreamWork::saveFile()不能执行--cptx的保存不能进行预编译, + * 应该是流程的误改动,这里改回来,保存时仍然执行预编译。 + * 预编译本不应该受引擎模式的影响,但是cpt文件在设置为新引擎后是需要进行编译的 + * */ + + if (!CptAndCptxCompatibilityUtil.isEngineXEnable(target, path)){ + return; + } + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + TransformResultInfo resultInfo = compile0(workbook, file); + unSupportLog(resultInfo); + + } + + private static TransformResultInfo compile0(WorkBook workbook, FILE file) { + if (!(file instanceof FileNodeFILE)) { + try { + OutputStream outputStream = file.asOutputStream(); + workbook.export(outputStream); + return TransformResultInfo.generateResult(TransformResult.SUCCESS).saved(true); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResultInfo.generateResult(TransformResult.FAILED).saved(false); + } + } + boolean saved; + CompiledReport report = null; + CompileStatus compileStatus = CompileStatus.SUCCEED; + if (workbook == null || file == null) { + return TransformResultInfo + .generateResult(TransformResult.FAILED, "work and file must not be null") + .saved(false); + } + String failMessage = null; + // 编译 + ReportCompiler compiler; + try { + compiler = new ReportCompiler(new LegacyWorkBookAdapter(workbook)); + long startTime = System.currentTimeMillis(); + compiler.compile(); + report = compiler.getCompiledReport(); + // 折叠树埋点 + LayerProps props = ReportCompileUtils.getLayerProps(report); + LayerItem[] items; + if (props != null && (items = props.getLayerItems()) != null) { + CompileMonitorHandler.submitTreeCompileFocusPoint( + startTime, file.getPath(), items.length, + props.getExpandLayer(), true + ); + } + compileStatus = compiler.getStatus(); + failMessage = compiler.getFailMessage(); + long endTime = System.currentTimeMillis(); + CompileMonitorHandler.submitCompileMessage(startTime, endTime, file.getPath(), ""); + if (compileStatus != CompileStatus.SUCCEED) { + DesignerMetricRecorder.submitUnSupportTransform( + TransformResult.UNSUPPORT, + workbook.getTemplateID(), + file.getName(), + compileStatus == CompileStatus.FAILED_UNSUPPORT ? failMessage : null + ); + } + } catch (Exception exception) { + String templateID = workbook.getTemplateID(); + String fileName = file.getName(); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, templateID, fileName, exception); + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + } + + // 构建编译结果,当前的 cptx template 是未经反序列化钩子处理过的 cptx 模版对象,不能直接用于模版预览 + CptxTemplate template = CptxIOManager.createCptxTemplate(workbook, report, compileStatus, failMessage); + // 保存 + DesignReadWritableProvider cptx = new DesignReadWritableProvider(file); + CptxTemplateHandle handle = CptxIOManager.create(template, cptx); + try { + saved = handle.save(); + } catch (Exception exception) { + // 存储cptx格式报错或者失败 + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, workbook.getTemplateID(), file.getName(), exception); + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(false); + } + // 读取可 web 预览模版并缓存 + try { + CptxTemplate previewCptxTemplate = CptxIOManager.open(cptx).getTemplate(); + CptxTemplatePool.getInstance().addCptxTemplate(CptxFileUtils.getFormatPath(file.getPath()), previewCptxTemplate); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (report == null) { + // 编译报错或者失败 + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(saved); + } + return TransformResultInfo.generateResult(TransformResult.parse(compileStatus), failMessage).saved(saved); + } + + private static boolean needDoAfterCompile(TransformResult result) { + return ComparatorUtils.equals(TransformResult.SUCCESS, result) + || ComparatorUtils.equals(TransformResult.UNSUPPORT, result); + } + + private static void unSupportLog(TransformResultInfo transformResultInfo){ + TransformResult result = transformResultInfo.getResult(); + //这里只打印模板转换不支持的信息,没有打印模板转换失败的信息 + if (result.equals(TransformResult.UNSUPPORT)){ + FineLoggerFactory.getLogger().error(transformResultInfo.getTransformLog()); + } + } + + private static boolean isUnSupportFileType(String path){ + return FileExtension.CPT.matchExtension(path) || FileExtension.CPTX.matchExtension(path); + } +} diff --git a/designer-base/src/main/java/com/fr/start/BaseDesigner.java b/designer-base/src/main/java/com/fr/start/BaseDesigner.java index b3945d0d7f..6165ff7f7c 100644 --- a/designer-base/src/main/java/com/fr/start/BaseDesigner.java +++ b/designer-base/src/main/java/com/fr/start/BaseDesigner.java @@ -11,6 +11,7 @@ import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.file.TemplateTreePane; import com.fr.design.fun.DesignerStartOpenFileProcessor; +import com.fr.design.fun.impl.DesignerStartWithEmptyFile; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrame; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; @@ -31,6 +32,7 @@ import com.fr.process.engine.core.CarryMessageEvent; import com.fr.process.engine.core.FineProcessContext; import com.fr.stable.OperatingSystem; +import com.fr.workspace.base.WorkspaceStatus; import java.awt.Window; import java.io.File; import java.lang.reflect.Method; @@ -83,6 +85,7 @@ public abstract class BaseDesigner extends ToolBarMenuDock { if (eventPipe != null) { eventPipe.fire(new CarryMessageEvent(ReportState.STOP.getValue())); } + EventDispatcher.fire(WorkspaceStatus.Prepared); collectUserInformation(); } }); @@ -147,6 +150,10 @@ public abstract class BaseDesigner extends ToolBarMenuDock { //启动时打开指定文件的接口 DesignerStartOpenFileProcessor processor = ExtraDesignClassManager.getInstance().getSingle(DesignerStartOpenFileProcessor.XML_TAG); + // 如果插件没有,且又开启了启动时打开空文件,则使用启动时打开空文件 + if (processor == null && DesignerEnvManager.getEnvManager().isStartWithEmptyFile()) { + processor = DesignerStartWithEmptyFile.getInstance(); + } if (processor != null) { FILE f = processor.fileToShow(); if (f != null) { diff --git a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java index 854d260bf5..35e2090d93 100644 --- a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java +++ b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java @@ -8,8 +8,10 @@ import com.fr.stable.EncodeConstants; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; import com.fr.startup.FineWebApplicationInitializer; +import com.fr.third.guava.collect.Sets; import com.fr.third.springframework.web.SpringServletContainerInitializer; import com.fr.third.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import com.fr.web.socketio.WebSocketEndpoint; import com.fr.workspace.WorkContext; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; @@ -17,6 +19,7 @@ import org.apache.catalina.Wrapper; import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.webresources.StandardRoot; +import org.apache.tomcat.websocket.server.WsSci; import java.io.File; import java.util.HashSet; @@ -92,6 +95,7 @@ public class FineEmbedServerActivator extends Activator { Set> classes = new HashSet>(); classes.add(FineWebApplicationInitializer.class); context.addServletContainerInitializer(initializer, classes); + context.addServletContainerInitializer(new WsSci(), Sets.newHashSet(WebSocketEndpoint.class)); } // tomcat的maxPostSize会影响到post参数获取,默认2M diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties index 786fe2ad0c..aa4a83f3e4 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties @@ -12,4 +12,6 @@ com.fr.design.web.pane.text.field=450*20 com.fr.design.actions.server.dialog=800*630 com.fr.design.report.fit.templatePane.dialog=800*400 com.fr.design.report.fit.firstColumn=120*20 -com.fr.design.report.fit.column=160*20 \ No newline at end of file +com.fr.design.report.fit.column=160*20 +com.fr.design.lock.LockInfoDialog=500*180 +com.fr.design.mainframe.ForbiddenPane.refreshButton=75*24 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties index 0956fa79d7..96558262fd 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties @@ -11,4 +11,6 @@ com.fr.design.web.pane.text.field=400*20 com.fr.design.actions.server.dialog=700*630 com.fr.design.report.fit.templatePane.dialog=600*400 com.fr.design.report.fit.firstColumn=170*20 -com.fr.design.report.fit.column=100*20 \ No newline at end of file +com.fr.design.report.fit.column=100*20 +com.fr.design.lock.LockInfoDialog=500*180 +com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties index 17031793ff..05e20c7aa8 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties @@ -11,4 +11,6 @@ com.fr.design.web.pane.text.field=450*20 com.fr.design.actions.server.dialog=700*630 com.fr.design.report.fit.templatePane.dialog=600*400 com.fr.design.report.fit.firstColumn=130*20 -com.fr.design.report.fit.column=100*20 \ No newline at end of file +com.fr.design.report.fit.column=100*20 +com.fr.design.lock.LockInfoDialog=500*180 +com.fr.design.mainframe.ForbiddenPane.refreshButton=80*24 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties index 931b79b44f..a4b2993e60 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties @@ -12,4 +12,6 @@ com.fr.design.web.pane.text.field=450*20 com.fr.design.actions.server.dialog=700*630 com.fr.design.report.fit.templatePane.dialog=600*400 com.fr.design.report.fit.firstColumn=80*20 -com.fr.design.report.fit.column=100*20 \ No newline at end of file +com.fr.design.report.fit.column=100*20 +com.fr.design.lock.LockInfoDialog=400*160 +com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties index 8ea7fd7c26..5813cd96cc 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties @@ -11,4 +11,6 @@ com.fr.design.web.pane.text.field=450*20 com.fr.design.actions.server.dialog=700*630 com.fr.design.report.fit.templatePane.dialog=600*400 com.fr.design.report.fit.firstColumn=80*20 -com.fr.design.report.fit.column=100*20 \ No newline at end of file +com.fr.design.report.fit.column=100*20 +com.fr.design.lock.LockInfoDialog=400*160 +com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/buttonicon/select_disabled.svg b/designer-base/src/main/resources/com/fr/design/images/buttonicon/select_disabled.svg new file mode 100644 index 0000000000..b21c206a3a --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/buttonicon/select_disabled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/buttonicon/select_normal.svg b/designer-base/src/main/resources/com/fr/design/images/buttonicon/select_normal.svg new file mode 100644 index 0000000000..60a2855aa5 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/buttonicon/select_normal.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png new file mode 100644 index 0000000000..0e8dce8ef4 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png new file mode 100644 index 0000000000..2f519cf39e Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/gui/file_lock.png b/designer-base/src/main/resources/com/fr/design/images/gui/file_lock.png new file mode 100644 index 0000000000..a0b08e6e27 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/gui/file_lock.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/m_file/formula.png b/designer-base/src/main/resources/com/fr/design/images/m_file/formula.png new file mode 100644 index 0000000000..7e495da1b2 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/m_file/formula.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/m_file/param.png b/designer-base/src/main/resources/com/fr/design/images/m_file/param.png new file mode 100644 index 0000000000..011c395813 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/m_file/param.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/mainframe/openloading.png b/designer-base/src/main/resources/com/fr/design/images/mainframe/loading.png similarity index 100% rename from designer-base/src/main/resources/com/fr/design/images/mainframe/openloading.png rename to designer-base/src/main/resources/com/fr/design/images/mainframe/loading.png diff --git a/designer-base/src/main/resources/com/fr/design/images/mainframe/lock_template.png b/designer-base/src/main/resources/com/fr/design/images/mainframe/lock_template.png new file mode 100644 index 0000000000..f75bfe4799 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/mainframe/lock_template.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/mainframe/refreh_icon.png b/designer-base/src/main/resources/com/fr/design/images/mainframe/refreh_icon.png new file mode 100644 index 0000000000..99b4e53740 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/mainframe/refreh_icon.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/add.png b/designer-base/src/main/resources/com/fr/design/images/sort/add.png new file mode 100644 index 0000000000..a14e2a40b8 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/sort/add.png differ 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 new file mode 100644 index 0000000000..67dd9e829e --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/sort/asc.svg @@ -0,0 +1,19 @@ + + + 升序备份 + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 0000000000..2fcef077e6 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/sort/des.svg @@ -0,0 +1,17 @@ + + + 降序 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/down_arrow.png b/designer-base/src/main/resources/com/fr/design/images/sort/down_arrow.png new file mode 100644 index 0000000000..84b4909efc Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/sort/down_arrow.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/left_arrow.png b/designer-base/src/main/resources/com/fr/design/images/sort/left_arrow.png new file mode 100644 index 0000000000..9166a9c96d Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/sort/left_arrow.png differ 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 new file mode 100644 index 0000000000..ca04928fc8 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/sort/nosort.svg @@ -0,0 +1,41 @@ + + + 不排序 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/sort/sequence.png b/designer-base/src/main/resources/com/fr/design/images/sort/sequence.png new file mode 100644 index 0000000000..ac321ae174 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/sort/sequence.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/toolbarbtn/lock.png b/designer-base/src/main/resources/com/fr/design/images/toolbarbtn/lock.png new file mode 100644 index 0000000000..882bbaeb32 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/toolbarbtn/lock.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/toolbarbtn/unlock.png b/designer-base/src/main/resources/com/fr/design/images/toolbarbtn/unlock.png new file mode 100644 index 0000000000..69def397ee Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/toolbarbtn/unlock.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/transparent_background.png b/designer-base/src/main/resources/com/fr/design/images/transparent_background.png new file mode 100644 index 0000000000..3db1fd14f2 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/transparent_background.png differ diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_down.png b/designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_down.png new file mode 100644 index 0000000000..cf65b3bc4f Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_down.png differ diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_right.png b/designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_right.png new file mode 100644 index 0000000000..a1ac42cfea Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_right.png differ diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/close.png b/designer-base/src/main/resources/com/fr/design/mainframe/guide/close.png new file mode 100644 index 0000000000..6f17a8e1c7 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/mainframe/guide/close.png differ diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_all.svg b/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_all.svg new file mode 100644 index 0000000000..f18c158027 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_all.svg @@ -0,0 +1,13 @@ + + + 全部完成 + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_none.svg b/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_none.svg new file mode 100644 index 0000000000..ec078243bf --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_none.svg @@ -0,0 +1,13 @@ + + + 未完成@2x + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_some.svg b/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_some.svg new file mode 100644 index 0000000000..e6151ea038 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_some.svg @@ -0,0 +1,23 @@ + + + 部分完成 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/guide.png b/designer-base/src/main/resources/com/fr/design/mainframe/guide/guide.png new file mode 100644 index 0000000000..ef5a197834 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/mainframe/guide/guide.png differ diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/loading.gif b/designer-base/src/main/resources/com/fr/design/mainframe/guide/loading.gif new file mode 100644 index 0000000000..90d13277af Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/mainframe/guide/loading.gif differ diff --git a/designer-base/src/main/resources/com/fr/design/mainframe/guide/success.png b/designer-base/src/main/resources/com/fr/design/mainframe/guide/success.png new file mode 100644 index 0000000000..efd7a04f4b Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/mainframe/guide/success.png differ diff --git a/designer-base/src/main/resources/com/fr/env/jarVersion.properties b/designer-base/src/main/resources/com/fr/env/jarVersion.properties index 8619fca7c3..7eff54deba 100644 --- a/designer-base/src/main/resources/com/fr/env/jarVersion.properties +++ b/designer-base/src/main/resources/com/fr/env/jarVersion.properties @@ -1 +1 @@ -report-engine-key=fine-report-engine-10.0.jar \ No newline at end of file +report-engine-key=fine-report-engine-11.0.jar \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfoTest.java b/designer-base/src/test/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfoTest.java index c90e7a8b05..4095390016 100644 --- a/designer-base/src/test/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfoTest.java +++ b/designer-base/src/test/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfoTest.java @@ -18,13 +18,11 @@ public class ComponentReuseNotificationInfoTest { @Test public void testReadXML() { try { - XMLableReader xmlReader = XMLableReader.createXMLableReader(new StringReader("\n")); + XMLableReader xmlReader = XMLableReader.createXMLableReader(new StringReader("\n")); ComponentReuseNotificationInfo notificationInfo = ComponentReuseNotificationInfo.getInstance(); notificationInfo.readXML(xmlReader); xmlReader.close(); - Assert.assertEquals(2, notificationInfo.getNotifiedNumber()); Assert.assertEquals(true, notificationInfo.isClickedWidgetLib()); - Assert.assertEquals(1620612153215L, notificationInfo.getLastNotifyTime()); } catch (XMLStreamException e) { Assert.fail(e.getMessage()); } @@ -35,12 +33,11 @@ public class ComponentReuseNotificationInfoTest { StringWriter sw = new StringWriter(); XMLPrintWriter writer = XMLPrintWriter.create(new PrintWriter(sw)); ComponentReuseNotificationInfo notificationInfo = ComponentReuseNotificationInfo.getInstance(); - notificationInfo.setNotifiedNumber(1); notificationInfo.writeXML(writer); writer.flush(); writer.close(); Assert.assertEquals("\n" + - "\n", sw.toString()); + "\n", sw.toString()); } } diff --git a/designer-base/src/test/java/com/fr/design/upm/UpmUtilsTest.java b/designer-base/src/test/java/com/fr/design/upm/UpmUtilsTest.java index 31119d049c..5d96a6f0b3 100644 --- a/designer-base/src/test/java/com/fr/design/upm/UpmUtilsTest.java +++ b/designer-base/src/test/java/com/fr/design/upm/UpmUtilsTest.java @@ -34,7 +34,7 @@ public class UpmUtilsTest { EasyMock.expect(ServerPreferenceConfig.getInstance()).andReturn(serverPreferenceConfig).anyTimes(); CloudCenter cloudCenter = EasyMock.mock(CloudCenter.class); - EasyMock.expect(cloudCenter.acquireUrlByKind("upm.script.version")).andReturn("2.0").anyTimes(); + EasyMock.expect(cloudCenter.acquireUrlByKind("upm.script.version.v11")).andReturn("2.0").anyTimes(); PowerMock.mockStatic(CloudCenter.class); EasyMock.expect(CloudCenter.getInstance()).andReturn(cloudCenter).anyTimes(); diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java new file mode 100644 index 0000000000..6a8f8247bd --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java @@ -0,0 +1,239 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.Parameter; +import com.fr.base.chart.BaseChartCollection; +import com.fr.base.io.XMLEncryptKey; +import com.fr.base.io.XMLEncryptUtils; +import com.fr.base.iofile.IOFileAttrMarkManager; +import com.fr.base.parameter.ParameterUI; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.config.dao.DaoContext; +import com.fr.config.dao.impl.LocalClassHelperDao; +import com.fr.config.dao.impl.LocalEntityDao; +import com.fr.config.dao.impl.LocalXmlEntityDao; +import com.fr.file.MemFILE; +import com.fr.form.DefaultFormOperator; +import com.fr.form.FormOperator; +import com.fr.form.main.ExtraFormClassManager; +import com.fr.form.main.Form; +import com.fr.form.main.FormHyperlink; +import com.fr.form.main.parameter.FormParameterUI; +import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.plugin.DefaultSwitcherImpl; +import com.fr.general.xml.GeneralXMLTools; +import com.fr.io.EncryptUtils; +import com.fr.js.FormHyperlinkProvider; +import com.fr.main.impl.WorkBook; +import com.fr.nx.calculable.Calculable; +import com.fr.nx.calculable.type.ConstantCalculable; +import com.fr.nx.cell.CellKey; +import com.fr.nx.cell.CellTemplate; +import com.fr.nx.cptx.cache.CptxTemplatePool; +import com.fr.nx.cptx.entry.CptxTemplate; +import com.fr.nx.cptx.resource.ImageResourceRef; +import com.fr.page.BaseSinglePagePrintable; +import com.fr.page.BaseSingleReportCache; +import com.fr.page.ClippedChartPage; +import com.fr.page.ClippedECPage; +import com.fr.page.ClippedPageProvider; +import com.fr.page.PDF2Painter; +import com.fr.page.PageGeneratorProvider; +import com.fr.page.PagePainter; +import com.fr.page.PagePainterProvider; +import com.fr.page.PageSetChainProvider; +import com.fr.page.PageSetProvider; +import com.fr.page.PageXmlOperator; +import com.fr.page.PageXmlProvider; +import com.fr.page.PaperSettingProvider; +import com.fr.page.ReportPage; +import com.fr.page.ReportPageAttrProvider; +import com.fr.page.ReportPageProvider; +import com.fr.page.SheetPage; +import com.fr.page.SinglePagePrintable; +import com.fr.page.SingleReportCache; +import com.fr.page.generator.PaginateReportPageGenerator; +import com.fr.page.generator.PolyReportPageGenerator; +import com.fr.page.generator.SheetPageGenerator; +import com.fr.page.pageset.ArrayPageSet; +import com.fr.page.pageset.PageSetChain; +import com.fr.page.stable.PaperSetting; +import com.fr.page.stable.ReportPageAttr; +import com.fr.plugin.attr.CalculatorAttrMark; +import com.fr.runtime.FineRuntime; +import com.fr.stable.EssentialUtils; +import com.fr.stable.bridge.BridgeMark; +import com.fr.stable.bridge.StableFactory; +import com.fr.stable.fun.WidgetSwitcher; +import com.fr.stable.module.Module; +import com.fr.stable.plugin.ExtraFormClassManagerProvider; +import com.fr.transaction.Configurations; +import com.fr.transaction.LocalConfigurationHelper; +import com.fr.xml.ReportXMLUtils; +import org.easymock.EasyMock; +import org.easymock.IArgumentMatcher; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import java.io.InputStream; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({CptxTemplatePool.class, XMLEncryptUtils.class}) +@SuppressStaticInitializationFor({"com.fr.nx.cptx.cache.CptxTemplatePool", "com.fr.base.io.XMLEncryptUtils"}) +@PowerMockIgnore({"com.sun.tools.attach.*", "sun.tools.attach.*"}) +public class TemplateTransformerDebugTest { + + @BeforeClass + public static void beforeClass() { + System.setProperty("apple.awt.UIElement", "true"); + StableFactory.registerXMLDescription(ReportPageAttrProvider.XML_TAG, new ReportPageAttr()); + StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG, ReportPage.class); + StableFactory.registerMarkedClass(PaperSettingProvider.XML_TAG, PaperSetting.class); + StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG_4_SHEET, SheetPage.class); + StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG, PagePainter.class); + StableFactory.registerMarkedClass(PageSetChainProvider.XML_TAG, PageSetChain.class); + StableFactory.registerMarkedClass(PageXmlProvider.XML_TAG, PageXmlOperator.class); + StableFactory.registerMarkedClass(BaseSinglePagePrintable.XML_TAG, SinglePagePrintable.class); + StableFactory.registerMarkedClass(BaseSingleReportCache.XML_TAG, SingleReportCache.class); + StableFactory.registerMarkedClass(PageSetProvider.XML_TAG_4_ARRAY, ArrayPageSet.class); + StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_EC, ClippedECPage.class); + StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_CHART, ClippedChartPage.class); + StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_PAGE, PaginateReportPageGenerator.class); + StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_POLY, PolyReportPageGenerator.class); + StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_SHEET, SheetPageGenerator.class); + StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG_4_PDF, PDF2Painter.class); + StableFactory.registerMarkedClass(BridgeMark.SUBMIT_BUTTON, FormSubmitButton.class); + StableFactory.registerMarkedClass(FormOperator.MARK_STRING, DefaultFormOperator.class); + StableFactory.registerMarkedClass(Module.FORM_MODULE, Form.class); + StableFactory.registerMarkedClass(ParameterUI.FORM_XML_TAG, FormParameterUI.class); + StableFactory.registerMarkedClass(FormHyperlinkProvider.XML_TAG, FormHyperlink.class); + StableFactory.registerMarkedObject(WidgetSwitcher.XML_TAG, new DefaultSwitcherImpl()); + StableFactory.registerMarkedClass(ExtraFormClassManagerProvider.XML_TAG, ExtraFormClassManager.class); + StableFactory.registerXMLDescription(BaseChartCollection.XML_TAG, new ChartCollection()); + StableFactory.registerXMLDescription(Parameter.XML_TAG, new Parameter()); + FineRuntime.start(); + GeneralXMLTools.Object_Tokenizer = new ReportXMLUtils.ReportObjectTokenizer(); + GeneralXMLTools.Object_XML_Writer_Finder = new ReportXMLUtils.ReportObjectXMLWriterFinder(); + DaoContext.setEntityDao(new LocalEntityDao()); + DaoContext.setClassHelperDao(new LocalClassHelperDao()); + DaoContext.setXmlEntityDao(new LocalXmlEntityDao()); + Configurations.setHelper(new LocalConfigurationHelper()); + + IOFileAttrMarkManager.register(new CalculatorAttrMark()); + } + + @Before + public void before() { + Whitebox.setInternalState(XMLEncryptUtils.class, "KEY", new XMLEncryptKey()); + } + + @Test + public void testUnsupportedCompile() { + WorkBook workbook = readCpt("read-write-expand-order.cpt"); + + CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class); + PowerMock.mockStatic(CptxTemplatePool.class); + EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes(); + + PowerMock.replay(CptxTemplatePool.class); + pool.addCptxTemplate(EasyMock.anyString(), matchUnsupportedWebPreviewCptxTemplate()); + EasyMock.expectLastCall().once(); + + EasyMock.replay(pool); + TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-expand-order.cpt")); + + EasyMock.verify(pool); + PowerMock.verify(CptxTemplatePool.class); + + } + + @Test + public void testImageRefCompile() { + WorkBook workbook = readCpt("read-write-image-ref.cpt"); + + CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class); + PowerMock.mockStatic(CptxTemplatePool.class); + EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes(); + + PowerMock.replay(CptxTemplatePool.class); + pool.addCptxTemplate(EasyMock.anyString(), matchImageRefWebPreviewCptxTemplate()); + EasyMock.expectLastCall().once(); + + EasyMock.replay(pool); + TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-image-ref.cpt")); + + EasyMock.verify(pool); + PowerMock.verify(CptxTemplatePool.class); + + } + + private CptxTemplate matchImageRefWebPreviewCptxTemplate() { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object argument) { + if (argument instanceof CptxTemplate) { + CptxTemplate cptxTemplate = (CptxTemplate) argument; + Assert.assertNotNull(cptxTemplate.getTemplate()); + Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult()); + Assert.assertEquals(1, cptxTemplate.getTemplate().getCompileResult().getCellBlocks().length); + Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure()); + Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells()); + CellTemplate cellTemplate = cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells().get(CellKey.fromString("A2")); + Assert.assertNotNull(cellTemplate); + Calculable calculable = cellTemplate.getCalculable(); + ConstantCalculable constantCalculable = calculable.unWrap(ConstantCalculable.KEY); + Assert.assertNotNull(constantCalculable); + Assert.assertTrue(constantCalculable.get() instanceof ImageResourceRef); + return true; + } + return false; + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("cptx template should be previewed on the web side but not."); + } + }); + return null; + } + + private CptxTemplate matchUnsupportedWebPreviewCptxTemplate() { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object argument) { + if (argument instanceof CptxTemplate) { + CptxTemplate cptxTemplate = (CptxTemplate) argument; + Assert.assertEquals("unsupported feature: sort after expand", + cptxTemplate.getMetadata().getFailMessage()); + return true; + } + return false; + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("should find unsupported error message but not"); + } + }); + return null; + } + + private static WorkBook readCpt(String subPath) { + InputStream is = TemplateTransformerDebugTest.class.getClassLoader().getResourceAsStream("cpt/" + subPath); + WorkBook wb = new WorkBook(); + try { + wb.readStream(EncryptUtils.decodeInputStream(is)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return wb; + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java new file mode 100644 index 0000000000..e0afe9313e --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java @@ -0,0 +1,85 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.FRContext; +import com.fr.base.operator.common.CommonOperator; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNodes; +import com.fr.invoke.Reflect; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static com.fr.nx.app.designer.toolbar.TemplateTransformer.OTHER; +import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPT; +import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPTX; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({FRContext.class}) +@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*", "com.fr.license.*"}) +public class TemplateTransformerTest { + + @Test + public void testParse() { + assertEquals(TO_CPTX, TemplateTransformer.parse("/sdf/abc.cpt")); + assertEquals(TO_CPT, TemplateTransformer.parse("/sdf/abc.cptx")); + assertEquals(OTHER, TemplateTransformer.parse("/sdf/abc.frm")); + assertEquals(OTHER, TemplateTransformer.parse(null)); + assertEquals(OTHER, TemplateTransformer.parse("abc")); + } + + @Test + public void testCompileFailed() { + TransformResultInfo result = TemplateTransformer.compileCPTX(null, null); + assertEquals(result.getResult(), TransformResult.FAILED); + } + + @Test + public void testGenerateNewPath() { + assertEquals(generateNewPath("/abc/dd.cpt", ".cpt", ".cptx"), "/abc/dd.cptx"); + assertEquals(generateNewPath("/abc/dd.cptx", ".cpt", ".cptx"), "/abc/dd.cptx"); + assertEquals(generateNewPath("/abc/dd.cptx", ".cptx", ".cpt"), "/abc/dd.cpt"); + assertEquals(generateNewPath("/abc/dd.frm", ".cpt", ".cptx"), "/abc/dd.frm"); + assertNull(generateNewPath(null, null, null)); + assertEquals(generateNewPath("abc", null, null), "abc"); + } + + private String generateNewPath(String oldPath, String oldSuffix, String newSuffix) { + return Reflect.on(TemplateTransformer.class).call("generateNewPath", oldPath, oldSuffix, newSuffix).get(); + } + + @Test + public void testCreateOutputFile() { + CommonOperator commonOperator = EasyMock.mock(CommonOperator.class); + FileNodes fileNodes = EasyMock.mock(FileNodes.class); + EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes(); + PowerMock.mockStatic(FRContext.class); + EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes(); + EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes(); + EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes(); + EasyMock.replay(commonOperator, fileNodes); + PowerMock.replayAll(); + FILE file1 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cpt", ".cptx"); + FILE file2 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cptx", ".cpt"); + assertEquals("WorkBook1.cptx", file1.getPath()); + assertEquals("WorkBook1.cpt", file2.getPath()); + } + + + @Test + public void testNeedDoAfterTransformed() { + Assert.assertTrue(needDoAfterTransformed(TransformResult.SUCCESS)); + Assert.assertTrue(needDoAfterTransformed(TransformResult.UNSUPPORT)); + Assert.assertFalse(needDoAfterTransformed(TransformResult.FAILED)); + } + + private boolean needDoAfterTransformed(TransformResult result) { + return Reflect.on(TemplateTransformer.class).call("needDoAfterTransformed", result).get(); + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java new file mode 100644 index 0000000000..66a32b95f2 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java @@ -0,0 +1,32 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.locale.InterProviderFactory; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class TransformResultInfoTest { + @Test + public void testGetTransformLog() { + TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed"); + Assert.assertEquals("failed\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"), + resultInfo1.getTransformLog()); + TransformResultInfo resultInfo2 = TransformResultInfo.generateResult(TransformResult.SUCCESS); + Assert.assertEquals(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"), + resultInfo2.getTransformLog()); + TransformResultInfo resultInfo3 = TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "unsupport"); + Assert.assertEquals("unsupport\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"), + resultInfo3.getTransformLog()); + + } + + @Test + public void testSaved() { + TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed").saved(false); + Assert.assertFalse(resultInfo1.isSaved()); + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java new file mode 100644 index 0000000000..c0b68c0ab0 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java @@ -0,0 +1,27 @@ +package com.fr.nx.app.designer.transform; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class BatchTransformProgressTest { + @Test + public void testGetProgress(){ + BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100); + Assert.assertEquals(0.0D, batchTransformProgress.getProgress(), 0.0D); + } + + @Test + public void testUpdateProgress(){ + BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100); + for (int i = 0; i < 80; i++) { + batchTransformProgress.updateProgress(); + } + Assert.assertEquals(0.8D, batchTransformProgress.getProgress(), 0.0D); + batchTransformProgress.updateProgress(); + Assert.assertEquals(0.81D, batchTransformProgress.getProgress(), 0.0D); + + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java new file mode 100644 index 0000000000..b3adc12463 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java @@ -0,0 +1,35 @@ +package com.fr.nx.app.designer.transform; + +import com.fr.file.filetree.FileNode; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-02-14 + */ +public class BatchTransformUtilTest { + @Test + public void testFilterTransformedFile(){ + FileNode[] fileNodes = new FileNode[]{ + new FileNode("test1", false), new FileNode("test2", false) + }; + List transformedFileNodes = new ArrayList(); + FileNode[] result1 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(2, result1.length); + + transformedFileNodes.add( new FileNode("test1", false)); + FileNode[] result2 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(1, result2.length); + + transformedFileNodes.add( new FileNode("test2", false)); + FileNode[] result3 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(0, result3.length); + + transformedFileNodes.add( new FileNode("test3", false)); + FileNode[] result4 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(0, result4.length); + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java new file mode 100644 index 0000000000..d29d3e7421 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java @@ -0,0 +1,124 @@ +package com.fr.nx.app.designer.transform; + +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; + +/** + * Created by kerry on 2020-01-15 + */ +// FIXME @kerry 打包失败,暂时先注释 +//@RunWith(value = PowerMockRunner.class) +//@PrepareForTest({CompileTransformUtil.class, PluginContexts.class}) +//@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"}) +public class BatchTransformerTest { + + private static final int MAXPOOLSIZE = 5; + private static final int COREPOOLSIZE = 3; + private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s"; + + @Before + public void setUp() { +// FineRuntime.start(); +// ExecutorService threadPoolExecutor = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE, +// 0L, TimeUnit.MILLISECONDS, +// new LinkedBlockingQueue(), +// new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); +// PowerMock.mockStatic(PluginContexts.class); +// PluginContext pluginContext = EasyMock.mock(PluginContext.class); +// EasyMock.expect(pluginContext.newFixedThreadPool( +// EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))) +// .andReturn(threadPoolExecutor).anyTimes(); +// EasyMock.expect(PluginContexts.currentContext()).andReturn(pluginContext).anyTimes(); +// +// PowerMock.mockStatic(CompileTransformUtil.class); +// TransformResultInfo resultInfo = TransformResultInfo.generateResult(TransformResult.SUCCESS); +// EasyMock.expect(CompileTransformUtil.compileFile(EasyMock.anyObject(FileNode.class))) +// .andReturn(resultInfo).anyTimes(); +// EasyMock.replay(pluginContext); +// PowerMock.replayAll(); + } + + @Test + public void testBatchTransform() { +// final CountDownLatch countDownLatch = new CountDownLatch(2); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// List nodeList = new ArrayList<>(); +// FileNode test1 = new FileNode("path1", false); +// FileNode test2 = new FileNode("path2", false); +// nodeList.add(test1); +// nodeList.add(test2); +// transformer.batchTransform(nodeList); +// try { +// countDownLatch.await(5, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(2, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test1).getResult()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test2).getResult()); + + } + + @Test + public void testTransform() { +// final CountDownLatch countDownLatch = new CountDownLatch(1); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// FileNode test = new FileNode("path", false); +// Reflect.on(transformer).call("transform", test); +// try { +// countDownLatch.await(5, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(1, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult()); + } + + @Test + public void testShutDown() { +// final CountDownLatch countDownLatch = new CountDownLatch(1); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// List nodeList = new ArrayList<>(); +// FileNode test = new FileNode("path", false); +// nodeList.add(test); +// transformer.batchTransform(nodeList); +// transformer.shutDown(); +// try { +// countDownLatch.await(3, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(1, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult()); + } + + + private class MockUpdateCallBack implements UpdateCallBack { + private CountDownLatch countDownLatch; + + + public MockUpdateCallBack(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } + + @Override + public void updateProgress(double progress) { + countDownLatch.countDown(); + } + + @Override + public void shutDown() { + + } + + @Override + public void reset() { + + } + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java new file mode 100644 index 0000000000..653bbdef20 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java @@ -0,0 +1,58 @@ +package com.fr.nx.app.designer.utils; + +import com.fr.base.FRContext; +import com.fr.base.operator.common.CommonOperator; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNodes; +import com.fr.nx.app.designer.toolbar.TemplateTransformer; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Created by kerry on 2019-12-04 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({FRContext.class}) +@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"}) +public class CompileTransformUtilTest { + @Test + public void testGetTargetFile() { + CommonOperator commonOperator = EasyMock.mock(CommonOperator.class); + FileNodes fileNodes = EasyMock.mock(FileNodes.class); + EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes(); + PowerMock.mockStatic(FRContext.class); + EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes(); + EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes(); + EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes(); + EasyMock.replay(commonOperator, fileNodes); + PowerMock.replayAll(); + JTemplate jTemplate1 = EasyMock.mock(JTemplate.class); + FILE file1 = EasyMock.mock(FILE.class); + EasyMock.expect(jTemplate1.getEditingFILE()).andReturn(file1).anyTimes(); + EasyMock.expect(file1.getPath()).andReturn("WorkBook1.cpt").anyTimes(); + EasyMock.replay(jTemplate1, file1); + FILE targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPTX); + Assert.assertEquals("WorkBook1.cptx", targetFile.getPath()); + + targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPT); + Assert.assertEquals("WorkBook1.cpt", targetFile.getPath()); + + JTemplate jTemplate2 = EasyMock.mock(JTemplate.class); + FILE file2 = EasyMock.mock(FILE.class); + EasyMock.expect(jTemplate2.getEditingFILE()).andReturn(file2).anyTimes(); + EasyMock.expect(file2.getPath()).andReturn("WorkBook1.cpt").anyTimes(); + EasyMock.replay(jTemplate2, file2); + targetFile = CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPTX); + Assert.assertEquals("WorkBook1.cptx", targetFile.getPath()); + + targetFile =CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPT); + Assert.assertEquals("WorkBook1.cpt", targetFile.getPath()); + } +} diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java b/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java index 4cd00e5772..bce90aaaeb 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java @@ -3,6 +3,7 @@ package com.fr.design.chart; import com.fr.base.chart.BaseChartCollection; import com.fr.chart.chartattr.ChartCollection; import com.fr.design.dialog.BasicDialog; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.chart.MiddleChartDialog; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.i18n.Toolkit; @@ -110,6 +111,7 @@ public class ChartDialog extends MiddleChartDialog { if (cc == null) { return; } + cc.setThemeStyle(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme()); this.cc = cc; } diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java index d31cd32088..1408b6a770 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java @@ -13,6 +13,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.log.FineLoggerFactory; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; @@ -23,10 +24,10 @@ import javax.swing.JSplitPane; import javax.swing.ListCellRenderer; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.awt.Color; import java.awt.Component; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class ChartTypePane extends ChartCommonWizardPane implements CallbackEvent { private static final long serialVersionUID = -1175602484968520546L; @@ -153,6 +154,8 @@ public class ChartTypePane extends ChartCommonWizardPane implements CallbackEven } } + DefaultStyleHelper4Van.checkChartDefaultStyle4Duchamp(chart4Update); + update(chart4Update); } diff --git a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java index 1ce2fbffd9..b251abc6a8 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java +++ b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java @@ -146,7 +146,6 @@ public class ChartComponent extends MiddleChartComponent implements MouseListene return; } - chartCollection4Design.setPredefinedStyleName(getGlobalPredefinedStyleName(), false); Graphics2D g2d = (Graphics2D) g; if (this.isOpaque()) { diff --git a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java index 7e64f3d209..30d01cb55d 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java +++ b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java @@ -2,6 +2,7 @@ package com.fr.design.chart.gui; import com.fr.base.chart.BaseChartGetter; import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.core.WidgetOption; import com.fr.form.ui.ChartEditor; import com.fr.form.ui.Widget; @@ -40,6 +41,7 @@ public class ChartWidgetOption extends WidgetOption { try { ChartEditor widget = clz.newInstance(); ChartCollection chartCollection = (ChartCollection) BaseChartGetter.createChartCollection(this.chartID); + chartCollection.setThemeStyle(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme()); VanChart vanChart = chartCollection.getSelectedChartProvider(VanChart.class); if (vanChart !=null) { vanChart.resetAttrInForm(); diff --git a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java index ae38672204..11d2e32e4d 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java @@ -7,12 +7,14 @@ import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chart.web.ChartHyperPoplink; import com.fr.chartx.attr.ChartProvider; import com.fr.design.chart.gui.ChartComponent; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.hyperlink.AbstractHyperLinkPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.chart.ChartHyperEditPane; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.log.FineLoggerFactory; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import java.awt.BorderLayout; import java.awt.Dimension; @@ -64,11 +66,14 @@ public class ChartHyperPoplinkPane extends AbstractHyperLinkPane implemen addButton.addActionListener((e) -> { String name = getNewChartName(); ChartProvider chart = getChangeStateNewChart(); + DefaultStyleHelper4Van.checkChartDefaultStyle4Duchamp(chart); checkInForm(chart); addNewChart(chart, name, editingCollection.getChartCount()); }); @@ -660,7 +662,7 @@ public class ChartTypeButtonPane extends BasicBeanPane implemen //记录改变前的plotID String lastPlotID = editingCollection == null ? StringUtils.EMPTY : editingCollection.getSelectedChartProvider(ChartProvider.class).getID(); changeCollectionSelected(getButtonName()); - setSelectedWithFireListener(true); + setSelected(true, true); fireSelectedChanged(); //需要先更新,最后重构面板 diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectBoxWithOutTransparent.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectBoxWithOutTransparent.java index ba0b032411..33498d39a0 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectBoxWithOutTransparent.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectBoxWithOutTransparent.java @@ -1,7 +1,7 @@ package com.fr.design.mainframe.chart.gui; import com.fr.design.style.color.ColorSelectBox; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; /** * Created by Fangjie on 2016/4/8. @@ -14,7 +14,7 @@ public class ColorSelectBoxWithOutTransparent extends ColorSelectBox { @Override - protected ColorSelectPane getColorSelectPane(){ + protected NewColorSelectPane getColorSelectPane(){ return new ColorSelectPaneWithOutTransparent(); } } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectPaneWithOutTransparent.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectPaneWithOutTransparent.java index beab8a7a5f..7acc164323 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectPaneWithOutTransparent.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ColorSelectPaneWithOutTransparent.java @@ -1,43 +1,21 @@ package com.fr.design.mainframe.chart.gui; import com.fr.chart.base.ChartConstants; -import com.fr.design.style.color.ColorCell; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; -import javax.swing.*; -import java.awt.*; +import java.awt.Color; /** * Created by Fangjie on 2016/4/8. */ -public class ColorSelectPaneWithOutTransparent extends ColorSelectPane { +public class ColorSelectPaneWithOutTransparent extends NewColorSelectPane { public ColorSelectPaneWithOutTransparent(){ super(false); } - public void initCenterPaneChildren(JPanel centerPane) { - JPanel menuColorPane1 = new JPanel(); - centerPane.add(menuColorPane1); - menuColorPane1.setLayout(new GridLayout(3, 8, 5, 5)); - for (int i = 0; i < ChartConstants.MAP_COLOR_ARRAY.length; i++) { - menuColorPane1.add(new ColorCell(ChartConstants.MAP_COLOR_ARRAY[i], this)); - } - centerPane.add(Box.createVerticalStrut(5)); - centerPane.add(new JSeparator()); - } - protected Color[] getColorArray(){ return ChartConstants.MAP_COLOR_ARRAY; } - protected JPanel getMenuColorPane() { - JPanel menuColorPane = new JPanel(); - menuColorPane.setLayout(new GridLayout(0, 8, 1, 1)); - menuColorPane.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8)); - - menuColorPane.setPreferredSize(new Dimension(205, 62)); - - return menuColorPane; - } } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java index d07ec476e9..5a15bc1720 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java @@ -94,6 +94,10 @@ public class ChartTextAttrPane extends BasicPane { populate(frFont); } + public void populate(TextAttr textAttr, boolean autoFont) { + populate(textAttr); + } + public void update(TextAttr textAttr) { if (textAttr == null) { textAttr = new TextAttr(); diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithPreStyle.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithThemeStyle.java similarity index 71% rename from designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithPreStyle.java rename to designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithThemeStyle.java index e27ed43e1e..345d57de8a 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithPreStyle.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithThemeStyle.java @@ -7,10 +7,11 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.van.chart.designer.TableLayout4VanChartHelper; +import javax.swing.BorderFactory; 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; @@ -19,7 +20,7 @@ import java.awt.event.ActionListener; * @version 10.0 * Created by Bjorn on 2020-09-03 */ -public class ChartTextAttrPaneWithPreStyle extends ChartTextAttrPane { +public class ChartTextAttrPaneWithThemeStyle extends ChartTextAttrPane { private static final int PREDEFINED_STYLE = 0; private static final int CUSTOM = 1; @@ -27,27 +28,26 @@ public class ChartTextAttrPaneWithPreStyle extends ChartTextAttrPane { private UIButtonGroup preButton; private JPanel textFontPane; - public ChartTextAttrPaneWithPreStyle() { + public ChartTextAttrPaneWithThemeStyle() { initListener(); } protected JPanel getContentPane(JPanel buttonPane) { - preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Predefined"), + JPanel panel = new JPanel(new BorderLayout(0, 10)); + + preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Follow_Theme"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); double f = TableLayout.FILL; double e = getEdithAreaWidth(); - double[] columnSize = {f, e}; double p = TableLayout.PREFERRED; - textFontPane = TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), getRowSize(), columnSize); - - double[] rowSize = {p, p, p}; + double[] columnSize = {f, e}; UILabel text = new UILabel(Toolkit.i18nText("Fine-Design_Chart_Character"), SwingConstants.LEFT); - Component[][] components = { - new Component[]{null, null}, - new Component[]{text, preButton}, - new Component[]{textFontPane, null}, - }; - return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); + JPanel preButtonPane = TableLayout4VanChartHelper.createGapTableLayoutPane(new Component[][]{new Component[]{text, preButton}}, new double[]{p}, columnSize); + textFontPane = TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), getRowSize(), columnSize); + panel.add(preButtonPane, BorderLayout.CENTER); + panel.add(textFontPane, BorderLayout.SOUTH); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + return panel; } protected double getEdithAreaWidth() { @@ -72,11 +72,19 @@ public class ChartTextAttrPaneWithPreStyle extends ChartTextAttrPane { private void checkPreButton() { textFontPane.setVisible(preButton.getSelectedIndex() == CUSTOM); - textFontPane.setPreferredSize(preButton.getSelectedIndex() == CUSTOM ? new Dimension(0, 60) : new Dimension(0, 0)); + } + + protected double[] getRowSize() { + double p = TableLayout.PREFERRED; + return new double[]{p, p}; } public void populate(TextAttr textAttr) { - if (textAttr.isPredefinedStyle()) { + populate(textAttr, false); + } + + public void populate(TextAttr textAttr, boolean autoFont) { + if (textAttr.isThemed() || autoFont) { preButton.setSelectedIndex(PREDEFINED_STYLE); } else { preButton.setSelectedIndex(CUSTOM); @@ -88,9 +96,9 @@ public class ChartTextAttrPaneWithPreStyle extends ChartTextAttrPane { public void update(TextAttr textAttr) { int selectedIndex = preButton.getSelectedIndex(); if (selectedIndex == PREDEFINED_STYLE) { - textAttr.setPredefinedStyle(true); + textAttr.setThemed(true); } else { - textAttr.setPredefinedStyle(false); + textAttr.setThemed(false); } super.update(textAttr); } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithPreStyle.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithThemeStyle.java similarity index 66% rename from designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithPreStyle.java rename to designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithThemeStyle.java index a4a0344fa4..db59476792 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithPreStyle.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithThemeStyle.java @@ -1,11 +1,11 @@ package com.fr.design.mainframe.chart.gui.style; -import com.fr.chart.base.ColorWithPreStyle; +import com.fr.chart.base.ColorWithThemeStyle; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.TableLayout; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.design.style.color.ColorSelectBox; import com.fr.van.chart.designer.TableLayout4VanChartHelper; @@ -22,7 +22,7 @@ import java.awt.event.ActionListener; * @version 10.0 * Created by Bjorn on 2020-09-07 */ -public class ColorSelectBoxWithPreStyle extends BasicPane { +public class ColorSelectBoxWithThemeStyle extends BasicPane { private static final int PREDEFINED_STYLE = 0; private static final int CUSTOM = 1; @@ -30,8 +30,8 @@ public class ColorSelectBoxWithPreStyle extends BasicPane { private UIButtonGroup preButton; private ColorSelectBox colorSelectBox; - public ColorSelectBoxWithPreStyle(int preferredWidth) { - preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Predefined"), + public ColorSelectBoxWithThemeStyle(int preferredWidth) { + preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Follow_Theme"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); colorSelectBox = new ColorSelectBox(preferredWidth); initContent(); @@ -39,18 +39,16 @@ public class ColorSelectBoxWithPreStyle extends BasicPane { } private void initContent() { - double f = TableLayout.FILL; - double e = TableLayout4VanChartHelper.EDIT_AREA_WIDTH; - double[] columnSize = {f, e}; - double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p}; UILabel text = new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color"), SwingConstants.LEFT); - Component[][] components = { + Component[][] components = ChartEditContext.supportTheme() ? new Component[][]{ new Component[]{text, preButton}, new Component[]{null, colorSelectBox}, + } : new Component[][]{ + new Component[]{text, colorSelectBox} }; - JPanel gapTableLayoutPane = TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); + + JPanel gapTableLayoutPane = TableLayout4VanChartHelper.createGapTableLayoutPane(components); this.setLayout(new BorderLayout()); this.add(gapTableLayoutPane, BorderLayout.CENTER); } @@ -66,22 +64,22 @@ public class ColorSelectBoxWithPreStyle extends BasicPane { private void checkPreButton() { colorSelectBox.setVisible(preButton.getSelectedIndex() == CUSTOM); - this.setPreferredSize(preButton.getSelectedIndex() == CUSTOM ? new Dimension(0, 55) : new Dimension(0, 23)); + this.setPreferredSize(ChartEditContext.supportTheme() && preButton.getSelectedIndex() == CUSTOM ? new Dimension(0, 55) : new Dimension(0, 23)); } public String title4PopupWindow() { return null; } - public void populate(ColorWithPreStyle colorWithPreStyle) { - preButton.setSelectedIndex(colorWithPreStyle.isPredefinedStyle() ? PREDEFINED_STYLE : CUSTOM); + public void populate(ColorWithThemeStyle colorWithPreStyle) { + preButton.setSelectedIndex(ChartEditContext.supportTheme() && colorWithPreStyle.isThemed() ? PREDEFINED_STYLE : CUSTOM); colorSelectBox.setSelectObject(colorWithPreStyle.getColor()); checkPreButton(); } - public ColorWithPreStyle update() { - ColorWithPreStyle colorWithPreStyle = new ColorWithPreStyle(); - colorWithPreStyle.setPredefinedStyle(preButton.getSelectedIndex() == PREDEFINED_STYLE); + public ColorWithThemeStyle update() { + ColorWithThemeStyle colorWithPreStyle = new ColorWithThemeStyle(); + colorWithPreStyle.setThemed(ChartEditContext.supportTheme() && preButton.getSelectedIndex() == PREDEFINED_STYLE); colorWithPreStyle.setColor(colorSelectBox.getSelectObject()); return colorWithPreStyle; } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java index 8a0c2c5cb5..ba617b5e78 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java @@ -370,6 +370,11 @@ public class UIColorPickerPane extends BasicPane implements UIObserver { ColorRecButton.this.repaint(); } + @Override + protected ColorSelectionPopupPane createColorSelectionPopupPane(boolean isSupportTransparent) { + return new ColorSelectionPopupPane(isSupportTransparent, supportThemeColor(), ColorRecButton.this.color); + } + }; } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java index 8606ffab9d..217b01d8b8 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java @@ -2,15 +2,10 @@ package com.fr.design.mainframe.chart.gui.style.series; import com.fr.chart.base.ChartConstants; import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; -import com.fr.design.style.color.ColorCell; import com.fr.design.style.color.ColorSelectBox; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; -import javax.swing.Box; -import javax.swing.JPanel; -import javax.swing.JSeparator; import java.awt.Color; -import java.awt.GridLayout; /** * Created by IntelliJ IDEA. @@ -27,23 +22,12 @@ public class UIColorPickerPane4Map extends UIColorPickerPane { return new ColorSelectBox4Map(100); } - private class ColorSelectPane4Map extends ColorSelectPane { + private class ColorSelectPane4Map extends NewColorSelectPane { public ColorSelectPane4Map(){ super(false); } - public void initCenterPaneChildren(JPanel centerPane) { - JPanel menuColorPane1 = new JPanel(); - centerPane.add(menuColorPane1); - menuColorPane1.setLayout(new GridLayout(5, 8, 5, 5)); - for (int i = 0; i < ChartConstants.MAP_COLOR_ARRAY.length; i++) { - menuColorPane1.add(new ColorCell(ChartConstants.MAP_COLOR_ARRAY[i], this)); - } - centerPane.add(Box.createVerticalStrut(5)); - centerPane.add(new JSeparator()); - } - protected Color[] getColorArray(){ return ChartConstants.MAP_COLOR_ARRAY; } @@ -54,7 +38,7 @@ public class UIColorPickerPane4Map extends UIColorPickerPane { super(preferredWidth); } - protected ColorSelectPane getColorSelectPane(){ + protected NewColorSelectPane getColorSelectPane(){ return new ColorSelectPane4Map(); } } diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java index 8091a78eb0..4cc8466fd4 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java @@ -8,6 +8,7 @@ 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.style.background.gradient.FixedGradientBarNoTheme; import com.fr.design.style.color.ColorAdjustPane; import com.fr.design.style.background.gradient.FixedGradientBar; @@ -58,7 +59,7 @@ public class ChartPreFillStylePane extends BasicBeanPane { changeColorSetPane = new JPanel(cardLayout = new CardLayout()); changeColorSetPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); - changeColorSetPane.add(colorGradient = new FixedGradientBar(4, 150), "gradient"); + changeColorSetPane.add(colorGradient = new FixedGradientBarNoTheme(4, 150), "gradient"); changeColorSetPane.add(colorAdjustPane = new ColorAdjustPane(), "acc"); cardLayout.show(changeColorSetPane, "acc"); customPane.add(changeColorSetPane, BorderLayout.CENTER); diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java index 61b9a8c4f5..e989e1a364 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java @@ -16,6 +16,8 @@ import com.fr.transaction.WorkerFacade; import com.fr.van.chart.designer.component.VanChartFillStylePane; import javax.swing.KeyStroke; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.util.concurrent.ExecutorService; import java.awt.event.ActionEvent; @@ -43,6 +45,7 @@ public class ChartPreStyleAction extends UpdateAction { */ public void actionPerformed(ActionEvent e) { DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + DesignerContext.getDesignerFrame().setServerConfig(true); final ChartPreStyleManagerPane pane = new ChartPreStyleManagerPane(); BasicDialog dialog = pane.showWindow(designerFrame); dialog.addDialogActionListener(new DialogActionAdapter() { @@ -79,7 +82,13 @@ public class ChartPreStyleAction extends UpdateAction { })); } }); - + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + DesignerContext.getDesignerFrame().setServerConfig(false); + } + }); pane.populateBean(); dialog.setVisible(true); diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java index 73914a320f..99d048a811 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java @@ -10,7 +10,6 @@ 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.ilist.JNameEdList; -import com.fr.design.gui.ilist.ModNameActionListener; import com.fr.design.i18n.Toolkit; import com.fr.design.menu.ShortCut; import com.fr.general.ComparatorUtils; @@ -20,8 +19,6 @@ import com.fr.stable.StringUtils; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -34,12 +31,8 @@ import java.util.List; */ public class ChartPreStyleListPane extends JListControlPane { - ChartPreStyleManagerPane chartPreStyleManagerPane; - - public ChartPreStyleListPane(ChartPreStyleManagerPane chartPreStyleManagerPane) { + public ChartPreStyleListPane() { super(); - this.chartPreStyleManagerPane = chartPreStyleManagerPane; - initListener(); addModNameActionListener((int index, String oldName, String newName) -> { if (ComparatorUtils.equals(oldName, newName)) { return; @@ -94,13 +87,7 @@ public class ChartPreStyleListPane extends JListControlPane { @Override public BasicBeanPane createPaneByCreators(NameableCreator creator) { - return new ChartPreStylePane() { - @Override - protected void refreshWhenStyleChange(ChartColorMatching preStyle) { - super.refreshWhenStyleChange(preStyle); - chartPreStyleManagerPane.refreshDefaultColorBox(); - } - }; + return new ChartPreStylePane(); } @@ -123,21 +110,6 @@ public class ChartPreStyleListPane extends JListControlPane { return shortCut4JControlPane; } - public void initListener() { - nameableList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - chartPreStyleManagerPane.refreshDefaultColorBox(); - } - }); - nameableList.addModNameActionListener(new ModNameActionListener() { - @Override - public void nameModed(int index, String oldName, String newName) { - chartPreStyleManagerPane.refreshDefaultColorBox(oldName, newName); - } - }); - } - public void populateBean() { ChartPreStyleConfig config = ChartPreStyleConfig.getInstance().mirror(); ArrayList list = new ArrayList(); @@ -152,15 +124,10 @@ public class ChartPreStyleListPane extends JListControlPane { Nameable[] values = (Nameable[]) list.toArray(new Nameable[list.size()]); populate(values); - - if (config.containsName(config.getCurrentStyle())) { - this.setSelectedName(config.getCurrentStyle()); - } } public void updateBean() { ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - Nameable[] values = update(); config.clearAllPreStyle(); @@ -180,4 +147,4 @@ public class ChartPreStyleListPane extends JListControlPane { this.shortCut.setEnabled(nameableList.getModel().getSize() > 1); } } -} +} \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java index 98f3862dcc..26ee8f20e2 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java @@ -1,24 +1,10 @@ package com.fr.design.module; -import com.fr.base.ChartColorMatching; -import com.fr.base.ChartPreStyleConfig; -import com.fr.design.gui.icombobox.ColorSchemeComboBox; import com.fr.design.dialog.BasicPane; -import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.general.ComparatorUtils; -import com.fr.general.GeneralUtils; -import com.fr.general.NameObject; -import com.fr.stable.Nameable; -import com.fr.van.chart.designer.TableLayout4VanChartHelper; -import javax.swing.JPanel; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; import java.awt.BorderLayout; -import java.awt.Dimension; /** * 图表预定义管理 界面, 在工具栏-服务器管理中. @@ -28,8 +14,6 @@ import java.awt.Dimension; */ public class ChartPreStyleManagerPane extends BasicPane { - private ColorSchemeComboBox defaultColorBox; - private ChartPreStyleListPane chartPreStyleListPane; public ChartPreStyleManagerPane() { @@ -38,78 +22,20 @@ public class ChartPreStyleManagerPane extends BasicPane { private void initComponent() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel colorBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - - chartPreStyleListPane = new ChartPreStyleListPane(this); - - initDefaultColorBox(); - colorBoxPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Chart_Match_Default_Color_Scheme") + ":")); - colorBoxPane.add(defaultColorBox); - - this.add(colorBoxPane, BorderLayout.NORTH); + chartPreStyleListPane = new ChartPreStyleListPane(); this.add(chartPreStyleListPane, BorderLayout.CENTER); } - private void initDefaultColorBox() { - Map colorSchemes = new LinkedHashMap<>(); - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - Iterator names = config.names(); - while (names.hasNext()) { - Object key = names.next(); - ColorSchemeComboBox.ColorInfo colorInfo = new ColorSchemeComboBox.ColorInfo(); - ChartColorMatching colorMatching = (ChartColorMatching) config.getPreStyle(key); - colorInfo.setGradient(colorMatching.getGradient()); - colorInfo.setColors(colorMatching.getColorList()); - colorSchemes.put(colorMatching.getId(), colorInfo); - } - defaultColorBox = new ColorSchemeComboBox(colorSchemes); - defaultColorBox.setPreferredSize(new Dimension(TableLayout4VanChartHelper.EDIT_AREA_WIDTH, 20)); - } - - private void refreshColorSchemes() { - Nameable[] nameables = chartPreStyleListPane.update(); - Map colorSchemes = new LinkedHashMap<>(); - for (Nameable value : nameables) { - String name = value.getName(); - ChartColorMatching colorMatching = (ChartColorMatching) ((NameObject) value).getObject(); - ColorSchemeComboBox.ColorInfo colorInfo = new ColorSchemeComboBox.ColorInfo(); - colorInfo.setGradient(colorMatching.getGradient()); - colorInfo.setColors(colorMatching.getColorList()); - colorSchemes.put(name, colorInfo); - } - defaultColorBox.refresh(colorSchemes); - } - - public void refreshDefaultColorBox() { - Object selectedItem = defaultColorBox.getSelectedItem(); - refreshColorSchemes(); - defaultColorBox.setSelectedItem(selectedItem); - } - - public void refreshDefaultColorBox(String oldName, String newName) { - Object selectedItem = defaultColorBox.getSelectedItem(); - if (ComparatorUtils.equals(selectedItem, oldName)) { - selectedItem = newName; - } - refreshColorSchemes(); - defaultColorBox.setSelectedItem(selectedItem); - } - @Override protected String title4PopupWindow() { return Toolkit.i18nText("Fine-Design_Report_ServerM_Predefined_Styles"); } public void populateBean() { - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - String currentStyle = config.getCurrentStyle(); - defaultColorBox.setSelectedItem(currentStyle); chartPreStyleListPane.populateBean(); } public void updateBean() { - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - config.setCurrentStyle(GeneralUtils.objectToString(defaultColorBox.getSelectedItem())); chartPreStyleListPane.updateBean(); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java index b83a20f612..27c5882221 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java @@ -71,9 +71,7 @@ public class VanChartColumnSeriesPane extends VanChartAbstractPlotSeriesPane { //边框(有圆角) protected VanChartBorderPane createDiffBorderPane() { - return new VanChartBorderWithRadiusPane(); - //TODO Bjorn 边框自动回退 - //return new VanChartBorderWithRadiusPane(true); + return new VanChartBorderWithRadiusPane(true); } private JPanel createSeriesStylePane(double[] row, double[] col) { diff --git a/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java index 4cbba62906..64f9838f96 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java +++ b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java @@ -58,28 +58,39 @@ public class DefaultStyleConstants { static final Background BACK = null; + //新特新 + public static String COLOR_NAME_1; + //经典高亮 + private static String COLOR_NAME_2; + + static { + try { + COLOR_NAME_1 = CodeUtils.cjkDecode("\u65b0\u7279\u6027"); + COLOR_NAME_2 = CodeUtils.cjkDecode("\u7ecf\u5178\u9ad8\u4eae"); + } catch (Exception e) { + e.printStackTrace(); + } + } + static String COLORS = null; static { ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - try { - DefaultStyleConstants.COLORS = CodeUtils.cjkDecode("\u7ecf\u5178\u9ad8\u4eae"); - // 没有经典高亮, 用新特性 - if (config.getPreStyle(DefaultStyleConstants.COLORS) == null) { - DefaultStyleConstants.COLORS = CodeUtils.cjkDecode("\u65b0\u7279\u6027"); - } - // 没有新特性, 用第一个配色 - if (config.getPreStyle(DefaultStyleConstants.COLORS) == null) { - if (config.names().hasNext()) { - - String name = GeneralUtils.objectToString(config.names().next()); - if (config.getPreStyle(name) != null) { - DefaultStyleConstants.COLORS = name; - } + + COLORS = COLOR_NAME_2; + // 没有经典高亮, 用新特性 + if (config.getPreStyle(COLORS) == null) { + COLORS = COLOR_NAME_1; + } + // 没有新特性, 用第一个配色 + if (config.getPreStyle(COLORS) == null) { + if (config.names().hasNext()) { + + String name = GeneralUtils.objectToString(config.names().next()); + if (config.getPreStyle(name) != null) { + COLORS = name; } } - } catch (Exception e) { - e.printStackTrace(); } } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java index 31694433ff..8421492fa8 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java +++ b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java @@ -8,6 +8,7 @@ import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.ConditionAttr; import com.fr.chart.chartglyph.DataSheet; +import com.fr.chartx.attr.ChartProvider; import com.fr.config.predefined.ColorFillStyle; import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.plugin.chart.PiePlot4VanChart; @@ -21,6 +22,7 @@ import com.fr.plugin.chart.custom.type.CustomPlotType; import com.fr.plugin.chart.gauge.VanChartGaugePlot; import com.fr.plugin.chart.map.VanChartMapPlot; import com.fr.plugin.chart.type.GaugeStyle; +import com.fr.plugin.chart.vanchart.VanChart; /** * @author shine @@ -39,6 +41,16 @@ public class DefaultStyleHelper4Van { } } + public static void checkChartDefaultStyle4Duchamp(ChartProvider chartProvider) { + if (!ChartEditContext.supportTheme() && chartProvider instanceof VanChart) { + //主题中有的属性 界面上屏蔽不跟随主题 属性全部设置成自定义 + ((VanChart) chartProvider).setThemeCustom(); + dealChartColor((VanChart) chartProvider); +// //主题中没有的 根据主题深浅色自动 的属性 默认自动 +// ((VanChart) chart4Update).setAutoThemeCustom(); + } + } + public static void dealVanPlot4Custom(VanChartPlot plot, CustomPlotType customPlotType) { if (!duchampMode()) { return; @@ -95,25 +107,7 @@ public class DefaultStyleHelper4Van { if (plot instanceof VanChartPlot) { VanChartPlot vanChartPlot = (VanChartPlot) plot; - ChartPreStyleConfig manager = ChartPreStyleConfig.getInstance(); - Object preStyle = manager.getPreStyle(DefaultStyleConstants.COLORS); - if (preStyle instanceof ChartColorMatching) { - ColorFillStyle colorFillStyle = new ColorFillStyle(); - //default是默认的意思,为服务器默认配色方案 - //acc为多个颜色组合 - //gradient为渐变颜色 - colorFillStyle.setColorStyle(ChartConstants.COLOR_ACC); - colorFillStyle.setFillStyleName(DefaultStyleConstants.COLORS); - colorFillStyle.setColorList(((ChartColorMatching) preStyle).getColorList()); - - AttrFillStyle plotFillStyle = vanChartPlot.getPlotFillStyle(); - if (plotFillStyle == null) { - plotFillStyle = new AttrFillStyle(); - vanChartPlot.setPlotFillStyle(plotFillStyle); - } - plotFillStyle.setColorFillStyle(colorFillStyle); - } - + dealChartColor(vanChartPlot); if (vanChartPlot.getLegend() != null) { vanChartPlot.getLegend().setFRFont(DefaultStyleConstants.LEGEND); @@ -139,6 +133,31 @@ public class DefaultStyleHelper4Van { } + private static void dealChartColor(VanChart vanChart) { + dealChartColor(vanChart.getPlot()); + } + + private static void dealChartColor(VanChartPlot vanChartPlot) { + ChartPreStyleConfig manager = ChartPreStyleConfig.getInstance(); + Object preStyle = manager.getPreStyle(DefaultStyleConstants.COLORS); + if (preStyle instanceof ChartColorMatching) { + ColorFillStyle colorFillStyle = new ColorFillStyle(); + //default是默认的意思,为服务器默认配色方案 + //acc为多个颜色组合 + //gradient为渐变颜色 + colorFillStyle.setColorStyle(ChartConstants.COLOR_ACC); + colorFillStyle.setFillStyleName(DefaultStyleConstants.COLORS); + colorFillStyle.setColorList(((ChartColorMatching) preStyle).getColorList()); + + AttrFillStyle plotFillStyle = vanChartPlot.getPlotFillStyle(); + if (plotFillStyle == null) { + plotFillStyle = new AttrFillStyle(); + vanChartPlot.setPlotFillStyle(plotFillStyle); + } + plotFillStyle.setColorFillStyle(colorFillStyle); + } + } + private static void dealBorder(VanChartPlot vanChartPlot) { ConditionAttr defaultAttr = vanChartPlot.getConditionCollection().getDefaultAttr(); AttrBorder attrBorder = defaultAttr.getExisted(AttrBorder.class); diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java index 99498c58a8..589b03cad3 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java @@ -1,9 +1,11 @@ package com.fr.van.chart.custom.component; +import com.fr.chart.base.ChartThemeStyleProvider; import com.fr.chart.chartattr.Chart; import com.fr.design.beans.BasicBeanPane; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.plugin.chart.attr.plot.VanChartPlot; @@ -265,6 +267,13 @@ public class VanChartCustomPlotSelectPane extends BasicBeanPane { //设置公共属性 setCommonAttr(vanChartPlot, customPlot); + if (!ChartEditContext.supportTheme()) { + //主题中有的属性 界面上屏蔽不跟随主题 属性全部设置成自定义 + setThemeCustom(vanChartPlot); +// //主题中没有的 根据主题深浅色自动 的属性 默认自动 +// ((VanChart) chart4Update).setAutoThemeCustom(); + } + newCustomPlotList.add(vanChartPlot); } } @@ -272,6 +281,14 @@ public class VanChartCustomPlotSelectPane extends BasicBeanPane { customPlot.setCustomPlotList(newCustomPlotList); } + private void setThemeCustom(VanChartPlot customPlot) { + List chartThemeStyleProviders = new ArrayList<>(); + customPlot.getChartPreStyleProvider(chartThemeStyleProviders); + for (ChartThemeStyleProvider chartThemeStyleProvider : chartThemeStyleProviders) { + chartThemeStyleProvider.setThemeCustom(); + } + } + private void setCommonAttr(VanChartPlot vanChartPlot, VanChartCustomPlot customPlot) { //坐标轴公共属性 dealAxisAttr(vanChartPlot, customPlot); diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java index 057675a0a7..3f7374c34d 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java @@ -6,6 +6,7 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerBean; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.design.mainframe.predefined.ui.detail.ColorFillStylePane; import com.fr.design.utils.gui.GUICoreUtils; @@ -26,16 +27,8 @@ public class VanChartFillStylePane extends ColorFillStylePane implements Designe DesignerContext.setDesignerBean(name, this); } - protected void styleSelectBoxChange() { - //TODO Bjorn 配色预定义回退 - //getCustomPane().setVisible(getStyleSelectBox().getSelectedIndex() != 0); - super.styleSelectBoxChange(); - } - protected ColorSchemeComboBox createColorSchemeComboBox() { - return new ColorSchemeComboBox(); - //TODO Bjorn 配色预定义回退 - //return new ColorSchemeComboBox(null, true); + return new ColorSchemeComboBox(null, true); } protected void initLayout() { @@ -63,21 +56,19 @@ public class VanChartFillStylePane extends ColorFillStylePane implements Designe } public void populateBean(AttrFillStyle condition) { - /* if (condition.isPredefinedStyle()) { + if (condition.isThemed()) { getStyleSelectBox().setSelectType(ColorSchemeComboBox.SelectType.DEFAULT); return; - }*/ - //TODO Bjorn 配色预定义回退 + } populateBean(condition.getColorFillStyle()); } public void updateBean(AttrFillStyle attrFillStyle) { - /* if (getStyleSelectBox().getSelectedIndex() == 0) { - attrFillStyle.setPredefinedStyle(true); + if (getStyleSelectBox().getSelectedIndex() == 0 && ChartEditContext.supportTheme()) { + attrFillStyle.setThemed(true); return; } - attrFillStyle.setPredefinedStyle(false);*/ - //TODO Bjorn 配色预定义回退 + attrFillStyle.setThemed(false); attrFillStyle.setColorFillStyle(updateBean()); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java index e3bd8248f3..54200fcdee 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java @@ -1,10 +1,18 @@ package com.fr.van.chart.designer.component; +import com.fr.design.gui.ibutton.UIColorButtonWithAuto; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithAuto; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.plugin.chart.base.AttrTooltipContent; +import com.fr.plugin.chart.type.FontAutoType; import com.fr.plugin.chart.type.TextAlign; import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; public class VanChartLabelContentPane extends VanChartTooltipContentPane { @@ -22,12 +30,11 @@ public class VanChartLabelContentPane extends VanChartTooltipContentPane { return new AttrTooltipContent(TextAlign.CENTER); } - //TODO Bjorn 标签面板回退 - /* public JPanel createCommonStylePane() { - if (isInCondition()) { + public JPanel createCommonStylePane() { + if (isInCondition() || !ChartEditContext.supportTheme()) { return super.createCommonStylePane(); } - setTextAttrPane(new ChartTextAttrPaneWithPreStyle()); + setTextAttrPane(new LabelAttrPaneWithThemeStyle()); JPanel stylePanel = new JPanel(new BorderLayout()); stylePanel.add(getTextAttrPane(), BorderLayout.CENTER); @@ -35,16 +42,36 @@ public class VanChartLabelContentPane extends VanChartTooltipContentPane { return stylePanel; } + @Override + protected ChartTextAttrPane createChartTextAttrPane() { + return new ChartTextAttrPaneWithAuto(FontAutoType.COLOR) { + protected Component[][] getComponents(JPanel buttonPane) { + return new Component[][]{ + new Component[]{null, null}, + new Component[]{null, getFontNameComboBox()}, + new Component[]{null, buttonPane} + }; + } + }; + } + public void updateTextAttr(AttrTooltipContent attrTooltipContent) { - if (isInCondition()) { + if (isInCondition() || !ChartEditContext.supportTheme()) { super.updateTextAttr(attrTooltipContent); return; } if (hasTextStylePane()) { this.getTextAttrPane().update(attrTooltipContent.getTextAttr()); - if (!attrTooltipContent.getTextAttr().isPredefinedStyle()) { + if (!attrTooltipContent.getTextAttr().isThemed()) { attrTooltipContent.setCustom(true); } } - }*/ + } + + class LabelAttrPaneWithThemeStyle extends ChartTextAttrPaneWithThemeStyle { + @Override + protected void initFontColorState() { + setFontColor(new UIColorButtonWithAuto()); + } + } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java index d7c590e642..ab84b88b89 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java @@ -39,10 +39,6 @@ import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.SwingUtilities; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; @@ -51,6 +47,10 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * 数据点提示内容界面,含有通用设置、富文本编辑器、自定义JS界面 @@ -315,15 +315,7 @@ public class VanChartTooltipContentPane extends BasicBeanPane { } private JPanel createTitleStylePane() { - //TODO Bjorn 标题预定义逻辑 - //textAttrPane = new ChartTextAttrPaneWithPreStyle(); - textAttrPane = new ChartTextAttrPane(); + textAttrPane = ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() : new ChartTextAttrPane(); return TableLayout4VanChartHelper.createExpandablePaneWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Widget_Style"), textAttrPane); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java index e126c53598..eb87f4363a 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java @@ -14,8 +14,6 @@ public class VanChartTitleWithAutoBackground extends VanChartTitlePane { } protected VanChartBackgroundWithOutShadowWithRadiusPane createBackgroundPane() { - //TODO Bjorn 地图标题背景自动逻辑 - //return new VanChartBackgroundWithOutShadowWithRadiusPane(true); - return new VanChartBackgroundWithOutShadowWithRadiusPane(); + return new VanChartBackgroundWithOutShadowWithRadiusPane(true); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java index daa7ca3c95..46b210c7ec 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java @@ -1,5 +1,6 @@ package com.fr.van.chart.designer.style.axis; +import com.fr.chart.base.ColorWithThemeStyle; import com.fr.chart.chartattr.Axis; import com.fr.design.beans.FurtherBasicBeanPane; import com.fr.design.gui.frpane.UIComboBoxPane; @@ -17,9 +18,9 @@ import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.BorderFactory; import javax.swing.JPanel; -import java.awt.BorderLayout; import java.util.ArrayList; import java.util.List; +import java.awt.BorderLayout; /** * 带有坐标轴类型选择控件。可选类型:分类、时间、数值 @@ -99,11 +100,13 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll public VanChartAxis update(VanChartAxis axis) { int index = axisTypePane.getSelectedIndex(); + ColorWithThemeStyle mainGridColorWithPreStyle = axis.getMainGridColorWithPreStyle(); if(ComparatorUtils.equals(index, AxisType.AXIS_CATEGORY.ordinal())){ if(ComparatorUtils.equals(axis.getAxisType(), AxisType.AXIS_CATEGORY)){ textAxisPane.updateBean(axis); } else { axis = new VanChartAxis(axis.getAxisName(), axis.getPosition(), axis.getGridLineType(), axis.getMainGridColor()); + axis.setMainGridColorWithPreStyle(mainGridColorWithPreStyle); textAxisPane.updateBean(axis); } } else if(ComparatorUtils.equals(index, AxisType.AXIS_TIME.ordinal())){ @@ -111,6 +114,7 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll timeAxisPane.updateBean(axis); } else { axis = new VanChartTimeAxis(axis.getAxisName(), axis.getPosition(), axis.getGridLineType(), axis.getMainGridColor()); + axis.setMainGridColorWithPreStyle(mainGridColorWithPreStyle); timeAxisPane.updateBean(axis); } } else if(ComparatorUtils.equals(index, AxisType.AXIS_VALUE.ordinal())){ @@ -118,6 +122,7 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll valueAxisPane.updateBean(axis); } else { axis = new VanChartValueAxis(axis.getAxisName(), axis.getPosition(), axis.getGridLineType(), axis.getMainGridColor()); + axis.setMainGridColorWithPreStyle(mainGridColorWithPreStyle); valueAxisPane.updateBean(axis); } } 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 9fb0c7e31e..aff9d64c30 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 @@ -20,7 +20,9 @@ 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.style.color.ColorSelectBox; +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; @@ -85,9 +87,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected LineComboBox axisLineStyle; - //TODO Bjorn 坐标轴面板回退 - protected ColorSelectBox axisLineColor; - //protected ColorSelectBoxWithPreStyle axisLineColor; + protected ColorSelectBoxWithThemeStyle axisLineColor; protected UIButtonGroup mainTick; protected UIButtonGroup secondTick; @@ -381,13 +381,11 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { } protected ChartTextAttrPane getChartTextAttrPane() { - //TODO Bjorn 坐标轴面板回退 - /* return new ChartTextAttrPaneWithPreStyle() { + return ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() { protected double getEdithAreaWidth() { return TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; } - };*/ - return new ChartTextAttrPane() { + } : new ChartTextAttrPane() { @Override protected JPanel getContentPane(JPanel buttonPane) { double p = TableLayout.PREFERRED; @@ -403,9 +401,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected JPanel createLineStylePane(double[] row, double[] col) { axisLineStyle = createLineComboBox(); - //TODO Bjorn 坐标轴面板回退 - //axisLineColor = new ColorSelectBoxWithPreStyle(100); - axisLineColor = new ColorSelectBox(100); + axisLineColor = new ColorSelectBoxWithThemeStyle(100); String[] strings = new String[]{Toolkit.i18nText("Fine-Design_Chart_Open"), Toolkit.i18nText("Fine-Design_Chart_Close")}; AxisTickLineType[] values = new AxisTickLineType[]{AxisTickLineType.TICK_LINE_OUTSIDE, AxisTickLineType.TICK_LINE_NONE}; mainTick = new UIButtonGroup(strings, values); @@ -423,9 +419,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { return new Component[][]{ new Component[]{null, null}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Type")), axisLineStyle}, - //TODO Bjorn 坐标轴面板回退 - //new Component[]{axisLineColor, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), axisLineColor}, + new Component[]{axisLineColor, null}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Main_Graduation_Line")), mainTick}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Second_Graduation_Line")), secondTick}, }; @@ -735,9 +729,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { axisLineStyle.setSelectedLineStyle(axis.getAxisStyle()); } if (axisLineColor != null) { - axisLineColor.setSelectObject(axis.getAxisColor()); - //TODO Bjorn 坐标轴面板回退 - //axisLineColor.populate(axis.getLineColorWithPreStyle()); + axisLineColor.populate(axis.getLineColorWithPreStyle()); } if (mainTick != null) { mainTick.setSelectedItem(axis.getMainTickLine()); @@ -880,9 +872,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { axis.setAxisStyle(axisLineStyle.getSelectedLineStyle()); } if (axisLineColor != null) { - axis.setAxisColor(axisLineColor.getSelectObject()); - //TODO Bjorn 坐标轴面板回退 - //axis.setLineColorWithPreStyle(axisLineColor.update()); + axis.setLineColorWithPreStyle(axisLineColor.update()); } if (mainTick != null) { axis.setMainTickLine(mainTick.getSelectedItem()); diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartAxisButtonPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartAxisButtonPane.java index d5f866c818..3020093278 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartAxisButtonPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartAxisButtonPane.java @@ -356,7 +356,7 @@ public class VanChartAxisButtonPane extends BasicBeanPane { if (isEnabled()) { noSelected(); changeAxisSelected(getButtonName()); - setSelectedWithFireListener(true); + setSelected(true, true); fireSelectedChanged(); } } 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 cd6c4fcf63..91de3ed359 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 @@ -8,6 +8,8 @@ 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.ChartTextAttrPaneWithAuto; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.design.style.color.ColorSelectBox; import com.fr.plugin.chart.attr.axis.VanChartAxis; import com.fr.plugin.chart.attr.axis.VanChartGaugeAxis; @@ -102,9 +104,7 @@ public class VanChartGaugeDetailAxisPane extends VanChartValueAxisPane { if (isMulti(gaugeStyle)) { return new ChartTextAttrPaneWithAuto(FontAutoType.SIZE_AND_COLOR); } else { - return new ChartTextAttrPane(); - //TODO Bjorn 坐标轴面板回退 - //return new ChartTextAttrPaneWithPreStyle(); + return ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() : new ChartTextAttrPane(); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java index 309a7daa66..3558443c4f 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java @@ -46,9 +46,7 @@ public class VanChartRadarXAxisPane extends VanChartBaseAxisPane { return new Component[][]{ new Component[]{null,null} , new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Type")), axisLineStyle}, - //TODO Bjorn 坐标轴面板回退 - //new Component[]{axisLineColor, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), axisLineColor}, + new Component[]{axisLineColor, null}, }; } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java index cf4ffb3864..0015676882 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java @@ -90,9 +90,7 @@ public class VanChartRadarYAxisPane extends VanChartValueAxisPane { return new Component[][]{ new Component[]{null, null}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Type")), axisLineStyle}, - //TODO Bjorn 坐标轴面板回退 - //new Component[]{axisLineColor, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), axisLineColor}, + new Component[]{axisLineColor, null}, }; } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java index 19f5d40510..e6eb8c6131 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java @@ -8,9 +8,11 @@ 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.mode.ChartEditContext; import com.fr.van.chart.designer.AbstractVanChartScrollPane; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.component.background.VanChartBackgroundPane; +import com.fr.van.chart.designer.component.background.VanChartBackgroundPaneWithThemeStyle; import com.fr.van.chart.designer.component.border.VanChartBorderWithRadiusPane; import com.fr.van.chart.designer.style.background.radar.VanChartRadarAxisAreaPane; @@ -45,13 +47,11 @@ public class VanChartAreaBackgroundPane extends AbstractVanChartScrollPane { private LineTypeComboBox horizonLineType; private LineTypeComboBox verticalLineType; - private ColorSelectBox horizontalColorBox; - private ColorSelectBox verticalColorBox; - //TODO Bjorn 背景坐标轴面板回退 - /* private ColorSelectBoxWithPreStyle horizontalColorBox; - private ColorSelectBoxWithPreStyle verticalColorBox;*/ + private ColorSelectBoxWithThemeStyle horizontalColorBox; + private ColorSelectBoxWithThemeStyle verticalColorBox; private JPanel horizontalColorPane; private JPanel verticalColorPane; @@ -56,11 +54,8 @@ public class VanChartAxisAreaPane extends BasicBeanPane { } private void initComponents() { - horizontalColorBox = new ColorSelectBox(PREFERRED_WIDTH); - verticalColorBox = new ColorSelectBox(PREFERRED_WIDTH); - //TODO Bjorn 背景坐标轴面板回退 - /* horizontalColorBox = new ColorSelectBoxWithPreStyle(PREFERRED_WIDTH); - verticalColorBox = new ColorSelectBoxWithPreStyle(PREFERRED_WIDTH);*/ + horizontalColorBox = new ColorSelectBoxWithThemeStyle(PREFERRED_WIDTH); + verticalColorBox = new ColorSelectBoxWithThemeStyle(PREFERRED_WIDTH); horizonLineType = new LineTypeComboBox(new LineType[]{LineType.NONE, LineType.SOLID, LineType.DASHED}); verticalLineType = new LineTypeComboBox(new LineType[]{LineType.NONE, LineType.SOLID, LineType.DASHED}); @@ -93,18 +88,15 @@ public class VanChartAxisAreaPane extends BasicBeanPane { } protected void initGridLineComponents() { - //TODO Bjorn 背景坐标轴面板回退 Component[][] upComponent = new Component[][]{ new Component[]{null, null}, - new Component[]{null, horizontalColorBox} - //new Component[]{horizontalColorBox, null} + new Component[]{horizontalColorBox, null} }; horizontalColorPane = TableLayout4VanChartHelper.createGapTableLayoutPane(upComponent); Component[][] downComponent = new Component[][]{ new Component[]{null, null}, - new Component[]{null, verticalColorBox} - //new Component[]{verticalColorBox, null} + new Component[]{verticalColorBox, null} }; verticalColorPane = TableLayout4VanChartHelper.createGapTableLayoutPane(downComponent); @@ -228,16 +220,13 @@ public class VanChartAxisAreaPane extends BasicBeanPane { VanChartAxis defaultXAxis = rectanglePlot.getDefaultXAxis(); VanChartAxis defaultYAxis = rectanglePlot.getDefaultYAxis(); - //TODO Bjorn 背景坐标轴面板回退 if (defaultXAxis != null) { - //verticalColorBox.populate(defaultXAxis.getMainGridColorWithPreStyle()); - verticalColorBox.setSelectObject(defaultXAxis.getMainGridColor()); + verticalColorBox.populate(defaultXAxis.getMainGridColorWithPreStyle()); verticalLineType.setSelectedItem(defaultXAxis.getGridLineType()); } if (defaultYAxis != null) { - //horizontalColorBox.populate(defaultYAxis.getMainGridColorWithPreStyle()); - horizontalColorBox.setSelectObject(defaultYAxis.getMainGridColor()); + horizontalColorBox.populate(defaultYAxis.getMainGridColorWithPreStyle()); horizonLineType.setSelectedItem(defaultYAxis.getGridLineType()); } } @@ -264,16 +253,13 @@ public class VanChartAxisAreaPane extends BasicBeanPane { VanChartAxis defaultXAxis = rectanglePlot.getDefaultXAxis(); VanChartAxis defaultYAxis = rectanglePlot.getDefaultYAxis(); - //TODO Bjorn 背景坐标轴面板回退 if (defaultXAxis != null) { - //defaultXAxis.setMainGridColorWithPreStyle(verticalColorBox.update()); - defaultXAxis.setMainGridColor(verticalColorBox.getSelectObject()); + defaultXAxis.setMainGridColorWithPreStyle(verticalColorBox.update()); defaultXAxis.setGridLineType((LineType) verticalLineType.getSelectedItem()); } if (defaultYAxis != null) { - //defaultYAxis.setMainGridColorWithPreStyle(horizontalColorBox.update()); - defaultYAxis.setMainGridColor(horizontalColorBox.getSelectObject()); + defaultYAxis.setMainGridColorWithPreStyle(horizontalColorBox.update()); defaultYAxis.setGridLineType((LineType) horizonLineType.getSelectedItem()); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java index d6fa66bfb5..045b6cd3fa 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java @@ -10,7 +10,9 @@ 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.info.ChartInfoCollector; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.general.ComparatorUtils; import com.fr.plugin.chart.VanChartAttrHelper; import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot; @@ -19,6 +21,7 @@ import com.fr.plugin.chart.type.AxisType; import com.fr.van.chart.designer.AbstractVanChartScrollPane; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.component.border.VanChartBorderPane; +import com.fr.van.chart.designer.component.border.VanChartBorderPaneWithPreStyle; import com.fr.van.chart.designer.component.format.FormatPaneWithNormalType; import javax.swing.JPanel; @@ -103,15 +106,12 @@ public class VanChartDataSheetPane extends AbstractVanChartScrollPane { return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); } - //TODO Bjorn 数据表面板回退 protected VanChartBorderPane createBorderPanePane() { - return new VanChartBorderPane(); - //return new VanChartBorderPaneWithPreStyle(); + return ChartEditContext.supportTheme() ? new VanChartBorderPaneWithPreStyle() : new VanChartBorderPane(); } protected ChartTextAttrPane createChartTextAttrPane() { - return new ChartTextAttrPane(); - //return new ChartTextAttrPaneWithPreStyle(); + return ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() : new ChartTextAttrPane(); } @Override diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java index 3d6ad86e88..d8c3217380 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java @@ -49,11 +49,6 @@ public class VanChartGaugeCateOrPercentLabelDetailPane extends VanChartGaugeLabe return getGaugeStyle() == GaugeStyle.RING || getGaugeStyle() == GaugeStyle.SLOT; } - //TODO Bjorn 仪表盘自动逻辑 - protected boolean isFontColorAuto() { - return getGaugeStyle() == GaugeStyle.RING || getGaugeStyle() == GaugeStyle.SLOT; - } - protected boolean hasLabelPosition(Plot plot) { switch (getGaugeStyle()) { case RING: diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java index 8c672bab62..0f9e84729d 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java @@ -79,10 +79,8 @@ public class VanChartGaugeLabelDetailPane extends VanChartPlotLabelDetailPane { return false; } - //TODO Bjorn 仪表盘自动逻辑 protected boolean isFontColorAuto() { - return false; - //return true; + return true; } private FontAutoType getFontAutoType() { diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java index 849507e059..0a5f7b8feb 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java @@ -271,9 +271,7 @@ public abstract class VanChartAbstractPlotSeriesPane extends AbstractPlotSeriesP } protected VanChartBorderPane createDiffBorderPane() { - return new VanChartBorderPane(); - //TODO Bjorn 边框自动回退 - //return new VanChartBorderPane(true); + return new VanChartBorderPane(true); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java index 9cf9165547..ef58809795 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java @@ -24,6 +24,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.chart.gui.type.AbstractChartTypePane; import com.fr.design.mainframe.chart.gui.type.ChartImagePane; import com.fr.design.mainframe.chart.info.ChartInfoCollector; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.general.Background; import com.fr.js.NameJavaScriptGroup; import com.fr.log.FineLoggerFactory; @@ -31,6 +32,7 @@ import com.fr.plugin.chart.attr.plot.VanChartPlot; import com.fr.plugin.chart.base.VanChartTools; import com.fr.plugin.chart.base.VanChartZoom; import com.fr.plugin.chart.vanchart.VanChart; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import javax.swing.BorderFactory; import javax.swing.JPanel; @@ -144,6 +146,7 @@ public abstract class AbstractVanChartTypePane extends AbstractChartTypePane(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), diff --git a/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java index a2adff77a7..073002642b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java @@ -337,9 +337,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { } protected JPanel createAreaPane() { - //TODO Bjorn 地图背景自动 - //borderWithAlphaPane = new VanChartBorderWithAlphaPane(true); - borderWithAlphaPane = new VanChartBorderWithAlphaPane(); + borderWithAlphaPane = new VanChartBorderWithAlphaPane(true); double p = TableLayout.PREFERRED; double f = TableLayout.FILL; @@ -355,8 +353,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { } protected JPanel createNullValueColorPane() { - //TODO Bjorn 地图空值背景自动 - /* nullValueAuto = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), + nullValueAuto = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); initNullValueListener(); nullValueColorBox = new ColorSelectBox(80); @@ -373,10 +370,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { new Component[]{text, nullValueAuto}, new Component[]{null, nullValueColorBox}, }; - return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize);*/ - - nullValueColorBox = new ColorSelectBox(80); - return TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_NULL_Value_Color"), nullValueColorBox); + return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); } @@ -593,15 +587,13 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { markerTypeCom.setSelectedItem(mapPlot.getMapMarkerType().toLocalString()); } if (nullValueColorBox != null) { - //TODO Bjorn 地图空值背景自动 - /* if (((VanChartMapPlot) plot).isAutoNullValue()) { + if (((VanChartMapPlot) plot).isAutoNullValue()) { nullValueAuto.setSelectedIndex(0); } else { nullValueAuto.setSelectedIndex(1); } nullValueColorBox.setSelectObject(((VanChartMapPlot) plot).getNullValueColor()); - checkNullValueButton();*/ - nullValueColorBox.setSelectObject(mapPlot.getNullValueColor()); + checkNullValueButton(); } //大数据模式 恢复用注释。下面3行删除。 if (lineMapLargeDataModelGroup != null) { @@ -623,8 +615,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { } } if (nullValueColorBox != null) { - //TODO Bjorn 地图空值背景自动 - //((VanChartMapPlot) plot).setAutoNullValue(nullValueAuto.getSelectedIndex() == 0); + ((VanChartMapPlot) plot).setAutoNullValue(nullValueAuto.getSelectedIndex() == 0); mapPlot.setNullValueColor(nullValueColorBox.getSelectObject()); } //大数据模式 恢复用注释。下面3行删除。 diff --git a/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java b/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java index 4a43d7619e..43a770beae 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java @@ -9,6 +9,7 @@ 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.mode.ChartEditContext; import com.fr.general.ComparatorUtils; import com.fr.plugin.chart.base.GisLayer; import com.fr.plugin.chart.map.VanChartMapPlot; @@ -73,13 +74,18 @@ public class GisLayerPane extends JPanel implements UIObserver { } private boolean isStandardGis() { + return gisButton.getSelectedIndex() == 1; + } + + private boolean isAuto() { return gisButton.getSelectedIndex() == 0; } private JPanel createGISLayerPane() { - gisButton = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Form_Widget_Style_Standard"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); - gisButton.setSelectedIndex(0); + gisButton = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Mode_Auto"), + Toolkit.i18nText("Fine-Design_Form_Widget_Style_Standard"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); + gisButton.setSelectedIndex(ChartEditContext.supportTheme() ? 0 : 1); gisGaoDeLayer = new UIComboBox(MapLayerConfigManager.getGaoDeLayerItems()); gisButton.addActionListener(event -> { refreshZoomLevel(); @@ -94,6 +100,9 @@ public class GisLayerPane extends JPanel implements UIObserver { layerPaneCheckPane = new JPanel(new CardLayout()) { @Override public Dimension getPreferredSize() { + if (isAuto()) { + return new Dimension(0, 0); + } if (isStandardGis()) { return gisGaoDeLayer.getPreferredSize(); } else { @@ -101,6 +110,7 @@ public class GisLayerPane extends JPanel implements UIObserver { } } }; + layerPaneCheckPane.add(new JPanel(), "auto"); layerPaneCheckPane.add(gisGaoDeLayer, "standard"); layerPaneCheckPane.add(gisLayer, "custom"); @@ -129,7 +139,7 @@ public class GisLayerPane extends JPanel implements UIObserver { layerCardPane = new JPanel(new CardLayout()) { @Override public Dimension getPreferredSize() { - if (isStandardGis()) { + if (isStandardGis() || isAuto()) { return new Dimension(0, 0); } String itemName = Utils.objectToString(gisLayer.getSelectedItem()); @@ -188,7 +198,9 @@ public class GisLayerPane extends JPanel implements UIObserver { private void refreshZoomLevel() { //gis图层不同,对应的缩放等级不同。 ZoomLevel[] levels; - if (isStandardGis()) { + if (isAuto()) { + levels = MapStatusPane.ZOOM_LEVELS; + } else if (isStandardGis()) { if (gisGaoDeLayer.getSelectedIndex() == gisGaoDeLayer.getItemCount() - 1) { levels = MapStatusPane.ZOOM_LEVELS; } else { @@ -209,7 +221,14 @@ public class GisLayerPane extends JPanel implements UIObserver { private void checkLayerCardPane() { CardLayout cardLayout = (CardLayout) layerPaneCheckPane.getLayout(); - cardLayout.show(layerPaneCheckPane, isStandardGis() ? "standard" : "custom"); + if (isAuto()) { + cardLayout.show(layerPaneCheckPane, "auto"); + } else if (isStandardGis()) { + cardLayout.show(layerPaneCheckPane, "standard"); + } else { + cardLayout.show(layerPaneCheckPane, "custom"); + } + } private void checkCustomLayerCardPane() { @@ -218,17 +237,26 @@ public class GisLayerPane extends JPanel implements UIObserver { } public void resetGisLayer(VanChartMapPlot mapPlot) { - //TODO Bjorn 地图gis图层自动逻辑 - /* mapPlot.getGisLayer().setGisLayerType(GISLayerType.AUTO); - mapPlot.getGisLayer().setLayerName(GISLayerType.getLocString(GISLayerType.AUTO));*/ - GisLayer defaultGisLayer = mapPlot.getDefaultGisLayer(); - mapPlot.setGisLayer(defaultGisLayer); - populate(defaultGisLayer); +// if (ChartEditContext.supportTheme()) { + GisLayer defaultGisLayer = mapPlot.getDefaultGisLayer(); + mapPlot.setGisLayer(defaultGisLayer); + populate(defaultGisLayer); +// } else { +// GaoDeGisType gaoDeGisType = mapPlot.getDefaultGisLayerType(); +// +// mapPlot.getGisLayer().setGisLayerType(GISLayerType.GAO_DE_API); +// mapPlot.getGisLayer().setLayerName(gaoDeGisType.getTypeName()); +// mapPlot.getGisLayer().setGaoDeGisType(gaoDeGisType); +// populate(mapPlot.getGisLayer()); +// } } public void populate(GisLayer layer) { switch (layer.getGisLayerType()) { + case AUTO: + gisButton.setSelectedIndex(0); + break; case GAO_DE_API: case LAYER_NULL: populateStandardGis(layer); @@ -243,7 +271,7 @@ public class GisLayerPane extends JPanel implements UIObserver { } private void populateStandardGis(GisLayer layer) { - gisButton.setSelectedIndex(0); + gisButton.setSelectedIndex(1); if (layer.getGisLayerType() == GISLayerType.LAYER_NULL) { gisGaoDeLayer.setSelectedIndex(gisGaoDeLayer.getItemCount() - 1); } else { @@ -252,7 +280,7 @@ public class GisLayerPane extends JPanel implements UIObserver { } private void populateCustomGis(GisLayer layer) { - gisButton.setSelectedIndex(1); + gisButton.setSelectedIndex(2); gisLayer.setSelectedItem(layer.getShowItemName()); switch (layer.getGisLayerType()) { @@ -266,7 +294,10 @@ public class GisLayerPane extends JPanel implements UIObserver { } public void update(GisLayer layer) { - if (isStandardGis()) { + if (isAuto()) { + layer.setGisLayerType(GISLayerType.AUTO); + layer.setLayerName(GISLayerType.getLocString(GISLayerType.AUTO)); + } else if (isStandardGis()) { updateStandardGis(layer); } else { updateCustomGis(layer); diff --git a/designer-chart/src/main/java/com/fr/van/chart/pie/style/VanChartPieCategoryLabelContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/pie/style/VanChartPieCategoryLabelContentPane.java index 73c63bbeec..5039f53881 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/pie/style/VanChartPieCategoryLabelContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/pie/style/VanChartPieCategoryLabelContentPane.java @@ -1,13 +1,14 @@ package com.fr.van.chart.pie.style; import com.fr.design.i18n.Toolkit; -import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithAuto; import com.fr.design.ui.ModernUIPane; import com.fr.plugin.chart.base.AttrTooltipContent; import com.fr.plugin.chart.base.format.AttrTooltipCategoryFormat; import com.fr.plugin.chart.base.format.AttrTooltipFormat; import com.fr.plugin.chart.base.format.AttrTooltipSummaryValueFormat; import com.fr.plugin.chart.pie.attr.PieCategoryLabelContent; +import com.fr.plugin.chart.type.FontAutoType; import com.fr.van.chart.designer.component.VanChartLabelContentPane; import com.fr.van.chart.designer.component.format.CategoryNameFormatPaneWithCheckBox; import com.fr.van.chart.designer.component.format.SummaryValueFormatPaneWithCheckBox; @@ -86,7 +87,7 @@ public class VanChartPieCategoryLabelContentPane extends VanChartLabelContentPan } public JPanel createCommonStylePane() { - setTextAttrPane(new ChartTextAttrPane()); + setTextAttrPane(new ChartTextAttrPaneWithAuto(FontAutoType.COLOR)); return getTextAttrPane(); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java b/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java index 8401f86a9c..6096056a4b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java +++ b/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java @@ -274,7 +274,8 @@ public class LegendGradientBar extends JComponent implements ColorSelectable, UI private void dealClick(SelectColorPointBtn selectColorPointBtn) { ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); this.setColor(selectColorPointBtn.getColorInner()); - ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, Color.WHITE, LegendGradientBar.this); + Color selectColor = selectColorPointBtn.getColorInner() == null ? Color.WHITE : selectColorPointBtn.getColorInner(); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, selectColor, LegendGradientBar.this); Color color = this.getColor(); if (color != null) { DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); diff --git a/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java index 9c79f9b8cd..85bbc3c5a2 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java @@ -1,10 +1,15 @@ package com.fr.van.chart.scatter; +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.plugin.chart.base.AttrTooltipContent; import com.fr.van.chart.designer.component.VanChartHtmlLabelPane; import com.fr.van.chart.designer.component.VanChartHtmlLabelPaneWithBackGroundLabel; import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.JPanel; +import java.awt.BorderLayout; /** * 散点图标签界面 @@ -21,12 +26,11 @@ public class VanChartScatterLabelContentPane extends VanChartScatterTooltipCont return new VanChartHtmlLabelPaneWithBackGroundLabel(); } - //TODO Bjorn 散点图标签预定义样式 - /* public JPanel createCommonStylePane() { + public JPanel createCommonStylePane() { if (isInCondition()) { return super.createCommonStylePane(); } - setTextAttrPane(new ChartTextAttrPaneWithPreStyle()); + setTextAttrPane(ChartEditContext.supportTheme() ? new ChartTextAttrPaneWithThemeStyle() : new ChartTextAttrPane()); JPanel stylePanel = new JPanel(new BorderLayout()); stylePanel.add(getTextAttrPane(), BorderLayout.CENTER); @@ -41,9 +45,9 @@ public class VanChartScatterLabelContentPane extends VanChartScatterTooltipCont } if (hasTextStylePane()) { this.getTextAttrPane().update(attrTooltipContent.getTextAttr()); - if (!attrTooltipContent.getTextAttr().isPredefinedStyle()) { + if (!attrTooltipContent.getTextAttr().isThemed()) { attrTooltipContent.setCustom(true); } } - }*/ + } } diff --git a/designer-chart/src/main/resources/com/fr/design/editor/rich_editor.html b/designer-chart/src/main/resources/com/fr/design/editor/rich_editor.html index 6df5a29a14..da8dd5bed1 100644 --- a/designer-chart/src/main/resources/com/fr/design/editor/rich_editor.html +++ b/designer-chart/src/main/resources/com/fr/design/editor/rich_editor.html @@ -20,6 +20,33 @@