diff --git a/build.gradle b/build.gradle index 8e2e8b627..671e64fb9 100644 --- a/build.gradle +++ b/build.gradle @@ -67,10 +67,10 @@ allprojects { implementation 'com.fr.third:jxbrowser:6.23' implementation 'com.fr.third:jxbrowser-mac:6.23' implementation 'com.fr.third:jxbrowser-win64:6.23' - implementation 'com.fr.third:jxbrowser-v7:7.15' - implementation 'com.fr.third:jxbrowser-mac-v7:7.15' - implementation 'com.fr.third:jxbrowser-win64-v7:7.15' - implementation 'com.fr.third:jxbrowser-swing-v7:7.15' + implementation 'com.fr.third:jxbrowser-v7:7.22' + implementation 'com.fr.third:jxbrowser-mac-v7:7.22' + implementation 'com.fr.third:jxbrowser-win64-v7:7.22' + implementation 'com.fr.third:jxbrowser-swing-v7:7.22' implementation 'com.fr.third.server:servlet-api:3.0' implementation 'org.swingexplorer:swexpl:2.0.1' implementation 'org.swingexplorer:swag:1.0' 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 3eb3b7857..013c703fb 100644 --- a/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java +++ b/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java @@ -4,6 +4,7 @@ import com.fr.base.Parameter; import com.fr.base.ParameterConfig; import com.fr.base.TableData; import com.fr.base.io.BaseBook; +import com.fr.base.param.ParameterSource; import com.fr.data.TableDataSource; import com.fr.data.operator.DataOperator; import com.fr.design.file.HistoryTemplateListCache; @@ -19,8 +20,8 @@ import com.fr.stable.Filter; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; import com.fr.stable.js.WidgetName; - import com.fr.util.ParameterApplyHelper; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -283,9 +284,9 @@ public abstract class DesignModelAdapter map, ParameterProvider[] parameterProviders, Filter filter) { if (filter != null) { - ParameterApplyHelper.addPara2Map(map, parameterProviders, filter); + ParameterApplyHelper.addPara2Map(map, parameterProviders, filter, null, ParameterSource.DEFAULT_SOURCE); } else { - ParameterApplyHelper.addPara2Map(map, parameterProviders); + ParameterApplyHelper.addPara2Map(map, parameterProviders, null, ParameterSource.DEFAULT_SOURCE); } } @@ -378,7 +379,7 @@ public abstract class DesignModelAdapter map) { // 添加全局参数 Parameter[] glbParas = ParameterConfig.getInstance().getGlobalParameters(); - ParameterApplyHelper.addPara2Map(map, glbParas); + ParameterApplyHelper.addPara2Map(map, glbParas, null, ParameterSource.GLOBAL_SOURCE); } 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 b57ad6c7a..7761038b7 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -214,6 +214,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private boolean useOptimizedUPM4Adapter; + private boolean propertiesUsable; + /** * DesignerEnvManager. */ @@ -442,12 +444,35 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private static File envFile = null; private File getEnvFile() { + checkDebugStart(); if (envFile == null) { envFile = new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "Env.xml"); } return envFile; } + /** + * 在VM options里加入-Ddebug=true激活 + */ + private static void checkDebugStart() { + + if (ComparatorUtils.equals("true", System.getProperty("debug"))) { + setDebugEnv(); + } + } + + /** + * 端口改一下,环境配置文件改一下。便于启动两个设计器,进行对比调试 + */ + private static void setDebugEnv() { + + DesignUtils.setPort(DesignerPort.getInstance().getDebugMessagePort()); + DesignerEnvManager.setEnvFile(new File(StableUtils.pathJoin( + ProductConstants.getEnvHome(), + ProductConstants.APP_NAME + "Env_debug.xml" + ))); + } + /** * 是否启用了https * @@ -676,6 +701,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.useOptimizedUPM4Adapter = useOptimizedUPM4Adapter; } + public boolean isPropertiesUsable() { + return this.propertiesUsable; + } + + public void setPropertiesUsable(boolean propertiesUsable) { + this.propertiesUsable = propertiesUsable; + } + /** * 知否自动备份 * @@ -797,6 +830,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { designerPushUpdateConfigManager.setAutoPushUpdateEnabled(autoPushUpdateEnabled); } + public boolean isCloudAnalyticsDelay() { + return designerPushUpdateConfigManager.isCloudAnalyticsDelay(); + } + + public void setCloudAnalyticsDelay(boolean cloudAnalyticsDelay) { + designerPushUpdateConfigManager.setCloudAnalyticsDelay(cloudAnalyticsDelay); + } + /** * 设计器登录相关配置 */ @@ -1900,6 +1941,7 @@ 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.setPropertiesUsable(reader.getAttrAsBoolean("propertiesUsable", false)); this.setShowServerDatasetAuthTip(reader.getAttrAsBoolean("showServerDatasetAuthTip", true)); this.setLayoutTemplateStyle(reader.getAttrAsInt("layoutTemplateStyle", LAYOUT_TEMPLATE_SIMPLE_STYLE)); } @@ -2178,6 +2220,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { writer.attr("layoutTemplateStyle", this.getLayoutTemplateStyle()); writer.attr("showServerDatasetAuthTip", this.isShowServerDatasetAuthTip()); writer.attr("useOptimizedUPM4Adapter", this.isUseOptimizedUPM4Adapter()); + writer.attr("propertiesUsable", this.isPropertiesUsable()); writer.end(); } diff --git a/designer-base/src/main/java/com/fr/design/RestartHelper.java b/designer-base/src/main/java/com/fr/design/RestartHelper.java index 64fdda7ba..9c14fd415 100644 --- a/designer-base/src/main/java/com/fr/design/RestartHelper.java +++ b/designer-base/src/main/java/com/fr/design/RestartHelper.java @@ -57,10 +57,8 @@ public class RestartHelper { properties.setProperty((i + size) + "", files[i]); } } - try { - FileOutputStream file2DeleteOutputStream = new FileOutputStream(file); + try (FileOutputStream file2DeleteOutputStream = new FileOutputStream(file)) { properties.store(file2DeleteOutputStream, "save"); - file2DeleteOutputStream.close(); } catch (IOException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } 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 2fa06a564..9c12c491c 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 @@ -171,6 +171,7 @@ public class PreferencePane extends BasicPane { private UICheckBox autoPushUpdateCheckBox; private UICheckBox embedServerLazyStartupCheckBox; private UICheckBox imageCompressPanelCheckBox; + private UICheckBox cloudAnalyticsDelayCheckBox; private UICheckBox vcsEnableCheckBox; private UICheckBox saveCommitCheckBox; @@ -273,6 +274,11 @@ public class PreferencePane extends BasicPane { imageCompressPanelCheckBox = new UICheckBox(i18nText("Fine-Design_Image_Compress")); imageCompressPanel.add(imageCompressPanelCheckBox); advancePane.add(imageCompressPanel); + + JPanel designerStartupOption = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Startup_Option")); + cloudAnalyticsDelayCheckBox = new UICheckBox(i18nText("Fine-Design_Cloud_Analytics_Delay")); + designerStartupOption.add(cloudAnalyticsDelayCheckBox); + advancePane.add(designerStartupOption); } private void createVcsSettingPane(JPanel generalPane) { @@ -444,10 +450,10 @@ public class PreferencePane extends BasicPane { requestFocusInWindow(); label = new UILabel(text); add(GUICoreUtils.createBorderLayoutPane( - new UILabel(i18nText("Fine-Design_Basic_Support_Current_Auto_Complete_Shortcut") + ":"), - BorderLayout.WEST, - label, - BorderLayout.CENTER), + new UILabel(i18nText("Fine-Design_Basic_Support_Current_Auto_Complete_Shortcut") + ":"), + BorderLayout.WEST, + label, + BorderLayout.CENTER), BorderLayout.NORTH); addKeyListener(new KeyAdapter() { @Override @@ -729,7 +735,7 @@ public class PreferencePane extends BasicPane { if (useOptimizedUPMCheckbox != null) { useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM() - || DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter()); + || DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter()); } if (useNewVersionLoginCheckbox != null) { @@ -750,6 +756,7 @@ public class PreferencePane extends BasicPane { this.startWithEmptyFile.setSelected(designerEnvManager.isStartWithEmptyFile()); this.imageCompressPanelCheckBox.setSelected(designerEnvManager.isImageCompress()); + this.cloudAnalyticsDelayCheckBox.setSelected(designerEnvManager.isCloudAnalyticsDelay()); } private int chooseCase(int sign) { @@ -810,6 +817,7 @@ public class PreferencePane extends BasicPane { designerEnvManager.setEmbedServerLazyStartup(this.embedServerLazyStartupCheckBox.isSelected()); designerEnvManager.setImageCompress(this.imageCompressPanelCheckBox.isSelected()); designerEnvManager.setUseOptimizedUPM4Adapter(this.useOptimizedUPMCheckbox != null && this.useOptimizedUPMCheckbox.isSelected()); + designerEnvManager.setCloudAnalyticsDelay(this.cloudAnalyticsDelayCheckBox.isSelected()); VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue()); vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected()); diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java index 029632709..a8970f9d1 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java @@ -1,5 +1,6 @@ package com.fr.design.actions.help.alphafine; +import com.fr.design.DesignerEnvManager; import com.fr.general.ComparatorUtils; import com.fr.license.function.VT4FR; import com.fr.stable.OperatingSystem; @@ -8,6 +9,12 @@ import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLable; import com.fr.stable.xml.XMLableReader; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.Stack; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -82,9 +89,29 @@ public class AlphaFineConfigManager implements XMLable { */ private boolean needRemind = true; + /** + * 产品动态 + */ + private boolean productDynamics = true; + private Map actionSearchTextCache = new HashMap<>(8); private String cacheBuildNO; + + + // todo 暂不持久化 方便测试 + /** + * key: 登录的bbs用户 + * value: alphaFine历史搜索记录 + */ + private Map> historySearchMap = new LinkedHashMap<>(); + + /** + * key: 登录的bbs用户 + * value: 已读的cid的集合 + */ + private Map> readSetMap = new LinkedHashMap<>(); + /** * 直接操作菜单次数 */ @@ -120,6 +147,7 @@ public class AlphaFineConfigManager implements XMLable { this.setContainFileContent(reader.getAttrAsBoolean("isContainFileContent", false)); this.setNeedSegmentationCheckbox(reader.getAttrAsBoolean("needSegmentationCheckbox", true)); this.setNeedIntelligentCustomerService(reader.getAttrAsBoolean("needIntelligentCustomerService", true)); + this.setProductDynamics(reader.getAttrAsBoolean("productDynamics", true)); this.setShortcuts(reader.getAttrAsString("shortcuts", getDefaultShortCuts())); this.setNeedRemind(reader.getAttrAsBoolean("isNeedRemind", true)); this.setOperateCount(reader.getAttrAsInt("operateCount", 0)); @@ -167,7 +195,8 @@ public class AlphaFineConfigManager implements XMLable { .attr("isNeedRemind", this.isNeedRemind()) .attr("operateCount", this.getOperateCount()) .attr("needSegmentationCheckbox", this.isNeedSegmentationCheckbox()) - .attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService()); + .attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService()) + .attr("productDynamics", this.isProductDynamics()); writeActionSearchTextCacheXML(writer); writer.end(); } @@ -335,4 +364,20 @@ public class AlphaFineConfigManager implements XMLable { public void setCacheBuildNO(@NotNull String cacheBuildNO) { this.cacheBuildNO = cacheBuildNO; } + + public Stack getHistorySearch() { + return historySearchMap.computeIfAbsent(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), k -> new SizedStack<>(3)); + } + + public Set getReadSet() { + return readSetMap.computeIfAbsent(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), k -> new HashSet<>()); + } + + public boolean isProductDynamics() { + return productDynamics; + } + + public void setProductDynamics(boolean productDynamics) { + this.productDynamics = productDynamics; + } } diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java index 5bf0214e0..55d467e88 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java @@ -25,37 +25,12 @@ import java.awt.event.MouseEvent; public class AlphaFineConfigPane extends BasicPane { private static final String TYPE = "pressed"; private static final String DISPLAY_TYPE = "+"; - private static final String BACK_SLASH = "BACK_SLASH"; - private static final String DISPLAY_BACK_SLASH = "\\"; - private static final String SLASH = "SLASH"; - private static final String DISPLAY_SLASH = "/"; - private static final String CONTROL = "CONTROL"; - private static final String DISPLAY_CONTROL = "ctrl"; - private static final String OPEN_BRACKET = "OPEN_BRACKET"; - private static final String DISPLAY_OPEN_BRACKET = "{"; - private static final String CLOSE_BRACKET = "CLOSE_BRACKET"; - private static final String DISPLAY_CLOSE_BRACKET = "}"; - private static final String COMMA = "COMMA"; - private static final String DISPLAY_COMMA = ","; - private static final String PERIOD = "PERIOD"; - private static final String DISPLAY_PERIOD = "."; - private static final String SEMICOLON = "SEMICOLON"; - private static final String DISPLAY_SEMICOLON = ";"; - private static final String QUOTE = "QUOTE"; - private static final String DISPLAY_QUOTE = "'"; - private static final String EQUALS = "EQUALS"; - private static final String DISPLAY_EQUALS = "+"; - private static final String MINUS = "MINUS"; - private static final String DISPLAY_MINUS = "-"; - private static final String COMMAND = "META"; - private static final String SMALL_COMMAND = "meta"; - private static final String DISPLAY_COMMAND = "\u2318"; private static final double COLUMN_GAP = 180; private static final double ROW_GAP = 25; private KeyStroke shortCutKeyStore = null; - private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox, needIntelligentCustomerService, containRecommendCheckbox, containActionCheckbox, containDocumentCheckbox, containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox; + private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox, needIntelligentCustomerService, productDynamicsCheckbox, containActionCheckbox, containDocumentCheckbox, containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox; private UITextField shortcutsField; public AlphaFineConfigPane() { @@ -75,9 +50,8 @@ public class AlphaFineConfigPane extends BasicPane { private Component[][] initSearchRangeComponents() { Component[][] components = new Component[][]{ - new Component[]{containRecommendCheckbox, containActionCheckbox, containDocumentCheckbox}, + new Component[]{productDynamicsCheckbox, containActionCheckbox, containDocumentCheckbox}, new Component[]{containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox}, - new Component[]{needIntelligentCustomerService, null, null} }; return components; } @@ -95,7 +69,7 @@ public class AlphaFineConfigPane extends BasicPane { double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP}; JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Search_Range")); - containRecommendCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Recommend")); + productDynamicsCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_Dynamics")); containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set")); containPluginCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon")); containDocumentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help")); @@ -139,7 +113,7 @@ public class AlphaFineConfigPane extends BasicPane { int keyCode = e.getKeyCode(); shortCutKeyStore = KeyStroke.getKeyStroke(keyCode, modifier); String str = shortCutKeyStore.toString(); - shortcutsField.setText(getDisplayShortCut(str)); + shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(str)); shortcutsField.selectAll(); } }); @@ -153,16 +127,16 @@ public class AlphaFineConfigPane extends BasicPane { @Override public void actionPerformed(ActionEvent e) { if (!searchOnlineCheckbox.isSelected()) { - containRecommendCheckbox.setEnabled(false); + productDynamicsCheckbox.setEnabled(false); containPluginCheckbox.setEnabled(false); containDocumentCheckbox.setEnabled(false); needIntelligentCustomerService.setEnabled(false); - containRecommendCheckbox.setSelected(false); + productDynamicsCheckbox.setSelected(false); containPluginCheckbox.setSelected(false); containDocumentCheckbox.setSelected(false); needIntelligentCustomerService.setSelected(false); } else { - containRecommendCheckbox.setEnabled(true); + productDynamicsCheckbox.setEnabled(true); containPluginCheckbox.setEnabled(true); containDocumentCheckbox.setEnabled(true); needIntelligentCustomerService.setEnabled(true); @@ -207,10 +181,10 @@ public class AlphaFineConfigPane extends BasicPane { this.containPluginCheckbox.setSelected(alphaFineConfigManager.isContainPlugin() && enabled4Locale); this.containPluginCheckbox.setEnabled(enabled4Locale); - this.containRecommendCheckbox.setSelected(alphaFineConfigManager.isContainRecommend() && enabled4Locale); - this.containRecommendCheckbox.setEnabled(enabled4Locale); + this.productDynamicsCheckbox.setSelected(alphaFineConfigManager.isProductDynamics() && enabled4Locale); + this.productDynamicsCheckbox.setEnabled(enabled4Locale); - this.shortcutsField.setText(getDisplayShortCut(alphaFineConfigManager.getShortcuts())); + this.shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(alphaFineConfigManager.getShortcuts())); this.needSegmentationCheckbox.setSelected(alphaFineConfigManager.isNeedSegmentationCheckbox()); @@ -226,7 +200,7 @@ public class AlphaFineConfigPane extends BasicPane { alphaFineConfigManager.setContainPlugin(this.containPluginCheckbox.isSelected()); alphaFineConfigManager.setContainAction(this.containActionCheckbox.isSelected()); alphaFineConfigManager.setContainDocument(this.containDocumentCheckbox.isSelected()); - alphaFineConfigManager.setContainRecommend(this.containRecommendCheckbox.isSelected()); + alphaFineConfigManager.setProductDynamics(this.productDynamicsCheckbox.isSelected()); alphaFineConfigManager.setEnabled(this.enabledCheckbox.isSelected()); alphaFineConfigManager.setSearchOnLine(this.searchOnlineCheckbox.isSelected()); alphaFineConfigManager.setContainTemplate(this.containTemplateCheckbox.isSelected()); @@ -245,13 +219,6 @@ public class AlphaFineConfigPane extends BasicPane { } - private String getDisplayShortCut(String shortCut) { - return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH) - .replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET) - .replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE) - .replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND); - } - private KeyStroke convert2KeyStroke(String ks) { return KeyStroke.getKeyStroke(ks.replace(DISPLAY_TYPE, TYPE)); diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java new file mode 100644 index 000000000..e21fc84ee --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java @@ -0,0 +1,44 @@ +package com.fr.design.actions.help.alphafine; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/26 + */ +public class AlphaFineShortCutUtil { + + private static final String TYPE = "pressed"; + private static final String DISPLAY_TYPE = "+"; + private static final String BACK_SLASH = "BACK_SLASH"; + private static final String DISPLAY_BACK_SLASH = "\\"; + private static final String SLASH = "SLASH"; + private static final String DISPLAY_SLASH = "/"; + private static final String CONTROL = "CONTROL"; + private static final String DISPLAY_CONTROL = "ctrl"; + private static final String OPEN_BRACKET = "OPEN_BRACKET"; + private static final String DISPLAY_OPEN_BRACKET = "{"; + private static final String CLOSE_BRACKET = "CLOSE_BRACKET"; + private static final String DISPLAY_CLOSE_BRACKET = "}"; + private static final String COMMA = "COMMA"; + private static final String DISPLAY_COMMA = ","; + private static final String PERIOD = "PERIOD"; + private static final String DISPLAY_PERIOD = "."; + private static final String SEMICOLON = "SEMICOLON"; + private static final String DISPLAY_SEMICOLON = ";"; + private static final String QUOTE = "QUOTE"; + private static final String DISPLAY_QUOTE = "'"; + private static final String EQUALS = "EQUALS"; + private static final String DISPLAY_EQUALS = "+"; + private static final String MINUS = "MINUS"; + private static final String DISPLAY_MINUS = "-"; + private static final String COMMAND = "META"; + private static final String SMALL_COMMAND = "meta"; + private static final String DISPLAY_COMMAND = "\u2318"; + + public static String getDisplayShortCut(String shortCut) { + return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH) + .replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET) + .replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE) + .replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND); + } +} diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java new file mode 100644 index 000000000..fbc6eca00 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java @@ -0,0 +1,30 @@ +package com.fr.design.actions.help.alphafine; + +import java.util.Stack; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/23 + */ +public class SizedStack extends Stack { + + private final int maxSize; + + public SizedStack(int size) { + super(); + this.maxSize = size; + } + + @Override + public T push(T object) { + while (this.size() >= maxSize) { + this.remove(0); + } + // 不重复 + if (this.contains(object)) { + return object; + } + return super.push(object); + } +} \ 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 530b46693..f45e84f20 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 @@ -378,9 +378,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp } protected boolean isDsNameRepeaded(String name) { - if (allDSNames == null) { - allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); - } + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); for (int i = 0; i < allDSNames.length; i++) { if (ComparatorUtils.equals(name, allDSNames[i])) { return true; 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 f7eb9bacc..468982d96 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 @@ -308,6 +308,17 @@ public abstract class DesignTableDataManager { return resMap; } + /** + * 不根据过滤设置,返回当前模板数据集,是有顺序的 + */ + public static java.util.Map getTemplateDataSet(TableDataSource source) { + java.util.Map resMap = new java.util.LinkedHashMap(); + // 模板数据集 + addTemplateData(resMap, source); + + return resMap; + } + public static java.util.Map getAllDataSetIncludingProcedure(java.util.Map resMap) { java.util.LinkedHashMap dsMap = new java.util.LinkedHashMap(); Iterator> entryIt = resMap.entrySet().iterator(); diff --git a/designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java b/designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java new file mode 100644 index 000000000..f7492aefc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java @@ -0,0 +1,53 @@ +package com.fr.design.data; + +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2022/3/28 + */ +public final class MapCompareUtils { + + + /** + * 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 + * + * @param orig 原始map + * @param other 参考的新map + * @param eventHandler 有区别时的事件处理器 + * @param K + * @param V + */ + public static void contrastMapEntries(@NotNull Map orig, @NotNull Map other, @NotNull EventHandler eventHandler) { + + Map copiedOrig = new LinkedHashMap<>(orig); + + other.forEach((k, v) -> { + V existedV = copiedOrig.remove(k); + if (existedV != null) { + if (!v.equals(existedV)) { + eventHandler.on(EntryEventKind.UPDATED, k, v); + } + } else { + eventHandler.on(EntryEventKind.ADDED, k, v); + } + }); + + copiedOrig.forEach((k, v) -> eventHandler.on(EntryEventKind.REMOVED, k, v)); + } + + + public interface EventHandler { + void on(EntryEventKind entryEventKind, K k, V v); + } + + public enum EntryEventKind { + ADDED, + REMOVED, + UPDATED; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/SummaryMethodComboBox.java b/designer-base/src/main/java/com/fr/design/data/datapane/SummaryMethodComboBox.java new file mode 100644 index 000000000..7aee00e24 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/SummaryMethodComboBox.java @@ -0,0 +1,70 @@ +package com.fr.design.data.datapane; + +import com.fr.data.util.function.AbstractDataFunction; +import com.fr.data.util.function.AverageFunction; +import com.fr.data.util.function.CountFunction; +import com.fr.data.util.function.MaxFunction; +import com.fr.data.util.function.MinFunction; +import com.fr.data.util.function.NoneFunction; +import com.fr.data.util.function.SumFunction; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.i18n.Toolkit; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.base.FirstFunction; + +/** + * 图表数据汇总方式下拉框 + * + * 支持首个,最后一个,求和,平均,最大值,最小值,个数 + * + */ +public class SummaryMethodComboBox extends UIComboBox { + public static final String[] CALCULATE_ARRAY = {Toolkit.i18nText("Fine-Design_Chart_Data_Function_First"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Last"), + Toolkit.i18nText("Fine-Design_Chart_Data_Function_Sum"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Average"), + Toolkit.i18nText("Fine-Design_Chart_Data_Function_Max"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Min"), + Toolkit.i18nText("Fine-Design_Chart_Data_Function_Count")}; + public static final Class[] CLASS_ARRAY = {FirstFunction.class, NoneFunction.class, SumFunction.class, AverageFunction.class, + MaxFunction.class, MinFunction.class, CountFunction.class}; + + public SummaryMethodComboBox() { + super(CALCULATE_ARRAY); + setSelectedIndex(2); + } + + public void reset() { + this.setSelectedItem(Toolkit.i18nText("Fine-Design_Chart_Data_Function_Sum")); + } + + /** + * 更新公式选择. + */ + public void populateBean(AbstractDataFunction function) { + for (int i = 0; i < CLASS_ARRAY.length; i++) { + if (function != null && ComparatorUtils.equals(function.getClass(), CLASS_ARRAY[i])) { + setSelectedIndex(i); + break; + } + } + } + + /** + * 返回当前选择的公式 + */ + public AbstractDataFunction updateBean() { + try { + int selectIndex = getSelectedIndex(); + if (selectIndex >= 0 && selectIndex < CLASS_ARRAY.length) { + return (AbstractDataFunction) CLASS_ARRAY[selectIndex].newInstance(); + } + } catch (InstantiationException e) { + FineLoggerFactory.getLogger().error("Function Error"); + return null; + } catch (IllegalAccessException e) { + FineLoggerFactory.getLogger().error("Function Error"); + return null; + } + + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java index 80471b9e6..0c000f5af 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java @@ -1,7 +1,10 @@ package com.fr.design.data.datapane; import com.fr.base.BaseUtils; +import com.fr.data.impl.storeproc.StoreProcedure; import com.fr.design.constants.UIConstants; +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; +import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; import com.fr.design.data.tabledata.wrapper.TableDataWrapper; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; import com.fr.design.gui.itree.refreshabletree.UserObjectRefreshJTree; @@ -17,6 +20,10 @@ import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import java.awt.Color; import java.awt.Component; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * TableData Tree @@ -24,6 +31,10 @@ import java.awt.Component; public class TableDataTree extends UserObjectRefreshJTree { private static final long serialVersionUID = 1L; + private static final String TABLE_DATA_NODE = "tableData"; + + private static final String COLUMN_NODE = "column"; + /** * Constructor. */ @@ -84,12 +95,13 @@ public class TableDataTree extends UserObjectRefreshJTree { this.tableDataTreeCellRenderer = tableDataTreeCellRenderer; } + @Override protected void refreshTreeNode(ExpandMutableTreeNode eTreeNode, String childName) { if (interceptRefresh(eTreeNode)) { return; } boolean refreshall = childName.isEmpty(); - ExpandMutableTreeNode[] new_nodes = loadChildTreeNodes(eTreeNode); + ExpandMutableTreeNode[] newNodes = loadChildTreeNodes(eTreeNode); java.util.List childTreeNodeList = new java.util.ArrayList(); for (int i = 0, len = eTreeNode.getChildCount(); i < len; i++) { @@ -102,30 +114,30 @@ public class TableDataTree extends UserObjectRefreshJTree { eTreeNode.removeAllChildren(); - for (int ci = 0; ci < new_nodes.length; ci++) { - Object cUserObject = new_nodes[ci].getUserObject(); + for (int ci = 0; ci < newNodes.length; ci++) { + Object cUserObject = newNodes[ci].getUserObject(); ExpandMutableTreeNode cTreeNode = null; for (int ni = 0, nlen = childTreeNodeList.size(); ni < nlen; ni++) { cTreeNode = (ExpandMutableTreeNode) childTreeNodeList.get(ni); if (ComparatorUtils.equals(cTreeNode.getUserObject(), cUserObject)) { if (!refreshall && !ComparatorUtils.equals(childName, ((NameObject) cUserObject).getName())) { - new_nodes[ci] = cTreeNode; + newNodes[ci] = cTreeNode; break; } - new_nodes[ci].setExpanded(cTreeNode.isExpanded()); + newNodes[ci].setExpanded(cTreeNode.isExpanded()); // REPORT-41299 如果建立的是错误的数据集(没有Child的情况)且这个错误数据集处于isExpanded状态,会在后面的if语句中调用getFirstChild()产生异常,因此这里判断一下 - if (cTreeNode.isExpanded() && cTreeNode.getChildCount() == 0) { - new_nodes[ci].setExpanded(false); + if (cTreeNode.getChildCount() == 0) { + newNodes[ci].setExpanded(false); break; } if (cTreeNode.getFirstChild() instanceof ExpandMutableTreeNode && cTreeNode.isExpanded()) { - checkChildNodes(cTreeNode, new_nodes[ci]); + checkChildNodes(cTreeNode, newNodes[ci]); } break; } } - eTreeNode.add(new_nodes[ci]); + eTreeNode.add(newNodes[ci]); } } @@ -140,9 +152,7 @@ public class TableDataTree extends UserObjectRefreshJTree { for (int k = 0; k < nodes.length; k++) { newChild.add(nodes[k]); } - if (newChild.getChildCount() > 1 && ((ExpandMutableTreeNode) newChild.getFirstChild()).getUserObject() == PENDING) { - newChild.remove(0); - } + removePending(newChild); if (ComparatorUtils.equals(oldChild.getUserObject(), newChild.getUserObject())) { newChild.setExpanded(oldChild.isExpanded()); } @@ -150,9 +160,100 @@ public class TableDataTree extends UserObjectRefreshJTree { } } + private void removePending(ExpandMutableTreeNode treeNode) { + if (treeNode.getChildCount() > 1 && ((ExpandMutableTreeNode) treeNode.getFirstChild()).getUserObject() == PENDING) { + treeNode.remove(0); + } + } + + @Override + public void refresh4TreeSearch() { + ExpandMutableTreeNode root = (ExpandMutableTreeNode) this.getModel().getRoot(); + refreshTreeNode4TreeSearch(root); + ((DefaultTreeModel) this.getModel()).reload(root); + root.expandCurrentTreeNode(this); + } + + /** + * 主要是处理节点是否应该添加为搜索结果,以及节点是否需要展开 + * + * @param root + */ + private void refreshTreeNode4TreeSearch(ExpandMutableTreeNode root) { + if (interceptRefresh(root)) { + return; + } + // 获取数据集子节点 + ExpandMutableTreeNode[] dsTreeNodes = loadChildTreeNodes(root); + root.removeAllChildren(); + for (ExpandMutableTreeNode dsTreeNode : dsTreeNodes) { + if (TableDataTreeSearchManager.getInstance().nodeNameMatches(dsTreeNode.getUserObject().toString())) { + // 加载数据列节点 + loadAndAddChildTreeChild(dsTreeNode); + // 处理子节点的展开 + dealWithNodeExpand(dsTreeNode); + // 添加数据集子节点 + root.add(dsTreeNode); + } + } + } + + /** + * 加载所有子节点,并添加到父节点中 + * + * @param treeNode + * @return + */ + private ExpandMutableTreeNode loadAndAddChildTreeChild(ExpandMutableTreeNode treeNode) { + if (isTreeNodeStoreProcedure(treeNode)) { + // 如果是存储过程,则再加载一次其子表节点,这里比较坑的就是存储过程不能使用loadChildTreeNodes + int tableChildCounts = treeNode.getChildCount(); + ExpandMutableTreeNode[] childs = new ExpandMutableTreeNode[tableChildCounts]; + for (int i = 0; i < tableChildCounts; i++) { + ExpandMutableTreeNode tableChild = (ExpandMutableTreeNode) treeNode.getChildAt(i); + loadAndAddChildTreeChild(tableChild); + childs[i] = tableChild; + removePending(tableChild); + } + treeNode.addChildTreeNodes(childs); + } else { + ExpandMutableTreeNode[] expandMutableTreeNodes = loadChildTreeNodes(treeNode); + treeNode.addChildTreeNodes(expandMutableTreeNodes); + } + removePending(treeNode); + return treeNode; + } + + /** + * 处理节点的展开,如果此节点是存储过程,还会处理其子表节点的展开 + * 只针对数据集节点 + * + * @param treeNode + * @return + */ + public ExpandMutableTreeNode dealWithNodeExpand(ExpandMutableTreeNode treeNode) { + String tableDataName = treeNode.getUserObject().toString(); + // 主要还是处理存储过程 + if (isTreeNodeStoreProcedure(treeNode)) { + int childCount = treeNode.getChildCount(); + for (int i = 0; i < childCount; i++) { + ExpandMutableTreeNode child = (ExpandMutableTreeNode) treeNode.getChildAt(i); + String nodeName = tableDataName + "_" + child.getUserObject().toString(); + if (TableDataTreeSearchManager.getInstance().nodeCanExpand(nodeName)) { + child.setExpanded(true); + } + } + } + if (TableDataTreeSearchManager.getInstance().nodeCanExpand(treeNode.getUserObject().toString())) { + treeNode.setExpanded(true); + } + return treeNode; + } + /* * p:获得选中的NameObject = name + tabledata. */ + @Override public NameObject getSelectedNameObject() { TreePath selectedTreePath = this.getSelectionPath(); if (selectedTreePath == null) { @@ -182,6 +283,108 @@ public class TableDataTree extends UserObjectRefreshJTree { } + /** + * 获得选中的数据集节点的NameObject的数组,只会返回数据集节点的NameObject + * 当多选了数据集或数据列时,也只返回选中的数据集 + */ + public NameObject[] getSelectedTableDataNameObjects() { + Map> tableDataNodesAndColumnNodes = getSelectedTableDataNodesAndColumnNodes(); + List tableDataNodes = tableDataNodesAndColumnNodes.get(TABLE_DATA_NODE); + if (tableDataNodes == null) { + return new NameObject[0]; + } + return tableDataNodes.stream().map(node -> (NameObject) node.getUserObject()).toArray(NameObject[]::new); + } + + /** + * 获取选中的数据集节点和列名节点 + * 其中存储过程的子表节点不计入数据集节点中,仅存储过程节点本身计入数据集节点 + * @return + */ + private Map> getSelectedTableDataNodesAndColumnNodes() { + TreePath[] selectedTreePaths = this.getSelectionPaths(); + if (selectedTreePaths == null) { + return new HashMap<>(); + } + Map> resultMap = new HashMap<>(); + List tableDataNodes = new ArrayList<>(); + List columnNodes = new ArrayList<>(); + resultMap.put(TABLE_DATA_NODE, tableDataNodes); + resultMap.put(COLUMN_NODE, columnNodes); + for (TreePath selectedTreePath : selectedTreePaths) { + if (selectedTreePath == null) { + continue; + } + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + if (isTableDataNodes(selectedTreeNode)) { + // 数据集节点 + tableDataNodes.add(selectedTreeNode); + } else { + // 列名节点 + columnNodes.add(selectedTreeNode); + } + } + return resultMap; + } + + /** + * 获取选中的数据集数量,选中数据列则不计入 + * + * @return + */ + public int getSelectedTableDataCounts() { + return getSelectedTableDataNameObjects().length; + } + + /** + * 是否存在单独选了数据列节点,但没选其对应数据集的情况 + * @return + */ + public boolean hasSelectedIndependentColumns() { + Map> tableDataNodesAndColumnNodes = getSelectedTableDataNodesAndColumnNodes(); + List tableDataNodes = tableDataNodesAndColumnNodes.get(TABLE_DATA_NODE); + List columnNodes = tableDataNodesAndColumnNodes.get(COLUMN_NODE); + if (columnNodes == null || columnNodes.size() == 0) { + // 未选中数据列 + return false; + } + if (tableDataNodes == null || tableDataNodes.size() == 0) { + // 选中数据列而未选中数据集 + return true; + } + boolean result = false; + for (ExpandMutableTreeNode columnNode : columnNodes) { + ExpandMutableTreeNode tableDataNode = getBelongedTableDataNodes(columnNode); + if (!tableDataNodes.contains(tableDataNode)) { + result = true; + } + } + return result; + } + + /** + * 获取一个节点归属的数据集层级父节点 + * @param treeNode + * @return + */ + private ExpandMutableTreeNode getBelongedTableDataNodes(ExpandMutableTreeNode treeNode) { + if (isTableDataNodes(treeNode)) { + return treeNode; + } + return getBelongedTableDataNodes((ExpandMutableTreeNode) treeNode.getParent()); + } + + private boolean isTableDataNodes(ExpandMutableTreeNode treeNode) { + if (treeNode == null) { + return false; + } + Object userObject = treeNode.getUserObject(); + if (userObject instanceof NameObject && ((NameObject) userObject).getObject() instanceof AbstractTableDataWrapper) { + return true; + } + return false; + } + public TableDataWrapper[] getSelectedDatas() { TreePath[] selectedTreePaths = this.getSelectionPaths(); if (selectedTreePaths == null || selectedTreePaths.length == 0) { @@ -247,4 +450,20 @@ public class TableDataTree extends UserObjectRefreshJTree { treeModel.reload(root); } + + /** + * 判断此节点是否为存储过程 + * + * @param treeNode + * @return + */ + public boolean isTreeNodeStoreProcedure(ExpandMutableTreeNode treeNode) { + Object userObject = treeNode.getUserObject(); + if (userObject instanceof NameObject) { + NameObject nameObject = (NameObject) userObject; + TableDataWrapper tableDataWrapper = (TableDataWrapper) nameObject.getObject(); + return tableDataWrapper.getTableData() instanceof StoreProcedure; + } + return false; + } } 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 5a6366602..8f03b1cfc 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 @@ -13,6 +13,11 @@ 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.datapane.management.clip.TableDataTreeClipboard; +import com.fr.design.data.datapane.management.search.pane.TableDataSearchRemindPane; +import com.fr.design.data.datapane.management.search.pane.TreeSearchToolbarPane; +import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode; +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; import com.fr.design.data.tabledata.StoreProcedureWorkerListener; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane; @@ -20,12 +25,15 @@ 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.ilable.UILabel; +import com.fr.design.gui.ilist.CheckBoxListWithPartialSelect; +import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itoolbar.UIToolbar; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; @@ -37,6 +45,7 @@ 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.design.utils.gui.GUICoreUtils; import com.fr.esd.core.strategy.config.StrategyConfig; import com.fr.esd.core.strategy.config.StrategyConfigHelper; import com.fr.esd.event.DSMapping; @@ -45,7 +54,6 @@ 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; @@ -61,7 +69,6 @@ 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; @@ -69,9 +76,12 @@ import javax.swing.ToolTipManager; import javax.swing.tree.TreePath; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Dimension; import java.awt.GridLayout; import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; @@ -105,15 +115,36 @@ public class TableDataTreePane extends BasicTableDataTreePane { return singleton; } + /** + * 获取不必每次都refreshDockingView的数据集树面板 + * 不会主动替换DesignModelAdapter,需要保证使用时没有跨模板动作,谨慎使用 + * @param tc + * @return + */ + public synchronized static BasicTableDataTreePane getInstanceWithoutRefreshEverytime(DesignModelAdapter tc) { + TableDataPaneProcessor treePaneProcessor = ExtraDesignClassManager.getInstance().getSingle(TableDataPaneProcessor.XML_TAG); + if (treePaneProcessor != null) { + return treePaneProcessor.createTableDataTreePane(tc); + } + return singleton.tc == null ? getInstance(tc) : singleton; + } + private TableDataSourceOP op; private TableDataTree tableDataTree; + private UIPopupMenu popupMenu; private EditAction editAction; private RemoveAction removeAction; + private CopyAction copyAction; + private PasteAction pasteAction; private EsdOnAction esdAction; private EsdOffAction esdOffAction; + private SwitchAction switchAction; private PreviewTableDataAction previewTableDataAction; private JPanel serverDatasetAuthTipJPanel = new JPanel(); + private TableDataSearchRemindPane remindPane; + private TreeSearchToolbarPane toolbarPane; + private TableDataTreePane() { initPane(); } @@ -122,63 +153,131 @@ public class TableDataTreePane extends BasicTableDataTreePane { this.setLayout(new BorderLayout(4, 0)); this.setBorder(null); - //TableDataTree - tableDataTree = new TableDataTree(); + initTableDataTree(); + toolbarPane = initToolBarPane(); + JPanel treePane = initTreePane(); + dealWithTableDataTree(); + this.add(toolbarPane, BorderLayout.NORTH); + this.add(treePane, BorderLayout.CENTER); + checkButtonEnabled(); + } + + /** + * 处理TableDataTree的监听等 + */ + private void dealWithTableDataTree() { + // tooltip ToolTipManager.sharedInstance().registerComponent(tableDataTree); ToolTipManager.sharedInstance().setDismissDelay(3000); ToolTipManager.sharedInstance().setInitialDelay(0); + // 右键菜单 + popupMenu = new UIPopupMenu(); + popupMenu.add(editAction.createMenuItem()); + popupMenu.add(previewTableDataAction.createMenuItem()); + popupMenu.addSeparator(); + popupMenu.add(copyAction.createMenuItem()); + popupMenu.add(pasteAction.createMenuItem()); + popupMenu.add(removeAction.createMenuItem()); + popupMenu.addSeparator(); + // 监听 + tableDataTree.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + // 服务器暂不支持右键菜单 + if (SwingUtilities.isRightMouseButton(e) && op.getDataMode() != TableDataSourceOP.SERVER_TABLE_DATA) { + GUICoreUtils.showPopupMenu(popupMenu, e.getComponent(), e.getX(), e.getY()); + } + checkButtonEnabled(); + } + }); + tableDataTree.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + //F2重命名先屏蔽了, 有bug没时间弄 + if (e.getKeyCode() == KeyEvent.VK_F2) { + return; + } + + super.keyPressed(e); + checkButtonEnabled(); + } + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + checkButtonEnabled(); + } + }); + // TreeCellEditor + tableDataTree.setEditable(true); + TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this); + treeCellEditor.addCellEditorListener(treeCellEditor); + tableDataTree.setCellEditor(treeCellEditor); + new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY); + } + /** + * 工具栏面板 + * + * @return + */ + private TreeSearchToolbarPane initToolBarPane() { + // toolbar addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); - addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + addMenuDef.setIconPath("/com/fr/design/images/control/addPopup"); createAddMenuDef(); // 创建插件监听 createPluginListener(); editAction = new EditAction(); + copyAction = new CopyAction(); + pasteAction = new PasteAction(); removeAction = new RemoveAction(); previewTableDataAction = new PreviewTableDataAction(tableDataTree); connectionTableAction = new ConnectionTableAction(); esdAction = new EsdOnAction(); esdOffAction = new EsdOffAction(); - + switchAction = new SwitchAction(); toolbarDef = new ToolBarDef(); - toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction); + toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction, switchAction); UIToolbar toolBar = ToolBarDef.createJToolBar(); toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); toolBar.setBorderPainted(true); toolbarDef.updateToolBar(toolBar); - JPanel toolbarPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - toolbarPane.add(toolBar, BorderLayout.CENTER); - this.add(toolbarPane, BorderLayout.NORTH); + TreeSearchToolbarPane searchLayerdPane = new TreeSearchToolbarPane(toolBar); + searchLayerdPane.setPreferredSize(new Dimension(this.getWidth(), 23)); - UIScrollPane scrollPane = new UIScrollPane(tableDataTree); - scrollPane.setBorder(null); + return searchLayerdPane; + } + + /** + * 数据集树面板 + * + * @return + */ + private JPanel initTreePane() { + JPanel treePane = new JPanel(new BorderLayout(0, 6)); + // north + JPanel northPane = new JPanel(FRGUIPaneFactory.createBorderLayout()); initServerDatasetAuthTipJPanel(); initButtonGroup(); - JPanel jPanel = new JPanel(new BorderLayout(0, 0)); - 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); - tableDataTree.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - checkButtonEnabled(); - } - }); - tableDataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, tableDataTree)); - // TreeCellEditor - tableDataTree.setEditable(true); - TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this); - treeCellEditor.addCellEditorListener(treeCellEditor); - tableDataTree.setCellEditor(treeCellEditor); - new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY); - checkButtonEnabled(); + northPane.add(buttonGroup, BorderLayout.CENTER); + northPane.add(serverDatasetAuthTipJPanel, BorderLayout.SOUTH); + // center + remindPane = new TableDataSearchRemindPane(getDataTree()); + + treePane.add(northPane, BorderLayout.NORTH); + treePane.add(remindPane, BorderLayout.CENTER); + return treePane; + } + + /** + * 初始化 TableDataTree + */ + private void initTableDataTree() { + tableDataTree = new TableDataTree(); } private void initServerDatasetAuthTipJPanel() { @@ -300,6 +399,10 @@ public class TableDataTreePane extends BasicTableDataTreePane { */ @Override public void dgEdit(final AbstractTableDataPane tableDataPane, String originalName, boolean isUpdate) { + // 编辑时如果正在搜索,跳回原树 + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } tableDataPane.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { public void fireDoneAction() { if (tableDataTree.getSelectionPath() == null) { @@ -471,6 +574,17 @@ public class TableDataTreePane extends BasicTableDataTreePane { ((TableDataSourceDependent) td).setTableDataSource(tds); } String tdName = nPanel.getObjectName(); + + //处理缓存策略配置 + if (uPanel instanceof DBTableDataPane) { + StrategyConfig editingConfig = ((DBTableDataPane) uPanel).updateStrategyConfig(); + if (editingConfig != null) { + editingConfig.setDsName(tdName); + StrategyConfigAttrUtils.addStrategyConfig(editingConfig); + } + ((DBTableData) td).setDsName(tdName); + } + tds.putTableData(tdName, td); Map map = new HashMap(); if (!ComparatorUtils.equals(paneName, tdName)) { @@ -482,6 +596,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { int[] rows = tableDataTree.getSelectionRows(); tableDataTree.refreshChildByName(tdName); tableDataTree.setSelectionRows(rows); + FineLoggerFactory.getLogger().info("add table data succeeded for {}", tdName); } @Override @@ -501,11 +616,61 @@ public class TableDataTreePane extends BasicTableDataTreePane { this.createAddMenuDef(); } + /** + * 感觉这里,把一堆Action和Op之类的送到抽象类里去检查,很奇怪,抽象类本身定义的Action只有add和connection + * 另外因为改动了数据集树节点的选中逻辑,所以这边改成自己类内部实现 + * 不直接改抽象类是怕影响到部分插件兼容 + */ private void checkButtonEnabled() { - super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, tableDataTree); + // 检查添加与定义数据连接操作 + this.checkAddAndConnectionEnabled(); + // 检查编辑、预览、复制、粘贴、删除等基本操作 + this.checkBasicButtonEnabled(); + // 检查esd相关操作 this.checkESDComponentsEnabled(); } + private void checkAddAndConnectionEnabled() { + connectionTableAction.setEnabled(WorkContext.getCurrent() != null && WorkContext.getCurrent().isRoot()); + addMenuDef.setEnabled(!(op == null || op.interceptButtonEnabled() || op.getDataMode() == SERVER_TABLE_DATA)); + } + + private void checkBasicButtonEnabled() { + // 设置下各个button的基本状态,避免代码重复 + editAction.setEnabled(false); + copyAction.setEnabled(false); + pasteAction.setEnabled(false); + removeAction.setEnabled(false); + previewTableDataAction.setEnabled(false); + if (op == null || op.interceptButtonEnabled()) { + // 保持false状态 + return; + } + // 获取选中的数据集数量 + int selectioncount = getDataTree().getSelectedTableDataCounts(); + if (op.getDataMode() == SERVER_TABLE_DATA) { + // 服务器数据集下,选中数据集数量为1时,可以预览 + if (selectioncount == 1 && !getDataTree().hasSelectedIndependentColumns()) { + previewTableDataAction.setEnabled(true); + } + // 其它保持false状态 + return; + } + // 模板数据集时,粘贴可用 + pasteAction.setEnabled(true); + if (selectioncount == 0 || getDataTree().hasSelectedIndependentColumns()) { + // 未选中数据集,或存在单独选中的数据列时,其它保持false状态 + return; + } + if (selectioncount == 1) { + // 仅选中单个数据集时,才可以编译、预览 + editAction.setEnabled(true); + previewTableDataAction.setEnabled(true); + } + removeAction.setEnabled(true); + copyAction.setEnabled(true); + } + private void checkESDComponentsEnabled() { if (buttonGroup.getSelectedIndex() == 1) { @@ -594,6 +759,9 @@ public class TableDataTreePane extends BasicTableDataTreePane { if (op != null) { op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA); + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } refreshDockingView(); } @@ -689,8 +857,8 @@ public class TableDataTreePane extends BasicTableDataTreePane { } @Override - public Icon getIcon() { - return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_on.png"); + public String getIconResource() { + return "/com/fr/design/images/control/batch_esd_on"; } @Override @@ -736,8 +904,8 @@ public class TableDataTreePane extends BasicTableDataTreePane { } @Override - public Icon getIcon() { - return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_off.png"); + public String getIconResource() { + return "/com/fr/design/images/control/batch_esd_off"; } @Override @@ -758,14 +926,14 @@ public class TableDataTreePane extends BasicTableDataTreePane { public abstract String getName(); - public abstract Icon getIcon(); + public abstract String getIconResource(); public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper); public AbstractESDAction() { this.setName(getName()); this.setMnemonic('R'); - this.setSmallIcon(getIcon()); + this.setSmallIcon(getIconResource()); } @Override @@ -831,7 +999,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { public EditAction() { this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit")); this.setMnemonic('E'); - this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH)); + this.setSmallIcon("/com/fr/design/images/control/edit"); } @Override @@ -858,39 +1026,138 @@ public class TableDataTreePane extends BasicTableDataTreePane { public RemoveAction() { this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); this.setMnemonic('R'); - this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + this.setSmallIcon("/com/fr/design/images/control/remove"); } @Override public void actionPerformed(ActionEvent e) { - NameObject selectedNO = tableDataTree.getSelectedNameObject(); - - if (selectedNO == null) { + NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects(); + if (selectedNameObjects == null || selectedNameObjects.length == 0) { + FineLoggerFactory.getLogger().error("Table Data to remove is null or not selected"); return; } + // 可以半选的CheckBoxList + CheckBoxListWithPartialSelect tableDataCheckBoxPane = new CheckBoxListWithPartialSelect(selectedNameObjects); + UIScrollPane scrollPane = new UIScrollPane(tableDataCheckBoxPane); + UILabel tips = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Select_Source_To_Remove")); + BasicPane basicPane = new BasicPane() { + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Remove"); + } + }; + basicPane.setLayout(new BorderLayout()); + basicPane.add(tips, BorderLayout.NORTH); + basicPane.add(scrollPane, BorderLayout.CENTER); + BasicDialog basicDialog = basicPane.showSmallWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { + @Override + public void doOk() { + List selectedValues = tableDataCheckBoxPane.getSelectedObjects(); + // 删除时如果正在搜索,跳回原树 + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } + for (Object toRemove : selectedValues) { + try { + doRemove((String) toRemove); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, "remove table data failed for {}", toRemove); + } + } + } - 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(); + @Override + public void doCancel() { + super.doCancel(); + } + }); + basicDialog.setVisible(true); + } + + private void doRemove(String toRemove) throws Exception { + // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 + op.removeAction(toRemove); + tableDataTree.refresh(); + // Richie:默认最后一行获得焦点. + tableDataTree.requestFocus(); + tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1); + fireDSChanged(); + checkButtonEnabled(); + + //删掉缓存配置 + StrategyConfigAttrUtils.removeStrategyConfig(toRemove); + + // 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样 + // 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效 + // 这里额外发出一次数据集修改事件 + StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(toRemove))); + DesignTableDataManager.removeSelectedColumnNames(toRemove); + DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(toRemove); + FineLoggerFactory.getLogger().info("remove table data succeeded for {}", toRemove); + } + } + + private class CopyAction extends UpdateAction { + + public CopyAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Copy")); + this.setMnemonic('C'); + this.setSmallIcon("/com/fr/design/images/m_edit/copy"); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects(); + Map dataWrapperMap = TableDataTreeClipboard.getInstance().transferNameObjectArray2Map(selectedNameObjects); + TableDataTreeClipboard.getInstance().addToClip(dataWrapperMap); + } + } - //删掉缓存配置 - StrategyConfigAttrUtils.removeStrategyConfig(selectedNO.getName()); + private class PasteAction extends UpdateAction { - // 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样 - // 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效 - // 这里额外发出一次数据集修改事件 - StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName()))); - DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); - DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName()); + public PasteAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Action_Paste_Name")); + this.setMnemonic('P'); + this.setSmallIcon("/com/fr/design/images/m_edit/paste"); + } + + @Override + public void actionPerformed(ActionEvent e) { + // 粘贴时如果正在搜索,跳回原树 + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); } + Map dataWrapperMap = TableDataTreeClipboard.getInstance().takeFromClip(); + for (Map.Entry dataWrapperEntry : dataWrapperMap.entrySet()) { + // 处理数据集名称 + String dsName = getNoRepeatedDsName4Paste(dataWrapperEntry.getKey()); + AbstractTableDataWrapper wrapper = dataWrapperEntry.getValue(); + AbstractTableDataPane tableDataPane = wrapper.creatTableDataPane(); + addDataPane(tableDataPane, dsName); + } + } + } + + public String getNoRepeatedDsName4Paste(String oldName) { + while (isDsNameRepeaded(oldName)) { + oldName = oldName + Toolkit.i18nText("Fine-Design_Table_Data_Copy_Of_Table_Data"); + } + return oldName; + } + + private class SwitchAction extends UpdateAction { + + public SwitchAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Search")); + this.setMnemonic('S'); + this.setSmallIcon("/com/fr/design/images/data/search"); + } + + @Override + public void actionPerformed(ActionEvent e) { + // 交换层级 + toolbarPane.switchPane(TreeSearchToolbarPane.SEARCH_PANE); + TableDataTreeSearchManager.getInstance().switchToSearch(TableDataSearchMode.match(buttonGroup.getSelectedIndex()), DesignTableDataManager.getEditingTableDataSource()); } } 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 1566395ed..12c62b435 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 @@ -6,6 +6,7 @@ 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.data.MapCompareUtils; import com.fr.design.dialog.BasicDialog; import com.fr.design.fun.ConnectionProvider; import com.fr.design.gui.controlpane.JListControlPane; @@ -16,21 +17,21 @@ import com.fr.design.i18n.Toolkit; import com.fr.event.EventDispatcher; import com.fr.file.ConnectionConfig; 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.transaction.Configurations; +import com.fr.transaction.WorkerFacade; import com.fr.workspace.WorkContext; import java.awt.Window; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -42,7 +43,8 @@ import java.util.UUID; public class ConnectionListPane extends JListControlPane implements ConnectionShowPane { public static final String TITLE_NAME = Toolkit.i18nText("Fine-Design_Basic_Server_Define_Data_Connection"); private boolean isNamePermitted = true; - private HashMap renameMap = new HashMap(); + private final HashMap renameMap = new HashMap<>(); + private final Map populatedConnectionsSnapshot = new LinkedHashMap<>(); public ConnectionListPane() { renameMap.clear(); @@ -149,11 +151,16 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh */ public void populate(ConnectionConfig connectionConfig) { List nameObjectList = new ArrayList(); + populatedConnectionsSnapshot.clear(); for (Map.Entry entry : connectionConfig.getConnections().entrySet()) { nameObjectList.add(new NameObject(entry.getKey(), entry.getValue())); + try { + populatedConnectionsSnapshot.put(entry.getKey(), (Connection) entry.getValue().clone()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } } this.populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); - } /** @@ -162,23 +169,36 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh public void update(ConnectionConfig connectionConfig) { // Nameable[]居然不能强转成NameObject[],一定要这么写... Nameable[] res = this.update(); - 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; + Map updatedMap = new LinkedHashMap<>(); + Arrays.stream(res).map(n -> (NameObject) n).forEach(no -> updatedMap.put(no.getName(), (Connection) no.getObject())); + + List removedConnNames = new ArrayList<>(); + List addedOrUpdatedConnections = new ArrayList<>(); + + MapCompareUtils.contrastMapEntries(populatedConnectionsSnapshot, updatedMap, (entryEventKind, s, connection) -> { + switch (entryEventKind) { + case REMOVED: + removedConnNames.add(s); + break; + case ADDED: + case UPDATED: + addedOrUpdatedConnections.add(new ConnectionBean(s, StringUtils.EMPTY, connection)); + default: + break; } - connectionBeans.add(new ConnectionBean(nameObject.getName(), oldName, (Connection) nameObject.getObject())); - } + }); + + + this.alterConnections(removedConnNames, addedOrUpdatedConnections); + } + + private void alterConnections(List removedConnNames, List addedOrUpdatedConnections) { + try { - WorkContext.getCurrent().get(ConnectionOperator.class, new ExceptionHandler() { - @Override - public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) { - return saveByOldWay(connectionBeans); - } - }).saveConnection(new ArrayList<>(connectionConfig.getConnections().keySet()), connectionBeans); + WorkContext.getCurrent().get(ConnectionOperator.class, exceptionInfo -> saveByOldWay(removedConnNames, addedOrUpdatedConnections)) + .saveConnection(removedConnNames, addedOrUpdatedConnections); + + // hades:远程环境时,由于时直接RPC调用远程修改,因此设计器本地配置需要失效 if (!WorkContext.getCurrent().isLocal()) { EventDispatcher.fire(RemoteConfigEvent.EDIT, ConnectionConfig.getInstance().getNameSpace()); } @@ -187,13 +207,20 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh } } - private boolean saveByOldWay(List connectionBeans) { + private boolean saveByOldWay(List removedConnNames, List addedOrUpdatedConnections) { try { - return ConnectionOperatorImpl.getInstance().saveConnection(connectionBeans); + return Configurations.modify(new WorkerFacade(ConnectionConfig.class) { + @Override + public void run() { + removedConnNames.forEach(n -> ConnectionConfig.getInstance().removeConnection(n)); + addedOrUpdatedConnections.forEach(cb -> ConnectionConfig.getInstance().addConnection(cb.getName(), cb.getConnection())); + } + }); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - return false; } + + return false; } public static void showDialog(Window parent) { diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java index 9a870d07d..48f710dfb 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java @@ -7,6 +7,7 @@ import com.fr.data.security.ssh.SshException; import com.fr.data.security.ssh.SshType; import com.fr.data.security.ssh.impl.KeyVerifySsh; import com.fr.data.security.ssh.impl.NormalSsh; +import com.fr.data.security.ssl.SslUtils; import com.fr.design.border.UITitledBorder; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicPane; @@ -25,7 +26,6 @@ import com.fr.file.FILE; import com.fr.file.FILEChooserPane; import com.fr.file.filter.ChooseFileFilter; import com.fr.stable.StringUtils; -import com.fr.stable.project.ProjectConstants; import com.fr.third.guava.collect.HashBiMap; import javax.swing.ImageIcon; @@ -131,7 +131,7 @@ public class SshPane extends BasicPane { fileChooserButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true)); + FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(SslUtils.PREFIX, new ChooseFileFilter(true), SslUtils.CERTIFICATES); int type = fileChooser.showOpenDialog(SshPane.this, StringUtils.EMPTY); if (type == FILEChooserPane.OK_OPTION) { final FILE file = fileChooser.getSelectedFILE(); @@ -142,6 +142,7 @@ public class SshPane extends BasicPane { } } fileChooser.removeAllFilter(); + fileChooser.removeTopPath(); } }); } @@ -241,7 +242,6 @@ public class SshPane extends BasicPane { public static class KeyFileUITextField extends UITextField { private static final Pattern ERROR_START = Pattern.compile("^([/\\\\.]+).*"); private static final Pattern MUTI_DOT = Pattern.compile("\\.+"); - private static final String PREFIX = ProjectConstants.RESOURCES_NAME + "/"; private static final String UPPER = ".."; public KeyFileUITextField(int columns) { @@ -283,7 +283,7 @@ public class SshPane extends BasicPane { public String getText() { // 获取的时候,不为空,给他加上前缀就好了,否则还是空 if (!StringUtils.isEmpty(super.getText())) { - return PREFIX + super.getText(); + return SslUtils.PREFIX + super.getText(); } return StringUtils.EMPTY; } @@ -291,8 +291,8 @@ public class SshPane extends BasicPane { @Override public void setText(String text) { // 设置的时候,不为空,说明文件指定了(文件需要是resource下),替换掉前缀 - if (!StringUtils.isEmpty(text) && text.startsWith(PREFIX)) { - super.setText(text.replaceFirst(PREFIX, "")); + if (!StringUtils.isEmpty(text) && text.startsWith(SslUtils.PREFIX)) { + super.setText(text.replaceFirst(SslUtils.PREFIX, "")); } else { super.setText(text); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java index 2d9c26e23..c44007991 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java @@ -4,6 +4,7 @@ import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.security.ssl.Ssl; import com.fr.data.security.ssl.SslException; import com.fr.data.security.ssl.SslType; +import com.fr.data.security.ssl.SslUtils; import com.fr.data.security.ssl.impl.NormalSsl; import com.fr.design.border.UITitledBorder; import com.fr.design.constants.UIConstants; @@ -21,7 +22,6 @@ import com.fr.file.FILE; import com.fr.file.FILEChooserPane; import com.fr.file.filter.ChooseFileFilter; import com.fr.stable.StringUtils; -import com.fr.stable.project.ProjectConstants; import javax.swing.ImageIcon; import javax.swing.JPanel; @@ -148,7 +148,7 @@ public class SslPane extends BasicPane { @Override public void actionPerformed(ActionEvent e) { - FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true)); + FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(SslUtils.PREFIX, new ChooseFileFilter(true), SslUtils.CERTIFICATES); int type = fileChooser.showOpenDialog(SslPane.this, StringUtils.EMPTY); if (type == FILEChooserPane.OK_OPTION) { final FILE file = fileChooser.getSelectedFILE(); @@ -159,6 +159,7 @@ public class SslPane extends BasicPane { } } fileChooser.removeAllFilter(); + fileChooser.removeTopPath(); } } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java new file mode 100644 index 000000000..44ae90b2c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java @@ -0,0 +1,68 @@ +package com.fr.design.data.datapane.management.clip; + +import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; +import com.fr.general.NameObject; + +import java.util.HashMap; +import java.util.Map; + +/** + * 用于数据集的复制粘贴 + * + * @author Yvan + */ +public class TableDataTreeClipboard { + + /** + * 数据集名称 - 数据集Wrapper + */ + private Map clip = new HashMap<>(); + + private static class Holder { + private static final TableDataTreeClipboard INSTANCE = new TableDataTreeClipboard(); + } + + private TableDataTreeClipboard() { + } + + public static TableDataTreeClipboard getInstance() { + return Holder.INSTANCE; + } + + /** + * 添加选中的数据集数据到剪切板,覆盖原本剪切板内数据 + * + * @param copyMap + * @return + */ + public void addToClip(Map copyMap) { + this.clip = copyMap; + } + + public Map transferNameObjectArray2Map(NameObject[] selectedNameObjects) { + Map resultMap = new HashMap<>(); + if (selectedNameObjects == null) { + return resultMap; + } + for (NameObject selectedNameObject : selectedNameObjects) { + resultMap.put(selectedNameObject.getName(), (AbstractTableDataWrapper) selectedNameObject.getObject()); + } + return resultMap; + } + + /** + * 取出剪切板内的所有数据集数据,剪切板不清空 + * + * @return + */ + public Map takeFromClip() { + return clip; + } + + /** + * 清空剪切板 + */ + public void reset() { + clip.clear(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/TableDataTreeSearchManager.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/TableDataTreeSearchManager.java new file mode 100644 index 000000000..f77a94db8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/TableDataTreeSearchManager.java @@ -0,0 +1,242 @@ +package com.fr.design.data.datapane.management.search; + +import com.fr.data.TableDataSource; +import com.fr.design.DesignModelAdapter; +import com.fr.design.data.datapane.TableDataTree; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeEvent; +import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeListener; +import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode; +import com.fr.design.data.datapane.management.search.searcher.TableDataTreeSearcher; +import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus; +import com.fr.design.data.datapane.management.search.view.TreeSearchRendererHelper; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; + +import javax.swing.SwingUtilities; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 数据集树搜索管理器 + * + * @author Yvan + */ +public class TableDataTreeSearchManager { + + /** + * 数据集树搜索器 + */ + private TableDataTreeSearcher treeSearcher; + + /** + * 搜索任务的状态 + */ + private TreeSearchStatus treeSearchStatus; + + /** + * 缓存上次搜索文本,避免重复搜索 + */ + private String lastSearchText; + + /** + * 存储与复原 原本数据集树的UI + */ + private TreeSearchRendererHelper rendererHelper; + + /** + * 取数计数器 + */ + private AtomicInteger count; + + /** + * 搜索状态变化监听 + */ + private List listeners = new ArrayList<>(); + + private TableDataTreeSearchManager() { + init(); + } + + private void init() { + this.treeSearchStatus = TreeSearchStatus.NOT_IN_SEARCH_MODE; + } + + private static class Holder { + private static final TableDataTreeSearchManager INSTANCE = new TableDataTreeSearchManager(); + } + + public static TableDataTreeSearchManager getInstance() { + return Holder.INSTANCE; + } + + public TreeSearchStatus getTreeSearchStatus() { + return treeSearchStatus; + } + + public void setTreeSearchStatus(TreeSearchStatus treeSearchStatus) { + this.treeSearchStatus = treeSearchStatus; + // 每次设置搜索状态,都触发下监听,让页面跟随变化 + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + for (TreeSearchStatusChangeListener listener : listeners) { + listener.updateTreeSearchChange(new TreeSearchStatusChangeEvent(treeSearchStatus)); + } + } + }); + } + + public void registerTreeSearchStatusChangeListener(TreeSearchStatusChangeListener listener) { + listeners.add(listener); + } + + /** + * 工具栏处切换到搜索面板 + * + * @param searchMode + * @param tableDataSource + */ + public void switchToSearch(TableDataSearchMode searchMode, TableDataSource tableDataSource) { + setTreeSearchStatus(TreeSearchStatus.SEARCH_NOT_BEGIN); + rendererHelper = new TreeSearchRendererHelper(); + rendererHelper.save(getCurrentTableDataTree()); + treeSearcher = new TableDataTreeSearcher(); + FineLoggerFactory.getLogger().debug("switch to table data search for mode: {}", searchMode.name()); + treeSearcher.beforeSearch(searchMode, tableDataSource); + } + + /** + * 获取当前的tableDataTree + * + * @return + */ + private TableDataTree getCurrentTableDataTree() { + DesignModelAdapter currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter(); + TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstance(currentModelAdapter); + return tableDataTreePane.getDataTree(); + } + + public boolean isMatchSetsEmpty() { + return treeSearcher.isMatchSetsEmpty(); + } + + /** + * 开始搜索 + * + * @param searchText + */ + public void startSearch(String searchText) { + if (isRepeatSearch(searchText) || StringUtils.isEmpty(searchText)) { + return; + } + setTreeSearchStatus(TreeSearchStatus.SEARCHING); + rendererHelper.replaceTreeRenderer(getCurrentTableDataTree(), searchText); + count = new AtomicInteger(treeSearcher.getAllWrappersSize()); + FineLoggerFactory.getLogger().debug("start table data search for search text: {}", searchText); + treeSearcher.startSearch(searchText); + } + + /** + * 计数-1 + */ + public void decreaseCount() { + if (count == null) { + return; + } + int cunrrentCount = count.decrementAndGet(); + // 减到0后判断状态 + if (cunrrentCount == 0 && getTreeSearchStatus() == TreeSearchStatus.SEARCHING) { + completeSearch(); + } + } + + private boolean isRepeatSearch(String searchText) { + boolean repeat = StringUtils.equals(lastSearchText, searchText); + lastSearchText = searchText; + return repeat; + } + + /** + * 刷新树,更新搜索的结果 + */ + public void updateTableDataTree() { + getCurrentTableDataTree().refresh4TreeSearch(); + } + + /** + * 中断搜索 + */ + public void stopSearch() { + setTreeSearchStatus(TreeSearchStatus.SEARCH_STOPPED); + count = null; + FineLoggerFactory.getLogger().debug("stop table data search for search text: {}", lastSearchText); + treeSearcher.stopSearch(); + } + + /** + * 搜索完成 + */ + public void completeSearch() { + setTreeSearchStatus(TreeSearchStatus.SEARCH_COMPLETED); + count = null; + FineLoggerFactory.getLogger().debug("complete table data search for search text: {}", lastSearchText); + treeSearcher.completeSearch(); + } + + /** + * 切换回工具栏,恢复数据集树UI + */ + public void restoreToolBarAndTreePane() { + setTreeSearchStatus(TreeSearchStatus.NOT_IN_SEARCH_MODE); + FineLoggerFactory.getLogger().info("out of table data search"); + if (treeSearcher != null) { + treeSearcher.afterSearch(); + } + lastSearchText = null; + if (rendererHelper != null) { + rendererHelper.restore(getCurrentTableDataTree()); + } + } + + /** + * 恢复数据集树UI + */ + public void restoreTreePane() { + setTreeSearchStatus(TreeSearchStatus.SEARCH_NOT_BEGIN); + lastSearchText = null; + if (rendererHelper != null) { + rendererHelper.restore(getCurrentTableDataTree()); + } + } + + /** + * 节点是否应该添加到搜索结果树的根节点中 + * 只针对数据集节点 + * + * @param treeNodeName 数据集节点名称 + * @return + */ + public boolean nodeNameMatches(String treeNodeName) { + return treeSearcher.nodeMatches(treeNodeName); + } + + /** + * 节点是否应该展开 + * + * @param treeNodeName 节点名称 + * @return + */ + public boolean nodeCanExpand(String treeNodeName) { + return treeSearcher.nodeCanExpand(treeNodeName); + } + + public boolean isInSearchMode() { + return getTreeSearchStatus() != TreeSearchStatus.NOT_IN_SEARCH_MODE; + } + + public void outOfSearchMode() { + restoreToolBarAndTreePane(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchCallback.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchCallback.java new file mode 100644 index 000000000..a3c8c5c98 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchCallback.java @@ -0,0 +1,12 @@ +package com.fr.design.data.datapane.management.search.control; + + +/** + * 搜索任务回调 + * + * @author Yvan + */ +public interface TreeSearchCallback { + + void done(TreeSearchResult treeSearchResult); +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchResult.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchResult.java new file mode 100644 index 000000000..320eca947 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchResult.java @@ -0,0 +1,37 @@ +package com.fr.design.data.datapane.management.search.control; + +import java.util.List; + +/** + * @author Yvan + */ +public interface TreeSearchResult { + + /** + * 任务结果是否成功 + * + * @return + */ + boolean isSuccess(); + + /** + * 数据集名称匹配或者列名匹配时,需要将数据集名称添加到匹配结果集中 + * + * @return + */ + List getAddToMatch(); + + /** + * 数据集有列名匹配时,需要添加到展开结果集中 + * + * @return + */ + List getAddToExpand(); + + /** + * 数据集完成计算后,需要添加到完成结果集中 + * + * @return + */ + List getAddToCalculated(); +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchTask.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchTask.java new file mode 100644 index 000000000..695c7d3c2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchTask.java @@ -0,0 +1,10 @@ +package com.fr.design.data.datapane.management.search.control; + +/** + * @author Yvan + */ +public interface TreeSearchTask extends Runnable { + + @Override + void run(); +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchCallBack.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchCallBack.java new file mode 100644 index 000000000..6137032f0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchCallBack.java @@ -0,0 +1,54 @@ +package com.fr.design.data.datapane.management.search.control.common; + +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; +import com.fr.design.data.datapane.management.search.control.TreeSearchCallback; +import com.fr.design.data.datapane.management.search.control.TreeSearchResult; +import com.fr.design.data.datapane.management.search.searcher.TableDataTreeSearcher; +import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus; + +import javax.swing.SwingUtilities; + +/** + * @author Yvan + */ +public class TableDataSearchCallBack implements TreeSearchCallback { + + protected TableDataTreeSearcher treeSearcher; + + public TableDataSearchCallBack(TableDataTreeSearcher treeSearcher) { + this.treeSearcher = treeSearcher; + } + + @Override + public void done(TreeSearchResult treeSearchResult) { + if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() != TreeSearchStatus.SEARCHING) { + return; + } + if (treeSearchResult.isSuccess()) { + // 添加结果 + addToTreeSearcher(treeSearchResult); + } + // 处理UI + updateTableDataTree(); + } + + protected void updateTableDataTree() { + SwingUtilities.invokeLater(() -> { + if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() != TreeSearchStatus.SEARCHING) { + return; + } + TableDataTreeSearchManager.getInstance().updateTableDataTree(); + // 搜索计数 + TableDataTreeSearchManager.getInstance().decreaseCount(); + }); + } + + protected void addToTreeSearcher(TreeSearchResult treeSearchResult) { + // 添加到已计算结果集 + treeSearcher.addToCalculatedSets(treeSearchResult.getAddToCalculated()); + // 添加到匹配结果集 + treeSearcher.addToMatchSets(treeSearchResult.getAddToMatch()); + // 添加到展开结果集 + treeSearcher.addToCanExpandSets(treeSearchResult.getAddToExpand()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchResult.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchResult.java new file mode 100644 index 000000000..387933df5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchResult.java @@ -0,0 +1,105 @@ +package com.fr.design.data.datapane.management.search.control.common; + +import com.fr.design.data.datapane.management.search.control.TreeSearchResult; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Yvan + */ +public class TableDataSearchResult implements TreeSearchResult { + + private boolean success; + + private List addToMatch; + + private List addToExpand; + + private List addToCalculated; + + protected TableDataSearchResult(Builder builder) { + this.success = builder.success; + this.addToMatch = builder.addToMatch; + this.addToExpand = builder.addToExpand; + this.addToCalculated = builder.addToCalculated; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public void setAddToMatch(List addToMatch) { + this.addToMatch = addToMatch; + } + + public void setAddToExpand(List addToExpand) { + this.addToExpand = addToExpand; + } + + public void setAddToCalculated(List addToCalculated) { + this.addToCalculated = addToCalculated; + } + + @Override + public boolean isSuccess() { + return this.success; + } + + @Override + public List getAddToMatch() { + return this.addToMatch; + } + + @Override + public List getAddToExpand() { + return this.addToExpand; + } + + @Override + public List getAddToCalculated() { + return this.addToCalculated; + } + + public static class Builder { + + private boolean success; + + private List addToMatch; + + private List addToExpand; + + private List addToCalculated; + + public Builder() { + this.success = false; + this.addToMatch = new ArrayList<>(); + this.addToExpand = new ArrayList<>(); + this.addToCalculated = new ArrayList<>(); + } + + public Builder buildSuccess(boolean success) { + this.success = success; + return this; + } + + public Builder buildAddToMatch(List addToMatch) { + this.addToMatch = addToMatch; + return this; + } + + public Builder buildAddToExpand(List addToExpand) { + this.addToExpand = addToExpand; + return this; + } + + public Builder buildAddToCalculated(List addToCalculated) { + this.addToCalculated = addToCalculated; + return this; + } + + public TableDataSearchResult build() { + return new TableDataSearchResult(this); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchTask.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchTask.java new file mode 100644 index 000000000..1a8b607c2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchTask.java @@ -0,0 +1,147 @@ +package com.fr.design.data.datapane.management.search.control.common; + +import com.fr.design.data.datapane.management.search.control.TreeSearchCallback; +import com.fr.design.data.datapane.management.search.control.TreeSearchResult; +import com.fr.design.data.datapane.management.search.control.TreeSearchTask; +import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Yvan + */ +public class TableDataSearchTask implements TreeSearchTask { + + /** + * 用户搜索的文本 + */ + private String searchText; + + private TableDataWrapper tableDataWrapper; + + private TreeSearchCallback callback; + + public TableDataSearchTask(String searchText, TableDataWrapper tableDataWrapper, TreeSearchCallback callback) { + this.searchText = searchText; + this.tableDataWrapper = tableDataWrapper; + this.callback = callback; + } + + @Override + public void run() { + TreeSearchResult result; + try { + if (isTableDataStoreProcedure(tableDataWrapper)) { + result = dealWithStoreProcedureTableDataWrapper((StoreProcedureDataWrapper) tableDataWrapper); + } else { + result = dealWithCommonTableDataWrapper(tableDataWrapper); + } + FineLoggerFactory.getLogger().debug("calculate {}'s columns succeeded", tableDataWrapper.getTableDataName()); + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e, "calculate {}'s columns failed", tableDataWrapper.getTableDataName()); + result = dealWithErrorTableDataWrapper(tableDataWrapper); + } + callback.done(result); + } + + /** + * 处理错误情况 + * + * @param tableDataWrapper + */ + private TreeSearchResult dealWithErrorTableDataWrapper(TableDataWrapper tableDataWrapper) { + return new TableDataSearchResult.Builder().buildSuccess(false).build(); + } + + /** + * 处理普通数据集的搜索与匹配 + * + * @param tableDataWrapper + */ + private TreeSearchResult dealWithCommonTableDataWrapper(TableDataWrapper tableDataWrapper) { + String tableDataName = tableDataWrapper.getTableDataName(); + boolean isTableDataNameMatch = isMatchSearch(tableDataName, searchText); + List columnNameList = tableDataWrapper.calculateColumnNameList(); + // 没取到列名的话,代表取数那边出错了,就不添加数据集了 + if (columnNameList.size() == 0) { + return new TableDataSearchResult.Builder().buildSuccess(false).build(); + } + boolean isColumnMatch = columnNameList.stream().anyMatch(columnName -> isMatchSearch(columnName, searchText)); + return new TableDataSearchResult.Builder() + .buildSuccess(true) + .buildAddToMatch(isTableDataNameMatch || isColumnMatch ? Arrays.asList(tableDataName) : new ArrayList<>()) + .buildAddToExpand(isColumnMatch ? Arrays.asList(tableDataName) : new ArrayList<>()) + .buildAddToCalculated(Arrays.asList(tableDataName)) + .build(); + } + + /** + * 处理存储过程的搜索与匹配 + * + * @param procedureDataWrapper + */ + private TreeSearchResult dealWithStoreProcedureTableDataWrapper(StoreProcedureDataWrapper procedureDataWrapper) { + // 存储过程数据集名称,例如 Proc1_Table1 + String tableDataName = procedureDataWrapper.getTableDataName(); + // 存储过程名称,例如 Proc1 + String storeProcedureName = procedureDataWrapper.getStoreprocedureName(); + // 存储过程子表名称,例如 Table1 + String tableName = tableDataName.replaceFirst(storeProcedureName, StringUtils.EMPTY).replaceFirst("_", StringUtils.EMPTY); + boolean isStoreProcedureNameMatch = isMatchSearch(storeProcedureName, searchText); + boolean isTableNameMatch = isMatchSearch(tableName, searchText); + // 再处理子表的columns + List columnNameList = tableDataWrapper.calculateColumnNameList(); + boolean isColumnMatch = columnNameList.stream().anyMatch(columnName -> isMatchSearch(columnName, searchText)); + Set addToMatch = new HashSet<>(); + Set addToExpand = new HashSet<>(); + Set addToCalculated = new HashSet<>(); + if (isStoreProcedureNameMatch) { + addToMatch.add(storeProcedureName); + } + if (isTableNameMatch) { + addToMatch.add(storeProcedureName); + addToExpand.add(storeProcedureName); + } + if (isColumnMatch) { + addToMatch.add(storeProcedureName); + addToExpand.add(storeProcedureName); + // 这里有重名风险,所以要添加 “Proc1_Table1”,在结果树展示的时候再去处理 + addToExpand.add(tableDataName); + } + addToCalculated.add(tableDataName); + return new TableDataSearchResult.Builder() + .buildSuccess(true) + .buildAddToMatch(new ArrayList<>(addToMatch)) + .buildAddToExpand(new ArrayList<>(addToExpand)) + .buildAddToCalculated(new ArrayList<>(addToCalculated)) + .build(); + + } + + /** + * 判断TableDataWrapper内的TableData是否为存储过程 + * + * @param tableDataWrapper + * @return + */ + private boolean isTableDataStoreProcedure(TableDataWrapper tableDataWrapper) { + return tableDataWrapper instanceof StoreProcedureDataWrapper; + } + + /** + * 判断是否匹配搜索文本,不区分大小写 + * + * @param str + * @return + */ + private boolean isMatchSearch(String str, String searchText) { + return str.toUpperCase().contains(searchText.toUpperCase()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchCallBack.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchCallBack.java new file mode 100644 index 000000000..929c81a12 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchCallBack.java @@ -0,0 +1,23 @@ +package com.fr.design.data.datapane.management.search.control.pre; + +import com.fr.design.data.datapane.management.search.control.TreeSearchResult; +import com.fr.design.data.datapane.management.search.control.common.TableDataSearchCallBack; +import com.fr.design.data.datapane.management.search.searcher.TableDataTreeSearcher; + +/** + * 预取数任务回调 + * + * @author Yvan + */ +public class TableDataPreSearchCallBack extends TableDataSearchCallBack { + + + public TableDataPreSearchCallBack(TableDataTreeSearcher treeSearcher) { + super(treeSearcher); + } + + @Override + public void done(TreeSearchResult treeSearchResult) { + // do nothing + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchResult.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchResult.java new file mode 100644 index 000000000..6ebdb33ab --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchResult.java @@ -0,0 +1,40 @@ +package com.fr.design.data.datapane.management.search.control.pre; + +import com.fr.design.data.datapane.management.search.control.TreeSearchResult; + +import java.util.ArrayList; +import java.util.List; + +/** + * 预取数任务结果,不需要回调,因此空实现即可 + * + * @author Yvan + */ +public class TableDataPreSearchResult implements TreeSearchResult { + + private boolean success; + + public TableDataPreSearchResult(boolean success) { + this.success = success; + } + + @Override + public boolean isSuccess() { + return this.success; + } + + @Override + public List getAddToMatch() { + return new ArrayList<>(); + } + + @Override + public List getAddToExpand() { + return new ArrayList<>(); + } + + @Override + public List getAddToCalculated() { + return new ArrayList<>(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchTask.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchTask.java new file mode 100644 index 000000000..979eef1b0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchTask.java @@ -0,0 +1,45 @@ +package com.fr.design.data.datapane.management.search.control.pre; + +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; +import com.fr.design.data.datapane.management.search.control.TreeSearchTask; +import com.fr.design.data.datapane.management.search.control.common.TableDataSearchResult; +import com.fr.design.data.datapane.management.search.control.TreeSearchCallback; +import com.fr.design.data.datapane.management.search.control.TreeSearchResult; +import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.log.FineLoggerFactory; + +/** + * 预取数任务 + * + * @author Yvan + */ +public class TableDataPreSearchTask implements TreeSearchTask { + + private TreeSearchCallback callback; + + private TableDataWrapper tableDataWrapper; + + public TableDataPreSearchTask(TreeSearchCallback callback, TableDataWrapper tableDataWrapper) { + this.callback = callback; + this.tableDataWrapper = tableDataWrapper; + } + + @Override + public void run() { + TreeSearchResult result; + try { + tableDataWrapper.calculateColumnNameList(); + result = new TableDataSearchResult.Builder() + .buildSuccess(true) + .build(); + FineLoggerFactory.getLogger().debug("pre calculate {}'s columns succeeded", tableDataWrapper.getTableDataName()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, "pre calculate {}'s columns failed", tableDataWrapper.getTableDataName()); + result = new TableDataSearchResult.Builder() + .buildSuccess(false) + .build(); + } + callback.done(result); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeEvent.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeEvent.java new file mode 100644 index 000000000..9d28e2d73 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeEvent.java @@ -0,0 +1,22 @@ +package com.fr.design.data.datapane.management.search.event; + +import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus; + +import java.util.EventObject; + +/** + * @author Yvan + */ +public class TreeSearchStatusChangeEvent extends EventObject { + + private TreeSearchStatus status; + + public TreeSearchStatusChangeEvent(Object source) { + super(source); + this.status = (TreeSearchStatus) source; + } + + public TreeSearchStatus getTreeSearchStatus() { + return status; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeListener.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeListener.java new file mode 100644 index 000000000..63dc4e698 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeListener.java @@ -0,0 +1,11 @@ +package com.fr.design.data.datapane.management.search.event; + +import java.util.EventListener; + +/** + * @author Yvan + */ +public interface TreeSearchStatusChangeListener extends EventListener { + + void updateTreeSearchChange(TreeSearchStatusChangeEvent event); +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java new file mode 100644 index 000000000..01b767623 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java @@ -0,0 +1,215 @@ +package com.fr.design.data.datapane.management.search.pane; + +import com.fr.base.svg.IconUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.data.datapane.TableDataTree; +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; +import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeEvent; +import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeListener; +import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus; +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 javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + * @author Yvan + */ +public class TableDataSearchRemindPane extends JPanel implements TreeSearchStatusChangeListener { + + private RemindPane remindPane; + private TreePane treePane; + + public TableDataSearchRemindPane(TableDataTree tableDataTree) { + this.setLayout(new BorderLayout()); + remindPane = new RemindPane(); + treePane = new TreePane(tableDataTree); + // 初始状态 + this.add(remindPane, BorderLayout.NORTH); + this.add(treePane, BorderLayout.CENTER); + TableDataTreeSearchManager.getInstance().registerTreeSearchStatusChangeListener(this); + } + + /** + * 根据搜索状态变化,来调整自身面板的显示 + * + * @param event + */ + @Override + public void updateTreeSearchChange(TreeSearchStatusChangeEvent event) { + TreeSearchStatus status = event.getTreeSearchStatus(); + if (status == TreeSearchStatus.SEARCH_NOT_BEGIN || status == TreeSearchStatus.NOT_IN_SEARCH_MODE) { + remindPane.onNotBegin(); + treePane.onNotBegin(); + } else if (status == TreeSearchStatus.SEARCHING) { + remindPane.onInSearching(); + treePane.onInSearching(); + } else if (status == TreeSearchStatus.SEARCH_STOPPED) { + remindPane.onStoppedSearching(); + treePane.onStoppedSearching(); + } else { + boolean matchSetsEmpty = TableDataTreeSearchManager.getInstance().isMatchSetsEmpty(); + // 代表是否搜索出结果 + remindPane.onDoneSearching(matchSetsEmpty); + treePane.onDoneSearching(matchSetsEmpty); + } + this.revalidate(); + } + + private interface TreeSearchStatusChange { + + void onNotBegin(); + + void onInSearching(); + + void onStoppedSearching(); + + void onDoneSearching(boolean matchSetsEmpty); + } + + private class TreePane extends JPanel implements TreeSearchStatusChange { + + private UIScrollPane scrollPane; + + private JPanel notFoundPane; + + private CardLayout cardLayout; + + private static final String SCROLL_PANE = "scrollPane"; + + private static final String NOT_FOUND_PANE = "notFoundPane"; + + public TreePane(TableDataTree tableDataTree) { + init(tableDataTree); + } + + private void init(TableDataTree tableDataTree) { + + scrollPane = new UIScrollPane(tableDataTree); + scrollPane.setBorder(null); + + notFoundPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5); + UILabel emptyPicLabel = new UILabel(); + emptyPicLabel.setIcon(IconUtils.readIcon("com/fr/base/images/share/no_match_icon.png")); + emptyPicLabel.setHorizontalAlignment(SwingConstants.CENTER); + emptyPicLabel.setPreferredSize(new Dimension(240, 100)); + UILabel textLabel = new UILabel(Toolkit.i18nText("Fine-Design_Tree_Search_Not_Match"), SwingConstants.CENTER); + textLabel.setForeground(Color.gray); + textLabel.setHorizontalAlignment(SwingConstants.CENTER); + textLabel.setPreferredSize(new Dimension(240, 20)); + notFoundPane.add(emptyPicLabel); + notFoundPane.add(textLabel); + notFoundPane.setBorder(BorderFactory.createEmptyBorder(80, 0, 0, 0)); + + cardLayout = new CardLayout(); + this.setLayout(cardLayout); + this.add(scrollPane, SCROLL_PANE); + this.add(notFoundPane, NOT_FOUND_PANE); + cardLayout.show(this, SCROLL_PANE); + } + + @Override + public void onNotBegin() { + switchPane(SCROLL_PANE); + } + + @Override + public void onInSearching() { + switchPane(SCROLL_PANE); + } + + @Override + public void onStoppedSearching() { + switchPane(SCROLL_PANE); + } + + @Override + public void onDoneSearching(boolean matchSetsEmpty) { + if (matchSetsEmpty) { + switchPane(NOT_FOUND_PANE); + } + } + + private void switchPane(String paneName) { + cardLayout.show(this, paneName); + } + } + + private static class RemindPane extends JPanel implements TreeSearchStatusChange { + + private static final String IN_SEARCHING = Toolkit.i18nText("Fine-Design_Tree_Search_In_Searching"); + private static final String STOP_SEARCHING = Toolkit.i18nText("Fine-Design_Tree_Search_Stop_Search"); + private static final String SEARCHING_STOPPED = Toolkit.i18nText("Fine-Design_Tree_Search_Search_Stopped"); + private static final String DONE_SEARCHING = Toolkit.i18nText("Fine-Design_Tree_Search_Search_Completed"); + + private UILabel textLabel; + + private UILabel stopLabel; + + private MouseListener stopSearch; + + public RemindPane() { + init(); + } + + private void init() { + this.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0)); + // 初始情况下为Not_Begin + textLabel = new UILabel(); + textLabel.setForeground(Color.gray); + stopLabel = new UILabel(); + stopLabel.setForeground(UIConstants.NORMAL_BLUE); + stopSearch = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + TableDataTreeSearchManager.getInstance().stopSearch(); + } + }; + stopLabel.addMouseListener(stopSearch); + this.add(textLabel); + this.add(stopLabel); + onNotBegin(); + } + + @Override + public void onNotBegin() { + this.setVisible(false); + } + + @Override + public void onInSearching() { + this.textLabel.setVisible(false); + this.stopLabel.setText(STOP_SEARCHING); + this.stopLabel.setVisible(true); + this.setVisible(true); + } + + @Override + public void onStoppedSearching() { + this.textLabel.setText(SEARCHING_STOPPED); + this.textLabel.setVisible(true); + this.stopLabel.setVisible(false); + this.setVisible(true); + } + + @Override + public void onDoneSearching(boolean matchSetsEmpty) { + this.textLabel.setText(DONE_SEARCHING); + this.textLabel.setVisible(true); + this.stopLabel.setVisible(false); + this.setVisible(true); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java new file mode 100644 index 000000000..7524efed2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java @@ -0,0 +1,208 @@ +package com.fr.design.data.datapane.management.search.pane; + +import com.fr.base.svg.IconUtils; +import com.fr.design.DesignModelAdapter; +import com.fr.design.constants.UIConstants; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; +import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeEvent; +import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeListener; +import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Yvan + */ +public class TreeSearchToolbarPane extends JPanel implements TreeSearchStatusChangeListener { + + public static final String TOOLBAR_PANE = "toolbarPane"; + + public static final String SEARCH_PANE = "searchPane"; + + /** + * 工具栏 + */ + private UIToolbar toolbar; + + /** + * 工具栏面板 + */ + private JPanel toolbarPane; + + /** + * 搜索面板 + */ + private JPanel searchPane; + + /** + * 搜索输入框 + */ + private UITextField searchTextField; + + /** + * 内容面板 + */ + private JPanel contentPane; + + /** + * 卡片布局管理器 + */ + private CardLayout cardLayout; + + private final KeyAdapter enterPressed = new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + TableDataTreeSearchManager.getInstance().startSearch(searchTextField.getText()); + } + } + }; + + public TreeSearchToolbarPane(UIToolbar toolbar) { + this.toolbar = toolbar; + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initToolbarPane(); + initSearchPane(); + initContentPane(); + add(contentPane, BorderLayout.CENTER); + setPreferredSize(new Dimension(240, 30)); + TableDataTreeSearchManager.getInstance().registerTreeSearchStatusChangeListener(this); + } + + private void initContentPane() { + cardLayout = new CardLayout(); + contentPane = new JPanel(cardLayout); + contentPane.add(searchPane, SEARCH_PANE); + contentPane.add(toolbarPane, TOOLBAR_PANE); + cardLayout.show(contentPane, TOOLBAR_PANE); + } + + private void initSearchPane() { + searchPane = new JPanel(FRGUIPaneFactory.createBorderLayout()); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); + searchPane.setBackground(Color.WHITE); + // 左侧搜索图标 + UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search")); + searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 0)); + searchLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + // do nothing + } + }); + // 中间输入框 + searchTextField = new UITextField(){ + @Override + public Insets getInsets() { + return new Insets(2, 4, 0, 4); + } + }; + searchTextField.setBorderPainted(false); + searchTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Tree_Search_Press_Enter_For_Search")); + searchTextField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.NORMAL_BLUE)); + searchPane.repaint(); + } + + @Override + public void focusLost(FocusEvent e) { + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); + searchPane.repaint(); + } + }); + this.searchTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + } + + @Override + public void removeUpdate(DocumentEvent e) { + dealWithTextChange(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + } + }); + this.searchTextField.addKeyListener(enterPressed); + // 右侧返回图标 + UILabel returnLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/clear")); + returnLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Tree_Search_Return")); + returnLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 11)); + returnLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } + }); + + searchPane.add(searchLabel, BorderLayout.WEST); + searchPane.add(searchTextField, BorderLayout.CENTER); + searchPane.add(returnLabel, BorderLayout.EAST); + } + + private void dealWithTextChange() { + if (StringUtils.isEmpty(searchTextField.getText()) && TableDataTreeSearchManager.getInstance().isInSearchMode()) { + // 如果是搜索模式下,看作是用户删除输入框文字,仅复原TableDataTreePane + TableDataTreeSearchManager.getInstance().restoreTreePane(); + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).refreshDockingView(); + } + } + + private void initToolbarPane() { + toolbarPane = new JPanel(); + toolbarPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + toolbarPane.add(toolbar, BorderLayout.CENTER); + } + + /** + * 交换当前面板层级 + */ + public void switchPane(String name) { + cardLayout.show(contentPane, name); + } + + public void setPlaceHolder(String placeHolder) { + this.searchTextField.setPlaceholder(placeHolder); + } + + /** + * 根据搜索状态变化,来调整自身面板的显示 + * + * @param event + */ + @Override + public void updateTreeSearchChange(TreeSearchStatusChangeEvent event) { + TreeSearchStatus treeSearchStatus = event.getTreeSearchStatus(); + if (treeSearchStatus == TreeSearchStatus.NOT_IN_SEARCH_MODE) { + this.searchTextField.setText(StringUtils.EMPTY); + switchPane(TOOLBAR_PANE); + } else { + switchPane(SEARCH_PANE); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataSearchMode.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataSearchMode.java new file mode 100644 index 000000000..d68455db5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataSearchMode.java @@ -0,0 +1,38 @@ +package com.fr.design.data.datapane.management.search.searcher; + +/** + * 搜索模式 + * + * @author Yvan + */ +public enum TableDataSearchMode { + + /** + * 搜索模板数据集 + */ + TEMPLATE_TABLE_DATA(0), + + /** + * 搜索服务器数据集 + */ + SERVER_TABLE_DATA(1); + + private final int mode; + + TableDataSearchMode(int mode) { + this.mode = mode; + } + + public int getMode() { + return mode; + } + + public static TableDataSearchMode match(int mode) { + for (TableDataSearchMode searchMode : TableDataSearchMode.values()) { + if (searchMode.getMode() == mode) { + return searchMode; + } + } + return TEMPLATE_TABLE_DATA; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataTreeSearcher.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataTreeSearcher.java new file mode 100644 index 000000000..672ef1e38 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataTreeSearcher.java @@ -0,0 +1,148 @@ +package com.fr.design.data.datapane.management.search.searcher; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.data.TableDataSource; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager; +import com.fr.design.data.datapane.management.search.control.common.TableDataSearchCallBack; +import com.fr.design.data.datapane.management.search.control.common.TableDataSearchTask; +import com.fr.design.data.datapane.management.search.control.pre.TableDataPreSearchCallBack; +import com.fr.design.data.datapane.management.search.control.pre.TableDataPreSearchTask; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author Yvan + */ +public class TableDataTreeSearcher implements TreeSearcher { + + private ExecutorService executorService; + + private Map allWrappers = new ConcurrentHashMap<>(); + + private final Set calculatedSets = new HashSet<>(); + + private final Set notCalculatedSets = new HashSet<>(); + + private final Set matchSets = new HashSet<>(); + + private final Set canExpandSets = new HashSet<>(); + + public TableDataTreeSearcher() { + } + + public boolean isMatchSetsEmpty() { + return matchSets.isEmpty(); + } + + public int getAllWrappersSize() { + return allWrappers.size(); + } + + public synchronized void addToCalculatedSets(List tableDataNames) { + for (String tableDataName : tableDataNames) { + TableDataWrapper tableDataWrapper = allWrappers.get(tableDataName); + if (tableDataWrapper == null) { + return; + } + calculatedSets.add(tableDataName); + } + } + + public synchronized void addToMatchSets(List matchNodeNames) { + matchSets.addAll(matchNodeNames); + } + + public synchronized void addToCanExpandSets(List canExpandNodeNames) { + canExpandSets.addAll(canExpandNodeNames); + } + + + /** + * 正式搜索前,预加载一下数据集列名 + * + * @param searchMode + * @param tableDataSource + */ + public void beforeSearch(TableDataSearchMode searchMode, TableDataSource tableDataSource) { + executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new NamedThreadFactory(TableDataTreeSearcher.class)); + collectTableDataWrappers(searchMode, tableDataSource); + preCalculateColumns(); + } + + /** + * 预先对数据集进行取列名的操作,提升用户搜索体验 + */ + private void preCalculateColumns() { + for (String notCalculatedSet : notCalculatedSets) { + TableDataWrapper tableDataWrapper = allWrappers.get(notCalculatedSet); + if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() == TreeSearchStatus.SEARCH_NOT_BEGIN) { + executorService.execute(new TableDataPreSearchTask(new TableDataPreSearchCallBack(this), tableDataWrapper)); + } + } + } + + /** + * 收集下此次搜索需要进行取数的TableDataWrapper + * + * @param searchSubject + * @param tableDataSource + */ + private void collectTableDataWrappers(TableDataSearchMode searchSubject, TableDataSource tableDataSource) { + Map dataSet = searchSubject == TableDataSearchMode.TEMPLATE_TABLE_DATA ? + DesignTableDataManager.getTemplateDataSet(tableDataSource) : + DesignTableDataManager.getGlobalDataSet(); + // 转化一下存储过程 + Map setIncludingProcedure = DesignTableDataManager.getAllDataSetIncludingProcedure(dataSet); + notCalculatedSets.addAll(setIncludingProcedure.keySet()); + allWrappers.putAll(setIncludingProcedure); + } + + @Override + public void startSearch(String searchText) { + reset(); + for (String notCalculatedSet : notCalculatedSets) { + TableDataWrapper tableDataWrapper = allWrappers.get(notCalculatedSet); + if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() == TreeSearchStatus.SEARCHING) { + executorService.execute(new TableDataSearchTask(searchText, tableDataWrapper, new TableDataSearchCallBack(this))); + } + } + } + + @Override + public void stopSearch() { + + } + + @Override + public void completeSearch() { + + } + + private void reset() { + matchSets.clear(); + canExpandSets.clear(); + calculatedSets.clear(); + notCalculatedSets.addAll(allWrappers.keySet()); + } + + public void afterSearch() { + allWrappers.clear(); + executorService.shutdownNow(); + } + + public boolean nodeMatches(String dsName) { + return matchSets.contains(dsName); + } + + public boolean nodeCanExpand(String dsName) { + return canExpandSets.contains(dsName); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearchStatus.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearchStatus.java new file mode 100644 index 000000000..ff577995f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearchStatus.java @@ -0,0 +1,28 @@ +package com.fr.design.data.datapane.management.search.searcher; + +/** + * @author Yvan + */ +public enum TreeSearchStatus { + + /** + * 非搜索模式 + */ + NOT_IN_SEARCH_MODE, + /** + * 搜索未开始 + */ + SEARCH_NOT_BEGIN, + /** + * 搜索中 + */ + SEARCHING, + /** + * 搜索已停止 + */ + SEARCH_STOPPED, + /** + * 搜索已完成 + */ + SEARCH_COMPLETED; +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearcher.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearcher.java new file mode 100644 index 000000000..b6f694470 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearcher.java @@ -0,0 +1,27 @@ +package com.fr.design.data.datapane.management.search.searcher; + + +/** + * 用于搜索RefreshableJTree数据的搜索器 + * + * @author Yvan + */ +public interface TreeSearcher { + + /** + * 开始搜索 + * + * @param text + */ + void startSearch(String text); + + /** + * 停止搜索 + */ + void stopSearch(); + + /** + * 搜索完成 + */ + void completeSearch(); +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java new file mode 100644 index 000000000..340c6912a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java @@ -0,0 +1,82 @@ +package com.fr.design.data.datapane.management.search.view; + +import com.fr.design.data.datapane.TableDataTree; + +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellRenderer; +import java.awt.Component; +import java.util.regex.Pattern; + +/** + * @author Yvan + */ +public class TreeSearchRendererHelper { + + /** + * 缓存下原来的渲染器 + */ + private TreeCellRenderer originTreeCellRenderer; + + public TreeSearchRendererHelper() { + } + + public TreeCellRenderer getOriginTreeCellRenderer() { + return originTreeCellRenderer; + } + + public void setOriginTreeCellRenderer(TreeCellRenderer originTreeCellRenderer) { + this.originTreeCellRenderer = originTreeCellRenderer; + } + + public void replaceTreeRenderer(TableDataTree tableDataTree, String searchText) { + tableDataTree.setCellRenderer(getNewTreeCellRenderer(searchText)); + } + + public void save(TableDataTree tableDataTree) { + if (getOriginTreeCellRenderer() == null) { + setOriginTreeCellRenderer(tableDataTree.getTableDataTreeCellRenderer()); + } + } + + public void restore(TableDataTree tableDataTree) { + if (getOriginTreeCellRenderer() != null) { + tableDataTree.setCellRenderer(getOriginTreeCellRenderer()); + } + } + + /** + * 获取新树渲染器,也就是搜索结果树的TreeCellRenderer,主要是为了文本高亮 + * + * @param searchText + * @return + */ + private TreeCellRenderer getNewTreeCellRenderer(String searchText) { + return new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + Component treeCellRendererComponent = getOriginTreeCellRenderer().getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + if (treeCellRendererComponent instanceof DefaultTreeCellRenderer) { + DefaultTreeCellRenderer defaultTreeCellRenderer = (DefaultTreeCellRenderer) treeCellRendererComponent; + String text = defaultTreeCellRenderer.getText(); + defaultTreeCellRenderer.setText(getHighlightText(text, searchText)); + } + return treeCellRendererComponent; + } + }; + } + + private String getHighlightText(String text, String textToHighlight) { + String highLightTemplate = "$1"; + if (textToHighlight.length() == 0) { + return text; + } + try { + text = text.replaceAll("(?i)(" + Pattern.quote(textToHighlight) + ")", highLightTemplate); + } catch (Exception e) { + return text; + } + text = "" + text + ""; + return text; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java b/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java new file mode 100644 index 000000000..f69312d47 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java @@ -0,0 +1,340 @@ +package com.fr.design.data.tabledata.paste; + +import com.fr.base.TableData; +import com.fr.base.chart.BaseChartCollection; +import com.fr.data.TableDataSource; +import com.fr.design.DesignModelAdapter; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +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.form.FormElementCaseProvider; +import com.fr.form.data.DataBinding; +import com.fr.form.data.DataTableConfig; +import com.fr.form.main.Form; +import com.fr.form.main.WidgetGather; +import com.fr.form.ui.DataControl; +import com.fr.form.ui.DictionaryContainer; +import com.fr.form.ui.ElementCaseEditor; +import com.fr.form.ui.Widget; +import com.fr.form.ui.concept.data.ValueInitializer; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.report.cell.FloatElement; +import com.fr.report.cell.tabledata.ElementUsedTableDataProvider; +import com.fr.report.worksheet.FormElementCase; +import com.fr.stable.StringUtils; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 数据集跟随复制粘贴的工具类 + * + * @author Yvan + */ +public class TableDataFollowingPasteUtils { + + private static final String UNDERLINE = "_"; + + /** + * 粘贴所有Map中的tabledata到当前模板 + * + * @param tableDataWrapperMap + */ + public static void paste(Map tableDataWrapperMap) { + if (tableDataWrapperMap == null) { + return; + } + // 获取当前的TableDataTreePane + DesignModelAdapter currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter(); + TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstanceWithoutRefreshEverytime(currentModelAdapter); + // 粘贴(添加)数据集 + for (Map.Entry dataWrapperEntry : tableDataWrapperMap.entrySet()) { + String dsName = dataWrapperEntry.getKey(); + // 处理名称重复情况 + if (isDsNameRepeated(dsName)) { + continue; + } + AbstractTableDataWrapper tableDataWrapper = new TemplateTableDataWrapper(dataWrapperEntry.getValue(), dsName); + AbstractTableDataPane tableDataPane = tableDataWrapper.creatTableDataPane(); + tableDataTreePane.addDataPane(tableDataPane, dsName); + } + } + + private static boolean isDsNameRepeated(String dsName) { + DesignModelAdapter currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter(); + String[] allDSNames = DesignTableDataManager.getAllDSNames(currentModelAdapter.getBook()); + return Arrays.stream(allDSNames).anyMatch(name -> StringUtils.equals(name, dsName)); + } + + /** + * 处理 ElementUsedTableDataProvider,从中获取数据集名称 - 数据集Wrapper 的Map + * + * @param providers + * @return + */ + public static Map transferProvider2TableDataMap(ElementUsedTableDataProvider... providers) { + if (providers == null) { + return new HashMap<>(); + } + // 获取当前的所有模板数据集 + Map templateTableData = getCurrentTemplateTableDataWrapperIncludingProcedure(); + Map tempMap = new HashMap<>(); + try { + for (ElementUsedTableDataProvider tableDataProvider : providers) { + Set usedTableDataNames = tableDataProvider.getElementUsedTableDataNames(); + for (String usedTableDataName : usedTableDataNames) { + if (templateTableData.containsKey(usedTableDataName)) { + tempMap.put(usedTableDataName, templateTableData.get(usedTableDataName).getTableData()); + } + } + } + // 处理存储过程名称问题 + return dealWithStoreProcedure(tempMap); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("transfer widget tabledata failed", e); + } + return new HashMap<>(); + } + + /** + * 处理结果集,将结果集中的存储过程子表替换为原本的存储过程,否则跟随粘贴过去的存储过程名称有问题 + * + * @param tableDataMap + */ + public static Map dealWithStoreProcedure(Map tableDataMap) { + Map resultMap = new HashMap<>(); + if (tableDataMap == null) { + return resultMap; + } + for (Map.Entry result : tableDataMap.entrySet()) { + String tableDataName = result.getKey(); + TableData tableData = result.getValue(); + // 判断名称中存在"_"的 + if (tableDataName.contains(UNDERLINE)) { + String matchedName = matchTableDataName(tableDataName, tableData); + resultMap.put(matchedName, tableData); + } else { + resultMap.put(tableDataName, tableData); + } + } + return resultMap; + } + + /** + * 存储过程子表名称匹配其存储过程数据集名称,其余模板数据集名称不变 + * + * @param tableDataName 待匹配的数据集名称 + * @param tableData + * @return + */ + private static String matchTableDataName(String tableDataName, TableData tableData) { + if (tableDataName == null) { + return null; + } + // 获取不包括存储过程子表的所有TableDataMap + Map dataWrapperMap = getCurrentTemplateTableDataWrapper(); + // 名称匹配时,直接返回 + if (dataWrapperMap.containsKey(tableDataName)) { + return tableDataName; + } + // 名称不匹配时,判断TableData是否一致 + for (Map.Entry dataWrapperEntry : dataWrapperMap.entrySet()) { + String tdName = dataWrapperEntry.getKey(); + TableData td = dataWrapperEntry.getValue().getTableData(); + if (ComparatorUtils.equals(td, tableData)) { + return tdName; + } + } + return tableDataName; + } + + + /** + * 提取控件内使用的数据集,转化成Map返回 + * + * @param widgets + * @return + */ + public static Map transferWidgetArray2TableDataMap(Widget... widgets) { + if (widgets == null) { + return new HashMap<>(); + } + // 获取当前的所有模板数据集 + Map templateTableData = getCurrentTemplateTableDataWrapperIncludingProcedure(); + Map tempMap = new HashMap<>(); + try { + for (Widget widget : widgets) { + // widget这个接口太大了,布局和子控件互相嵌套,所以只能分情况一个个收集 + collectTableDataInDictionary(templateTableData, tempMap, widget); + collectTableDataInWidgetValue(templateTableData, tempMap, widget); + collectTableDataInChartCollection(templateTableData, tempMap, widget); + collectTableDataInElementCaseEditor(templateTableData, tempMap, widget); + } + // 处理存储过程名称问题 + return dealWithStoreProcedure(tempMap); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("transfer widget tabledata failed", e); + } + return new HashMap<>(); + } + + /** + * 收集控件-报表块中使用的数据集 + * + * @param templateTableData + * @param tempMap + * @param widget + */ + private static void collectTableDataInElementCaseEditor(Map templateTableData, Map tempMap, Widget widget) { + Form.traversalWidget(widget, new WidgetGather() { + @Override + public void dealWith(Widget widget) { + ElementCaseEditor elementCaseEditor = (ElementCaseEditor) widget; + FormElementCaseProvider elementCase = elementCaseEditor.getElementCase(); + if (elementCase != null) { + // 普通单元格 + Iterator cellIterator = elementCase.cellIterator(); + while (cellIterator.hasNext()) { + ElementUsedTableDataProvider cellElement = (ElementUsedTableDataProvider) cellIterator.next(); + collectElement(cellElement); + } + // 悬浮元素 + Iterator floatIterator = ((FormElementCase) elementCase).floatIterator(); + while (floatIterator.hasNext()) { + ElementUsedTableDataProvider floatElement = floatIterator.next(); + collectElement(floatElement); + } + } + } + + private void collectElement(ElementUsedTableDataProvider provider) { + Set usedTableDataNames = provider.getElementUsedTableDataNames(); + for (String usedTableDataName : usedTableDataNames) { + if (templateTableData.containsKey(usedTableDataName)) { + tempMap.put(usedTableDataName, templateTableData.get(usedTableDataName).getTableData()); + } + } + } + + @Override + public boolean dealWithAllCards() { + return true; + } + }, ElementCaseEditor.class); + } + + /** + * 收集控件-图表中的TableData + * + * @param templateTableData + * @param tempMap + * @param widget + */ + private static void collectTableDataInChartCollection(Map templateTableData, Map tempMap, Widget widget) { + List chartCollections = widget.getChartCollections(); + for (BaseChartCollection chartCollection : chartCollections) { + Set dataSetNames = chartCollection.getDataSetNames(); + for (String dataSetName : dataSetNames) { + if (templateTableData.containsKey(dataSetName)) { + tempMap.put(dataSetName, templateTableData.get(dataSetName).getTableData()); + } + } + } + } + + /** + * 收集控件值中的TableData + * + * @param templateTableData + * @param tempMap + * @param widget + */ + private static void collectTableDataInWidgetValue(Map templateTableData, Map tempMap, Widget widget) { + Form.traversalWidget(widget, new WidgetGather() { + @Override + public void dealWith(Widget widget) { + if (((DataControl) widget).getWidgetValue() != null) { + ValueInitializer widgetValue = ((DataControl) widget).getWidgetValue(); + Object value = widgetValue.getValue(); + if (value instanceof DataBinding) { + String dataSourceName = ((DataBinding) value).getDataSourceName(); + if (templateTableData.containsKey(dataSourceName)) { + tempMap.put(dataSourceName, templateTableData.get(dataSourceName).getTableData()); + } + } + if (value instanceof DataTableConfig) { + String tableDataName = ((DataTableConfig) value).getTableDataName(); + if (templateTableData.containsKey(tableDataName)) { + tempMap.put(tableDataName, templateTableData.get(tableDataName).getTableData()); + } + } + } + } + + @Override + public boolean dealWithAllCards() { + return true; + } + }, DataControl.class); + + } + + /** + * 收集控件-数据字典中的TableData + * + * @param templateTableData + * @param tempMap + * @param widget + */ + private static void collectTableDataInDictionary(Map templateTableData, Map tempMap, Widget widget) { + Form.traversalWidget(widget, new WidgetGather() { + @Override + public void dealWith(Widget widget) { + Set usedTableDataSets = ((DictionaryContainer) widget).getUsedTableDataSets(); + for (String usedTableDataSet : usedTableDataSets) { + if (templateTableData.containsKey(usedTableDataSet)) { + tempMap.put(usedTableDataSet, templateTableData.get(usedTableDataSet).getTableData()); + } + } + } + + @Override + public boolean dealWithAllCards() { + return true; + } + }, DictionaryContainer.class); + } + + /** + * 获取当前所有的模板数据集,包括存储过程 + * + * @return + */ + private static Map getCurrentTemplateTableDataWrapperIncludingProcedure() { + Map templateTableDataWrapper = getCurrentTemplateTableDataWrapper(); + // 处理存储过程 + Map dataWrapperMap = DesignTableDataManager.getAllDataSetIncludingProcedure(templateTableDataWrapper); + return dataWrapperMap; + } + + /** + * 获取当前所有的模板数据集,不包括存储过程 + * + * @return + */ + private static Map getCurrentTemplateTableDataWrapper() { + TableDataSource tableDataSource = DesignTableDataManager.getEditingTableDataSource(); + List> editingDataSet = DesignTableDataManager.getEditingDataSet(tableDataSource); + Map templeteDataSet = editingDataSet.get(0); + return templeteDataSet; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java b/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java index 08274fd71..515bd8dd0 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java @@ -63,26 +63,27 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName) { this(component, storeProcedure, storeprocedureName, dsName, true); } - + /** - * @param: component loadingBar的父弹框(如果不设置父弹框的话,可能出现loadingBar隐藏在一个弹框后的情况) - * @param: storeProcedure 存储过程 - * @param: storeprocedureName 存储过程的名字(某些情况下可以为空) - * @param: dsName 存储过程一个返回数据集的名字 - * @param: needLoad 是否要加载 + * @param component loadingBar的父弹框(如果不设置父弹框的话,可能出现loadingBar隐藏在一个弹框后的情况) + * @param storeProcedure 存储过程 + * @param storeprocedureName 存储过程的名字(某些情况下可以为空) + * @param dsName 存储过程一个返回数据集的名字 + * @param needLoad 是否要加载 **/ public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName, boolean needLoad) { this.dsName = dsName; this.storeProcedure = storeProcedure; this.storeProcedure.setCalculating(false); this.storeprocedureName = storeprocedureName; - if (needLoad) { - setWorker(); - } if (component == null) { component = new JFrame(); } + if (needLoad) { + setWorker(component); + } loadingBar = new AutoProgressBar(component, Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) { + @Override public void doMonitorCanceled() { getWorker().cancel(true); } @@ -93,16 +94,17 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { * 数据集执行结果返回的所有字段 * * @return 数据集执行结果返回的所有字段 - * - * - * @date 2014-12-3-下午7:43:17 - * - */ + * @date 2014-12-3-下午7:43:17 + */ + @Override public List calculateColumnNameList() { if (columnNameList != null) { return columnNameList; } - if (!createStore(false)) { + + try { + createStore(false); + } catch (Exception e) { FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Engine_No_TableData")); return new ArrayList(); } @@ -114,11 +116,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { * 生成子节点 * * @return 节点数组 - * - * - * @date 2014-12-3-下午7:06:47 - * - */ + * @date 2014-12-3-下午7:06:47 + */ + @Override public ExpandMutableTreeNode[] load() { List namelist; if (storeProcedure.isCalculating()) { @@ -134,23 +134,16 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { return res; } - private boolean createStore(boolean needLoadingBar) { - try { - dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar); - if (dataModels == null || dataModels.length == 0) { - return false; - } - for (int i = 0; i < dataModels.length; i++) { - if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModels[i].getName())) { - procedureDataModel = dataModels[i]; + private void createStore(boolean needLoadingBar) throws Exception { + dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar); + if (dataModels != null && dataModels.length != 0) { + for (ProcedureDataModel dataModel : dataModels) { + if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModel.getName())) { + procedureDataModel = dataModel; break; } } - return true; - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); } - return false; } @Override @@ -159,17 +152,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { } /** - * 预览数据 - * - * @param previewModel 预览模式, 全部还是一个 - * - * - * @date 2014-12-3-下午7:05:50 - * - */ + * 预览数据 + * + * @param previewModel 预览模式, 全部还是一个 + * @date 2014-12-3-下午7:05:50 + */ public void previewData(final int previewModel) { this.previewModel = previewModel; connectionBar = new AutoProgressBar(new JFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Now_Create_Connection"), "", 0, 100) { + @Override public void doMonitorCanceled() { connectionBar.close(); worker.cancel(true); @@ -178,8 +169,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { worker.execute(); } - private void setWorker() { + private void setWorker(final Component parent) { worker = new SwingWorker() { + @Override protected Void doInBackground() throws Exception { loadingBar.close(); PreviewTablePane.resetPreviewTable(); @@ -195,6 +187,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { return null; } + @Override public void done() { try { get(); @@ -206,13 +199,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { case StoreProcedureDataWrapper.PREVIEW_ONE: previewData(); break; + default: + break; } } catch (Exception e) { + loadingBar.close(); if (!(e instanceof CancellationException)) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage()); + FineJOptionPane.showMessageDialog(parent, e.getMessage()); } - loadingBar.close(); } } }; @@ -227,10 +222,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { /** * 预览返回的一个数据集 * - * - * @date 2014-12-3-下午7:42:53 - * - */ + * @date 2014-12-3-下午7:42:53 + */ + @Override public void previewData() { previewData(-1, -1); } @@ -240,13 +234,11 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { /** * 预览返回的一个数据集,带有显示值和实际值的标记结果 * - * @param keyIndex 实际值 - * @param valueIndex 显示值 - * - * - * @date 2014-12-3-下午7:42:27 - * - */ + * @param keyIndex 实际值 + * @param valueIndex 显示值 + * @date 2014-12-3-下午7:42:27 + */ + @Override public void previewData(final int keyIndex, final int valueIndex) { PreviewTablePane.previewStoreData(procedureDataModel, keyIndex, valueIndex); } @@ -257,7 +249,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { */ public void previewAllTable() { if (procedureDataModel == null) { - if (!createStore(true)) { + try { + createStore(true); + } catch (Exception e) { return; } } @@ -269,6 +263,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { return dsName; } + @Override public TableData getTableData() { return storeProcedure; } @@ -282,10 +277,12 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { * * @return 是否异常 */ + @Override public boolean isUnusual() { return false; } + @Override public boolean equals(Object obj) { return obj instanceof StoreProcedureDataWrapper && ComparatorUtils.equals(this.dsName, ((StoreProcedureDataWrapper) obj).getTableDataName()) diff --git a/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java b/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java index f73ec77df..2e839d27c 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java +++ b/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java @@ -37,15 +37,19 @@ public class MessageWithLink extends JEditorPane { } public MessageWithLink(String frontMessage, String linkName, String link, String backMessage) { - this(frontMessage, linkName, link, backMessage, LABEL.getBackground(), LABEL.getFont()); + this(frontMessage, linkName, link, backMessage, LABEL.getBackground(), LABEL.getFont(), LABEL.getForeground()); } public MessageWithLink(String message, String linkName, String link, Color color, Font font) { - this(message, linkName, link, StringUtils.EMPTY, color, font); + this(message, linkName, link, StringUtils.EMPTY, color, font, LABEL.getForeground()); } public MessageWithLink(String frontMessage, String linkName, String link, String backMessage, Color color, Font font) { - super("text/html", "" + frontMessage + "" + linkName + "" + backMessage + ""); + this(frontMessage, linkName, link, backMessage, color, font, LABEL.getForeground()); + } + + public MessageWithLink(String frontMessage, String linkName, String link, String backMessage, Color backgroundColor, Font font, Color fontColor) { + super("text/html", "" + frontMessage + "" + linkName + "" + backMessage + ""); initListener(link); setEditable(false); setBorder(null); @@ -66,12 +70,13 @@ public class MessageWithLink extends JEditorPane { }); } - private static StringBuilder generateStyle(Color color, Font font) { + private static StringBuilder generateStyle(Color backgroundColor, Font font, Color fontColor) { // 构建相同风格样式 StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";"); style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";"); style.append("font-size:").append(font.getSize()).append("pt;"); - style.append("background-color: rgb(").append(color.getRed()).append(",").append(color.getGreen()).append(",").append(color.getBlue()).append(");"); + style.append("color:rgb(").append(fontColor.getRed()).append(",").append(fontColor.getGreen()).append(",").append(fontColor.getBlue()).append(");"); + style.append("background-color: rgb(").append(backgroundColor.getRed()).append(",").append(backgroundColor.getGreen()).append(",").append(backgroundColor.getBlue()).append(");"); return style; } diff --git a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java index a7d6eb6c1..ec8d997c3 100644 --- a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java +++ b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java @@ -1,8 +1,6 @@ package com.fr.design.env; import com.fr.general.ComparatorUtils; -import com.fr.general.GeneralUtils; -import com.fr.locale.InterProviderFactory; import com.fr.stable.CoreConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; @@ -10,8 +8,8 @@ import com.fr.stable.project.ProjectConstants; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; import com.fr.workspace.connect.WorkspaceConnectionInfo; - import com.fr.workspace.engine.exception.MainVersionNotMatchException; + import java.io.File; import java.util.Properties; diff --git a/designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java b/designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java index f35fbdf11..3fe818461 100644 --- a/designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java +++ b/designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java @@ -1,6 +1,5 @@ package com.fr.design.extra; -import com.fr.base.FRContext; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.UIDialog; @@ -15,12 +14,12 @@ import com.fr.general.IOUtils; import com.fr.general.http.HttpToolbox; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; +import com.fr.plugin.PluginStoreConfig; import com.fr.plugin.PluginStoreConstants; import com.fr.stable.CommonUtils; import com.fr.stable.EnvChangedListener; import com.fr.stable.ProductConstants; import com.fr.stable.StableUtils; -import com.fr.stable.StringUtils; import javax.swing.JOptionPane; import javax.swing.SwingWorker; @@ -44,15 +43,14 @@ public class WebViewDlgHelper { private static final String LATEST = "latest"; private static final String SHOP_SCRIPTS = "shop_scripts"; private static final int VERSION_8 = 8; - private static String installHome = FRContext.getCommonOperator().getWebRootPath(); + private static String installHome = PluginStoreConstants.getLocalInstallHome(); private static final String MAIN_JS_PATH = "/scripts/plugin.html"; - private static final String ENV_VERSION = "ENV_VERSION"; static { GeneralContext.addEnvChangedListener(new EnvChangedListener() { @Override public void envChanged() { - installHome = FRContext.getCommonOperator().getWebRootPath(); + installHome = PluginStoreConstants.getLocalInstallHome(); } }); } @@ -74,8 +72,11 @@ public class WebViewDlgHelper { } return; } - String jar_version = PluginStoreConstants.getProps(ENV_VERSION, StringUtils.EMPTY); - if (ComparatorUtils.equals(jar_version, ProductConstants.VERSION)) { + // 检测更新前先刷新一下版本号 + PluginStoreConstants.refreshProps(); + + String jarVersion = PluginStoreConfig.getInstance().getEnvVersion(); + if (ComparatorUtils.equals(jarVersion, ProductConstants.VERSION)) { updateShopScripts(SHOP_SCRIPTS); showPluginDlg(); } else { @@ -133,7 +134,7 @@ public class WebViewDlgHelper { * * @param filePath 待删除文件路径 */ - private static void deleteExtraFile(String filePath){ + private static void deleteExtraFile(String filePath) { CommonIOUtils.deleteFile(new File(filePath)); } @@ -259,7 +260,7 @@ public class WebViewDlgHelper { try { if (get()) { File scriptZip = new File(StableUtils.pathJoin(PluginConstants.DOWNLOAD_PATH, PluginConstants.TEMP_FILE)); - if(scriptZip.exists()){ + if (scriptZip.exists()) { IOUtils.unzip(scriptZip, installHome); CommonUtils.deleteFile(scriptZip); } @@ -283,7 +284,7 @@ public class WebViewDlgHelper { protected Void doInBackground() throws Exception { String url = CloudCenter.getInstance().acquireUrlByKind("shop.plugin.update"); if (url != null) { - String text = HttpToolbox.get(url + "?" + PluginUtils.FR_VERSION + "=" + ProductConstants.VERSION + "&version=" + PluginStoreConstants.getProps("VERSION")); + String text = HttpToolbox.get(url + "?" + PluginUtils.FR_VERSION + "=" + ProductConstants.VERSION + "&version=" + PluginStoreConfig.getInstance().getVersion()); JSONObject resultJSONObject = new JSONObject(text); String isLatest = resultJSONObject.optString("result"); if (!ComparatorUtils.equals(isLatest, LATEST)) { 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 443a55671..d6b12efa6 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 @@ -24,7 +24,6 @@ import com.fr.stable.CoreConstants; import com.fr.stable.StringUtils; import com.fr.third.org.apache.commons.io.FilenameUtils; -import javax.swing.SwingWorker; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -44,7 +43,6 @@ public class HistoryTemplateListCache implements CallbackEvent { private static final int DEAD_LINE = DesignerEnvManager.getEnvManager().getCachingTemplateLimit(); private List> historyList; private JTemplate editingTemplate; - private SwingWorker stashWorker; public static HistoryTemplateListCache getInstance() { return Holder.INSTANCE; @@ -342,14 +340,7 @@ public class HistoryTemplateListCache implements CallbackEvent { * @see HistoryTemplateListCache#load() */ public void stash() { - stashWorker = new SwingWorker() { - @Override - protected Boolean doInBackground() throws Exception { - _stash(); - return true; - } - }; - stashWorker.execute(); + _stash(); } private void _stash() { @@ -370,16 +361,6 @@ public class HistoryTemplateListCache implements CallbackEvent { FineLoggerFactory.getLogger().info("Env Change Template Stashed."); } - - private boolean checkStash() { - try { - return stashWorker.get(); - } catch (Exception e) { - FineLoggerFactory.getLogger().debug(e.getMessage(), e); - return false; - } - } - /** * 切换环境前将正在编辑的模板暂存起来后,在新环境重新读取一遍 *

@@ -388,9 +369,6 @@ public class HistoryTemplateListCache implements CallbackEvent { * @see HistoryTemplateListCache#stash() */ public void load() { - if (!checkStash()) { - return; - } FineLoggerFactory.getLogger().info("Env Change Template Loading..."); if (stashFILEMap != null && stashFILEMap.size() != 0) { int size = historyList.size(); 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 a6346c4dd..ef321e708 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 @@ -14,6 +14,7 @@ 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.DialogActionListener; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.autocomplete.AutoCompleteExtraRefreshComponent; @@ -63,6 +64,7 @@ import com.fr.stable.script.Node; import com.fr.stable.script.Tiny; import com.fr.stable.script.TinyHunter; +import java.awt.Window; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; @@ -736,6 +738,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Formula_Definition"); } + public BasicDialog showLargeWindow(Window window, DialogActionListener l) { + BasicDialog basicDialog = super.showWindowWithCustomSize(window, l, new Dimension(900, 600)); + basicDialog.setMinimumSize(new Dimension(900, 600)); + basicDialog.setResizable(true); + return basicDialog; + } + /** * Populate */ @@ -1102,6 +1111,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initGroupTypeModel() { functionTypeListModel.addElement(FunctionConstants.COMMON); + functionTypeListModel.addElement(FunctionConstants.NEW); for (int i = 0; i < FunctionConstants.EMBFUNCTIONS.length; i++) { functionTypeListModel.addElement(FunctionConstants.EMBFUNCTIONS[i]); } @@ -1184,11 +1194,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initDescriptionTextArea() { // Description descriptionTextArea = new UITextArea(); - descriptionTextArea.setPreferredSize(new Dimension(350, 200)); - UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea); - desScrollPane.setBorder(null); - this.add(this.createNamePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Formula_Description") + ":", desScrollPane), BorderLayout.EAST); descriptionTextArea.setBackground(Color.white); descriptionTextArea.setLineWrap(true); descriptionTextArea.setWrapStyleWord(true); @@ -1256,12 +1262,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initVariablesTree() { + JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); // vairable. variablesTree = new JTree(); UIScrollPane variablesTreePane = new UIScrollPane(variablesTree); variablesTreePane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); - this.add(this.createNamePane( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables") + ":", variablesTreePane), BorderLayout.CENTER); + panel.add(this.createNamePane( + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables") + ":", variablesTreePane), BorderLayout.WEST); variablesTree.setRootVisible(false); variablesTree.setShowsRootHandles(true); variablesTree.addMouseListener(applyTextMouseListener); @@ -1269,7 +1276,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { initDescriptionTextArea(); + UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea); + desScrollPane.setBorder(null); + panel.add(this.createNamePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Formula_Description") + ":", desScrollPane), BorderLayout.CENTER); initVariablesTreeSelectionListener(); + this.add(panel,BorderLayout.CENTER); } private void initComponents() { diff --git a/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java b/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java index 28bb98555..6a1b32aaa 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java +++ b/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java @@ -5,10 +5,19 @@ import com.fr.function.AVERAGE; import com.fr.function.CHAR; import com.fr.function.COUNT; import com.fr.function.DATE; +import com.fr.function.ENBYSTRNUM; +import com.fr.function.ENDOFMONTH; +import com.fr.function.GCD; +import com.fr.function.GETCHARNUM; +import com.fr.function.ISWORKDAY; +import com.fr.function.LCM; import com.fr.function.MAX; +import com.fr.function.MIDCHAR; import com.fr.function.MIN; +import com.fr.function.NUMTOZH; import com.fr.function.RANGE; import com.fr.function.SUM; +import com.fr.function.TEXTGETNUM; import com.fr.function.TIME; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralUtils; @@ -36,6 +45,7 @@ import java.util.Comparator; import java.util.Enumeration; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -46,6 +56,8 @@ public final class FunctionConstants { public static NameAndFunctionList COMMON = getCommonFunctionList(); public static NameAndTypeAndFunctionList[] EMBFUNCTIONS = getEmbededFunctionListArray(); public static FunctionGroup ALL = getAllFunctionGroup(); + public static List abandonFormulas = Arrays.asList("CIRCULAR", "CROSSLAYERTOTAL", "HIERARCHY", "LAYERTOTAL"); + public static NameAndFunctionList NEW = getNewFunctionList(); static { loadEmbededFunctions(); @@ -54,7 +66,8 @@ public final class FunctionConstants { /** * Don't let anyone instantiate this class. */ - private FunctionConstants() {} + private FunctionConstants() { + } private static void loadEmbededFunctions() { String pkgName = "com.fr.function"; @@ -88,7 +101,10 @@ public final class FunctionConstants { Class cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6)); if (StableUtils.classInstanceOf(cls, iface)) { Function inst; - inst = (Function)cls.newInstance(); + inst = (Function) cls.newInstance(); + if (abandonFormulas.contains(inst.getClass().getSimpleName())) { + continue; + } for (NameAndTypeAndFunctionList EMBFUNCTION : EMBFUNCTIONS) { if (EMBFUNCTION.test(inst)) { break; @@ -270,6 +286,13 @@ public final class FunctionConstants { }); } + private static NameAndFunctionList getNewFunctionList() { + return new NameAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_New"), new Function[]{ + new ENDOFMONTH(), new NUMTOZH(), new MIDCHAR(), new ISWORKDAY(),new ENBYSTRNUM(), new TEXTGETNUM(), + new GETCHARNUM(), new GCD(), new LCM() + }); + } + private static NameAndTypeAndFunctionList[] getEmbededFunctionListArray() { return new NameAndTypeAndFunctionList[] { new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Math_&_Trig"), Function.MATH), @@ -300,11 +323,12 @@ public final class FunctionConstants { Collections.addAll(all, CUSTOM.getDescriptions()); //hugh:自定义函数分组 Set containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING); - if(!containers.isEmpty()){ - for(Mutable container : containers){ - Collections.addAll(all,createFunctionGroup(((FunctionDefContainer)container)).getDescriptions()); + if (!containers.isEmpty()) { + for (Mutable container : containers) { + Collections.addAll(all, createFunctionGroup(((FunctionDefContainer) container)).getDescriptions()); } } + all = all.stream().filter(n -> !abandonFormulas.contains(n.getName())).collect(Collectors.toList()); Collections.sort(all, new Comparator() { @Override diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIControlPane.java index f7229136f..f9a3ed0db 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIControlPane.java @@ -212,7 +212,7 @@ public abstract class UIControlPane extends JControlPane { } // 点击"编辑"按钮,弹出面板 - class PopupEditDialog extends JDialog { + protected class PopupEditDialog extends JDialog { private JComponent editPane; private PopupToolPane popupToolPane; private static final int WIDTH = 570; diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListControlPane.java index 7ba536492..034847a70 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListControlPane.java @@ -34,6 +34,9 @@ public abstract class UIListControlPane extends UIControlPane implements ListCon private CommonShortCutHandlers commonHandlers; private ListControlPaneHelper helper; + // 目前被触发的事件 + private ListDataEvent currentEvent; + public UIListControlPane() { super(); @@ -96,7 +99,9 @@ public abstract class UIListControlPane extends UIControlPane implements ListCon nameableList.getModel().addListDataListener(new ListDataListener() { @Override public void intervalAdded(ListDataEvent e) { + setCurrentEvent(e); saveSettings(); + setCurrentEvent(null); } @Override @@ -321,4 +326,11 @@ public abstract class UIListControlPane extends UIControlPane implements ListCon } + public ListDataEvent getCurrentEvent() { + return currentEvent; + } + + public void setCurrentEvent(ListDataEvent currentEvent) { + this.currentEvent = currentEvent; + } } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/ClosableBubbleFloatPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/ClosableBubbleFloatPane.java new file mode 100644 index 000000000..41a4471da --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/ClosableBubbleFloatPane.java @@ -0,0 +1,46 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.BaseUtils; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ilable.UILabel; + +import javax.swing.Icon; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public abstract class ClosableBubbleFloatPane extends UIBubbleFloatPane { + public ClosableBubbleFloatPane(int arrowPosition, Point arrowPoint, BasicBeanPane contentPane) { + super(arrowPosition, arrowPoint, contentPane); + } + + public ClosableBubbleFloatPane(int arrowPosition, Point arrowPoint, BasicBeanPane contentPane, int width, int height) { + super(arrowPosition, arrowPoint, contentPane, width, height); + } + + protected void initAWTEventListener() { + + } + + public boolean forceLockFocus() { + return true; + } + + protected JPanel initTopOptionMenu() { + JPanel menu = new JPanel(new BorderLayout()); + Icon icon = BaseUtils.readIcon("/com/fr/design/images/buttonicon/close_icon.png"); + UILabel label = new UILabel(icon); + label.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + showDialog.setVisible(false); + updateContentPane(); + } + }); + + menu.add(label, BorderLayout.EAST); + return menu; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java index 04e3626a4..4c4785be0 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java @@ -42,14 +42,10 @@ public class JTreeControlPane extends ControlPane { private JTree tree; private DefaultTreeModel defaultTreeModel; - - boolean isEditor = false; - private UICheckBox isPerformanceFirst; - public JTreeControlPane(NameableCreator[] creators, BasicBeanPane updatePane, boolean isEditor) { + public JTreeControlPane(NameableCreator[] creators, BasicBeanPane updatePane) { this.initComponents(creators, updatePane); - this.isEditor = isEditor; } private void initComponents(NameableCreator[] creators, BasicBeanPane updatePane) { @@ -120,11 +116,7 @@ public class JTreeControlPane extends ControlPane { if (obj instanceof TreeNodeAttr[]) { treeNodeAttr = ((TreeNodeAttr[]) obj); isPerformanceFirst.setSelected(false); - } else if (obj instanceof TreeEditor) { - TreeEditor treeEditor = (TreeEditor) obj; - treeNodeAttr = treeEditor.getTreeNodeAttr(); - isPerformanceFirst.setSelected(treeEditor.isPerformanceFirst()); - } else if (obj instanceof TreeNodeWrapper) { + }else if (obj instanceof TreeNodeWrapper) { treeNodeAttr = ((TreeNodeWrapper) obj).getTreeNodeAttrs(); isPerformanceFirst.setSelected(((TreeNodeWrapper) obj).isPerformanceFirst()); } @@ -146,18 +138,8 @@ public class JTreeControlPane extends ControlPane { } public NameObject update() { - if (isEditor) { - TreeEditor treeEditor = new TreeEditor(); - - treeEditor.setTreeNodeAttr(updateTreeNodeAttr()); - - treeEditor.setPerformanceFirst(isPerformanceFirst.isSelected()); - - return new NameObject("tree", treeEditor); - } else { - TreeNodeWrapper treeNodeWrapper = new TreeNodeWrapper(isPerformanceFirst.isSelected(), updateTreeNodeAttr()); - return new NameObject("tree", treeNodeWrapper); - } + TreeNodeWrapper treeNodeWrapper = new TreeNodeWrapper(isPerformanceFirst.isSelected(), updateTreeNodeAttr()); + return new NameObject("tree", treeNodeWrapper); } public TreeNodeAttr[] updateTreeNodeAttr() { 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 db453c99f..77d3aa583 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 @@ -26,12 +26,18 @@ import java.awt.event.ItemListener; import java.util.Arrays; public class TreeSettingPane extends BasicPane implements DataCreatorUI { + /** + * 普通分层构建方式 + */ private JTreeControlPane controlPane; + /** + * 自动构建方式 + */ private JTreeAutoBuildPane autoBuildPane; /** - * 新的分层构建方式 + * 急速分层构建方式 */ private LayerDataControlPane layerDataControlPane; @@ -43,15 +49,15 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { private static final long serialVersionUID = 1762889323082827111L; private String[] buildWay = new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DataTable_Build"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Auto_Build"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Build")}; + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Auto_Build"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Build")}; - public TreeSettingPane(boolean isEditor) { - this.initComponents(isEditor); + public TreeSettingPane() { + this.initComponents(); } - private void initComponents(boolean isEditor) { + private void initComponents() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel buildWayPanel= FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); + JPanel buildWayPanel = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); buildWayPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); UILabel buildWayLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Build_Way") + " :"); buildWayPanel.add(buildWayLabel); @@ -65,8 +71,8 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { }); buildWayPanel.add(buildBox); - controlPane = new JTreeControlPane(new NameableCreator[] { treeNode }, - new TreeDataCardPane(), isEditor); + controlPane = new JTreeControlPane(new NameableCreator[]{treeNode}, + new TreeDataCardPane()); autoBuildPane = new JTreeAutoBuildPane(); layerDataControlPane = new LayerDataControlPane(); this.add(buildWayPanel, BorderLayout.NORTH); @@ -108,87 +114,14 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { } NameableCreator treeNode = new NameObjectCreator( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradation"), - "/com/fr/design/images/data/source/jdbcTableData.png", - TreeNodeAttr.class); - - /** - * - * @param treeEditor - */ - public void populate(TreeEditor treeEditor) { - boolean isAutoBuild = treeEditor.isAutoBuild(); - TreeAttr treeAttr = treeEditor.getTreeAttr(); - if (treeAttr != null) { - NameObject no = new NameObject("name", treeEditor); - controlPane.populate(no); - } - if (isAutoBuild) { - buildBox.setSelectedIndex(1); - TableDataDictionary dictionary = treeEditor.getDictionary(); - autoBuildPane.populate(dictionary); - } else if (treeEditor.isFastLayerBuild()) { - buildBox.setSelectedIndex(0); - java.util.List layerConfigList = treeEditor.getLayerConfigs(); - LayerConfig[] layerConfigs = new LayerConfig[layerConfigList.size()]; - int i = 0; - for (LayerConfig layerConfig : layerConfigList) { - layerConfigs[i++] = layerConfig; - } - this.layerDataControlPane.populate(new NameObject("Tree Layer Data", layerConfigs)); - } else { - buildBox.setSelectedIndex(2); - } - } + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradation"), + "/com/fr/design/images/data/source/jdbcTableData.png", + TreeNodeAttr.class); - /** - * 视图树的update - * @return - */ - public TreeEditor updateTreeEditor() { -// NameObject no = this.controlPane.update(); -// if (no != null) { -// return ((TreeEditor) no.getObject()); -// } -// -// return null; - TreeEditor te = new TreeEditor(); - if (buildBox.getSelectedIndex() == 1) { - TableDataDictionary dictionary = this.autoBuildPane.update(); - te.setAutoBuild(true); - te.setFastLayerBuild(false); - te.setDictionary(dictionary); - te.setNodeOrDict(dictionary); - } else if (buildBox.getSelectedIndex() == 2) { - te.setAutoBuild(false); - te.setFastLayerBuild(false); - NameObject no = this.controlPane.update(); - if (no != null) { - TreeEditor editor = (TreeEditor) no.getObject(); - te.setAllowBlank(editor.isAllowBlank()); - te.setEnabled(editor.isEnabled()); - te.setDirectEdit(editor.isDirectEdit()); - te.setErrorMessage(editor.getErrorMessage()); - te.setWidgetName(editor.getWidgetName()); - te.setVisible(editor.isVisible()); - te.setWaterMark(editor.getWaterMark()); - te.setRemoveRepeat(editor.isRemoveRepeat()); - te.setTreeAttr(editor.getTreeAttr()); - te.setTreeNodeAttr(editor.getTreeNodeAttr()); - te.setNodeOrDict(editor.getTreeNodeAttr()); - te.setPerformanceFirst(editor.isPerformanceFirst()); - } - } else { - LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject(); - te.setAutoBuild(false); - te.setFastLayerBuild(true); - te.setLayerConfigs(Arrays.asList(configs)); - } - return te; - } /** * 树节点属性的update + * * @return */ public Object updateTreeNodeAttrs() { @@ -207,64 +140,19 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI { } /** - * 下拉树的update - * @return - */ - public TreeComboBoxEditor updateTreeComboBox() { - TreeComboBoxEditor tcb = new TreeComboBoxEditor(); - if (buildBox.getSelectedIndex() == 1) { - TableDataDictionary dictionary = this.autoBuildPane.update(); - tcb.setAutoBuild(true); - tcb.setFastLayerBuild(false); - tcb.setDictionary(dictionary); - tcb.setNodeOrDict(dictionary); - } else if (buildBox.getSelectedIndex() == 2) { - tcb.setAutoBuild(false); - tcb.setFastLayerBuild(false); - NameObject no = this.controlPane.update(); - if (no != null) { - if (no.getObject() instanceof TreeComboBoxEditor) { - return (TreeComboBoxEditor) no.getObject(); - } - - TreeEditor editor = (TreeEditor) no.getObject(); - tcb.setAllowBlank(editor.isAllowBlank()); - tcb.setEnabled(editor.isEnabled()); - tcb.setDirectEdit(editor.isDirectEdit()); - tcb.setErrorMessage(editor.getErrorMessage()); - tcb.setWidgetName(editor.getWidgetName()); - tcb.setVisible(editor.isVisible()); - tcb.setWaterMark(editor.getWaterMark()); - tcb.setRemoveRepeat(editor.isRemoveRepeat()); - tcb.setTreeAttr(editor.getTreeAttr()); - tcb.setTreeNodeAttr(editor.getTreeNodeAttr()); - tcb.setNodeOrDict(editor.getTreeNodeAttr()); - tcb.setPerformanceFirst(editor.isPerformanceFirst()); - } - }else { - LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject(); - tcb.setAutoBuild(false); - tcb.setFastLayerBuild(true); - tcb.setLayerConfigs(Arrays.asList(configs)); - } - return tcb; - } - - /** - * * @param nodeOrDict */ public void populate(Object nodeOrDict) { - if(nodeOrDict instanceof TreeNodeAttr[] || nodeOrDict instanceof TreeNodeWrapper) { + if (nodeOrDict instanceof TreeNodeAttr[] || nodeOrDict instanceof TreeNodeWrapper) { buildBox.setSelectedIndex(2); NameObject no = new NameObject("name", nodeOrDict); controlPane.populate(no); - } else if(nodeOrDict instanceof TableDataDictionary) { + } else if (nodeOrDict instanceof TableDataDictionary) { buildBox.setSelectedIndex(1); - autoBuildPane.populate((TableDataDictionary)nodeOrDict); - } else if (nodeOrDict instanceof NameObject) { + autoBuildPane.populate((TableDataDictionary) nodeOrDict); + } else if (nodeOrDict instanceof LayerConfig[]) { buildBox.setSelectedIndex(0); - layerDataControlPane.populate((NameObject) nodeOrDict); + layerDataControlPane.populate((LayerConfig[]) nodeOrDict); } } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UIBubbleFloatPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UIBubbleFloatPane.java index 03927ca46..e50140121 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UIBubbleFloatPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UIBubbleFloatPane.java @@ -48,7 +48,7 @@ public abstract class UIBubbleFloatPane extends BasicBeanPane { private int arrowPosition; private double time = 0.5; - private UIDialog showDialog; + protected UIDialog showDialog; /** * @param arrowPosition 箭头的位置,上下左右,暂时只处理了左边,后面用到了再说 TODO @@ -93,11 +93,22 @@ public abstract class UIBubbleFloatPane extends BasicBeanPane { populateBean(ob); if (showDialog == null) { showDialog = showUnsizedWindow(SwingUtilities.getWindowAncestor(fatherPane)); + if (forceLockFocus()) { + showDialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); + } } - Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + initAWTEventListener(); showDialog.setVisible(true); } + public boolean forceLockFocus() { + return false; + } + + protected void initAWTEventListener() { + Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + } + /** * 数据展现 */ @@ -213,9 +224,14 @@ public abstract class UIBubbleFloatPane extends BasicBeanPane { } this.setLayout(new BorderLayout()); + this.add(initTopOptionMenu(), BorderLayout.NORTH); this.add(contentPane, BorderLayout.CENTER); } + protected JPanel initTopOptionMenu() { + return new JPanel(); + } + private class CustomShapedDialog extends UIDialog { private static final int GAP_SMALL = 10; diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java index 6d74e4801..eedc12058 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java @@ -179,7 +179,7 @@ public class LayerDataControlPane extends ControlPane { public void actionPerformed(ActionEvent e) { // TODO remove tree node int val = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?", - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (val != JOptionPane.OK_OPTION) { return; } @@ -193,36 +193,32 @@ public class LayerDataControlPane extends ControlPane { } } - public void populate(NameObject nameObject) { + public void populate(LayerConfig[] layerConfigs) { // 重新添加tree节点的时候需要remove掉原来的所有子节点 ((DefaultMutableTreeNode) defaultTreeModel.getRoot()).removeAllChildren(); - if (BEAN_NAME.equals(nameObject.getName())) { - Object obj = nameObject.getObject(); - LayerConfig[] layerConfigs = null; - if (obj instanceof LayerConfig[]) { - layerConfigs = ((LayerConfig[]) obj); - } + if (layerConfigs == null) { + return; + } - int count = layerConfigs == null ? 0 : layerConfigs.length; - //将树的层次一层一层的加上去 - DefaultMutableTreeNode node4root = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); - for (int i = 0; i < count; i++) { + int count = layerConfigs.length; + //将树的层次一层一层的加上去 + DefaultMutableTreeNode node4root = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); + for (int i = 0; i < count; i++) { - DefaultMutableTreeNode node4add = new DefaultMutableTreeNode( + DefaultMutableTreeNode node4add = new DefaultMutableTreeNode( new NameObject(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradation") + (i + 1), layerConfigs[i].clone())); - node4root.add(node4add); - node4root = node4add; - } - - defaultTreeModel.reload(); - expandAll(tree, true); - tree.setSelectionRow(0); + node4root.add(node4add); + node4root = node4add; } + + defaultTreeModel.reload(); + expandAll(tree, true); + tree.setSelectionRow(0); } - public NameObject update() { + public LayerConfig[] update() { - return new NameObject(BEAN_NAME, updateLayerDatas()); + return updateLayerDatas(); } private LayerConfig[] updateLayerDatas() { 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 index 7198eeef0..916cd3cf6 100644 --- 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 @@ -1,5 +1,6 @@ package com.fr.design.gui.icombobox; +import com.fr.concurrent.NamedThreadFactory; import com.fr.data.core.DataCoreUtils; import com.fr.data.core.db.TableProcedure; import com.fr.data.impl.Connection; @@ -9,6 +10,7 @@ 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.module.ModuleContext; import com.fr.stable.ArrayUtils; import com.fr.stable.Filter; import com.fr.stable.StringUtils; @@ -24,6 +26,7 @@ import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.util.Enumeration; +import java.util.concurrent.ExecutorService; /** * 实现模糊搜索表名的FRTreeComboBox @@ -37,6 +40,10 @@ import java.util.Enumeration; public class TableSearchTreeComboBox extends FRTreeComboBox { // 持有父容器,需要实时获取其他组件值 private final ChoosePane parent; + /** + * 保证模糊搜索的原子性操作 + */ + private final ExecutorService singleExecutor = ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory("TableSearchTreeComboBox")); public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) { super(tree, renderer); @@ -69,14 +76,15 @@ public class TableSearchTreeComboBox extends FRTreeComboBox { */ private void searchExecute() { UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor(); - new SwingWorker() { + String searchText = (String) searchEditor.getItem(); + singleExecutor.execute(new SwingWorker() { @Override protected Void doInBackground() { processTableDataNames( parent.getDSName(), parent.getConnection(), parent.getSchema(), - createFilter((String) searchEditor.getItem())); + createFilter(searchText)); return null; } @@ -86,7 +94,7 @@ public class TableSearchTreeComboBox extends FRTreeComboBox { // 输入框获取焦点 searchEditor.getEditorComponent().requestFocus(); } - }.execute(); + }); } private TableNameFilter createFilter(String text) { diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java index 942c3430c..47abaa8b6 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java @@ -32,7 +32,11 @@ class SwingFileChooser implements FileChooserProvider { @Override public File[] getSelectedFiles() { - return fileChooser.getSelectedFiles(); + if (ArrayUtils.isNotEmpty(fileChooser.getSelectedFiles())) { + return fileChooser.getSelectedFiles(); + } else { + return new File[]{fileChooser.getSelectedFile()}; + } } @Override diff --git a/designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java b/designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java new file mode 100644 index 000000000..fe1c6bda8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java @@ -0,0 +1,177 @@ +package com.fr.design.gui.ilist; + +import com.fr.design.event.StateChangeListener; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.itree.checkboxtree.TristateCheckBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.AbstractListModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +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.List; + +/** + * 支持全选、全不选、半选的CheckBoxList面板 + * @author Yvan + */ +public class CheckBoxListWithPartialSelect extends JPanel { + + private UICheckBox[] dataCheckBoxes; + + private TristateCheckBox chooseAllCheckBox; + + private UIList dataList; + + public CheckBoxListWithPartialSelect (Object[] data) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + init(data); + this.add(chooseAllCheckBox, BorderLayout.NORTH); + this.add(dataList, BorderLayout.CENTER); + } + + private void init(Object[] data) { + // 复选框组 + dataCheckBoxes = new UICheckBox[data.length]; + for (int i = 0; i < dataCheckBoxes.length; i++) { + dataCheckBoxes[i] = new UICheckBox(transferDataValue2Show(data[i])); + dataCheckBoxes[i].setSelected(true); + } + + // UIList + dataList = new UIList(dataCheckBoxes); + dataList.setModel(getListModel()); + dataList.setCellRenderer(getListCellRenderer()); + + // 全选框 + chooseAllCheckBox = new TristateCheckBox(Toolkit.i18nText("Fine-Design_Basic_Remove_All_Selected")) { + @Override + protected State getNextState(State current) { + if (current == TristateCheckBox.SELECTED || current == TristateCheckBox.DO_NOT_CARE) { + return TristateCheckBox.NOT_SELECTED; + } + return TristateCheckBox.SELECTED; + } + }; + chooseAllCheckBox.setState(TristateCheckBox.SELECTED); + chooseAllCheckBox.setFocusable(false); + chooseAllCheckBox.addStateChangeListener(getChooseAllCheckBoxStateChangeListener()); + dataList.addMouseListener(getDataListMouseListener()); + } + + public List getSelectedObjects() { + List seleted = new ArrayList<>(); + for (UICheckBox dataCheckBox : dataCheckBoxes) { + if (dataCheckBox.isSelected()) { + seleted.add(dataCheckBox.getText()); + } + } + return seleted; + } + + protected MouseListener getDataListMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + int index = dataList.getSelectedIndex(); + if (index < 0) { + return; + } + UICheckBox checkBox = (UICheckBox) dataList.getModel().getElementAt(index); + checkBox.setSelected(!checkBox.isSelected()); + //根据CheckBoxes中的选择情况来更新全选框的状态 + int selectedCount = calculateSelectedNum(); + if (selectedCount == 0) { + chooseAllCheckBox.setState(TristateCheckBox.NOT_SELECTED); + } else if (selectedCount == dataCheckBoxes.length) { + chooseAllCheckBox.setState(TristateCheckBox.SELECTED); + } else { + chooseAllCheckBox.setState(TristateCheckBox.DO_NOT_CARE); + } + dataList.repaint(); + } + }; + } + + /** + * 获取全选框状态改变监听 + * @return + */ + protected StateChangeListener getChooseAllCheckBoxStateChangeListener() { + return () -> { + if (chooseAllCheckBox.getState() == TristateCheckBox.DO_NOT_CARE) { + return; + } + boolean isSelected = chooseAllCheckBox.isSelected(); + for (int i = 0; i < dataList.getModel().getSize(); i++) { + UICheckBox checkBox = (UICheckBox) dataList.getModel().getElementAt(i); + checkBox.setSelected(isSelected); + } + dataList.repaint(); + }; + } + + /** + * 计算CheckBox的选中情况,用来更新全选框的状态 + * @return + */ + protected int calculateSelectedNum() { + int count = 0; + for (UICheckBox dataCheckBox : dataCheckBoxes) { + if (dataCheckBox.isSelected()) { + count++; + } + } + return count; + } + + /** + * 将传入的Object转化为字符串展示,默认调用toString方法 + * @param object + * @return + */ + protected String transferDataValue2Show(Object object) { + return object.toString(); + } + + protected AbstractListModel getListModel() { + return new SelectedListDataModel(); + } + + protected ListCellRenderer getListCellRenderer() { + return new SelectedListCellRender(); + } + + private class SelectedListCellRender extends DefaultListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, final boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + dataCheckBoxes[index] = (UICheckBox) value; + dataCheckBoxes[index].setBackground(list.getBackground()); + return dataCheckBoxes[index]; + } + + } + + private class SelectedListDataModel extends AbstractListModel { + @Override + public int getSize() { + return dataCheckBoxes.length; + } + + @Override + public Object getElementAt(int index) { + return (index > getSize() - 1 || index < 0) ? null : dataCheckBoxes[index]; + } + } +} 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 3106ebff7..2c1e6abf5 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 @@ -5,7 +5,6 @@ import com.fr.design.dialog.UIDialog; import com.fr.design.gui.ilable.UILabel; import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.utils.DesignUtils; -import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.FRFont; import com.fr.stable.os.support.OSBasedAction; import com.fr.stable.os.support.OSSupportCenter; @@ -23,9 +22,15 @@ import java.awt.Frame; * 加载进度弹窗 */ public class ProgressDialog extends UIDialog { - private JProgressBar progressBar; + protected static final FRFont font = DesignUtils + .getDefaultGUIFont() + .applySize(14) + .applyForeground(new ColorUIResource(333334)); + + protected JProgressBar progressBar; private JDialog centerDialog; - private JLabel text; + protected JLabel text; + protected JPanel progressPanel; public ProgressDialog(Frame parent) { super(parent); @@ -42,30 +47,37 @@ public class ProgressDialog extends UIDialog { } private void initComponent(Frame parent) { + initProgressBar(); + initProgressPanel(); + initCenterDialog(parent); + } + protected void initCenterDialog(Frame parent) { centerDialog = new JDialog(this); centerDialog.setSize(new Dimension(482, 124)); centerDialog.setUndecorated(true); 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)); + centerDialog.getContentPane().add(progressPanel); + } + + protected void initProgressBar() { progressBar = new JProgressBar(); progressBar.setUI(new ModernUIProgressBarUI()); progressBar.setBorderPainted(false); progressBar.setOpaque(false); progressBar.setBorder(null); progressBar.setMaximum(1000); - panel.add(progressBar, BorderLayout.CENTER); + } + + protected void initProgressPanel() { + progressPanel = new JPanel(); + progressPanel.setBorder(new UIProgressBorder(3, UIConstants.DEFAULT_BG_RULER, 14, 46, 47, 37, 47)); + progressPanel.setLayout(new BorderLayout(4, 15)); + progressPanel.add(progressBar, BorderLayout.CENTER); text = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Loading_Project"), JLabel.CENTER); - FRFont font = DesignUtils - .getDefaultGUIFont() - .applySize(14) - .applyForeground(new ColorUIResource(333334)); text.setFont(font); - panel.add(text, BorderLayout.SOUTH); - panel.setVisible(true); - centerDialog.getContentPane().add(panel); + progressPanel.add(text, BorderLayout.SOUTH); + progressPanel.setVisible(true); } @Override diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java index a22f2a302..161c1c7c7 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java @@ -154,6 +154,13 @@ public abstract class RefreshableJTree extends CheckBoxTree { refresh((ExpandMutableTreeNode) this.getModel().getRoot(), childName); } + /** + * 刷新树,用于搜索结果的展示 + */ + public void refresh4TreeSearch() { + + } + /* * 刷新expandRoot节点下所有已打开的节点的UserObject,并打开isExpanded为true的TreeNode */ 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 index 7e0db6051..a53235cf2 100644 --- 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 @@ -58,8 +58,9 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName private static final Integer[] TYPES = new Integer[]{ FormatContents.NULL, FormatContents.NUMBER, FormatContents.CURRENCY, FormatContents.PERCENT, - FormatContents.SCIENTIFIC, FormatContents.DATE, - FormatContents.TIME, FormatContents.TEXT}; + FormatContents.THOUSANDTHS,FormatContents.SCIENTIFIC, + FormatContents.DATE, FormatContents.TIME, + FormatContents.TEXT}; private static final Integer[] DATE_TYPES = new Integer[]{FormatContents.NULL, FormatContents.DATE, FormatContents.TIME}; diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java index 98b5265c3..6ffe49f4e 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java @@ -1,24 +1,24 @@ -/* The following code was generated by JFlex 1.4.1 on 9/18/19 6:12 PM */ +/* The following code was generated by JFlex 1.4.1 on 22-4-11 下午2:19 */ package com.fr.design.gui.syntax.ui.rsyntaxtextarea.modes; + import com.fr.design.gui.syntax.ui.rsyntaxtextarea.AbstractJFlexCTokenMaker; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.Token; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.TokenImpl; - -import javax.swing.text.Segment; import java.io.IOException; +import javax.swing.text.Segment; + /** - * This class is a scanner generated by + * This class is a scanner generated by * JFlex 1.4.1 - * on 9/18/19 6:12 PM from the specification file - * /Users/3dot141/Downloads/FolxDownload/App/jflex-1.4.1/bin/FormulaTokenMaker.flex + * on 22-4-11 下午2:19 from the specification file + * C:/Users/pengda/Desktop/bug/FormulaTokenMaker.flex */ -@SuppressWarnings("squid:S1192") public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { /** This character denotes the end of file */ @@ -32,57 +32,58 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { public static final int YYINITIAL = 0; public static final int MLC = 1; - /** + /** * Translates characters to character classes */ - private static final String ZZ_CMAP_PACKED = - "\11\0\1\50\1\43\1\0\1\50\1\56\22\0\1\50\1\36\1\44"+ - "\1\57\1\60\1\65\1\132\1\33\1\31\1\31\1\51\1\7\1\64"+ - "\1\37\1\54\1\32\1\47\1\41\1\100\1\120\1\5\1\127\1\121"+ - "\1\5\1\126\1\3\1\70\1\63\1\34\1\30\1\35\1\27\1\61"+ - "\1\72\1\73\1\75\1\4\1\6\1\55\1\110\1\77\1\105\1\125"+ - "\1\116\1\53\1\112\1\104\1\76\1\111\1\113\1\101\1\74\1\106"+ - "\1\52\1\107\1\115\1\122\1\102\1\123\1\62\1\40\1\62\1\131"+ - "\1\2\1\0\1\24\1\46\1\21\1\10\1\11\1\12\1\25\1\66"+ - "\1\13\1\1\1\117\1\15\1\26\1\14\1\20\1\23\1\114\1\17"+ - "\1\16\1\67\1\22\1\45\1\71\1\42\1\103\1\124\1\130\1\133"+ - "\1\130\1\64\uff81\0"; - - /** + private static final String ZZ_CMAP_PACKED = + "\11\0\1\50\1\43\1\0\1\50\1\56\22\0\1\50\1\36\1\44"+ + "\1\57\1\60\1\65\1\132\1\33\1\31\1\31\1\51\1\7\1\64"+ + "\1\37\1\54\1\32\1\47\1\41\1\100\1\120\1\5\1\127\1\121"+ + "\1\5\1\126\1\3\1\70\1\63\1\34\1\30\1\35\1\27\1\61"+ + "\1\72\1\73\1\75\1\4\1\6\1\55\1\110\1\77\1\105\1\125"+ + "\1\116\1\53\1\112\1\104\1\76\1\111\1\113\1\101\1\74\1\106"+ + "\1\52\1\107\1\115\1\122\1\102\1\123\1\62\1\40\1\62\1\131"+ + "\1\2\1\0\1\24\1\46\1\21\1\10\1\11\1\12\1\25\1\66"+ + "\1\13\1\1\1\117\1\15\1\26\1\14\1\20\1\23\1\114\1\17"+ + "\1\16\1\67\1\22\1\45\1\71\1\42\1\103\1\124\1\130\1\133"+ + "\1\130\1\64\uff81\0"; + + /** * Translates characters to character classes */ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - /** + /** * Translates DFA states to action switch labels. */ private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\3\0\1\1\2\2\1\3\2\2\1\4\17\2\2\4"+ - "\1\5\1\4\1\6\4\4\1\2\1\7\1\10\2\2"+ - "\1\3\1\11\2\2\1\4\1\2\2\1\30\2\2\4"+ - "\2\12\1\13\5\12\1\14\2\12\1\2\2\15\2\3"+ - "\1\16\16\2\1\17\61\2\1\0\1\20\1\21\2\22"+ - "\1\23\1\6\2\10\1\24\2\2\1\15\13\2\6\1"+ - "\1\0\77\2\2\0\1\25\6\0\1\2\1\3\1\0"+ - "\1\3\1\15\1\16\2\2\1\17\11\2\1\17\16\2"+ - "\1\17\3\2\1\17\2\2\1\17\14\2\1\17\10\2"+ - "\1\17\17\2\1\17\1\2\1\17\1\6\1\26\1\6"+ - "\3\22\1\6\2\10\1\27\2\2\1\30\10\2\4\1"+ - "\1\31\4\1\6\0\26\2\1\17\2\2\1\17\10\2"+ - "\1\17\17\2\1\17\25\2\1\17\1\2\1\17\6\2"+ - "\10\0\1\2\1\16\1\0\4\2\1\17\6\2\1\17"+ - "\34\2\1\17\15\2\1\17\4\2\1\6\1\10\2\2"+ - "\2\30\5\2\7\1\4\0\1\31\4\0\12\2\1\17"+ - "\4\2\1\17\32\2\1\17\1\2\2\17\23\2\1\17"+ - "\2\2\2\0\1\32\2\0\1\33\27\2\1\17\7\2"+ - "\1\17\14\2\1\30\3\2\1\31\3\1\7\0\30\2"+ - "\1\17\2\2\1\17\12\2\4\0\36\2\2\1\1\31"+ - "\3\0\54\2\2\0\116\2"; + "\3\0\1\1\2\2\1\3\2\2\1\4\17\2\2\4"+ + "\1\5\1\4\1\6\4\4\1\2\1\7\1\10\2\2"+ + "\1\3\1\11\2\2\1\4\1\2\2\1\30\2\2\4"+ + "\2\12\1\13\5\12\1\14\2\12\1\2\2\15\2\3"+ + "\1\16\16\2\1\17\62\2\1\0\1\20\1\21\2\22"+ + "\1\23\1\6\2\10\1\24\2\2\1\15\14\2\6\1"+ + "\1\0\101\2\2\0\1\25\6\0\1\2\1\3\1\0"+ + "\1\3\1\15\1\16\2\2\1\17\12\2\1\17\20\2"+ + "\1\17\3\2\1\17\2\2\1\17\14\2\1\17\10\2"+ + "\1\17\20\2\2\17\1\2\1\17\1\6\1\26\1\6"+ + "\3\22\1\6\2\10\1\27\2\2\1\30\10\2\4\1"+ + "\1\31\4\1\6\0\27\2\1\17\2\2\1\17\10\2"+ + "\1\17\17\2\1\17\26\2\1\17\1\2\2\17\6\2"+ + "\10\0\1\2\1\16\1\0\4\2\1\17\10\2\1\17"+ + "\40\2\1\17\17\2\1\17\6\2\1\6\1\10\2\2"+ + "\2\30\5\2\7\1\4\0\1\31\4\0\13\2\1\17"+ + "\5\2\1\17\34\2\1\17\1\2\2\17\27\2\1\17"+ + "\2\2\2\0\1\32\2\0\1\33\33\2\1\17\1\2"+ + "\1\17\10\2\1\17\7\2\1\17\6\2\1\30\3\2"+ + "\1\31\3\1\7\0\20\2\1\17\12\2\1\17\2\2"+ + "\1\17\1\2\1\17\14\2\4\0\44\2\2\1\1\31"+ + "\3\0\62\2\2\0\114\2"; private static int [] zzUnpackAction() { - int [] result = new int[887]; + int [] result = new int[943]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -101,126 +102,133 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { } - /** + /** * Translates a state to a row index in the transition table */ private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\134\0\270\0\u0114\0\u0170\0\u01cc\0\u0228\0\u0284"+ - "\0\u02e0\0\u033c\0\u0398\0\u03f4\0\u0450\0\u04ac\0\u0508\0\u0564"+ - "\0\u05c0\0\u061c\0\u0678\0\u06d4\0\u0730\0\u078c\0\u07e8\0\u0844"+ - "\0\u08a0\0\u08fc\0\u0958\0\u09b4\0\u0a10\0\u0a6c\0\u0ac8\0\u0b24"+ - "\0\u09b4\0\u0b80\0\u0114\0\u09b4\0\u0bdc\0\u0c38\0\u0c94\0\u0cf0"+ - "\0\u0d4c\0\u0da8\0\u0e04\0\u0e60\0\u0ebc\0\u09b4\0\u0f18\0\u09b4"+ - "\0\u0f74\0\u0fd0\0\u102c\0\u1088\0\u10e4\0\u1140\0\u119c\0\u11f8"+ - "\0\u1254\0\u12b0\0\u130c\0\u1368\0\u13c4\0\u1420\0\u147c\0\u14d8"+ - "\0\u1534\0\u1590\0\u15ec\0\u1648\0\u16a4\0\u1700\0\u175c\0\u17b8"+ - "\0\u1814\0\u1870\0\u18cc\0\u09b4\0\u1928\0\u1984\0\u19e0\0\u1a3c"+ - "\0\u1a98\0\u09b4\0\u1af4\0\u1b50\0\u1bac\0\u1c08\0\u1c64\0\u1cc0"+ - "\0\u1d1c\0\u1d78\0\u1dd4\0\u1e30\0\u1e8c\0\u1ee8\0\u1f44\0\u1fa0"+ - "\0\u1ffc\0\u2058\0\u20b4\0\u2110\0\u216c\0\u21c8\0\u2224\0\u2280"+ - "\0\u01cc\0\u22dc\0\u2338\0\u2394\0\u23f0\0\u244c\0\u24a8\0\u2504"+ - "\0\u2560\0\u25bc\0\u2618\0\u2674\0\u26d0\0\u272c\0\u2788\0\u27e4"+ - "\0\u2840\0\u289c\0\u28f8\0\u2954\0\u29b0\0\u2a0c\0\u2a68\0\u2ac4"+ - "\0\u2b20\0\u2b7c\0\u2bd8\0\u2c34\0\u2c90\0\u2cec\0\u2d48\0\u2da4"+ - "\0\u2e00\0\u2e5c\0\u2eb8\0\u2f14\0\u2f70\0\u2fcc\0\u3028\0\u3084"+ - "\0\u30e0\0\u313c\0\u3198\0\u31f4\0\u3250\0\u32ac\0\u3308\0\u3364"+ - "\0\u33c0\0\u341c\0\u3478\0\u09b4\0\u09b4\0\u34d4\0\u3530\0\u09b4"+ - "\0\u358c\0\u35e8\0\u3644\0\u09b4\0\u36a0\0\u36fc\0\u3758\0\u37b4"+ - "\0\u3810\0\u386c\0\u38c8\0\u3924\0\u3980\0\u39dc\0\u3a38\0\u3a94"+ - "\0\u3af0\0\u3b4c\0\u3ba8\0\u3c04\0\u3c60\0\u3cbc\0\u3d18\0\u3d74"+ - "\0\u3dd0\0\u3e2c\0\u3e88\0\u3ee4\0\u3f40\0\u3f9c\0\u3ff8\0\u4054"+ - "\0\u40b0\0\u410c\0\u4168\0\u41c4\0\u4220\0\u427c\0\u42d8\0\u4334"+ - "\0\u4390\0\u43ec\0\u4448\0\u44a4\0\u4500\0\u455c\0\u45b8\0\u4614"+ - "\0\u4670\0\u46cc\0\u4728\0\u4784\0\u47e0\0\u483c\0\u4898\0\u48f4"+ - "\0\u4950\0\u49ac\0\u4a08\0\u4a64\0\u4ac0\0\u4b1c\0\u4b78\0\u4bd4"+ - "\0\u4c30\0\u4c8c\0\u4ce8\0\u4d44\0\u4da0\0\u4dfc\0\u4e58\0\u4eb4"+ - "\0\u4f10\0\u4f6c\0\u4fc8\0\u5024\0\u5080\0\u50dc\0\u5138\0\u5194"+ - "\0\u51f0\0\u524c\0\u52a8\0\u5304\0\u5360\0\u53bc\0\u5418\0\u5474"+ - "\0\u54d0\0\u552c\0\u09b4\0\u5588\0\u55e4\0\u5640\0\u569c\0\u56f8"+ - "\0\u5754\0\u57b0\0\u580c\0\u5868\0\u1c08\0\u58c4\0\u1c08\0\u5920"+ - "\0\u597c\0\u59d8\0\u5a34\0\u5a90\0\u5aec\0\u5b48\0\u5ba4\0\u5c00"+ - "\0\u5c5c\0\u5cb8\0\u5d14\0\u5d70\0\u5dcc\0\u5e28\0\u5e84\0\u5ee0"+ - "\0\u5f3c\0\u5f98\0\u5ff4\0\u6050\0\u60ac\0\u6108\0\u6164\0\u61c0"+ - "\0\u621c\0\u6278\0\u62d4\0\u6330\0\u638c\0\u63e8\0\u6444\0\u64a0"+ - "\0\u64fc\0\u6558\0\u65b4\0\u6610\0\u666c\0\u66c8\0\u6724\0\u6780"+ - "\0\u67dc\0\u6838\0\u6894\0\u68f0\0\u694c\0\u69a8\0\u6a04\0\u6a60"+ - "\0\u6abc\0\u6b18\0\u6b74\0\u6bd0\0\u6c2c\0\u6c88\0\u6ce4\0\u6d40"+ - "\0\u6d9c\0\u6df8\0\u6e54\0\u6eb0\0\u6f0c\0\u6f68\0\u6fc4\0\u7020"+ - "\0\u707c\0\u70d8\0\u7134\0\u7190\0\u71ec\0\u7248\0\u72a4\0\u7300"+ - "\0\u735c\0\u73b8\0\u7414\0\u09b4\0\u7470\0\u74cc\0\u7528\0\u7584"+ - "\0\u75e0\0\u763c\0\u7698\0\u09b4\0\u76f4\0\u7750\0\u77ac\0\u7808"+ - "\0\u7864\0\u78c0\0\u791c\0\u7978\0\u79d4\0\u7a30\0\u7a8c\0\u7ae8"+ - "\0\u7b44\0\u7ba0\0\u7bfc\0\u7c58\0\u7cb4\0\u7d10\0\u7d6c\0\u7dc8"+ - "\0\u7e24\0\u7e80\0\u7edc\0\u7f38\0\u7f94\0\u7ff0\0\u804c\0\u80a8"+ - "\0\u8104\0\u8160\0\u81bc\0\u8218\0\u8274\0\u82d0\0\u832c\0\u8388"+ - "\0\u83e4\0\u8440\0\u849c\0\u84f8\0\u8554\0\u85b0\0\u860c\0\u8668"+ - "\0\u86c4\0\u8720\0\u877c\0\u87d8\0\u8834\0\u8890\0\u88ec\0\u8948"+ - "\0\u89a4\0\u8a00\0\u8a5c\0\u8ab8\0\u8b14\0\u8b70\0\u8bcc\0\u8c28"+ - "\0\u8c84\0\u8ce0\0\u8d3c\0\u8d98\0\u8df4\0\u8e50\0\u8eac\0\u8f08"+ - "\0\u8f64\0\u8fc0\0\u901c\0\u9078\0\u90d4\0\u9130\0\u918c\0\u91e8"+ - "\0\u9244\0\u92a0\0\u92fc\0\u9358\0\u93b4\0\u9410\0\u946c\0\u94c8"+ - "\0\u9524\0\u9580\0\u95dc\0\u9638\0\u9694\0\u96f0\0\u974c\0\u97a8"+ - "\0\u9804\0\u9860\0\u98bc\0\u9918\0\u9974\0\u99d0\0\u9a2c\0\u9a88"+ - "\0\u9ae4\0\u9b40\0\u9b9c\0\u9bf8\0\u9c54\0\u9cb0\0\u9d0c\0\u9d68"+ - "\0\u9dc4\0\u9e20\0\u9e7c\0\u9ed8\0\u9f34\0\u9f90\0\u9fec\0\u73b8"+ - "\0\ua048\0\ua0a4\0\ua100\0\ua15c\0\ua1b8\0\ua214\0\ua270\0\ua2cc"+ - "\0\ua328\0\ua384\0\ua3e0\0\ua43c\0\ua498\0\ua4f4\0\ua550\0\ua5ac"+ - "\0\ua608\0\ua664\0\ua6c0\0\ua71c\0\ua778\0\ua7d4\0\ua830\0\ua88c"+ - "\0\ua8e8\0\ua944\0\ua9a0\0\ua9fc\0\uaa58\0\uaab4\0\uab10\0\uab6c"+ - "\0\uabc8\0\uac24\0\uac80\0\uacdc\0\uad38\0\uad94\0\uadf0\0\uae4c"+ - "\0\uaea8\0\uaf04\0\uaf60\0\uafbc\0\ub018\0\ub074\0\ub0d0\0\ub12c"+ - "\0\ub188\0\ub1e4\0\ub240\0\ub29c\0\ub2f8\0\ub354\0\ub3b0\0\ub40c"+ - "\0\ub468\0\ub4c4\0\ub520\0\ub57c\0\ub5d8\0\ub634\0\ub690\0\ub6ec"+ - "\0\ub748\0\ub7a4\0\ub800\0\ub85c\0\ub8b8\0\ub914\0\ub970\0\ub9cc"+ - "\0\uba28\0\uba84\0\ubae0\0\ubb3c\0\ubb98\0\ubbf4\0\ubc50\0\ubcac"+ - "\0\ubd08\0\ubd64\0\ubdc0\0\ube1c\0\ube78\0\ubed4\0\ubf30\0\ubf8c"+ - "\0\ubfe8\0\uc044\0\uc0a0\0\uc0fc\0\uc158\0\uc1b4\0\uc210\0\uc26c"+ - "\0\uc2c8\0\uc324\0\uc380\0\uc3dc\0\uc438\0\u9a2c\0\uc494\0\uc4f0"+ - "\0\uc54c\0\uc5a8\0\uc604\0\uc660\0\uc6bc\0\uc718\0\uc774\0\uc7d0"+ - "\0\uc82c\0\uc888\0\uc8e4\0\uc940\0\uc99c\0\uc9f8\0\uca54\0\ucab0"+ - "\0\ucb0c\0\ucb68\0\ucbc4\0\ucc20\0\ucc7c\0\uccd8\0\ucd34\0\ucd90"+ - "\0\ucdec\0\uce48\0\ucea4\0\ucf00\0\ucf5c\0\ucfb8\0\ud014\0\ud070"+ - "\0\ud0cc\0\ud128\0\ud184\0\ud1e0\0\ud23c\0\ud298\0\ud2f4\0\ud350"+ - "\0\ud3ac\0\ud408\0\ud464\0\ud4c0\0\ud51c\0\ud578\0\ud5d4\0\ud630"+ - "\0\ud68c\0\ud6e8\0\ud744\0\ud7a0\0\ud7fc\0\ud858\0\ud8b4\0\ud910"+ - "\0\ud96c\0\ud9c8\0\uda24\0\uda80\0\udadc\0\udb38\0\udb94\0\udbf0"+ - "\0\udc4c\0\udca8\0\udd04\0\udd60\0\uddbc\0\ude18\0\ude74\0\uded0"+ - "\0\udf2c\0\udf88\0\udfe4\0\ue040\0\ue09c\0\ue0f8\0\ue154\0\ue1b0"+ - "\0\ue20c\0\ue268\0\ue2c4\0\ue320\0\ue37c\0\u6444\0\ue3d8\0\ue434"+ - "\0\ue490\0\ue4ec\0\ue548\0\ue5a4\0\ue600\0\ue65c\0\ue6b8\0\ue714"+ - "\0\ue770\0\ue7cc\0\ue828\0\ue884\0\ue8e0\0\ue93c\0\u1c08\0\ue998"+ - "\0\ue9f4\0\uea50\0\u0114\0\ueaac\0\ueb08\0\ueb64\0\uebc0\0\uec1c"+ - "\0\uec78\0\uecd4\0\ued30\0\ued8c\0\uede8\0\uee44\0\ueea0\0\ueefc"+ - "\0\uef58\0\uefb4\0\uf010\0\uf06c\0\uf0c8\0\uf124\0\uf180\0\uf1dc"+ - "\0\uf238\0\u8948\0\uf294\0\uf2f0\0\uf34c\0\uf3a8\0\uf404\0\uf460"+ - "\0\uf4bc\0\uf518\0\uf574\0\uf5d0\0\uf62c\0\uf688\0\uf6e4\0\uf740"+ - "\0\uf79c\0\uf7f8\0\uf854\0\uf8b0\0\uf90c\0\uf968\0\uf9c4\0\ufa20"+ - "\0\ufa7c\0\ufad8\0\ufb34\0\ufb90\0\ud8b4\0\ufbec\0\ud9c8\0\ufc48"+ - "\0\ufca4\0\ufd00\0\ufd5c\0\ufdb8\0\ufe14\0\ufe70\0\ufecc\0\uff28"+ - "\0\uff84\0\uffe0\1\74\1\230\1\364\1\u0150\1\u01ac\1\u0208"+ - "\1\u0264\1\u02c0\1\u031c\1\u0378\1\u03d4\1\u0430\1\u048c\1\u04e8"+ - "\1\u0544\1\u05a0\1\u05fc\1\u0658\1\u06b4\1\u0710\1\u076c\0\u09b4"+ - "\1\u07c8\1\u0824\1\u0880\1\u08dc\1\u0938\1\u0994\1\u09f0\1\u0a4c"+ - "\1\u0aa8\1\u0b04\1\u0b60\1\u0bbc\1\u0c18\1\u0c74\1\u0cd0\1\u0d2c"+ - "\1\u0d88\1\u0de4\1\u0e40\1\u0e9c\1\u0ef8\1\u0f54\1\u0fb0\1\u100c"+ - "\1\u1068\1\u10c4\1\u1120\1\u117c\1\u11d8\1\u1234\1\u1290\1\u12ec"+ - "\1\u1348\1\u13a4\1\u1400\1\u145c\1\u14b8\1\u1514\1\u1570\1\u15cc"+ - "\0\u7300\1\u1628\1\u1684\1\u16e0\1\u173c\1\u1798\1\u17f4\1\u1850"+ - "\1\u18ac\1\u1908\1\u1964\1\u19c0\1\u1a1c\0\u9ae4\1\u1a78\1\u1ad4"+ - "\1\u1b30\1\u1b8c\1\u1be8\1\u1c44\1\u1ca0\1\u1cfc\1\u1d58\1\u1db4"+ - "\1\u1e10\1\u1e6c\1\u1ec8\1\u1f24\1\u1f80\1\u1fdc\1\u2038\1\u2094"+ - "\1\u20f0\1\u214c\1\u21a8\1\u2204\1\u2260\1\u22bc\1\u2318\1\u2374"+ - "\1\u23d0\1\u242c\1\u2488\1\u24e4\1\u2540\1\u259c\1\u25f8\1\u2654"+ - "\1\u26b0\1\u270c\1\u2768\1\u27c4\1\u2820\1\u287c\1\u28d8\1\u2934"+ - "\1\u2990\1\u29ec\1\u2a48\1\u2aa4\1\u2b00\1\u2b5c\1\u2bb8\1\u2c14"+ - "\1\u2c70\1\u2ccc\1\u2d28\1\u2d84\1\u2de0\1\u2e3c\1\u2e98\1\u2ef4"+ - "\1\u2f50\1\u2fac\1\u3008\1\u3064\1\u30c0\1\u311c\1\u3178\1\u31d4"+ - "\1\u3230\1\u328c\1\u32e8\1\u3344\1\u33a0\1\u33fc\1\u3458"; + "\0\0\0\134\0\270\0\u0114\0\u0170\0\u01cc\0\u0228\0\u0284"+ + "\0\u02e0\0\u033c\0\u0398\0\u03f4\0\u0450\0\u04ac\0\u0508\0\u0564"+ + "\0\u05c0\0\u061c\0\u0678\0\u06d4\0\u0730\0\u078c\0\u07e8\0\u0844"+ + "\0\u08a0\0\u08fc\0\u0958\0\u09b4\0\u0a10\0\u0a6c\0\u0ac8\0\u0b24"+ + "\0\u09b4\0\u0b80\0\u0114\0\u09b4\0\u0bdc\0\u0c38\0\u0c94\0\u0cf0"+ + "\0\u0d4c\0\u0da8\0\u0e04\0\u0e60\0\u0ebc\0\u09b4\0\u0f18\0\u09b4"+ + "\0\u0f74\0\u0fd0\0\u102c\0\u1088\0\u10e4\0\u1140\0\u119c\0\u11f8"+ + "\0\u1254\0\u12b0\0\u130c\0\u1368\0\u13c4\0\u1420\0\u147c\0\u14d8"+ + "\0\u1534\0\u1590\0\u15ec\0\u1648\0\u16a4\0\u1700\0\u175c\0\u17b8"+ + "\0\u1814\0\u1870\0\u18cc\0\u09b4\0\u1928\0\u1984\0\u19e0\0\u1a3c"+ + "\0\u1a98\0\u09b4\0\u1af4\0\u1b50\0\u1bac\0\u1c08\0\u1c64\0\u1cc0"+ + "\0\u1d1c\0\u1d78\0\u1dd4\0\u1e30\0\u1e8c\0\u1ee8\0\u1f44\0\u1fa0"+ + "\0\u1ffc\0\u2058\0\u20b4\0\u2110\0\u216c\0\u21c8\0\u2224\0\u2280"+ + "\0\u01cc\0\u22dc\0\u2338\0\u2394\0\u23f0\0\u244c\0\u24a8\0\u2504"+ + "\0\u2560\0\u25bc\0\u2618\0\u2674\0\u26d0\0\u272c\0\u2788\0\u27e4"+ + "\0\u2840\0\u289c\0\u28f8\0\u2954\0\u29b0\0\u2a0c\0\u2a68\0\u2ac4"+ + "\0\u2b20\0\u2b7c\0\u2bd8\0\u2c34\0\u2c90\0\u2cec\0\u2d48\0\u2da4"+ + "\0\u2e00\0\u2e5c\0\u2eb8\0\u2f14\0\u2f70\0\u2fcc\0\u3028\0\u3084"+ + "\0\u30e0\0\u313c\0\u3198\0\u31f4\0\u3250\0\u32ac\0\u3308\0\u3364"+ + "\0\u33c0\0\u341c\0\u3478\0\u34d4\0\u09b4\0\u09b4\0\u3530\0\u358c"+ + "\0\u09b4\0\u35e8\0\u3644\0\u36a0\0\u09b4\0\u36fc\0\u3758\0\u37b4"+ + "\0\u3810\0\u386c\0\u38c8\0\u3924\0\u3980\0\u39dc\0\u3a38\0\u3a94"+ + "\0\u3af0\0\u3b4c\0\u3ba8\0\u3c04\0\u3c60\0\u3cbc\0\u3d18\0\u3d74"+ + "\0\u3dd0\0\u3e2c\0\u3e88\0\u3ee4\0\u3f40\0\u3f9c\0\u3ff8\0\u4054"+ + "\0\u40b0\0\u410c\0\u4168\0\u41c4\0\u4220\0\u427c\0\u42d8\0\u4334"+ + "\0\u4390\0\u43ec\0\u4448\0\u44a4\0\u4500\0\u455c\0\u45b8\0\u4614"+ + "\0\u4670\0\u46cc\0\u4728\0\u4784\0\u47e0\0\u483c\0\u4898\0\u48f4"+ + "\0\u4950\0\u49ac\0\u4a08\0\u4a64\0\u4ac0\0\u4b1c\0\u4b78\0\u4bd4"+ + "\0\u4c30\0\u4c8c\0\u4ce8\0\u4d44\0\u4da0\0\u4dfc\0\u4e58\0\u4eb4"+ + "\0\u4f10\0\u4f6c\0\u4fc8\0\u5024\0\u5080\0\u50dc\0\u5138\0\u5194"+ + "\0\u51f0\0\u524c\0\u52a8\0\u5304\0\u5360\0\u53bc\0\u5418\0\u5474"+ + "\0\u54d0\0\u552c\0\u5588\0\u55e4\0\u5640\0\u569c\0\u09b4\0\u56f8"+ + "\0\u5754\0\u57b0\0\u580c\0\u5868\0\u58c4\0\u5920\0\u597c\0\u59d8"+ + "\0\u1c08\0\u5a34\0\u1c08\0\u5a90\0\u5aec\0\u5b48\0\u5ba4\0\u5c00"+ + "\0\u5c5c\0\u5cb8\0\u5d14\0\u5d70\0\u5dcc\0\u5e28\0\u5e84\0\u5ee0"+ + "\0\u5f3c\0\u5f98\0\u5ff4\0\u6050\0\u60ac\0\u6108\0\u6164\0\u61c0"+ + "\0\u621c\0\u6278\0\u62d4\0\u6330\0\u638c\0\u63e8\0\u6444\0\u64a0"+ + "\0\u64fc\0\u6558\0\u65b4\0\u6610\0\u666c\0\u66c8\0\u6724\0\u6780"+ + "\0\u67dc\0\u6838\0\u6894\0\u68f0\0\u694c\0\u69a8\0\u6a04\0\u6a60"+ + "\0\u6abc\0\u6b18\0\u6b74\0\u6bd0\0\u6c2c\0\u6c88\0\u6ce4\0\u6d40"+ + "\0\u6d9c\0\u6df8\0\u6e54\0\u6eb0\0\u6f0c\0\u6f68\0\u6fc4\0\u7020"+ + "\0\u707c\0\u70d8\0\u7134\0\u7190\0\u71ec\0\u7248\0\u72a4\0\u7300"+ + "\0\u735c\0\u73b8\0\u7414\0\u7470\0\u74cc\0\u7528\0\u7584\0\u75e0"+ + "\0\u763c\0\u7698\0\u76f4\0\u7750\0\u09b4\0\u77ac\0\u7808\0\u7864"+ + "\0\u78c0\0\u791c\0\u7978\0\u79d4\0\u09b4\0\u7a30\0\u7a8c\0\u7ae8"+ + "\0\u7b44\0\u7ba0\0\u7bfc\0\u7c58\0\u7cb4\0\u7d10\0\u7d6c\0\u7dc8"+ + "\0\u7e24\0\u7e80\0\u7edc\0\u7f38\0\u7f94\0\u7ff0\0\u804c\0\u80a8"+ + "\0\u8104\0\u8160\0\u81bc\0\u8218\0\u8274\0\u82d0\0\u832c\0\u8388"+ + "\0\u83e4\0\u8440\0\u849c\0\u84f8\0\u8554\0\u85b0\0\u860c\0\u8668"+ + "\0\u86c4\0\u8720\0\u877c\0\u87d8\0\u8834\0\u8890\0\u88ec\0\u8948"+ + "\0\u89a4\0\u8a00\0\u8a5c\0\u8ab8\0\u8b14\0\u8b70\0\u8bcc\0\u8c28"+ + "\0\u8c84\0\u8ce0\0\u8d3c\0\u8d98\0\u8df4\0\u8e50\0\u8eac\0\u8f08"+ + "\0\u8f64\0\u8fc0\0\u901c\0\u9078\0\u90d4\0\u9130\0\u918c\0\u91e8"+ + "\0\u9244\0\u92a0\0\u92fc\0\u9358\0\u93b4\0\u9410\0\u946c\0\u94c8"+ + "\0\u9524\0\u9580\0\u95dc\0\u9638\0\u9694\0\u96f0\0\u974c\0\u97a8"+ + "\0\u9804\0\u9860\0\u98bc\0\u9918\0\u9974\0\u99d0\0\u9a2c\0\u9a88"+ + "\0\u9ae4\0\u9b40\0\u9b9c\0\u9bf8\0\u9c54\0\u9cb0\0\u9d0c\0\u9d68"+ + "\0\u9dc4\0\u9e20\0\u9e7c\0\u9ed8\0\u9f34\0\u9f90\0\u9fec\0\ua048"+ + "\0\ua0a4\0\ua100\0\ua15c\0\ua1b8\0\ua214\0\ua270\0\ua2cc\0\ua328"+ + "\0\ua384\0\ua3e0\0\ua43c\0\u76f4\0\ua498\0\ua4f4\0\ua550\0\ua5ac"+ + "\0\ua608\0\ua664\0\ua6c0\0\ua71c\0\ua778\0\ua7d4\0\ua830\0\ua88c"+ + "\0\ua8e8\0\ua944\0\ua9a0\0\ua9fc\0\uaa58\0\uaab4\0\uab10\0\uab6c"+ + "\0\uabc8\0\uac24\0\uac80\0\uacdc\0\uad38\0\uad94\0\uadf0\0\uae4c"+ + "\0\uaea8\0\uaf04\0\uaf60\0\uafbc\0\ub018\0\ub074\0\ub0d0\0\ub12c"+ + "\0\ub188\0\ub1e4\0\ub240\0\ub29c\0\ub2f8\0\ub354\0\ub3b0\0\ub40c"+ + "\0\ub468\0\ub4c4\0\ub520\0\ub57c\0\ub5d8\0\ub634\0\ub690\0\ub6ec"+ + "\0\ub748\0\ub7a4\0\ub800\0\ub85c\0\ub8b8\0\ub914\0\ub970\0\ub9cc"+ + "\0\uba28\0\uba84\0\ubae0\0\ubb3c\0\ubb98\0\ubbf4\0\ubc50\0\ubcac"+ + "\0\ubd08\0\ubd64\0\ubdc0\0\ube1c\0\ube78\0\ubed4\0\ubf30\0\ubf8c"+ + "\0\ubfe8\0\uc044\0\uc0a0\0\uc0fc\0\uc158\0\uc1b4\0\uc210\0\uc26c"+ + "\0\uc2c8\0\uc324\0\uc380\0\uc3dc\0\uc438\0\uc494\0\uc4f0\0\uc54c"+ + "\0\uc5a8\0\uc604\0\uc660\0\uc6bc\0\uc718\0\uc774\0\uc7d0\0\uc82c"+ + "\0\uc888\0\uc8e4\0\uc940\0\uc99c\0\uc9f8\0\uca54\0\ucab0\0\ucb0c"+ + "\0\ucb68\0\ucbc4\0\ucc20\0\ucc7c\0\u9e20\0\uccd8\0\ucd34\0\ucd90"+ + "\0\ucdec\0\uce48\0\ucea4\0\ucf00\0\ucf5c\0\ucfb8\0\ud014\0\ud070"+ + "\0\ud0cc\0\ud128\0\ud184\0\ud1e0\0\ud23c\0\ud298\0\ud2f4\0\ud350"+ + "\0\ud3ac\0\ud408\0\ud464\0\ud4c0\0\ud51c\0\ud578\0\ud5d4\0\ud630"+ + "\0\ud68c\0\ud6e8\0\ud744\0\ud7a0\0\ud7fc\0\ud858\0\ud8b4\0\ud910"+ + "\0\ud96c\0\ud9c8\0\uda24\0\uda80\0\udadc\0\udb38\0\udb94\0\udbf0"+ + "\0\udc4c\0\udca8\0\udd04\0\udd60\0\uddbc\0\ude18\0\ude74\0\uded0"+ + "\0\udf2c\0\udf88\0\udfe4\0\ue040\0\ue09c\0\ue0f8\0\ue154\0\ue1b0"+ + "\0\ue20c\0\ue268\0\ue2c4\0\ue320\0\ue37c\0\ue3d8\0\ue434\0\ue490"+ + "\0\ue4ec\0\ue548\0\ue5a4\0\ue600\0\ue65c\0\ue6b8\0\ue714\0\ue770"+ + "\0\ue7cc\0\ue828\0\ue884\0\ue8e0\0\ue93c\0\ue998\0\ue9f4\0\uea50"+ + "\0\ueaac\0\ueb08\0\ueb64\0\uebc0\0\uec1c\0\uec78\0\uecd4\0\ued30"+ + "\0\ued8c\0\uede8\0\uee44\0\ueea0\0\ueefc\0\uef58\0\uefb4\0\uf010"+ + "\0\uf06c\0\uf0c8\0\u66c8\0\uf124\0\uf180\0\uf1dc\0\uf238\0\uf294"+ + "\0\uf2f0\0\uf34c\0\uf3a8\0\uf404\0\uf460\0\uf4bc\0\uf518\0\uf574"+ + "\0\uf5d0\0\uf62c\0\uf688\0\uf6e4\0\uf740\0\u1c08\0\uf79c\0\uf7f8"+ + "\0\uf854\0\u0114\0\uf8b0\0\uf90c\0\uf968\0\uf9c4\0\ufa20\0\ufa7c"+ + "\0\ufad8\0\ufb34\0\ufb90\0\ufbec\0\ufc48\0\ufca4\0\ufd00\0\ufd5c"+ + "\0\ufdb8\0\ufe14\0\ufe70\0\ufecc\0\uff28\0\uff84\0\uffe0\1\74"+ + "\1\230\1\364\0\u8ce0\1\u0150\1\u01ac\1\u0208\1\u0264\1\u02c0"+ + "\1\u031c\1\u0378\1\u03d4\1\u0430\1\u048c\1\u04e8\1\u0544\1\u05a0"+ + "\1\u05fc\1\u0658\1\u06b4\1\u0710\1\u076c\1\u07c8\1\u0824\1\u0880"+ + "\1\u08dc\1\u0938\1\u0994\1\u09f0\1\u0a4c\1\u0aa8\1\u0b04\1\u0b60"+ + "\1\u0bbc\1\u0c18\0\ue37c\1\u0c74\0\ue490\1\u0cd0\1\u0d2c\1\u0d88"+ + "\1\u0de4\1\u0e40\1\u0e9c\1\u0ef8\1\u0f54\1\u0fb0\1\u100c\1\u1068"+ + "\1\u10c4\1\u1120\1\u117c\1\u11d8\1\u1234\1\u1290\1\u12ec\1\u1348"+ + "\1\u13a4\1\u1400\1\u145c\1\u14b8\1\u1514\1\u1570\1\u15cc\1\u1628"+ + "\1\u1684\1\u16e0\1\u173c\1\u1798\1\u17f4\1\u1850\1\u18ac\1\u1908"+ + "\1\u1964\1\u19c0\1\u1a1c\0\u09b4\1\u1a78\1\u1ad4\1\u1b30\1\u1b8c"+ + "\1\u1be8\1\u1c44\1\u1ca0\1\u1cfc\1\u1d58\1\u1db4\1\u1e10\1\u1e6c"+ + "\1\u1ec8\1\u1f24\1\u1f80\1\u1fdc\1\u2038\1\u2094\1\u20f0\1\u214c"+ + "\1\u21a8\1\u2204\1\u2260\1\u22bc\1\u2318\1\u2374\1\u23d0\1\u242c"+ + "\1\u2488\1\u24e4\1\u2540\1\u259c\1\u25f8\1\u2654\1\u26b0\1\u270c"+ + "\1\u2768\1\u27c4\1\u2820\1\u287c\1\u28d8\1\u2934\1\u2990\1\u29ec"+ + "\1\u2a48\1\u2aa4\0\u763c\1\u2b00\1\u2b5c\1\u2bb8\1\u2c14\1\u2c70"+ + "\1\u2ccc\1\u2d28\1\u2d84\1\u2de0\1\u2e3c\1\u2e98\1\u2ef4\0\u9f34"+ + "\1\u2f50\1\u2fac\1\u3008\1\u3064\1\u30c0\1\u311c\1\u3178\1\u31d4"+ + "\1\u3230\1\u328c\1\u32e8\1\u3344\1\u33a0\1\u33fc\1\u3458\1\u34b4"+ + "\1\u3510\1\u356c\1\u35c8\1\u3624\1\u3680\1\u36dc\1\u3738\1\u3794"+ + "\1\u37f0\1\u384c\1\u38a8\1\u3904\1\u3960\1\u39bc\1\u3a18\1\u3a74"+ + "\1\u3ad0\1\u3b2c\1\u3b88\1\u3be4\1\u3c40\1\u3c9c\1\u3cf8\1\u3d54"+ + "\1\u3db0\1\u3e0c\1\u3e68\1\u3ec4\1\u3f20\1\u3f7c\1\u3fd8\1\u4034"+ + "\1\u4090\1\u40ec\1\u4148\1\u41a4\1\u4200\1\u425c\1\u42b8\1\u4314"+ + "\1\u4370\1\u43cc\1\u4428\1\u4484\1\u44e0\1\u453c\1\u4598\1\u45f4"+ + "\1\u4650\1\u46ac\1\u4708\1\u4764\1\u47c0\1\u481c\1\u4878"; private static int [] zzUnpackRowMap() { - int [] result = new int[887]; + int [] result = new int[943]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -237,2415 +245,2584 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { return j; } - /** + /** * The transition table of the DFA */ private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\1\4\1\5\1\6\1\7\1\10\1\7\1\11\1\12"+ - "\1\13\1\14\1\15\1\16\1\17\1\20\1\21\1\22"+ - "\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+ - "\1\33\1\34\1\35\1\36\1\37\1\40\1\41\1\42"+ - "\1\43\1\7\1\6\1\44\1\45\1\46\1\47\1\50"+ - "\1\51\1\33\1\52\1\53\1\54\1\55\1\56\1\57"+ - "\2\4\1\34\1\60\1\41\1\33\1\61\1\62\1\41"+ - "\1\63\1\64\1\65\1\66\1\67\1\70\1\71\1\7"+ - "\1\72\1\73\1\74\1\75\1\76\1\77\1\100\1\101"+ - "\1\102\1\103\1\104\1\105\1\106\2\6\2\7\3\6"+ - "\1\107\2\7\1\34\1\41\1\110\1\111\12\112\1\113"+ - "\30\112\1\114\5\112\1\115\14\112\1\116\2\112\1\117"+ - "\42\112\12\120\1\121\30\120\1\122\22\120\1\123\2\120"+ - "\1\124\42\120\7\4\1\0\17\4\11\0\3\4\2\0"+ - "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ - "\2\4\1\0\37\4\4\0\1\4\6\6\1\0\10\6"+ - "\1\125\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\3\126\1\7\1\126\1\7\1\127\1\0"+ - "\1\126\1\127\3\126\1\130\4\126\1\131\4\126\11\0"+ - "\1\126\1\7\1\126\2\0\2\126\1\7\2\0\1\131"+ - "\1\130\1\132\1\126\1\0\3\126\4\0\2\126\1\0"+ - "\7\126\1\7\17\126\2\7\4\126\2\7\4\0\1\4"+ - "\5\6\1\133\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\134\35\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\135\2\6\1\136"+ - "\12\6\1\137\5\6\13\0\1\41\20\0\1\41\103\0"+ - "\1\4\6\6\1\0\1\6\1\140\12\6\1\141\2\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\4\6\1\142\12\6"+ - "\11\0\1\4\1\6\1\143\2\0\1\144\2\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ - "\1\145\1\6\1\146\2\6\1\147\3\6\1\150\2\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\2\6\1\151\1\6"+ - "\1\152\1\6\1\153\10\6\11\0\1\4\1\154\1\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\10\6\1\155\1\6\1\156\4\6\11\0"+ - "\1\4\2\6\2\0\1\157\2\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\160\2\6"+ - "\1\151\3\6\1\161\1\6\1\162\1\6\1\163\2\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\164\1\6"+ - "\1\165\1\6\1\166\2\6\1\167\1\6\1\170\1\171"+ - "\3\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\172\1\0\1\173\22\6\1\174\13\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\175\1\6\1\176\4\6\1\177"+ - "\3\6\1\200\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\201\6\6\1\151\7\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\202\1\6\1\203\1\204\1\205\1\6"+ - "\1\206\1\207\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\1\210\1\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\4\6\1\211\5\6\1\212\1\213\3\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\3\6\1\151\3\6\1\214"+ - "\1\215\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\216"+ - "\3\6\1\201\1\6\1\217\1\220\1\6\1\221\5\6"+ - "\11\0\1\4\2\6\2\0\1\222\1\223\1\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\1\6\1\224\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\6\1\225\5\6\1\226\7\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\227\1\6\1\230\4\6\1\231"+ - "\3\6\1\232\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\33\0\1\233\134\0\1\41"+ - "\267\0\1\41\1\0\1\234\16\0\1\235\62\0\27\236"+ - "\1\237\3\236\1\240\4\236\1\241\2\236\1\0\70\236"+ - "\34\0\1\33\134\0\1\33\126\0\1\41\6\0\1\41"+ - "\74\0\40\45\1\242\2\45\1\243\1\244\67\45\1\4"+ - "\6\6\1\0\14\6\1\245\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\3\6\1\246\13\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\3\126"+ - "\1\7\1\126\1\7\1\127\1\0\1\126\1\127\3\126"+ - "\1\130\4\126\1\131\4\126\11\0\1\126\1\7\1\247"+ - "\2\0\2\126\1\7\2\0\1\131\1\130\1\132\1\126"+ - "\1\0\3\126\4\0\2\126\1\0\7\126\1\7\17\126"+ - "\2\7\1\247\3\126\2\7\54\0\1\51\63\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\1\250\1\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\251\4\6\1\252"+ - "\16\6\4\0\1\4\5\6\1\253\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\1\254\1\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\1\6\1\255\3\6\1\256\5\6\1\151\23\6\7\0"+ - "\1\132\1\0\1\132\33\0\1\132\5\0\1\132\30\0"+ - "\1\132\17\0\2\132\4\0\2\132\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\6\1\257\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\1\6\1\260\3\6\1\261\6\6"+ - "\1\262\22\6\4\0\7\4\1\0\1\263\1\264\1\4"+ - "\1\265\1\4\1\266\4\4\1\267\1\270\3\4\11\0"+ - "\3\4\2\0\3\4\1\271\1\0\2\4\1\0\1\4"+ - "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\1\4"+ - "\6\6\1\0\3\6\1\272\4\6\1\273\6\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\3\6\1\274\3\6\1\275"+ - "\1\276\3\6\1\277\2\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\300\15\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\3\6"+ - "\1\301\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\2\6\1\302\1\303\1\304"+ - "\3\6\1\305\2\6\1\306\1\6\1\307\1\310\20\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\14\6\1\311\22\6"+ - "\4\0\1\4\5\6\1\312\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\1\313\1\314\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ - "\1\315\6\6\1\316\1\317\2\6\1\320\1\6\1\321"+ - "\1\6\1\322\12\6\4\0\1\4\5\6\1\323\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ - "\1\324\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\5\6\1\325\1\326\1\6\1\327\2\6"+ - "\1\330\1\331\22\6\4\0\1\4\3\6\1\306\2\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\151\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\5\6\1\332\6\6\1\333\22\6\4\0"+ - "\1\4\5\6\1\334\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\335\3\6"+ - "\1\336\6\6\1\337\22\6\4\0\1\4\5\6\1\340"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ - "\1\341\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\1\342\1\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\5\6\1\343\10\6\1\344\20\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\1\345\1\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\151\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\3\6\1\346\7\6\1\347"+ - "\23\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\350"+ - "\3\6\1\351\2\6\1\352\3\6\1\353\22\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\354\35\6\4\0"+ - "\1\4\5\6\1\355\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\10\6\1\356\26\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\5\6\1\357\2\6"+ - "\1\360\3\6\1\151\22\6\4\0\1\4\5\6\1\361"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\6\1\362\3\6\1\363\6\6\1\364"+ - "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\1\365\1\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\12\6\1\366\4\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\5\6\1\367\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\5\6\1\370\31\6\136\0"+ - "\1\41\134\0\1\41\12\112\1\0\30\112\1\0\5\112"+ - "\1\0\14\112\1\0\2\112\1\0\42\112\13\0\1\371"+ - "\53\0\1\372\76\0\1\373\170\0\1\374\135\0\1\375"+ - "\42\0\12\120\1\0\30\120\1\0\22\120\1\0\2\120"+ - "\1\0\42\120\13\0\1\376\53\0\1\377\133\0\1\u0100"+ - "\135\0\1\u0101\42\0\1\4\6\6\1\0\3\6\1\u0102"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\7\126\1\0\17\126\11\0\3\126"+ - "\2\0\3\126\2\0\2\126\1\0\1\126\1\0\3\126"+ - "\4\0\2\126\1\0\37\126\4\0\3\126\1\u0103\1\126"+ - "\1\u0103\1\126\1\u0104\17\126\10\0\1\u0104\1\126\1\u0103"+ - "\1\126\2\0\2\126\1\u0103\2\0\2\126\1\0\1\126"+ - "\1\0\3\126\4\0\2\126\1\0\7\126\1\u0103\17\126"+ - "\2\u0103\4\126\2\u0103\4\0\7\126\1\0\12\126\1\u0105"+ - "\4\126\11\0\3\126\2\0\3\126\2\0\1\u0105\1\126"+ - "\1\0\1\126\1\0\3\126\4\0\2\126\1\0\37\126"+ - "\4\0\7\126\1\0\5\126\1\u0105\11\126\11\0\3\126"+ - "\2\0\3\126\2\0\1\126\1\u0105\1\0\1\126\1\0"+ - "\3\126\4\0\2\126\1\0\37\126\4\0\3\126\1\132"+ - "\1\126\1\132\1\u0106\1\0\1\126\1\u0106\1\u0107\2\126"+ - "\1\u0107\11\126\11\0\1\126\1\132\1\126\2\0\2\126"+ - "\1\132\2\0\1\126\1\u0107\1\0\1\u0107\1\0\3\126"+ - "\4\0\2\126\1\0\7\126\1\132\17\126\2\132\4\126"+ - "\2\132\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\4\6\1\u0108"+ - "\12\6\1\u0109\17\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\11\6\1\u010a\3\6\1\u010b\21\6\4\0\1\4\3\6"+ - "\1\u010c\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\4\6\1\u010d\6\6\1\u010e"+ - "\5\6\1\u010f\15\6\4\0\1\4\5\6\1\u0110\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\1\6\1\344\35\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\1\6\1\260\16\6\1\151\16\6\4\0\1\4"+ - "\6\6\1\0\11\6\1\u0111\3\6\1\u0112\1\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\u0113\1\0\12\6\1\u0114"+ - "\24\6\4\0\1\4\6\6\1\0\1\u0115\3\6\1\u0116"+ - "\4\6\1\u0117\4\6\1\u0118\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\13\6\1\151\1\150\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u0119\12\6\1\157\2\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\6\1\u011a\2\6\1\201"+ - "\1\u011b\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\10\6"+ - "\1\u011c\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\7\6"+ - "\1\u011d\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\11\6"+ - "\1\u011e\5\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u011f"+ - "\13\6\1\u0120\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\1\6\1\151\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\4\6\1\u0121\12\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\35\6\1\u0119\1\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\151\36\6\4\0\1\4\6\6\1\0"+ - "\16\6\1\u0122\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\5\6"+ - "\1\151\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\2\6"+ - "\1\u011e\1\6\1\151\12\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\1\6\1\151\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\15\6\1\u0123\1\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\u0124\36\6\4\0"+ - "\1\4\6\6\1\0\4\6\1\210\12\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\12\6\1\u0125\24\6\4\0"+ - "\1\4\6\6\1\0\11\6\1\u0126\5\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\23\6\1\151"+ - "\13\6\4\0\1\4\6\6\1\0\4\6\1\u0127\10\6"+ - "\1\u0119\1\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ - "\1\u0128\13\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\7\6"+ - "\1\u0129\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\16\6"+ - "\1\u012a\11\0\1\4\2\6\2\0\1\6\1\u012b\1\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\5\6\1\u012c\11\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\u012d\13\6\1\u012e\2\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\3\6\1\u012f\13\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\5\6\1\151\1\6\1\u011e\7\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\11\6\1\u0130\1\6\1\u0131\1\6"+ - "\1\u0132\1\u0133\11\0\1\4\2\6\2\0\1\u0134\2\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\15\6\1\u0135\1\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\12\6\1\u0136\4\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\1\u0137\36\6\4\0\1\4\6\6"+ - "\1\0\1\u0138\3\6\1\u0139\12\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\151\16\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\3\6\1\u013a\13\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\7\6\1\u013b\7\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\16\6\1\u0118\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\14\6\1\u013c\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\10\6\1\u013d\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\u013e\3\6\1\u013f\1\u0140\1\u0127\1\u0141\2\6\1\u0142"+ - "\3\6\1\u0143\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ - "\1\u0144\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ - "\1\u0145\13\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ - "\1\201\13\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\13\6"+ - "\1\u0124\3\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\10\6"+ - "\1\u0146\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\1\u0124\36\6\4\0\1\4\6\6\1\0\1\u0147\16\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\3\6\1\u0148\13\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\7\6\1\u0149\7\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\10\6\1\u014a\6\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\u014b\15\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\6\6\1\151\10\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\14\6\1\u014c\2\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\1\6\1\u014d\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\6\1\u014e\15\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\u014f\16\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\1\151\3\6\1\u0150\12\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\151\3\6\1\u0151\11\6"+ - "\1\151\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\13\6\1\u0152"+ - "\3\6\11\0\1\4\1\6\1\151\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\34\0\10\41\74\0\33\u0153\1\u0154"+ - "\7\u0153\1\0\117\u0153\1\u0155\3\u0153\1\u0154\7\u0153\1\0"+ - "\75\u0153\1\u0156\4\u0153\1\236\1\u0153\1\236\2\u0153\1\236"+ - "\4\u0153\1\236\2\u0153\1\236\3\u0153\1\u0157\4\u0153\1\236"+ - "\1\u0158\1\u0159\1\0\3\236\1\u0158\17\u0153\1\236\10\u0153"+ - "\1\u0158\17\u0153\1\u0158\1\u0156\1\u0159\4\u0153\1\u0156\4\u0153"+ - "\5\243\1\45\4\243\1\45\1\243\1\45\2\243\1\45"+ - "\4\243\1\45\2\243\1\45\3\243\1\45\4\243\2\45"+ - "\1\u015a\1\0\4\45\17\243\1\45\10\243\1\45\17\243"+ - "\2\45\1\u015a\4\243\1\45\44\243\1\u015b\3\243\1\u015c"+ - "\67\243\1\4\6\6\1\0\5\6\1\u015d\11\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\u015e\1\0\37\6\4\0"+ - "\3\126\4\u015f\1\0\3\u015f\6\126\1\u015f\2\126\1\u015f"+ - "\2\126\11\0\1\126\1\u015f\1\126\2\0\1\126\2\u015f"+ - "\2\0\2\126\1\0\1\u015f\1\0\3\126\4\0\2\126"+ - "\1\0\1\126\2\u015f\1\126\1\u015f\2\126\1\u015f\17\126"+ - "\2\u015f\4\126\2\u015f\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\14\6\1\306\22\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\14\6\1\u0160\22\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\20\6\1\u0161\16\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\u0162\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\13\6\1\151\1\6\1\151\21\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\13\6\1\326\23\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\11\6\1\u0163\25\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\17\6\1\u0123\4\6\1\u0161\12\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\5\6\1\u0164\31\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\4\6\1\u0162\32\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\10\6\1\u0165\26\6\4\0"+ - "\1\4\5\6\1\u0166\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\1\6\1\u0167\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\13\6\1\306"+ - "\23\6\4\0\7\4\1\0\1\4\1\u0168\15\4\11\0"+ - "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ - "\3\4\4\0\2\4\1\0\37\4\4\0\7\4\1\0"+ - "\4\4\1\u0169\1\u016a\1\4\1\u016b\7\4\11\0\3\4"+ - "\2\0\3\4\2\0\2\4\1\0\1\4\1\0\3\4"+ - "\4\0\2\4\1\0\37\4\4\0\7\4\1\0\2\4"+ - "\1\u016c\1\4\1\u016d\12\4\11\0\3\4\2\0\3\4"+ - "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ - "\1\0\37\4\4\0\7\4\1\0\3\4\1\u016e\13\4"+ - "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ - "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ - "\1\0\4\4\1\u016f\12\4\11\0\3\4\2\0\3\4"+ - "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ - "\1\0\37\4\4\0\7\4\1\0\7\4\1\u0170\7\4"+ - "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ - "\1\0\3\4\4\0\2\4\1\0\37\4\14\0\1\u0171"+ - "\1\u0172\1\0\1\u0173\1\0\1\u0174\4\0\1\u0175\1\u0176"+ - "\24\0\1\271\63\0\1\4\6\6\1\0\1\6\1\u0177"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\u0144"+ - "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\16\6\1\u013e"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\u0178\1\6"+ - "\1\u0179\6\6\1\u017a\4\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\u017b\2\6\1\u017c\4\6\1\u017d\6\6\11\0"+ - "\1\4\2\6\2\0\1\6\1\u017e\1\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\u017f"+ - "\1\6\1\0\37\6\4\0\1\4\6\6\1\0\4\6"+ - "\1\u0127\12\6\11\0\1\4\2\6\2\0\1\6\1\u0180"+ - "\1\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\u0181\1\6\1\u0182\13\6\11\0\1\4"+ - "\2\6\2\0\1\6\1\u0183\1\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\3\6\1\u0184\2\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\3\6\1\151"+ - "\33\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u0185"+ - "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\5\6\1\u0186"+ - "\31\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\10\6\1\u0187"+ - "\26\6\4\0\1\4\3\6\1\151\2\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\u0188"+ - "\35\6\4\0\1\4\5\6\1\u0189\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\15\6\1\u018a\21\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\4\6\1\u018b\15\6"+ - "\1\151\14\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\2\6"+ - "\1\u018c\16\6\1\u018d\15\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\14\6\1\u018e\22\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\10\6\1\u018f\26\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\13\6\1\u0190\3\6\1\u0110\17\6\4\0\1\4"+ - "\3\6\1\u0191\2\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\u0192\35\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\1\6\1\u0193\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\1\6\1\151\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\10\6\1\u0162\26\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\14\6\1\u0194\22\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\14\6\1\u0195\22\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\u0196\35\6"+ - "\4\0\1\4\3\6\1\u0197\2\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\1\u0198\1\u0199\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\3\6\1\u0190\4\6\1\u019a\2\6\1\u019b\5\6\1\u019c"+ - "\15\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\u019d"+ - "\35\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\5\6\1\u019e"+ - "\31\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\21\6\1\u010f"+ - "\15\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\10\6\1\u019f"+ - "\26\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\1\u019d\1\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\5\6\1\u01a0\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\4\6\1\u01a1\11\6\1\u01a2"+ - "\1\u01a3\1\u01a4\1\u01a5\15\6\4\0\1\4\3\6\1\u01a6"+ - "\2\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\13\6\1\u01a7\23\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\1\u01a8\1\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\24\6\1\u01a9\12\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\17\6\1\u01aa\17\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\u01ab\35\6\4\0"+ - "\1\4\6\6\1\0\14\6\1\u01ac\2\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\21\6\1\u01ad\15\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\24\6\1\151\12\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\1\6\1\151\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\35\6\1\u0110\1\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\13\6\1\u01ae\23\6\4\0\1\4"+ - "\3\6\1\u01af\2\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\u01b0\13\6"+ - "\1\151\21\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\2\6"+ - "\1\u01b1\10\6\1\u0190\23\6\4\0\1\4\3\6\1\u01b2"+ - "\2\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\2\6\1\u01b3\2\6\1\u01b4\1\u01b5"+ - "\5\6\1\u01b6\22\6\4\0\1\4\5\6\1\u01b7\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\u01b8"+ - "\1\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\14\6\1\u01b9\22\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\21\6\1\u0197\15\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\6\1\u01ba\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\15\6\1\u01bb\21\6\4\0\1\4\5\6\1\u01bc"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\24\6\1\u0161\12\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\5\6\1\u01bd\31\6\4\0\1\4\3\6\1\u01be\2\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\20\6\1\u01bf\10\6\1\151\5\6\4\0\1\4\3\6"+ - "\1\151\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\u01c0\5\6\1\151"+ - "\15\6\4\0\1\4\3\6\1\151\2\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\13\6\1\u01c1\23\6\4\0\1\4\5\6\1\u01c2\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u01c3"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\5\6\1\u01c4\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\2\6\1\u01c5\11\6\1\u01c6\22\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\14\6\1\u01c7\22\6\21\0\1\u01c8\141\0"+ - "\1\u01c9\177\0\1\u01ca\135\0\1\u01cb\57\0\1\u01cc\141\0"+ - "\1\u01cd\177\0\1\u01ce\135\0\1\u01cf\42\0\1\4\6\6"+ - "\1\0\4\6\1\u01d0\12\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\3\126\1\u0103"+ - "\1\126\1\u0103\1\126\1\0\5\126\1\130\4\126\1\131"+ - "\4\126\11\0\1\126\1\u0103\1\126\2\0\2\126\1\u0103"+ - "\2\0\1\131\1\130\1\0\1\126\1\0\3\126\4\0"+ - "\2\126\1\0\7\126\1\u0103\17\126\2\u0103\4\126\2\u0103"+ - "\7\0\1\u0103\1\0\1\u0103\33\0\1\u0103\5\0\1\u0103"+ - "\30\0\1\u0103\17\0\2\u0103\4\0\2\u0103\4\0\3\126"+ - "\1\u01d1\1\126\1\u01d1\1\126\1\u01d2\17\126\10\0\1\u01d2"+ - "\1\126\1\u01d1\1\126\2\0\2\126\1\u01d1\2\0\2\126"+ - "\1\0\1\126\1\0\3\126\4\0\2\126\1\0\7\126"+ - "\1\u01d1\17\126\2\u01d1\4\126\2\u01d1\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\5\6\1\u01d3\6\6\1\u01d4\22\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\10\6\1\u01d5\26\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\3\6\1\u01d6\12\6\1\100"+ - "\20\6\4\0\1\4\5\6\1\u01d7\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\24\6\1\u01d8\12\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\5\6\1\u01d3\31\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\1\u01d9\1\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\5\6\1\u01da\31\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\151\23\6\4\0"+ - "\1\4\6\6\1\0\3\6\1\u01db\4\6\1\u01dc\6\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\7\6\1\u01dd\7\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\u01de\15\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\6\6\1\u01df\10\6"+ - "\11\0\1\4\2\6\2\0\1\46\2\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\u01e0"+ - "\36\6\4\0\1\4\6\6\1\0\12\6\1\u01e1\4\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\10\6\1\u01dc\6\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\10\6\1\u01e2\6\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\4\6\1\151\12\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\5\6\1\u01e3\11\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\u01e4\15\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\10\6\1\u0144\6\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\16\6\1\u01e5\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\151\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\1\6\1\u01e6\15\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\7\6\1\220\7\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\12\6\1\u01e7\4\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\1\6\1\u01e8\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\1\u01e9\1\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\u0144\15\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\u01ea\15\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\10\6\1\u01eb\6\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\1\151\1\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\11\6\1\u01ec\5\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u0152\1\0\37\6\4\0\1\4\6\6\1\0\6\6"+ - "\1\u01ed\4\6\1\u01ee\3\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\6\6\1\u01ef\10\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\3\6\1\u011e\13\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\u01f0\15\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\7\6\1\u01f1\7\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\1\6\1\u01f2\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\10\6\1\u01f3\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\6\1\u01e5\3\6\1\u01f4\11\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u01f5\15\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\10\6\1\u01f6\6\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u01f7\15\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\1\u011e\1\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\4\6\1\u01f8\12\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\11\6\1\u01f9\5\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\3\6\1\u01fa\13\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\u01fb\14\6\1\u013e\1\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\26\6\1\151\10\6"+ - "\4\0\1\4\6\6\1\0\5\6\1\u01fc\11\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\11\6\1\u01fd\5\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\6\6\1\223\10\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\6\6\1\u01fe\10\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\6\1\151\15\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\11\6\1\u01ff\5\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\4\6\1\u0200\4\6\1\u01f9"+ - "\5\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\u0201"+ - "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u011e"+ - "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\1\6\1\u0202\1\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\151"+ - "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\23\6"+ - "\1\u0203\13\6\4\0\1\4\6\6\1\0\1\u0204\12\6"+ - "\1\u0205\2\6\1\u0206\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\7\6\1\u01d0\27\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u0127\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\14\6\1\u0207\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\6\6\1\u0127\10\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\7\6\1\u0208\7\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u0209\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\12\6\1\u020a\4\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\13\6\1\u01d0\3\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\3\6\1\u020b\13\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\12\6\1\u020c\4\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u020d\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ - "\1\u0120\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\33\u0153\1\240\7\u0153\1\0"+ - "\120\u0153\3\236\1\u0157\4\236\3\u0153\1\0\75\u0153\1\236"+ - "\25\u0153\1\u0154\5\u0153\1\236\1\u0153\1\0\3\u0153\1\236"+ - "\30\u0153\1\236\17\u0153\2\236\5\u0153\1\236\4\u0153\33\0"+ - "\1\u0154\100\0\5\u0153\1\u0156\25\u0153\1\u0154\5\u0153\1\u0156"+ - "\1\u0153\1\0\3\u0153\1\u0156\30\u0153\1\u0156\17\u0153\2\u0156"+ - "\5\u0153\1\u0156\7\u0153\4\u020e\1\u0153\3\u020e\6\u0153\1\u020e"+ - "\2\u0153\1\u020e\6\u0153\1\240\5\u0153\1\u020e\1\u0153\1\0"+ - "\2\u0153\2\u020e\5\u0153\1\u020e\14\u0153\2\u020e\1\u0153\1\u020e"+ - "\2\u0153\1\u020e\17\u0153\2\u020e\4\u0153\2\u020e\4\u0153\3\243"+ - "\4\u020f\1\243\3\u020f\6\243\1\u020f\2\243\1\u020f\13\243"+ - "\1\u015b\1\u020f\2\243\1\u015c\1\243\2\u020f\5\243\1\u020f"+ - "\14\243\2\u020f\1\243\1\u020f\2\243\1\u020f\17\243\2\u020f"+ - "\4\243\2\u020f\47\243\1\0\70\243\1\4\6\6\1\0"+ - "\12\6\1\u013e\4\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u0210\3\6\1\u0211\6\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\3\126"+ - "\4\u015f\1\0\3\u015f\2\126\1\u0212\3\126\1\u015f\1\u0213"+ - "\1\126\1\u015f\2\126\11\0\1\126\1\u015f\1\126\2\0"+ - "\1\126\2\u015f\2\0\1\u0213\1\u0212\1\0\1\u015f\1\0"+ - "\3\126\4\0\2\126\1\0\1\126\2\u015f\1\126\1\u015f"+ - "\2\126\1\u015f\17\126\2\u015f\4\126\2\u015f\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\22\6\1\u0214\14\6\4\0\1\4"+ - "\5\6\1\u019d\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\15\6\1\151\21\6\4\0\1\4\5\6"+ - "\1\u0215\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\5\6\1\u019d\31\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\21\6\1\u0216\15\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ - "\1\u0217\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\5\6\1\u0218\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\7\4\1\0\2\4\1\266\14\4"+ - "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ - "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ - "\1\0\1\u0219\16\4\11\0\3\4\2\0\3\4\2\0"+ - "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ - "\37\4\4\0\7\4\1\0\3\4\1\u021a\2\4\1\u021b"+ - "\10\4\11\0\3\4\2\0\3\4\2\0\2\4\1\0"+ - "\1\4\1\0\3\4\4\0\2\4\1\0\37\4\4\0"+ - "\7\4\1\0\7\4\1\u021c\7\4\11\0\3\4\2\0"+ - "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ - "\2\4\1\0\37\4\4\0\7\4\1\0\1\u021d\3\4"+ - "\1\u016f\12\4\11\0\3\4\2\0\3\4\2\0\2\4"+ - "\1\0\1\4\1\0\3\4\4\0\2\4\1\0\37\4"+ - "\4\0\7\4\1\0\11\4\1\u021e\5\4\11\0\3\4"+ - "\2\0\3\4\2\0\2\4\1\0\1\4\1\0\3\4"+ - "\4\0\2\4\1\0\37\4\4\0\7\4\1\0\4\4"+ - "\1\u021b\12\4\11\0\3\4\2\0\3\4\2\0\2\4"+ - "\1\0\1\4\1\0\3\4\4\0\2\4\1\0\37\4"+ - "\4\0\7\4\1\0\1\u021d\16\4\11\0\3\4\2\0"+ - "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ - "\2\4\1\0\37\4\4\0\7\4\1\0\14\4\1\u021f"+ - "\2\4\11\0\3\4\2\0\3\4\2\0\2\4\1\0"+ - "\1\4\1\0\3\4\4\0\2\4\1\0\37\4\15\0"+ - "\1\u0220\136\0\1\u0221\1\u0222\1\0\1\u0223\126\0\1\u0224"+ - "\1\0\1\u0225\132\0\1\u0226\134\0\1\u0227\136\0\1\u0228"+ - "\114\0\1\4\6\6\1\0\7\6\1\u0229\7\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\6\1\u022a\15\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\16\6\1\151\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\4\6\1\u022b\12\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\10\6\1\u022c\3\6\1\u022d\2\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\4\6\1\u022e\11\6"+ - "\1\u0208\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\11\6\1\u022f"+ - "\5\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0230"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u0231"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\5\6\1\u0232"+ - "\11\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\26\6"+ - "\1\u0233\10\6\4\0\1\4\6\6\1\0\15\6\1\u0234"+ - "\1\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0235"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\7\6"+ - "\1\u0236\27\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\13\6"+ - "\1\u0190\23\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ - "\1\u0190\33\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\6"+ - "\1\u0237\35\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\13\6"+ - "\1\u0238\23\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\10\6"+ - "\1\u0239\26\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ - "\1\u023a\5\6\1\u023b\23\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\5\6\1\u023c\31\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\3\6\1\u023d\33\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\3\6\1\u023e\14\6\1\u023f\16\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\4\6\1\u0240\32\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\15\6\1\u01bf\21\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\6\6\1\151\30\6\4\0\1\4"+ - "\5\6\1\u0241\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\u0242\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\14\6\1\u0162\22\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\15\6\1\u0243\21\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\6\1\u0244\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\3\6\1\302\33\6\4\0\1\4\5\6\1\151"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\13\6\1\u0162\23\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\4\6\1\u0245\6\6\1\u0246\23\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\u0247\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\4\6\1\u0248\32\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\2\6\1\u0249\34\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\151\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\3\6\1\u024a\33\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\4\6\1\u024b\32\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\u024c\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\5\6\1\u024d\31\6\4\0\1\4\5\6"+ - "\1\u024e\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\5\6\1\u024f"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\5\6\1\u0216\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ - "\1\u0250\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\5\6\1\u0251\31\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\14\6\1\u0252\22\6\4\0\1\4\3\6\1\u0253\2\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\17\6\1\u0197\5\6\1\151\11\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\u0254\23\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\4\6\1\u0245\32\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\6\6\1\u0162\30\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\10\6\1\u0255\26\6\4\0"+ - "\1\4\6\6\1\0\7\6\1\u0256\7\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\15\6\1\u0257\21\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\1\u0258\1\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\5\6\1\u0259\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\305\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\6\1\u025a\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\1\6\1\u025b\3\6\1\u025c\31\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\14\6\1\u025d\22\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\4\6\1\u025e\32\6\4\0\1\4"+ - "\5\6\1\u025f\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\13\6\1\u0260\5\6\1\u0239\15\6\4\0"+ - "\1\4\5\6\1\u0261\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\13\6\1\u0262\23\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\21\6\1\151\15\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\1\u0197\1\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\u0263\1\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\20\6\1\u0236\16\6\4\0\1\4\3\6\1\u0264"+ - "\2\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\20\6\1\u0265\1\u0266\15\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\14\6\1\u0267\22\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\u01b0\35\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\15\6\1\u0268\21\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\1\u0269\1\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\10\6\1\u0237\26\6\4\0\1\4"+ - "\6\6\1\0\7\6\1\u0207\7\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\25\6\1\u026a\11\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\14\6\1\u026b\22\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\17\6\1\u026c\17\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\13\6\1\u0236\23\6\15\0\1\u01c9"+ - "\212\0\1\u026d\66\0\1\u026e\164\0\1\u026f\70\0\1\u01cd"+ - "\212\0\1\u0270\66\0\1\u0271\164\0\1\u0272\57\0\3\126"+ - "\1\u01d1\1\126\1\u01d1\1\126\1\0\2\126\1\u0107\2\126"+ - "\1\u0107\11\126\11\0\1\126\1\u01d1\1\126\2\0\2\126"+ - "\1\u01d1\2\0\1\126\1\u0107\1\0\1\u0107\1\0\3\126"+ - "\4\0\2\126\1\0\7\126\1\u01d1\17\126\2\u01d1\4\126"+ - "\2\u01d1\7\0\1\u01d1\1\0\1\u01d1\33\0\1\u01d1\5\0"+ - "\1\u01d1\30\0\1\u01d1\17\0\2\u01d1\4\0\2\u01d1\4\0"+ - "\1\4\3\6\1\u0197\2\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\21\6\1\u0273\15\6\4\0"+ - "\1\4\5\6\1\u0274\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\5\6\1\u0275\21\6\1\u0276\7\6"+ - "\4\0\1\4\3\6\1\u0277\2\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ - "\1\u0278\10\6\1\u0279\1\u027a\21\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\14\6\1\u027b\22\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\21\6\1\u027c\15\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\13\6\1\u027d\23\6\4\0\1\4\6\6"+ - "\1\0\16\6\1\u027e\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\u013e\16\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ - "\1\u027f\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u0280"+ - "\2\6\1\u0281\2\6\1\u0282\10\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\u0283\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\10\6\1\u0284\6\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\27\6\1\u0276"+ - "\7\6\4\0\1\4\6\6\1\0\3\6\1\u0285\13\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\16\6\1\u0286\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\4\6\1\u0287\12\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\223\16\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\4\6\1\u0200\1\6\1\u0288\10\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u0289"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u011e"+ - "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\1\6\1\u028a\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\5\6\1\157\11\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\10\6\1\151\6\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\2\6\1\151\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\7\6\1\u028b\7\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\4\6\1\201\12\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\1\6\1\u01d0\15\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\23\6\1\151\13\6"+ - "\4\0\1\4\6\6\1\0\7\6\1\u028c\7\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\u028d\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\1\151\2\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\1\6\1\u0115\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\11\6\1\u028e\5\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\7\6\1\u01e3\7\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\14\6\1\u028f\2\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\1\6\1\u0290\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\1\u01ec\2\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\7\6"+ - "\1\u0291\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u0292"+ - "\16\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\10\6\1\u0293"+ - "\6\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0294"+ - "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\1\6\1\u0295\1\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0296"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\u0297"+ - "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\6\6\1\u0298"+ - "\10\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0299"+ - "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\274"+ - "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\157"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0119"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\u01ec"+ - "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\150"+ - "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u0144"+ - "\6\6\1\u029a\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\10\6\1\u029b\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\12\6\1\151\24\6\4\0\1\4\6\6\1\0"+ - "\14\6\1\u029c\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\151"+ - "\1\6\1\0\7\6\1\151\27\6\4\0\1\4\6\6"+ - "\1\0\6\6\1\u029d\10\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\14\6\1\u0119\2\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\1\6\1\u013e\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\u0256"+ - "\1\6\1\0\37\6\4\0\3\u0153\4\236\1\u0153\3\236"+ - "\6\u0153\1\236\2\u0153\1\236\6\u0153\1\240\5\u0153\1\236"+ - "\1\u0153\1\0\2\u0153\2\236\5\u0153\1\236\14\u0153\2\236"+ - "\1\u0153\1\236\2\u0153\1\236\17\u0153\2\236\4\u0153\2\236"+ - "\4\u0153\3\243\4\45\1\243\3\45\6\243\1\45\2\243"+ - "\1\45\13\243\1\u015b\1\45\2\243\1\u015c\1\243\2\45"+ - "\5\243\1\45\14\243\2\45\1\243\1\45\2\243\1\45"+ - "\17\243\2\45\4\243\2\45\4\243\1\4\6\6\1\0"+ - "\10\6\1\u011e\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\13\6\1\u029e\3\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\7\126\1\0\12\126"+ - "\1\u029f\4\126\11\0\3\126\2\0\3\126\2\0\1\u029f"+ - "\1\126\1\0\1\126\1\0\3\126\4\0\2\126\1\0"+ - "\37\126\4\0\7\126\1\0\5\126\1\u029f\11\126\11\0"+ - "\3\126\2\0\3\126\2\0\1\126\1\u029f\1\0\1\126"+ - "\1\0\3\126\4\0\2\126\1\0\37\126\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\1\u0240\1\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\10\6\1\u02a0\26\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\6\1\u0162\35\6\4\0\1\4\3\6"+ - "\1\302\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\3\6\1\u02a1\7\6\1\u0246\1\6\1\u02a2"+ - "\21\6\4\0\7\4\1\0\3\4\1\u021a\13\4\11\0"+ - "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ - "\3\4\4\0\2\4\1\0\37\4\4\0\7\4\1\0"+ - "\2\4\1\u02a3\14\4\11\0\3\4\2\0\3\4\2\0"+ - "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ - "\37\4\4\0\7\4\1\0\1\4\1\u02a3\15\4\11\0"+ - "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ - "\3\4\4\0\2\4\1\0\37\4\4\0\7\4\1\0"+ - "\10\4\1\u02a4\6\4\11\0\3\4\2\0\3\4\2\0"+ - "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ - "\37\4\4\0\7\4\1\0\1\4\1\u021a\15\4\11\0"+ - "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ - "\3\4\4\0\2\4\1\0\37\4\4\0\7\4\1\0"+ - "\5\4\1\u02a5\11\4\11\0\3\4\2\0\3\4\2\0"+ - "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ - "\37\4\4\0\7\4\1\0\15\4\1\u02a6\1\4\11\0"+ - "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ - "\3\4\4\0\2\4\1\0\37\4\16\0\1\u0174\131\0"+ - "\1\u02a7\136\0\1\u02a8\2\0\1\u02a9\134\0\1\u02aa\124\0"+ - "\1\u02ab\3\0\1\u0227\140\0\1\u02ac\126\0\1\u02a9\127\0"+ - "\1\u02ab\147\0\1\u02ad\107\0\1\4\6\6\1\0\14\6"+ - "\1\u02ae\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\5\6"+ - "\1\u02af\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\11\6"+ - "\1\151\5\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\12\6"+ - "\1\u02b0\4\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u013e"+ - "\1\0\12\6\1\151\24\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u02b1\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u027e"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u02b2"+ - "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\1\6\1\151\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\u02b3\15\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\u02b4\16\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\u02b5\1\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\16\6\1\u0208\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\11\6\1\151\25\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\6\6\2\151\27\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\1\6\1\u02b6\35\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\20\6\1\u02b7\16\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\5\6\1\u0162\31\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\13\6\1\306\23\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\15\6\1\u02b8\21\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\22\6\1\151\14\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\10\6\1\u02b9\26\6\4\0\1\4"+ - "\5\6\1\u0236\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\16\6\1\151\20\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\15\6\1\u010c\21\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\4\6\1\u02ba\32\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\14\6\1\u02bb\22\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\5\6\1\u02bc\31\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\6\1\353\35\6\4\0\1\4\5\6"+ - "\1\344\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\1\6\1\u02bd\35\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\14\6\1\u0110\22\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\3\6\1\u02be\33\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\u02bf"+ - "\1\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\1\6\1\u02c0\35\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\10\6\1\u0217\26\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\10\6\1\u02c1\26\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\31\6\1\u02c2\5\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\1\6\1\u02c3\35\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\16\6\1\u0240\20\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\1\6\1\u02c4\35\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\2\6\1\u02c5\34\6\4\0\1\4\3\6\1\u02c6\2\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\3\6\1\u02c7\2\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u02c8"+ - "\16\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ - "\1\151\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\1\6\1\344\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\31\6\1\u02c9"+ - "\5\6\4\0\1\4\5\6\1\u02ca\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\11\6\1\151\3\6"+ - "\1\u0197\21\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\1\u02cb\1\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\13\6\1\u02cc"+ - "\23\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u0273"+ - "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\31\6\1\151"+ - "\5\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u02cd"+ - "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\1\6\1\u02ce\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\4\6\1\151\32\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\3\6\1\u02cf\33\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\1\260\1\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\5\6\1\u019d\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\5\6\1\u02d0\31\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\5\6\1\u02d1\31\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\u0110\35\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\6\6\1\u0255\30\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\15\6\1\u0197\21\6"+ - "\4\0\1\4\3\6\1\u02d2\2\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\21\6\1\u0239\15\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\6\6\1\u02d3\30\6"+ - "\36\0\1\u02d4\117\0\1\u01c9\51\0\1\u026d\44\0\1\u026f"+ - "\1\u02d5\4\u026f\1\u02d5\17\u026f\3\u02d5\1\u026f\1\u02d5\2\0"+ - "\2\u02d5\1\0\2\u026f\2\0\3\u026f\1\0\1\u02d5\2\u026f"+ - "\1\u02d5\1\u026f\1\0\1\u02d5\1\u026f\5\u02d5\2\u026f\1\u02d5"+ - "\37\u026f\2\0\1\u02d5\33\0\1\u02d6\117\0\1\u01cd\51\0"+ - "\1\u0270\44\0\1\u0272\1\u02d7\4\u0272\1\u02d7\17\u0272\3\u02d7"+ - "\1\u0272\1\u02d7\2\0\2\u02d7\1\0\2\u0272\2\0\3\u0272"+ - "\1\0\1\u02d7\2\u0272\1\u02d7\1\u0272\1\0\1\u02d7\1\u0272"+ - "\5\u02d7\2\u0272\1\u02d7\37\u0272\2\0\1\u02d7\1\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\1\6\1\344\35\6\4\0\1\4"+ - "\5\6\1\302\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\u02d8\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\30\6\1\u01e9\6\6\4\0\1\4\5\6\1\u02d9\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\14\6\1\u02da\22\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\u02db"+ - "\1\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\13\6\1\u02dc\23\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\5\6\1\u02dd\31\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\15\6\1\u02ba\21\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\2\6\1\u0161\34\6\4\0\1\4\5\6\1\u0237\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\157"+ - "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\223"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u02de"+ - "\1\6\1\u02df\13\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u02e0\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\12\6\1\u02e1\4\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\10\6\1\u02e2\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\2\6\1\u02e3\14\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u028e\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\1\6\1\u0124\1\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ - "\1\u0207\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ - "\1\u02e4\13\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\12\6\1\u02e5\24\6\4\0\1\4\6\6\1\0\10\6"+ - "\1\u02e6\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u02e7"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u02e8"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u02e9"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\11\6\1\u013e"+ - "\5\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\13\6\1\151"+ - "\3\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\6\6\1\u02ea"+ - "\10\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\u02eb\11\6"+ - "\1\u0290\4\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\36\6\1\151\4\0\1\4\6\6\1\0"+ - "\12\6\1\u0142\4\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\223\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\6\1\u02ec\15\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u02ed\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\5\6\1\210\11\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\5\6\1\u02ee\11\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u02ef\1\0\37\6\4\0\1\4\6\6\1\0\7\6"+ - "\1\u029b\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u02f0"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\15\6\1\u013e"+ - "\1\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u02f1"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u02f2"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\15\6"+ - "\1\u02f3\21\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\14\6"+ - "\1\u02f4\22\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\11\6"+ - "\1\u02f5\25\6\4\0\7\4\1\0\7\4\1\u02a3\7\4"+ - "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ - "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ - "\1\0\12\4\1\u02f6\4\4\11\0\3\4\2\0\3\4"+ - "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ - "\1\0\37\4\4\0\7\4\1\0\16\4\1\u02f7\11\0"+ - "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ - "\3\4\4\0\2\4\1\0\37\4\17\0\1\u02a8\132\0"+ - "\1\u02f8\132\0\1\u02f8\142\0\1\u02f9\124\0\1\u02a8\137\0"+ - "\1\u02fa\143\0\1\u02fb\106\0\1\4\6\6\1\0\7\6"+ - "\1\u02fc\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ - "\1\u02fd\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\1\6\1\u02fe\1\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ - "\1\u02ff\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ - "\1\u01c3\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u0300"+ - "\5\6\1\151\10\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\14\6\1\u022d\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u0301\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\17\6\1\u0197\17\6\4\0\1\4\5\6\1\u0302\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\14\6"+ - "\1\u0303\22\6\4\0\1\4\5\6\1\u0304\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\13\6\1\u0305"+ - "\23\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\1\u0198\1\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\15\6\1\u0306\21\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\1\6\1\u0307\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\1\6\1\326\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\10\6\1\u0308\26\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\3\6\1\u0309\33\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\20\6\1\151\16\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\4\6\1\u0197\32\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\13\6\1\302\23\6\4\0\1\4"+ - "\5\6\1\u030a\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\3\6"+ - "\1\u030b\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\1\u02c2\1\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\36\6\1\151\4\0"+ - "\1\4\5\6\1\u02d9\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u02de\15\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\5\6\1\u030c\31\6\4\0\1\4"+ - "\3\6\1\u030d\2\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\3\6\1\151\33\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\2\6\1\u030e\34\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\u01c2\35\6"+ - "\4\0\1\4\5\6\1\u030f\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\u0310\35\6\4\0"+ - "\1\4\5\6\1\u0311\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\10\6\1\u02d1\26\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\15\6\1\u0312\21\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\1\6\1\u025b\35\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\15\6\1\u0313\21\6\36\0\1\u026f"+ - "\133\0\1\u0272\101\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\11\6"+ - "\1\u0314\7\6\1\u0315\1\u0316\14\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\6\1\u0317\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\151\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\2\6"+ - "\1\u0318\34\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\11\6"+ - "\1\u0314\7\6\1\u0315\1\u0316\1\6\1\u0319\12\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\u010e\23\6\4\0"+ - "\1\4\6\6\1\0\5\6\1\u031a\11\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\2\6\1\151\14\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\16\6\1\u031b\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\u031c\11\6\1\u031d"+ - "\10\6\1\u031e\13\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\1\6\1\u031f\1\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\4\6"+ - "\1\u0116\12\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\16\6"+ - "\1\u031b\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\12\6\1\u031d\10\6\1\u031e\13\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\33\6\1\u013e\3\6\4\0\1\4"+ - "\6\6\1\0\13\6\1\u013e\3\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\2\6\1\u0152\14\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\10\6\1\u022f\6\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\11\6\1\u0320\5\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\1\6\1\u0321\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\u0152\15\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\10\6\1\u0322\6\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\1\6\1\u0323\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\15\6\1\151\1\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\14\6\1\163\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\6\1\u0324\15\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\3\6\1\u0325\13\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\7\6\1\u0326\7\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\7\6\1\u0327\7\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\5\6\1\u025e\31\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\32\6\1\u0197\4\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\20\6\1\u0197\16\6\4\0\7\4\1\0\1\u021b"+ - "\16\4\11\0\3\4\2\0\3\4\2\0\2\4\1\0"+ - "\1\4\1\0\3\4\4\0\2\4\1\0\37\4\4\0"+ - "\7\4\1\0\14\4\1\u02a3\2\4\11\0\3\4\2\0"+ - "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ - "\2\4\1\0\37\4\23\0\1\u02f8\136\0\1\u0328\137\0"+ - "\1\u0329\105\0\1\4\6\6\1\0\11\6\1\u032a\5\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\12\6\1\u0124"+ - "\24\6\4\0\1\4\6\6\1\0\5\6\1\u013e\11\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\15\6\1\u0124\1\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\14\6\1\u032b\2\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\1\6\1\u032c\15\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\10\6\1\u032d"+ - "\26\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u032e"+ - "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\4\6\1\u032f"+ - "\32\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\17\6\1\151"+ - "\17\6\4\0\1\4\5\6\1\u0330\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\1\6\1\255\35\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\4\6\1\u0331\32\6"+ - "\4\0\1\4\5\6\1\u01bf\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\15\6\1\u0332\21\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\5\6\1\u0333\31\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\u01bf\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\6\1\u0334\35\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\1\6\1\u0197\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\17\6\1\u0161\17\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\11\6\1\u0161\25\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\10\6\1\u0335\26\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\14\6\1\u0336\22\6\4\0\1\4\5\6\1\u0337"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\37\6\4\0\1\4\5\6\1\326\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ - "\1\u0338\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\1\u0339\1\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u033a"+ - "\21\6\4\0\1\4\3\6\1\u033b\2\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\5\6\1\u033c\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\u033d\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\10\6\1\u033e\6\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\1\6\1\u033f\15\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\1\6\1\210\15\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\12\6\1\u0340\4\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\1\u0341\16\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\3\6\1\u0342\13\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\1\u0119\36\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\u0343\36\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u0341\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\10\6\1\u0119\6\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\1\u0344\5\6"+ - "\1\0\1\u0345\16\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\14\6\1\u029b\2\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\14\0\1\u02a9\147\0\1\u02f8"+ - "\107\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\u0207\1\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\1\6\1\u0346\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\u0347\16\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\6\1\u02d1\35\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\14\6\1\u0348\22\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\13\6\1\u033b\23\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\6\6\1\u0237\30\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\24\6\1\u0349\12\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\24\6\1\u0110\12\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\15\6\1\u034a\21\6\4\0\1\4\3\6"+ - "\1\u034b\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\34\6\1\u034c\2\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\5\6\1\u0110\31\6\4\0"+ - "\1\4\3\6\1\u034d\2\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\13\6\1\u027b\23\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\u034e\35\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\151\35\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\1\6\1\u0269\35\6\4\0"+ - "\1\4\5\6\1\u034f\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\14\6\1\151\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\4\6\1\u0285\12\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u0350\15\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\14\6\1\u0351\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\14\6\1\u020c\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\6\6\1\u013e\10\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u0352\15\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\10\6\1\u0353\6\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\1\6\1\u0354\15\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\14\6\1\u0355\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\14\6\1\u0356\2\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\3\6\1\u0197\33\6\4\0\1\4"+ - "\5\6\1\u0357\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ - "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ - "\2\6\1\0\1\6\1\u0358\35\6\4\0\1\4\5\6"+ - "\1\u0359\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\5\6\1\u035a\31\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\1\6\1\u035b\35\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\10\6\1\u035c\26\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\25\6\1\151\11\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\26\6\1\151\10\6\4\0\1\4\6\6\1\0"+ - "\7\6\1\u035d\7\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\1\6\1\u0119\15\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\1\6\1\u035e\1\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\13\6\1\u035f\3\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\2\6\1\u0360\3\6\1\151\10\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\1\222"+ - "\2\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\5\6"+ - "\1\u0110\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\u0361\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\3\6\1\151\33\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\20\6\1\u0362\16\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\2\6\1\u0363\34\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\16\6\1\310\20\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\15\6\1\u0161\21\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\u0124\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u0364"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0365"+ - "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0366"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\14\6"+ - "\1\u0367\22\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\6"+ - "\1\u0368\35\6\4\0\1\4\6\6\1\0\17\6\11\0"+ - "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ - "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\15\6"+ - "\1\u0369\21\6\4\0\1\4\6\6\1\0\3\6\1\u036a"+ - "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\u036b"+ - "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u011a"+ - "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\37\6\4\0\1\4\5\6\1\u0166\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\10\6\1\u036c"+ - "\26\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u036d"+ - "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\1\6\1\u036e\1\0\37\6"+ - "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\1\6\1\u036f\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\15\6\1\u0370\21\6\4\0"+ - "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\15\6\1\u0371\21\6\4\0"+ - "\1\4\6\6\1\0\5\6\1\u027f\11\6\11\0\1\4"+ - "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ - "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ - "\1\4\6\6\1\0\16\6\1\u0372\11\0\1\4\2\6"+ - "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ - "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\21\6\1\u0373\15\6\4\0\1\4"+ - "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\1\6\1\u0274\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ - "\1\0\1\6\1\u0374\15\6\11\0\1\4\2\6\2\0"+ - "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ - "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\5\6"+ - "\1\u0375\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\4\6\1\u0376\12\6\11\0\1\4\2\6\2\0\3\6"+ - "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ - "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ - "\1\0\13\6\1\u0377\23\6\4\0\1\4\6\6\1\0"+ - "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ - "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ - "\1\223\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ - "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ - "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ - "\15\6\1\302\21\6\4\0"; + "\1\4\1\5\1\6\1\7\1\10\1\7\1\11\1\12"+ + "\1\13\1\14\1\15\1\16\1\17\1\20\1\21\1\22"+ + "\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+ + "\1\33\1\34\1\35\1\36\1\37\1\40\1\41\1\42"+ + "\1\43\1\7\1\6\1\44\1\45\1\46\1\47\1\50"+ + "\1\51\1\33\1\52\1\53\1\54\1\55\1\56\1\57"+ + "\2\4\1\34\1\60\1\41\1\33\1\61\1\62\1\41"+ + "\1\63\1\64\1\65\1\66\1\67\1\70\1\71\1\7"+ + "\1\72\1\73\1\74\1\75\1\76\1\77\1\100\1\101"+ + "\1\102\1\103\1\104\1\105\1\106\2\6\2\7\3\6"+ + "\1\107\2\7\1\34\1\41\1\110\1\111\12\112\1\113"+ + "\30\112\1\114\5\112\1\115\14\112\1\116\2\112\1\117"+ + "\42\112\12\120\1\121\30\120\1\122\22\120\1\123\2\120"+ + "\1\124\42\120\7\4\1\0\17\4\11\0\3\4\2\0"+ + "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ + "\2\4\1\0\37\4\4\0\1\4\6\6\1\0\10\6"+ + "\1\125\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\3\126\1\7\1\126\1\7\1\127\1\0"+ + "\1\126\1\127\3\126\1\130\4\126\1\131\4\126\11\0"+ + "\1\126\1\7\1\126\2\0\2\126\1\7\2\0\1\131"+ + "\1\130\1\132\1\126\1\0\3\126\4\0\2\126\1\0"+ + "\7\126\1\7\17\126\2\7\4\126\2\7\4\0\1\4"+ + "\5\6\1\133\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\1\6\1\134\35\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\13\6\1\135\2\6\1\136"+ + "\12\6\1\137\5\6\13\0\1\41\20\0\1\41\103\0"+ + "\1\4\6\6\1\0\1\6\1\140\12\6\1\141\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\4\6\1\142\12\6"+ + "\11\0\1\4\1\6\1\143\2\0\1\144\2\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ + "\1\145\1\6\1\146\2\6\1\147\3\6\1\150\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\2\6\1\151\1\6"+ + "\1\152\1\6\1\153\10\6\11\0\1\4\1\154\1\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\10\6\1\155\1\6\1\156\4\6\11\0"+ + "\1\4\2\6\2\0\1\157\2\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\160\2\6"+ + "\1\151\3\6\1\161\1\162\1\163\1\6\1\164\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\165\1\6"+ + "\1\166\1\6\1\167\2\6\1\170\1\6\1\171\1\172"+ + "\3\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ + "\1\173\1\0\1\174\22\6\1\175\13\6\4\0\1\4"+ + "\6\6\1\0\1\6\1\176\1\6\1\177\4\6\1\200"+ + "\3\6\1\201\2\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\202\6\6\1\151\7\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\203\1\6\1\204\1\205\1\206\1\6"+ + "\1\207\1\210\6\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\1\211\1\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\4\6\1\212\5\6\1\213\1\214\3\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\3\6\1\151\3\6\1\215"+ + "\1\216\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\217"+ + "\3\6\1\202\1\6\1\220\1\221\1\6\1\222\5\6"+ + "\11\0\1\4\2\6\2\0\1\223\1\224\1\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\1\6\1\225\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\6\1\226\5\6\1\227\1\6\1\202\5\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\230\1\6\1\231"+ + "\4\6\1\232\3\6\1\233\2\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\33\0\1\234"+ + "\134\0\1\41\267\0\1\41\1\0\1\235\16\0\1\236"+ + "\62\0\27\237\1\240\3\237\1\241\4\237\1\242\2\237"+ + "\1\0\70\237\34\0\1\33\134\0\1\33\126\0\1\41"+ + "\6\0\1\41\74\0\40\45\1\243\2\45\1\244\1\245"+ + "\67\45\1\4\6\6\1\0\14\6\1\246\2\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\3\6\1\247\13\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\3\126\1\7\1\126\1\7\1\127\1\0\1\126"+ + "\1\127\3\126\1\130\4\126\1\131\4\126\11\0\1\126"+ + "\1\7\1\250\2\0\2\126\1\7\2\0\1\131\1\130"+ + "\1\132\1\126\1\0\3\126\4\0\2\126\1\0\7\126"+ + "\1\7\17\126\2\7\1\250\3\126\2\7\54\0\1\51"+ + "\63\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\1\251\1\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\13\6\1\252"+ + "\4\6\1\253\16\6\4\0\1\4\5\6\1\254\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\255"+ + "\1\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\256\2\6\1\257\1\260\5\6"+ + "\1\151\23\6\7\0\1\132\1\0\1\132\33\0\1\132"+ + "\5\0\1\132\30\0\1\132\17\0\2\132\4\0\2\132"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\1\6\1\261\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\262"+ + "\3\6\1\263\6\6\1\264\22\6\4\0\7\4\1\0"+ + "\1\265\1\266\1\4\1\267\1\4\1\270\4\4\1\271"+ + "\1\272\3\4\11\0\3\4\2\0\3\4\1\273\1\0"+ + "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ + "\37\4\4\0\1\4\6\6\1\0\3\6\1\274\4\6"+ + "\1\275\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\276\1\6\1\277\3\6\1\300\1\301\3\6\1\302"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\303"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\3\6\1\304\2\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\2\6\1\305\1\306\1\307\3\6\1\310\2\6"+ + "\1\311\1\6\1\312\1\313\20\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\314\22\6\4\0\1\4\5\6"+ + "\1\315\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\316\1\317\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\5\6\1\320\6\6\1\321"+ + "\1\322\2\6\1\323\1\6\1\324\1\6\1\325\12\6"+ + "\4\0\1\4\5\6\1\326\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\1\6\1\327\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\330\1\331\1\6\1\332\2\6\1\333\1\334\22\6"+ + "\4\0\1\4\3\6\1\311\2\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\10\6"+ + "\1\151\26\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\335\6\6\1\336\22\6\4\0\1\4\5\6\1\337"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\340\3\6\1\341\6\6\1\342"+ + "\22\6\4\0\1\4\5\6\1\343\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\344\15\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\1\345\1\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\5\6\1\346"+ + "\10\6\1\347\20\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\1\350\1\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\151\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\3\6\1\351\7\6\1\352\23\6\4\0\1\4"+ + "\5\6\1\353\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\1\6\1\354\3\6\1\355"+ + "\2\6\1\356\3\6\1\357\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\360\35\6\4\0\1\4\5\6"+ + "\1\361\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\4\6\1\311\3\6\1\362\26\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\5\6\1\363\2\6"+ + "\1\364\3\6\1\151\22\6\4\0\1\4\5\6\1\365"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\366\3\6\1\367\6\6\1\370"+ + "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\1\371\1\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\12\6\1\372\4\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\5\6\1\373\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\5\6\1\374\31\6\136\0"+ + "\1\41\134\0\1\41\12\112\1\0\30\112\1\0\5\112"+ + "\1\0\14\112\1\0\2\112\1\0\42\112\13\0\1\375"+ + "\53\0\1\376\76\0\1\377\170\0\1\u0100\135\0\1\u0101"+ + "\42\0\12\120\1\0\30\120\1\0\22\120\1\0\2\120"+ + "\1\0\42\120\13\0\1\u0102\53\0\1\u0103\133\0\1\u0104"+ + "\135\0\1\u0105\42\0\1\4\6\6\1\0\3\6\1\u0106"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\7\126\1\0\17\126\11\0\3\126"+ + "\2\0\3\126\2\0\2\126\1\0\1\126\1\0\3\126"+ + "\4\0\2\126\1\0\37\126\4\0\3\126\1\u0107\1\126"+ + "\1\u0107\1\126\1\u0108\17\126\10\0\1\u0108\1\126\1\u0107"+ + "\1\126\2\0\2\126\1\u0107\2\0\2\126\1\0\1\126"+ + "\1\0\3\126\4\0\2\126\1\0\7\126\1\u0107\17\126"+ + "\2\u0107\4\126\2\u0107\4\0\7\126\1\0\12\126\1\u0109"+ + "\4\126\11\0\3\126\2\0\3\126\2\0\1\u0109\1\126"+ + "\1\0\1\126\1\0\3\126\4\0\2\126\1\0\37\126"+ + "\4\0\7\126\1\0\5\126\1\u0109\11\126\11\0\3\126"+ + "\2\0\3\126\2\0\1\126\1\u0109\1\0\1\126\1\0"+ + "\3\126\4\0\2\126\1\0\37\126\4\0\3\126\1\132"+ + "\1\126\1\132\1\u010a\1\0\1\126\1\u010a\1\u010b\2\126"+ + "\1\u010b\11\126\11\0\1\126\1\132\1\126\2\0\2\126"+ + "\1\132\2\0\1\126\1\u010b\1\0\1\u010b\1\0\3\126"+ + "\4\0\2\126\1\0\7\126\1\132\17\126\2\132\4\126"+ + "\2\132\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\4\6\1\u010c"+ + "\12\6\1\u010d\17\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\11\6\1\u010e\3\6\1\u010f\21\6\4\0\1\4\3\6"+ + "\1\u0110\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\2\6\1\u0111\1\6\1\u0112"+ + "\6\6\1\u0113\5\6\1\u0114\15\6\4\0\1\4\5\6"+ + "\1\u0115\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\347\35\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\262\16\6\1\151\16\6"+ + "\4\0\1\4\6\6\1\0\11\6\1\u0116\3\6\1\u0117"+ + "\1\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u0118\1\0"+ + "\12\6\1\u0119\24\6\4\0\1\4\6\6\1\0\1\u011a"+ + "\3\6\1\u011b\4\6\1\u011c\4\6\1\u011d\11\0\1\4"+ + "\2\6\2\0\1\6\1\u011e\1\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\13\6\1\151\1\150"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u011f"+ + "\12\6\1\157\2\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\6\1\u0120\2\6\1\202\1\u0121\11\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\10\6\1\u0122\6\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\7\6\1\u0123\7\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\11\6\1\u0124\5\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\1\u0125\13\6\1\u0126\2\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\151\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\4\6\1\u0127\12\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\1\u0128\36\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\35\6"+ + "\1\u011f\1\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\151"+ + "\36\6\4\0\1\4\6\6\1\0\16\6\1\u0129\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\5\6\1\151\11\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\2\6\1\u0124\1\6\1\151"+ + "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ + "\1\151\1\0\37\6\4\0\1\4\6\6\1\0\15\6"+ + "\1\u012a\1\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\u012b\36\6\4\0\1\4\6\6\1\0"+ + "\16\6\1\151\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\4\6"+ + "\1\211\12\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\12\6\1\u012c\24\6\4\0\1\4\6\6\1\0\11\6"+ + "\1\u012d\5\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\23\6\1\151\13\6\4\0\1\4\6\6"+ + "\1\0\4\6\1\u012e\10\6\1\u011f\1\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\3\6\1\u012f\13\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\7\6\1\u0130\7\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\16\6\1\u0131\11\0\1\4\2\6"+ + "\2\0\1\6\1\u0132\1\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\5\6\1\u0133\11\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\u0134\13\6\1\u0135\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\3\6\1\u0136\13\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\5\6\1\151\1\6"+ + "\1\u0124\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\11\6"+ + "\1\u0137\1\6\1\u0138\1\6\1\u0139\1\u013a\11\0\1\4"+ + "\2\6\2\0\1\u013b\2\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\15\6\1\u013c\1\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\12\6\1\u013d\4\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\u013e"+ + "\36\6\4\0\1\4\6\6\1\0\1\u013f\3\6\1\u0140"+ + "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\151\16\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\3\6\1\u0141\13\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\7\6\1\u0142\7\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\16\6\1\u011d\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\14\6\1\u0143\2\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\10\6\1\u0144\6\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\u0145\3\6\1\u0146\1\u0147"+ + "\1\u012e\1\u0148\2\6\1\u0149\3\6\1\u014a\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\14\6\1\u014b\2\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\3\6\1\u014c\13\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\3\6\1\202\13\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\13\6\1\u012b\3\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\10\6\1\u014d\6\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\1\u012b\36\6\4\0\1\4"+ + "\6\6\1\0\1\u014e\16\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\3\6\1\u014f\13\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\7\6\1\u0150\7\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\10\6\1\u0151\1\u0152\5\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\1\6\1\u0153\15\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\6\6\1\151\10\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\14\6\1\u0154\2\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\1\6\1\u0155\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\u0156\15\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\u0157\16\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\u0158\3\6\1\u0159\12\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\151\3\6\1\u015a\11\6\1\151\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\13\6\1\u015b\3\6\11\0\1\4"+ + "\1\6\1\151\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\34\0\10\41\74\0\33\u015c\1\u015d\7\u015c\1\0\117\u015c"+ + "\1\u015e\3\u015c\1\u015d\7\u015c\1\0\75\u015c\1\u015f\4\u015c"+ + "\1\237\1\u015c\1\237\2\u015c\1\237\4\u015c\1\237\2\u015c"+ + "\1\237\3\u015c\1\u0160\4\u015c\1\237\1\u0161\1\u0162\1\0"+ + "\3\237\1\u0161\17\u015c\1\237\10\u015c\1\u0161\17\u015c\1\u0161"+ + "\1\u015f\1\u0162\4\u015c\1\u015f\4\u015c\5\244\1\45\4\244"+ + "\1\45\1\244\1\45\2\244\1\45\4\244\1\45\2\244"+ + "\1\45\3\244\1\45\4\244\2\45\1\u0163\1\0\4\45"+ + "\17\244\1\45\10\244\1\45\17\244\2\45\1\u0163\4\244"+ + "\1\45\44\244\1\u0164\3\244\1\u0165\67\244\1\4\6\6"+ + "\1\0\5\6\1\u0166\11\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\1\6\1\u0167\1\0\37\6\4\0\3\126\4\u0168\1\0"+ + "\3\u0168\6\126\1\u0168\2\126\1\u0168\2\126\11\0\1\126"+ + "\1\u0168\1\126\2\0\1\126\2\u0168\2\0\2\126\1\0"+ + "\1\u0168\1\0\3\126\4\0\2\126\1\0\1\126\2\u0168"+ + "\1\126\1\u0168\2\126\1\u0168\17\126\2\u0168\4\126\2\u0168"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\14\6\1\311\22\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\14\6\1\u0169\22\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\20\6\1\u016a\16\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\u016b\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\151\1\6"+ + "\1\151\21\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\13\6"+ + "\1\331\23\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\11\6"+ + "\1\u016c\25\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\21\6"+ + "\1\151\15\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\17\6"+ + "\1\u012a\4\6\1\u016a\12\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\5\6\1\u016d\31\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\4\6\1\u016b\32\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\10\6\1\u016e\26\6\4\0\1\4\5\6\1\u016f"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\1\6\1\u0170\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\13\6\1\311\23\6\4\0\7\4"+ + "\1\0\1\4\1\u0171\15\4\11\0\3\4\2\0\3\4"+ + "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ + "\1\0\37\4\4\0\7\4\1\0\4\4\1\u0172\1\u0173"+ + "\1\4\1\u0174\7\4\11\0\3\4\2\0\3\4\2\0"+ + "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ + "\37\4\4\0\7\4\1\0\2\4\1\u0175\1\4\1\u0176"+ + "\12\4\11\0\3\4\2\0\3\4\2\0\2\4\1\0"+ + "\1\4\1\0\3\4\4\0\2\4\1\0\37\4\4\0"+ + "\7\4\1\0\3\4\1\u0177\13\4\11\0\3\4\2\0"+ + "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ + "\2\4\1\0\37\4\4\0\7\4\1\0\4\4\1\u0178"+ + "\12\4\11\0\3\4\2\0\3\4\2\0\2\4\1\0"+ + "\1\4\1\0\3\4\4\0\2\4\1\0\37\4\4\0"+ + "\7\4\1\0\7\4\1\u0179\7\4\11\0\3\4\2\0"+ + "\3\4\2\0\2\4\1\0\1\4\1\0\3\4\4\0"+ + "\2\4\1\0\37\4\14\0\1\u017a\1\u017b\1\0\1\u017c"+ + "\1\0\1\u017d\4\0\1\u017e\1\u017f\24\0\1\273\63\0"+ + "\1\4\6\6\1\0\1\6\1\u0180\15\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\12\6\1\u014b\4\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\1\6\1\u0181"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\16\6\1\u0145\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\u0182\1\6\1\162\6\6\1\u0183\4\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\u0184\2\6\1\u0185"+ + "\4\6\1\u0186\6\6\11\0\1\4\2\6\2\0\1\6"+ + "\1\u0187\1\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\u0188\1\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\4\6\1\u012e\12\6\11\0\1\4"+ + "\2\6\2\0\1\6\1\u0189\1\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u018a\1\6"+ + "\1\u018b\13\6\11\0\1\4\2\6\2\0\1\6\1\u018c"+ + "\1\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\3\6"+ + "\1\u018d\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\3\6\1\151\33\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\u018e\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\4\6\1\u018f\1\u0190\31\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\10\6\1\u0191\26\6\4\0\1\4"+ + "\3\6\1\151\2\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\u0192\35\6\4\0\1\4"+ + "\5\6\1\u0193\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u0194\21\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\4\6\1\u0195\15\6\1\151\14\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\2\6\1\u0196\16\6\1\u0197"+ + "\15\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u0198"+ + "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\10\6\1\u0199"+ + "\26\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\13\6\1\u019a"+ + "\3\6\1\u0115\17\6\4\0\1\4\3\6\1\u019b\2\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\u019c\35\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\1\6\1\u019d\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ + "\1\151\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u016b\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\u019e\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\u019f\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\u01a0\35\6\4\0\1\4\3\6"+ + "\1\u01a1\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\1\u01a2\1\u01a3\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\3\6\1\u019a\4\6"+ + "\1\u01a4\2\6\1\u01a5\5\6\1\u01a6\15\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\u01a7\35\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\5\6\1\u01a8\31\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\21\6\1\u0114\15\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\10\6\1\u01a9\26\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\u01a7\1\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\5\6"+ + "\1\u01aa\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\4\6\1\u01ab\11\6\1\u01ac\1\u01ad\1\u01ae\1\u01af"+ + "\15\6\4\0\1\4\3\6\1\u01b0\2\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\13\6\1\u01b1\23\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\1\u01b2\1\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\24\6\1\u01b3\12\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\17\6\1\u01b4\17\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\1\6\1\u01b5\35\6\4\0\1\4\6\6\1\0"+ + "\14\6\1\u01b6\2\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\21\6\1\u01b7\15\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\24\6\1\151\12\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ + "\1\151\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\35\6\1\u0115\1\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\13\6\1\u01b8\10\6\1\u01b9\12\6\4\0\1\4\3\6"+ + "\1\u01ba\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\1\6\1\u01bb\13\6\1\151"+ + "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\31\6\1\u01bc"+ + "\5\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\2\6\1\u01bd"+ + "\10\6\1\u019a\23\6\4\0\1\4\3\6\1\u01be\2\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\2\6\1\u01bf\2\6\1\u01c0\1\u01c1\5\6"+ + "\1\u01c2\22\6\4\0\1\4\5\6\1\u01c3\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\1\u01c4\1\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\14\6\1\257\22\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\21\6\1\u01a1\15\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ + "\1\u01c5\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\u01c6\21\6\4\0\1\4\5\6\1\u01c7\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\24\6"+ + "\1\u016a\12\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\u01c8\31\6\4\0\1\4\3\6\1\u01c9\2\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\20\6"+ + "\1\u01ca\10\6\1\151\5\6\4\0\1\4\3\6\1\151"+ + "\2\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\13\6\1\u01cb\5\6\1\151\15\6"+ + "\4\0\1\4\3\6\1\u01cc\2\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\13\6"+ + "\1\u01cd\23\6\4\0\1\4\5\6\1\u01ce\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u01cf\15\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\5\6\1\u01d0\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\2\6"+ + "\1\u01d1\11\6\1\u01d2\22\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\14\6\1\u01d3\22\6\21\0\1\u01d4\141\0\1\u01d5"+ + "\177\0\1\u01d6\135\0\1\u01d7\57\0\1\u01d8\141\0\1\u01d9"+ + "\177\0\1\u01da\135\0\1\u01db\42\0\1\4\6\6\1\0"+ + "\4\6\1\u01dc\12\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\3\126\1\u0107\1\126"+ + "\1\u0107\1\126\1\0\5\126\1\130\4\126\1\131\4\126"+ + "\11\0\1\126\1\u0107\1\126\2\0\2\126\1\u0107\2\0"+ + "\1\131\1\130\1\0\1\126\1\0\3\126\4\0\2\126"+ + "\1\0\7\126\1\u0107\17\126\2\u0107\4\126\2\u0107\7\0"+ + "\1\u0107\1\0\1\u0107\33\0\1\u0107\5\0\1\u0107\30\0"+ + "\1\u0107\17\0\2\u0107\4\0\2\u0107\4\0\3\126\1\u01dd"+ + "\1\126\1\u01dd\1\126\1\u01de\17\126\10\0\1\u01de\1\126"+ + "\1\u01dd\1\126\2\0\2\126\1\u01dd\2\0\2\126\1\0"+ + "\1\126\1\0\3\126\4\0\2\126\1\0\7\126\1\u01dd"+ + "\17\126\2\u01dd\4\126\2\u01dd\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\5\6\1\u01df\6\6\1\u01e0\22\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\10\6\1\u01e1\26\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\3\6\1\u01e2\12\6\1\100\20\6"+ + "\4\0\1\4\5\6\1\u01e3\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\5\6\1\u01e4\16\6\1\u01e5"+ + "\12\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\11\6\1\u01e6"+ + "\25\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\5\6\1\u01df"+ + "\31\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\1\u01e7\1\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\5\6\1\u01e8\31\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\151\23\6"+ + "\4\0\1\4\6\6\1\0\3\6\1\u01e9\4\6\1\u01ea"+ + "\6\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\u01eb"+ + "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u01ec"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\6\6\1\u01ed"+ + "\10\6\11\0\1\4\2\6\2\0\1\46\2\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\10\6"+ + "\1\u01ee\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\u01ef\36\6\4\0\1\4\6\6\1\0"+ + "\12\6\1\u01f0\4\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\10\6\1\u01ea\6\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\10\6\1\u01f1\6\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\12\6\1\u01f2\24\6\4\0\1\4\6\6\1\0"+ + "\4\6\1\151\12\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\5\6\1\u01f3\11\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\6\1\u01f4\15\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\10\6\1\u014b\6\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\16\6\1\u01f5\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\151"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u01f6"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\221"+ + "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\u01f7"+ + "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\10\6\1\u01f8"+ + "\6\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u01f9\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\1\u01fa\1\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\u014b\15\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\u01fb\15\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\10\6\1\u01fc\6\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\151\1\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\11\6\1\u01fd\5\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\1\6\1\u015b\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\3\6\1\u01fe\2\6\1\u01ff\4\6\1\u0200"+ + "\3\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\6\6\1\u0201"+ + "\10\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0124"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u0202"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\u0203"+ + "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u0204\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\10\6\1\u0205\6\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u01f5\3\6"+ + "\1\u0206\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\u0207\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\10\6"+ + "\1\u0208\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\u0209\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\u0124\1\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u020a"+ + "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\11\6\1\u020b"+ + "\5\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u020c"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\u020d\14\6"+ + "\1\u0145\1\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\26\6\1\151\10\6\4\0\1\4\6\6"+ + "\1\0\5\6\1\u020e\11\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\11\6\1\u020f\5\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\6\6\1\224\10\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\6\6\1\u0210\10\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\151\15\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\11\6\1\u0211\5\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\4\6\1\u0212\4\6\1\u020b\5\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\7\6\1\u0213\7\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\4\6\1\u0214\12\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\1\6\1\u0215\1\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\7\6\1\151\7\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\23\6\1\u0216\13\6\4\0"+ + "\1\4\6\6\1\0\1\u0217\12\6\1\u0218\2\6\1\u0219"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\7\6\1\u01dc"+ + "\27\6\4\0\1\4\6\6\1\0\4\6\1\u012e\12\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\14\6\1\u021a\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\6\6\1\u012e\10\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\6\6\1\u021b\10\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\7\6\1\u021c\7\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\4\6\1\u021d\12\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\11\6\1\u021e\1\u021f"+ + "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\13\6\1\u01dc"+ + "\3\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u0220"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\11\6\1\u0221"+ + "\5\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\u0222"+ + "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u0223\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\14\6\1\u0126\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\33\u015c\1\241\7\u015c\1\0\120\u015c\3\237"+ + "\1\u0160\4\237\3\u015c\1\0\75\u015c\1\237\25\u015c\1\u015d"+ + "\5\u015c\1\237\1\u015c\1\0\3\u015c\1\237\30\u015c\1\237"+ + "\17\u015c\2\237\5\u015c\1\237\4\u015c\33\0\1\u015d\100\0"+ + "\5\u015c\1\u015f\25\u015c\1\u015d\5\u015c\1\u015f\1\u015c\1\0"+ + "\3\u015c\1\u015f\30\u015c\1\u015f\17\u015c\2\u015f\5\u015c\1\u015f"+ + "\7\u015c\4\u0224\1\u015c\3\u0224\6\u015c\1\u0224\2\u015c\1\u0224"+ + "\6\u015c\1\241\5\u015c\1\u0224\1\u015c\1\0\2\u015c\2\u0224"+ + "\5\u015c\1\u0224\14\u015c\2\u0224\1\u015c\1\u0224\2\u015c\1\u0224"+ + "\17\u015c\2\u0224\4\u015c\2\u0224\4\u015c\3\244\4\u0225\1\244"+ + "\3\u0225\6\244\1\u0225\2\244\1\u0225\13\244\1\u0164\1\u0225"+ + "\2\244\1\u0165\1\244\2\u0225\5\244\1\u0225\14\244\2\u0225"+ + "\1\244\1\u0225\2\244\1\u0225\17\244\2\u0225\4\244\2\u0225"+ + "\47\244\1\0\70\244\1\4\6\6\1\0\12\6\1\u0145"+ + "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u0226"+ + "\3\6\1\u0227\6\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\3\126\4\u0168\1\0"+ + "\3\u0168\2\126\1\u0228\3\126\1\u0168\1\u0229\1\126\1\u0168"+ + "\2\126\11\0\1\126\1\u0168\1\126\2\0\1\126\2\u0168"+ + "\2\0\1\u0229\1\u0228\1\0\1\u0168\1\0\3\126\4\0"+ + "\2\126\1\0\1\126\2\u0168\1\126\1\u0168\2\126\1\u0168"+ + "\17\126\2\u0168\4\126\2\u0168\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\22\6\1\u022a\14\6\4\0\1\4\5\6\1\u01a7"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\151\21\6\4\0\1\4\5\6\1\u022b\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\u01a7\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\21\6"+ + "\1\u022c\15\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\1\6\1\u022d\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\5\6\1\u022e\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\7\4\1\0\2\4\1\270\14\4\11\0\3\4"+ + "\2\0\3\4\2\0\2\4\1\0\1\4\1\0\3\4"+ + "\4\0\2\4\1\0\37\4\4\0\7\4\1\0\1\u022f"+ + "\16\4\11\0\3\4\2\0\3\4\2\0\2\4\1\0"+ + "\1\4\1\0\3\4\4\0\2\4\1\0\37\4\4\0"+ + "\7\4\1\0\3\4\1\u0230\2\4\1\u0231\10\4\11\0"+ + "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ + "\3\4\4\0\2\4\1\0\37\4\4\0\7\4\1\0"+ + "\7\4\1\u0232\7\4\11\0\3\4\2\0\3\4\2\0"+ + "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ + "\37\4\4\0\7\4\1\0\1\u0233\3\4\1\u0178\12\4"+ + "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ + "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ + "\1\0\11\4\1\u0234\5\4\11\0\3\4\2\0\3\4"+ + "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ + "\1\0\37\4\4\0\7\4\1\0\4\4\1\u0231\12\4"+ + "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ + "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ + "\1\0\1\u0233\16\4\11\0\3\4\2\0\3\4\2\0"+ + "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ + "\37\4\4\0\7\4\1\0\14\4\1\u0235\2\4\11\0"+ + "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ + "\3\4\4\0\2\4\1\0\37\4\15\0\1\u0236\136\0"+ + "\1\u0237\1\u0238\1\0\1\u0239\126\0\1\u023a\1\0\1\u023b"+ + "\132\0\1\u023c\134\0\1\u023d\136\0\1\u023e\114\0\1\4"+ + "\6\6\1\0\7\6\1\u023f\7\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\1\6\1\u0240\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\u0241\15\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\4\6\1\u0242\12\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\10\6\1\u0243\3\6\1\u0244\2\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\4\6\1\u0245\11\6\1\u021c\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\11\6\1\u0246\5\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\3\6\1\u0247\13\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\u0248\15\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\5\6\1\u0249\11\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\26\6\1\u024a\10\6"+ + "\4\0\1\4\6\6\1\0\15\6\1\u024b\1\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\3\6\1\u024c\13\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\7\6\1\u024d\27\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\u019a\23\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\3\6\1\u024e\33\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\3\6\1\u019a\33\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\1\6\1\u024f\35\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\u0250\23\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\10\6\1\u0251\26\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\5\6\1\u0252\5\6"+ + "\1\u0253\23\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\u0254\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ + "\1\u0255\33\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ + "\1\u0256\10\6\1\u0257\3\6\1\u0258\16\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\4\6\1\u0259\32\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\15\6\1\u01ca\21\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\6\6\1\151\30\6\4\0\1\4"+ + "\5\6\1\u025a\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u025b\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\u016b\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u025c\21\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\1\6\1\u025d\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\3\6\1\305\33\6\4\0\1\4\5\6\1\151"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\13\6\1\u025e\23\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\4\6\1\u025f\6\6\1\u0260\23\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u0261\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\4\6\1\u0262\32\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\2\6\1\u0263\34\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\151\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\3\6\1\u0264\33\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\4\6\1\u0265\32\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u0266\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\5\6\1\u0267\31\6\4\0\1\4\5\6"+ + "\1\u0268\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\5\6\1\u0269"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\5\6\1\u022c\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ + "\1\u026a\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\5\6\1\u026b\31\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\14\6\1\u026c\22\6\4\0\1\4\3\6\1\u026d\2\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\17\6\1\u01a1\5\6\1\151\11\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\13\6\1\u026e\23\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\4\6\1\u025f\32\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\6\6\1\u016b\30\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\10\6\1\u026f\26\6\4\0"+ + "\1\4\6\6\1\0\7\6\1\u0270\7\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\15\6\1\u0271\21\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\1\u0272\1\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\5\6\1\u0273\31\6\4\0\1\4"+ + "\5\6\1\u0274\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\310\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u0275\21\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\1\6\1\u0276\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\1\6\1\u0277\3\6\1\u0278\31\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\14\6\1\u0279\22\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\4\6\1\u027a\32\6\4\0\1\4"+ + "\5\6\1\u027b\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\13\6\1\u027c\5\6\1\u0251\15\6\4\0"+ + "\1\4\5\6\1\u027d\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\13\6\1\u027e\23\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\u01a1\1\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\1\u027f\1\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\4\6\1\u0280\32\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\20\6\1\u024d\16\6\4\0\1\4"+ + "\3\6\1\u0281\2\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\20\6\1\u0282\1\u0283"+ + "\15\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u0284"+ + "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\u01bb"+ + "\35\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u0285"+ + "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\4\6\1\u0286"+ + "\32\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\1\u0287\1\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\10\6\1\u024f\26\6"+ + "\4\0\1\4\6\6\1\0\7\6\1\u021a\7\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\25\6\1\u0288\11\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\14\6\1\u0289\22\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\17\6\1\u028a\17\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\u024d\23\6"+ + "\15\0\1\u01d5\212\0\1\u028b\66\0\1\u028c\164\0\1\u028d"+ + "\70\0\1\u01d9\212\0\1\u028e\66\0\1\u028f\164\0\1\u0290"+ + "\57\0\3\126\1\u01dd\1\126\1\u01dd\1\126\1\0\2\126"+ + "\1\u010b\2\126\1\u010b\11\126\11\0\1\126\1\u01dd\1\126"+ + "\2\0\2\126\1\u01dd\2\0\1\126\1\u010b\1\0\1\u010b"+ + "\1\0\3\126\4\0\2\126\1\0\7\126\1\u01dd\17\126"+ + "\2\u01dd\4\126\2\u01dd\7\0\1\u01dd\1\0\1\u01dd\33\0"+ + "\1\u01dd\5\0\1\u01dd\30\0\1\u01dd\17\0\2\u01dd\4\0"+ + "\2\u01dd\4\0\1\4\3\6\1\u01a1\2\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\21\6\1\u0291"+ + "\15\6\4\0\1\4\5\6\1\u0292\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\5\6\1\u0293\21\6"+ + "\1\u0294\7\6\4\0\1\4\3\6\1\u0295\2\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\3\6\1\u0296\10\6\1\u0297\1\u0298\21\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\u0299\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\u029a\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\3\6\1\u029b\33\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\21\6\1\u029c\15\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\13\6\1\u029d\23\6\4\0\1\4\6\6"+ + "\1\0\16\6\1\u029e\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\u0145\16\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\u029f\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u02a0"+ + "\2\6\1\u02a1\2\6\1\u02a2\10\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\6\1\u02a3\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\10\6\1\u02a4\6\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\27\6\1\u0294"+ + "\7\6\4\0\1\4\6\6\1\0\2\6\1\u02a5\14\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\3\6\1\u02a6\13\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\16\6\1\u02a7\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\4\6\1\u02a8\12\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\6\6\1\u02a9\10\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\224\16\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\4\6\1\u0212\1\6\1\u02aa\10\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u02ab"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0124"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\1\6\1\u02ac\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\5\6\1\157\11\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\7\6\1\u02ad\7\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\10\6\1\u02ae\6\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\2\6\1\151\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\7\6\1\u02af\7\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\4\6\1\202\12\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\u01dc\15\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\2\6\1\224\14\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\23\6\1\151\13\6"+ + "\4\0\1\4\6\6\1\0\7\6\1\u02b0\7\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\6\1\u02b1\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\1\151\2\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\1\6\1\u02b2\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\11\6\1\u02b3\5\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\7\6\1\u01f3\7\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\14\6\1\u02b4\2\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\1\6\1\u02b5\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\1\u01fd\2\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\7\6"+ + "\1\u02b6\7\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u02b7"+ + "\16\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\10\6\1\u02b8"+ + "\6\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u02b9"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\1\6\1\u02ba\1\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u02bb"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\12\6\1\u02bc"+ + "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\6\6\1\u02bd"+ + "\10\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u02be"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\277"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\157"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u02bf\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\3\6\1\u011f\13\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\12\6\1\u01fd\4\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\12\6\1\150\4\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u014b\6\6"+ + "\1\u02c0\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\10\6"+ + "\1\u02c1\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\12\6\1\151\24\6\4\0\1\4\6\6\1\0\12\6"+ + "\1\162\4\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ + "\1\u02c2\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\151\1\6"+ + "\1\0\7\6\1\151\27\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\u02c3"+ + "\1\6\1\0\37\6\4\0\1\4\6\6\1\0\6\6"+ + "\1\u02c4\10\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ + "\1\u011f\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\211\1\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u0145\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\1\u0270\1\6\1\0\37\6"+ + "\4\0\3\u015c\4\237\1\u015c\3\237\6\u015c\1\237\2\u015c"+ + "\1\237\6\u015c\1\241\5\u015c\1\237\1\u015c\1\0\2\u015c"+ + "\2\237\5\u015c\1\237\14\u015c\2\237\1\u015c\1\237\2\u015c"+ + "\1\237\17\u015c\2\237\4\u015c\2\237\4\u015c\3\244\4\45"+ + "\1\244\3\45\6\244\1\45\2\244\1\45\13\244\1\u0164"+ + "\1\45\2\244\1\u0165\1\244\2\45\5\244\1\45\14\244"+ + "\2\45\1\244\1\45\2\244\1\45\17\244\2\45\4\244"+ + "\2\45\4\244\1\4\6\6\1\0\10\6\1\u0124\6\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\13\6\1\u02c5\3\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\7\126\1\0\12\126\1\u02c6\4\126\11\0"+ + "\3\126\2\0\3\126\2\0\1\u02c6\1\126\1\0\1\126"+ + "\1\0\3\126\4\0\2\126\1\0\37\126\4\0\7\126"+ + "\1\0\5\126\1\u02c6\11\126\11\0\3\126\2\0\3\126"+ + "\2\0\1\126\1\u02c6\1\0\1\126\1\0\3\126\4\0"+ + "\2\126\1\0\37\126\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\1\u0259\1\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\10\6"+ + "\1\u02c7\26\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\6"+ + "\1\u016b\35\6\4\0\1\4\3\6\1\305\2\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ + "\1\u02c8\7\6\1\u0260\1\6\1\u02c9\21\6\4\0\7\4"+ + "\1\0\3\4\1\u0230\13\4\11\0\3\4\2\0\3\4"+ + "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ + "\1\0\37\4\4\0\7\4\1\0\2\4\1\u02ca\14\4"+ + "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ + "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ + "\1\0\1\4\1\u02ca\15\4\11\0\3\4\2\0\3\4"+ + "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ + "\1\0\37\4\4\0\7\4\1\0\10\4\1\u02cb\6\4"+ + "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ + "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ + "\1\0\1\4\1\u0230\15\4\11\0\3\4\2\0\3\4"+ + "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ + "\1\0\37\4\4\0\7\4\1\0\5\4\1\u02cc\11\4"+ + "\11\0\3\4\2\0\3\4\2\0\2\4\1\0\1\4"+ + "\1\0\3\4\4\0\2\4\1\0\37\4\4\0\7\4"+ + "\1\0\15\4\1\u02cd\1\4\11\0\3\4\2\0\3\4"+ + "\2\0\2\4\1\0\1\4\1\0\3\4\4\0\2\4"+ + "\1\0\37\4\16\0\1\u017d\131\0\1\u02ce\136\0\1\u02cf"+ + "\2\0\1\u02d0\134\0\1\u02d1\124\0\1\u02d2\3\0\1\u023d"+ + "\140\0\1\u02d3\126\0\1\u02d0\127\0\1\u02d2\147\0\1\u02d4"+ + "\107\0\1\4\6\6\1\0\14\6\1\u02d5\2\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\15\6\1\u02d6\1\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\5\6\1\u02d7\11\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\11\6\1\151\5\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\12\6\1\u02d8\4\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\6\1\u0145\1\0\12\6\1\151"+ + "\24\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\1\6\1\u02d9\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\6\1\u029e\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\4\6\1\u02da\12\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\1\6\1\151"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\1\6\1\u02db\15\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\1\u02dc\16\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\1\u02dd\1\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\16\6\1\u021c\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\1\257\1\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\11\6"+ + "\1\151\25\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\6\6"+ + "\2\151\27\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\6"+ + "\1\u02de\35\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\20\6"+ + "\1\u02df\16\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\u016b\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\13\6"+ + "\1\311\23\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\15\6"+ + "\1\u02e0\21\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\22\6"+ + "\1\151\14\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\305"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\10\6\1\u02e1\26\6"+ + "\4\0\1\4\5\6\1\u024d\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\16\6\1\151\20\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\15\6\1\u02e2\21\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\4\6\1\u02e3\32\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\14\6\1\u02e4\22\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\15\6\1\u02e5\21\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\5\6\1\u02e6\31\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\1\6\1\357\35\6\4\0"+ + "\1\4\5\6\1\347\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\u02e7\35\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\14\6\1\u0115\22\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\3\6\1\u02e8\33\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\u02e9\1\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\u02ea\35\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u022d\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u02eb\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\31\6\1\u02ec\5\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\u02ed\35\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\16\6\1\u0259\20\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\u02ee\35\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\2\6\1\u02ef\34\6\4\0\1\4\3\6"+ + "\1\u02f0\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\3\6"+ + "\1\u02f1\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\u02f2\16\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\5\6\1\u02f3\31\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\6"+ + "\1\347\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\10\6\1\u02f4\26\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\31\6\1\u02f5\5\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\17\6\1\u02f6\17\6\4\0\1\4\5\6\1\u02f7\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\11\6"+ + "\1\151\3\6\1\u01a1\21\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\1\u02f8"+ + "\1\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\13\6\1\u02f9\23\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\u0291\21\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\31\6\1\151\5\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\u02fa\21\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\1\6\1\u02fb"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\4\6"+ + "\1\151\32\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ + "\1\u02fc\33\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\6\6"+ + "\1\u02fd\30\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\1\262\1\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\5\6\1\u01a7\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\u02fe\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\5\6"+ + "\1\u02ff\31\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\6"+ + "\1\u0115\35\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\6\6"+ + "\1\u026f\30\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\6\6"+ + "\1\331\30\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\15\6"+ + "\1\u01a1\21\6\4\0\1\4\3\6\1\u0300\2\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\21\6"+ + "\1\u0251\15\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\6\6"+ + "\1\u0301\30\6\36\0\1\u0302\117\0\1\u01d5\51\0\1\u028b"+ + "\44\0\1\u028d\1\u0303\4\u028d\1\u0303\17\u028d\3\u0303\1\u028d"+ + "\1\u0303\2\0\2\u0303\1\0\2\u028d\2\0\3\u028d\1\0"+ + "\1\u0303\2\u028d\1\u0303\1\u028d\1\0\1\u0303\1\u028d\5\u0303"+ + "\2\u028d\1\u0303\37\u028d\2\0\1\u0303\33\0\1\u0304\117\0"+ + "\1\u01d9\51\0\1\u028e\44\0\1\u0290\1\u0305\4\u0290\1\u0305"+ + "\17\u0290\3\u0305\1\u0290\1\u0305\2\0\2\u0305\1\0\2\u0290"+ + "\2\0\3\u0290\1\0\1\u0305\2\u0290\1\u0305\1\u0290\1\0"+ + "\1\u0305\1\u0290\5\u0305\2\u0290\1\u0305\37\u0290\2\0\1\u0305"+ + "\1\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\1\6\1\347\35\6"+ + "\4\0\1\4\5\6\1\305\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\u0306\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\30\6\1\u01fa\6\6\4\0\1\4\5\6"+ + "\1\u0307\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\14\6\1\u0308\22\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\u0309\1\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\13\6\1\u030a\23\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\5\6\1\u030b\31\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\21\6\1\u030c\15\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u02e3\21\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u030d\21\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\2\6\1\u016a\34\6\4\0\1\4\5\6"+ + "\1\u024f\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\14\6\1\157\2\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\6\1\224\15\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\6\1\u030e\1\6\1\u030f\13\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\4\6\1\u0310\12\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\12\6\1\u0311\4\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\10\6\1\u0312\6\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\2\6\1\u0313\14\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\16\6\1\u0314\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\1\6\1\u02b3\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\1\6\1\u012b\1\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\6\1\u021a\15\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ + "\1\u0315\1\0\37\6\4\0\1\4\6\6\1\0\3\6"+ + "\1\u0316\13\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\12\6\1\u0317\24\6\4\0\1\4\6\6\1\0\10\6"+ + "\1\u0318\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\26\6\1\u0319\10\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\33\6\1\u02b3\3\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u031a"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u031b"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u031c"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\u01ef"+ + "\36\6\4\0\1\4\6\6\1\0\11\6\1\u0145\5\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\13\6\1\151\3\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\6\6\1\u031d\10\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\u031e\11\6\1\u02b5"+ + "\4\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\36\6\1\151\4\0\1\4\6\6\1\0\12\6"+ + "\1\u031f\4\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\4\6"+ + "\1\224\12\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\u0320\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\4\6"+ + "\1\u0321\12\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\5\6"+ + "\1\211\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\5\6"+ + "\1\u0322\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u0323"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u01fe"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\7\6\1\u02c1"+ + "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u0324\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\15\6\1\u0145\1\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\14\6\1\u0315\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u0325\15\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u0326\15\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u0327"+ + "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u0328"+ + "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\11\6\1\u0329"+ + "\25\6\4\0\7\4\1\0\7\4\1\u02ca\7\4\11\0"+ + "\3\4\2\0\3\4\2\0\2\4\1\0\1\4\1\0"+ + "\3\4\4\0\2\4\1\0\37\4\4\0\7\4\1\0"+ + "\12\4\1\u032a\4\4\11\0\3\4\2\0\3\4\2\0"+ + "\2\4\1\0\1\4\1\0\3\4\4\0\2\4\1\0"+ + "\37\4\4\0\7\4\1\0\16\4\1\u032b\11\0\3\4"+ + "\2\0\3\4\2\0\2\4\1\0\1\4\1\0\3\4"+ + "\4\0\2\4\1\0\37\4\17\0\1\u02cf\132\0\1\u032c"+ + "\132\0\1\u032c\142\0\1\u032d\124\0\1\u02cf\137\0\1\u032e"+ + "\143\0\1\u032f\106\0\1\4\6\6\1\0\7\6\1\u0330"+ + "\7\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u0331"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0332"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\1\6\1\u0333\1\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u0334"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u01cf"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\u0335\5\6"+ + "\1\151\10\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\14\6"+ + "\1\u0244\2\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u0336"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\17\6"+ + "\1\u01a1\17\6\4\0\1\4\5\6\1\u0337\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u0338"+ + "\22\6\4\0\1\4\5\6\1\u0339\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\24\6\1\u01e5\12\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\u033a\23\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\14\6\1\u0257\22\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\1\u033b\1\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\15\6\1\u033c\21\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\1\6\1\u033d\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\6\1\331\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u033e\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\3\6\1\u033f\33\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\20\6\1\151\16\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\4\6\1\u01a1\32\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\13\6\1\305\23\6\4\0\1\4\5\6"+ + "\1\u0340\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\3\6\1\u0341"+ + "\2\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\u02ec\1\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\36\6\1\151\4\0\1\4"+ + "\5\6\1\u0307\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\u030e\15\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\32\6\1\u02e3\4\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\25\6\1\u0342\11\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\5\6\1\u0343\31\6\4\0\1\4\5\6"+ + "\1\u0344\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\3\6\1\u0345"+ + "\2\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\3\6\1\151\33\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\2\6\1\u0346\34\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\u01ce\35\6\4\0\1\4"+ + "\5\6\1\u0347\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\1\6\1\u0348\35\6\4\0\1\4\5\6"+ + "\1\u0349\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\1\6\1\u030d\35\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\10\6\1\u02ff\26\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\15\6\1\u034a\21\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\1\6\1\u0277\35\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\15\6\1\u034b\21\6\36\0\1\u028d\133\0\1\u0290"+ + "\101\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\11\6\1\u034c\7\6"+ + "\1\u030c\1\u034d\14\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\1\6\1\u034e"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\151"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\2\6\1\u034f\34\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\11\6\1\u034c\7\6"+ + "\1\u030c\1\u034d\1\6\1\u0350\12\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\13\6\1\u0113\23\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\5\6\1\u0351\31\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u0352\26\6\4\0\1\4\6\6"+ + "\1\0\5\6\1\u0353\11\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\2\6\1\151\14\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\16\6\1\u0314\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\u0354\11\6\1\u0355\10\6\1\u0356"+ + "\13\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\1\6\1\u0357\1\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\4\6\1\u011b\12\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\16\6\1\u0314\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\12\6"+ + "\1\u0355\10\6\1\u0356\13\6\4\0\1\4\6\6\1\0"+ + "\10\6\1\u0358\6\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\7\6\1\u0359\7\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\33\6\1\u0145\3\6\4\0\1\4\6\6\1\0"+ + "\13\6\1\u0145\3\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\2\6\1\u015b\14\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\1\u0150\16\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\10\6"+ + "\1\u0246\6\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\11\6"+ + "\1\u035a\5\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u035b"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u015b"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\10\6\1\u035c"+ + "\6\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u0124"+ + "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\1\6\1\u035d\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\15\6\1\151\1\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\14\6\1\164\2\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u035e\15\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\3\6\1\u035f\13\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\7\6\1\u0360\7\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\7\6\1\u0361\7\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\5\6\1\u027a"+ + "\31\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\32\6\1\u01a1"+ + "\4\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\20\6\1\u01a1"+ + "\16\6\4\0\7\4\1\0\1\u0231\16\4\11\0\3\4"+ + "\2\0\3\4\2\0\2\4\1\0\1\4\1\0\3\4"+ + "\4\0\2\4\1\0\37\4\4\0\7\4\1\0\14\4"+ + "\1\u02ca\2\4\11\0\3\4\2\0\3\4\2\0\2\4"+ + "\1\0\1\4\1\0\3\4\4\0\2\4\1\0\37\4"+ + "\23\0\1\u032c\136\0\1\u0362\137\0\1\u0363\105\0\1\4"+ + "\6\6\1\0\11\6\1\u0364\5\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\1\6\1\u0359\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\12\6\1\u012b\24\6\4\0\1\4\6\6"+ + "\1\0\5\6\1\u0145\11\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\15\6\1\u012b\1\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\14\6\1\u0365\2\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\1\6\1\u0366\15\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u0367\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u0368\21\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\4\6\1\u0369\32\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\17\6\1\151\17\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\13\6\1\u016b\23\6\4\0\1\4\5\6"+ + "\1\u036a\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\1\6\1\256\35\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\4\6\1\u036b\32\6\4\0\1\4\5\6\1\u01ca"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\u036c\21\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\5\6\1\u036d\31\6\4\0\1\4\3\6\1\u0191\2\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\u01ca\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u0352"+ + "\21\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\u036e"+ + "\35\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\1\6\1\u01a1\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\17\6\1\u016a\17\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\11\6\1\u016a\25\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\10\6\1\u036f\26\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\14\6\1\u0370\22\6"+ + "\4\0\1\4\5\6\1\u0371\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\37\6\4\0"+ + "\1\4\5\6\1\331\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\1\u0372\1\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\15\6\1\u0373\21\6\4\0\1\4\3\6"+ + "\1\u0374\2\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\5\6"+ + "\1\u0375\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\13\6\1\u029a\23\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\13\6\1\u024e\23\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ + "\1\u0376\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\u0377\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\6"+ + "\1\211\15\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\12\6"+ + "\1\u0378\4\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\1\u0379"+ + "\16\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u02a6"+ + "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\4\6\1\u021b"+ + "\12\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\3\6\1\u037a"+ + "\13\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\1\u011f"+ + "\36\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\1\u037b\36\6"+ + "\4\0\1\4\6\6\1\0\4\6\1\u0379\12\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\10\6\1\u011f\6\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\1\u037c\5\6\1\0\1\u037d\16\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\14\6\1\u02c1\2\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\14\0\1\u02d0\147\0\1\u032c\107\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\u021a"+ + "\1\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\1\6\1\u037e"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\u037f\16\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\u02ff"+ + "\35\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\14\6\1\u0380"+ + "\22\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\13\6\1\u0374"+ + "\23\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\6\6\1\u024f"+ + "\30\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\24\6\1\u0381"+ + "\12\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\24\6\1\u0115"+ + "\12\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\15\6\1\u0382"+ + "\21\6\4\0\1\4\3\6\1\u0383\2\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\34\6\1\u0384\2\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\5\6\1\u0115\31\6\4\0\1\4\3\6\1\u0385\2\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\1\6\1\u0386\35\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\1\6\1\151\35\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\1\6\1\u0287\35\6\4\0\1\4\5\6\1\u0387\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\151"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u0388"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0389"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u0222"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\6\6\1\u0145"+ + "\10\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u038a"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\10\6\1\u038b"+ + "\6\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\1\6\1\u038c"+ + "\15\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u038d"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\14\6\1\u038e"+ + "\2\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\3\6"+ + "\1\u01a1\33\6\4\0\1\4\5\6\1\u038f\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\17\6\11\0\1\4"+ + "\2\6\2\0\3\6\2\0\2\6\1\0\1\6\1\0"+ + "\1\4\1\6\1\4\4\0\2\6\1\0\1\6\1\u0390"+ + "\35\6\4\0\1\4\5\6\1\u0391\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\5\6\1\u0392\31\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\1\6\1\u0393\35\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\10\6\1\u0394\26\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\25\6\1\151\11\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\26\6\1\151\10\6"+ + "\4\0\1\4\6\6\1\0\7\6\1\u0395\7\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\1\6\1\u011f\15\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\1\6\1\u0396\1\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\13\6\1\u0397\3\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\2\6\1\u0398\3\6\1\151"+ + "\10\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\1\223\2\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\5\6\1\u0115\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\u0399\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\3\6\1\151\33\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\20\6\1\u039a\16\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\2\6\1\u039b\34\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\16\6\1\313\20\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\15\6\1\u016a\21\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\6\1\u012b\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\1\6\1\u039c\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\14\6\1\u039d\2\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\3\6\1\u039e\13\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\14\6\1\u039f\22\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\1\6\1\u03a0\35\6\4\0\1\4"+ + "\6\6\1\0\17\6\11\0\1\4\2\6\2\0\3\6"+ + "\2\0\2\6\1\0\1\6\1\0\1\4\1\6\1\4"+ + "\4\0\2\6\1\0\15\6\1\u03a1\21\6\4\0\1\4"+ + "\6\6\1\0\3\6\1\u03a2\13\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\7\6\1\u03a3\7\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\6\6\1\0\1\6\1\u0120\15\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\37\6\4\0\1\4"+ + "\5\6\1\u016f\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\37\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\10\6\1\u03a4\26\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\14\6\1\u03a5\22\6\4\0\1\4\6\6"+ + "\1\0\17\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\1\6\1\u03a6\1\0\37\6\4\0\1\4\6\6\1\0"+ + "\17\6\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\1\6"+ + "\1\u03a7\1\0\37\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\u03a8\21\6\4\0\1\4\6\6\1\0\17\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\15\6\1\u03a9\21\6\4\0\1\4\6\6\1\0\5\6"+ + "\1\u029f\11\6\11\0\1\4\2\6\2\0\3\6\2\0"+ + "\2\6\1\0\1\6\1\0\1\4\1\6\1\4\4\0"+ + "\2\6\1\0\37\6\4\0\1\4\6\6\1\0\16\6"+ + "\1\u03aa\11\0\1\4\2\6\2\0\3\6\2\0\2\6"+ + "\1\0\1\6\1\0\1\4\1\6\1\4\4\0\2\6"+ + "\1\0\37\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\21\6"+ + "\1\u03ab\15\6\4\0\1\4\6\6\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\1\6\1\u0292\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\6\6\1\0\1\6\1\u03ac\15\6"+ + "\11\0\1\4\2\6\2\0\3\6\2\0\2\6\1\0"+ + "\1\6\1\0\1\4\1\6\1\4\4\0\2\6\1\0"+ + "\37\6\4\0\1\4\5\6\1\u03ad\1\0\17\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\4\6\1\u03ae\12\6\11\0"+ + "\1\4\2\6\2\0\3\6\2\0\2\6\1\0\1\6"+ + "\1\0\1\4\1\6\1\4\4\0\2\6\1\0\37\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\2\6\1\0\13\6\1\u03af\23\6"+ + "\4\0\1\4\6\6\1\0\17\6\11\0\1\4\2\6"+ + "\2\0\3\6\2\0\2\6\1\0\1\6\1\0\1\4"+ + "\1\6\1\4\4\0\1\6\1\224\1\0\37\6\4\0"+ + "\1\4\6\6\1\0\17\6\11\0\1\4\2\6\2\0"+ + "\3\6\2\0\2\6\1\0\1\6\1\0\1\4\1\6"+ + "\1\4\4\0\2\6\1\0\15\6\1\305\21\6\4\0"; private static int [] zzUnpackTrans() { - int [] result = new int[79028]; + int [] result = new int[84180]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -2672,9 +2849,9 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { /* error messages for the codes above */ private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" }; /** @@ -2683,17 +2860,17 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\3\0\30\1\1\11\4\1\1\11\2\1\1\11\11\1"+ - "\1\11\1\1\1\11\33\1\1\11\5\1\1\11\110\1"+ - "\1\0\2\11\2\1\1\11\3\1\1\11\24\1\1\0"+ - "\77\1\2\0\1\11\6\0\2\1\1\0\117\1\1\11"+ - "\7\1\1\11\24\1\6\0\121\1\10\0\2\1\1\0"+ - "\115\1\4\0\1\1\4\0\104\1\2\0\1\1\2\0"+ - "\65\1\7\0\46\1\4\0\40\1\1\11\3\0\54\1"+ - "\2\0\116\1"; + "\3\0\30\1\1\11\4\1\1\11\2\1\1\11\11\1"+ + "\1\11\1\1\1\11\33\1\1\11\5\1\1\11\111\1"+ + "\1\0\2\11\2\1\1\11\3\1\1\11\25\1\1\0"+ + "\101\1\2\0\1\11\6\0\2\1\1\0\124\1\1\11"+ + "\7\1\1\11\24\1\6\0\124\1\10\0\2\1\1\0"+ + "\127\1\4\0\1\1\4\0\114\1\2\0\1\1\2\0"+ + "\76\1\7\0\55\1\4\0\46\1\1\11\3\0\62\1"+ + "\2\0\114\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[887]; + int [] result = new int[943]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -2721,7 +2898,7 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { private int zzLexicalState = YYINITIAL; /** this buffer contains the current text to be matched and is - the source of the yytext() string */ + the source of the yytext() string */ private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; /** the textposition at the last accepting state */ @@ -2737,7 +2914,7 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { private int zzStartRead; /** endRead marks the last character in the buffer, that has been read - from input */ + from input */ private int zzEndRead; /** number of newlines encountered up to the start of the matched text */ @@ -2747,12 +2924,12 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { private int yychar; /** - * the number of characters from the last newline up to the start of the + * the number of characters from the last newline up to the start of the * matched text */ private int yycolumn; - /** + /** * zzAtBOL == true <=> the scanner is currently at the beginning of a line */ private boolean zzAtBOL = true; @@ -2762,165 +2939,163 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { /* user code: */ - /** - * Constructor. This must be here because JFlex does not generate a - * no-parameter constructor. - */ - public FormulaTokenMaker() { - super(); - } - - - /** - * Adds the token specified to the current linked list of tokens. - * - * @param tokenType The token's type. - * @see #addToken(int, int, int) - */ - private void addHyperlinkToken(int start, int end, int tokenType) { - int so = start + offsetShift; - addToken(zzBuffer, start,end, tokenType, so, true); - } - - - /** - * Adds the token specified to the current linked list of tokens. - * - * @param tokenType The token's type. - */ - private void addToken(int tokenType) { - addToken(zzStartRead, zzMarkedPos-1, tokenType); - } - - - /** - * Adds the token specified to the current linked list of tokens. - * - * @param tokenType The token's type. - */ - private void addToken(int start, int end, int tokenType) { - int so = start + offsetShift; - addToken(zzBuffer, start,end, tokenType, so); - } - - - /** - * Adds the token specified to the current linked list of tokens. - * - * @param array The character array. - * @param start The starting offset in the array. - * @param end The ending offset in the array. - * @param tokenType The token's type. - * @param startOffset The offset in the document at which this token - * occurs. - */ - @Override - public void addToken(char[] array, int start, int end, int tokenType, int startOffset) { - super.addToken(array, start,end, tokenType, startOffset); - zzStartRead = zzMarkedPos; - } - - - /** - * Returns the text to place at the beginning and end of a - * line to "comment" it in a this programming language. - * - * @return The start and end strings to add to a line to "comment" - * it out. - */ - @Override - public String[] getLineCommentStartAndEnd() { - return new String[] { "//", null }; - } - - - /** - * Returns the first token in the linked list of tokens generated - * from text. This method must be implemented by - * subclasses so they can correctly implement syntax highlighting. - * - * @param text The text from which to get tokens. - * @param initialTokenType The token type we should start with. - * @param startOffset The offset into the document at which - * text starts. - * @return The first Token in a linked list representing - * the syntax highlighted text. - */ - public Token getTokenList(Segment text, int initialTokenType, int startOffset) { - - resetTokenList(); - this.offsetShift = -text.offset + startOffset; - - // Start off in the proper state. - int state = Token.NULL; - switch (initialTokenType) { - case Token.COMMENT_MULTILINE: - state = MLC; - start = text.offset; - break; - default: - state = Token.NULL; - } - - s = text; - try { - yyreset(zzReader); - yybegin(state); - return yylex(); - } catch (IOException ioe) { - ioe.printStackTrace(); - return new TokenImpl(); - } - - } - - - /** - * Refills the input buffer. - * - * @return true if EOF was reached, otherwise - * false. - * @exception IOException if any I/O-Error occurs. - */ - private boolean zzRefill() throws java.io.IOException { - return zzCurrentPos>=s.offset+s.count; - } - - - /** - * Resets the scanner to read from a new input stream. - * Does not close the old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). - * Lexical state is set to YY_INITIAL. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) throws java.io.IOException { - // 's' has been updated. - zzBuffer = s.array; - /* - * We replaced the line below with the two below it because zzRefill - * no longer "refills" the buffer (since the way we do it, it's always - * "full" the first time through, since it points to the segment's - * array). So, we assign zzEndRead here. - */ - //zzStartRead = zzEndRead = s.offset; - zzStartRead = s.offset; - zzEndRead = zzStartRead + s.count - 1; - zzCurrentPos = zzMarkedPos = zzPushbackPos = s.offset; - zzLexicalState = YYINITIAL; - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - } - - public final String test() { - return "abs|ABS|COUNT|count"; - } + /** + * Constructor. This must be here because JFlex does not generate a + * no-parameter constructor. + */ + public FormulaTokenMaker() { + super(); + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param tokenType The token's type. + * @see #addToken(int, int, int) + */ + private void addHyperlinkToken(int start, int end, int tokenType) { + int so = start + offsetShift; + addToken(zzBuffer, start,end, tokenType, so, true); + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param tokenType The token's type. + */ + private void addToken(int tokenType) { + addToken(zzStartRead, zzMarkedPos-1, tokenType); + } + + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param tokenType The token's type. + */ + private void addToken(int start, int end, int tokenType) { + int so = start + offsetShift; + addToken(zzBuffer, start,end, tokenType, so); + } + + /** + * Adds the token specified to the current linked list of tokens. + * + * @param array The character array. + * @param start The starting offset in the array. + * @param end The ending offset in the array. + * @param tokenType The token's type. + * @param startOffset The offset in the document at which this token + * occurs. + */ + @Override + public void addToken(char[] array, int start, int end, int tokenType, int startOffset) { + super.addToken(array, start,end, tokenType, startOffset); + zzStartRead = zzMarkedPos; + } + + + /** + * Returns the text to place at the beginning and end of a + * line to "comment" it in a this programming language. + * + * @return The start and end strings to add to a line to "comment" + * it out. + */ + @Override + public String[] getLineCommentStartAndEnd() { + return new String[] { "//", null }; + } + + + /** + * Returns the first token in the linked list of tokens generated + * from text. This method must be implemented by + * subclasses so they can correctly implement syntax highlighting. + * + * @param text The text from which to get tokens. + * @param initialTokenType The token type we should start with. + * @param startOffset The offset into the document at which + * text starts. + * @return The first Token in a linked list representing + * the syntax highlighted text. + */ + public Token getTokenList(Segment text, int initialTokenType, int startOffset) { + + resetTokenList(); + this.offsetShift = -text.offset + startOffset; + + // Start off in the proper state. + int state = Token.NULL; + switch (initialTokenType) { + case Token.COMMENT_MULTILINE: + state = MLC; + start = text.offset; + break; + default: + state = Token.NULL; + } + + s = text; + try { + yyreset(zzReader); + yybegin(state); + return yylex(); + } catch (IOException ioe) { + ioe.printStackTrace(); + return new TokenImpl(); + } + + } + + + /** + * Refills the input buffer. + * + * @return true if EOF was reached, otherwise + * false. + * @throws IOException if any I/O-Error occurs. + */ + private boolean zzRefill() throws java.io.IOException { + return zzCurrentPos >= s.offset + s.count; + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to YY_INITIAL. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) throws java.io.IOException { + // 's' has been updated. + zzBuffer = s.array; + /* + * We replaced the line below with the two below it because zzRefill + * no longer "refills" the buffer (since the way we do it, it's always + * "full" the first time through, since it points to the segment's + * array). So, we assign zzEndRead here. + */ + //zzStartRead = zzEndRead = s.offset; + zzStartRead = s.offset; + zzEndRead = zzStartRead + s.count - 1; + zzCurrentPos = zzMarkedPos = zzPushbackPos = s.offset; + zzLexicalState = YYINITIAL; + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + } + public final String test() { + return "abs|ABS|COUNT|count"; + } /** @@ -2943,7 +3118,7 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { this(new java.io.InputStreamReader(in)); } - /** + /** * Unpacks the compressed character translation table. * * @param packed the packed character translation table @@ -2961,8 +3136,6 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { return map; } - - /** * Closes the input stream. */ @@ -2976,6 +3149,7 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { + /** * Returns the current lexical state. */ @@ -3003,12 +3177,12 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { /** - * Returns the character at position pos from the - * matched text. - * + * Returns the character at position pos from the + * matched text. + * * It is equivalent to yytext().charAt(pos), but faster * - * @param pos the position of the character to fetch. + * @param pos the position of the character to fetch. * A value from 0 to yylength()-1. * * @return the character at position pos @@ -3029,8 +3203,8 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { /** * Reports an error that occured while scanning. * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method * will only be called with things that "Can't Possibly Happen". * If this method is called, something is seriously wrong * (e.g. a JFlex bug producing a faulty scanner etc.). @@ -3050,7 +3224,7 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { } throw new Error(message); - } + } /** @@ -3097,13 +3271,13 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { zzAction = -1; zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - + zzState = zzLexicalState; zzForAction: { while (true) { - + if (zzCurrentPosL < zzEndReadL) zzInput = zzBufferL[zzCurrentPosL++]; else if (zzAtEOF) { @@ -3146,134 +3320,134 @@ public class FormulaTokenMaker extends AbstractJFlexCTokenMaker { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 25: - { addToken(Token.PREPROCESSOR); - } + case 25: + { addToken(Token.PREPROCESSOR); + } case 28: break; - case 7: - { addNullToken(); return firstToken; - } + case 7: + { addNullToken(); return firstToken; + } case 29: break; - case 22: - { addToken(Token.LITERAL_CHAR); - } + case 22: + { addToken(Token.LITERAL_CHAR); + } case 30: break; - case 21: - { yybegin(YYINITIAL); addToken(start,zzStartRead+1, Token.COMMENT_MULTILINE); - } + case 21: + { yybegin(YYINITIAL); addToken(start,zzStartRead+1, Token.COMMENT_MULTILINE); + } case 31: break; - case 17: - { start = zzMarkedPos-2; yybegin(MLC); - } + case 17: + { start = zzMarkedPos-2; yybegin(MLC); + } case 32: break; - case 9: - { addToken(Token.WHITESPACE); - } + case 9: + { addToken(Token.WHITESPACE); + } case 33: break; - case 24: - { addToken(Token.LITERAL_NUMBER_HEXADECIMAL); - } + case 24: + { addToken(Token.LITERAL_NUMBER_HEXADECIMAL); + } case 34: break; - case 18: - { addToken(Token.ERROR_CHAR); /*addNullToken(); return firstToken;*/ - } + case 18: + { addToken(Token.ERROR_CHAR); /*addNullToken(); return firstToken;*/ + } case 35: break; - case 23: - { addToken(Token.ERROR_STRING_DOUBLE); - } + case 23: + { addToken(Token.ERROR_STRING_DOUBLE); + } case 36: break; - case 14: - { addToken(Token.LITERAL_NUMBER_FLOAT); - } + case 14: + { addToken(Token.LITERAL_NUMBER_FLOAT); + } case 37: break; - case 15: - { addToken(Token.RESERVED_WORD); - } + case 15: + { addToken(Token.RESERVED_WORD); + } case 38: break; - case 5: - { addToken(Token.SEPARATOR); - } + case 5: + { addToken(Token.SEPARATOR); + } case 39: break; - case 2: - { addToken(Token.IDENTIFIER); - } + case 2: + { addToken(Token.IDENTIFIER); + } case 40: break; - case 12: - { addToken(start,zzStartRead-1, Token.COMMENT_EOL); addNullToken(); return firstToken; - } + case 12: + { addToken(start,zzStartRead-1, Token.COMMENT_EOL); addNullToken(); return firstToken; + } case 41: break; - case 16: - { start = zzMarkedPos-2; yybegin(EOL_COMMENT); - } + case 16: + { start = zzMarkedPos-2; yybegin(EOL_COMMENT); + } case 42: break; - case 6: - { addToken(Token.ERROR_CHAR); addNullToken(); return firstToken; - } + case 6: + { addToken(Token.ERROR_CHAR); addNullToken(); return firstToken; + } case 43: break; - case 8: - { addToken(Token.ERROR_STRING_DOUBLE); addNullToken(); return firstToken; - } + case 8: + { addToken(Token.ERROR_STRING_DOUBLE); addNullToken(); return firstToken; + } case 44: break; - case 1: - { addToken(Token.ERROR_IDENTIFIER); - } + case 1: + { addToken(Token.ERROR_IDENTIFIER); + } case 45: break; - case 19: - { addToken(Token.ERROR_CHAR); - } + case 19: + { addToken(Token.ERROR_CHAR); + } case 46: break; - case 20: - { addToken(Token.LITERAL_STRING_DOUBLE_QUOTE); - } + case 20: + { addToken(Token.LITERAL_STRING_DOUBLE_QUOTE); + } case 47: break; - case 27: - { int temp=zzStartRead; addToken(start,zzStartRead-1, Token.COMMENT_EOL); addHyperlinkToken(temp,zzMarkedPos-1, Token.COMMENT_EOL); start = zzMarkedPos; - } + case 27: + { int temp=zzStartRead; addToken(start,zzStartRead-1, Token.COMMENT_EOL); addHyperlinkToken(temp,zzMarkedPos-1, Token.COMMENT_EOL); start = zzMarkedPos; + } case 48: break; - case 26: - { int temp=zzStartRead; addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); addHyperlinkToken(temp,zzMarkedPos-1, Token.COMMENT_MULTILINE); start = zzMarkedPos; - } + case 26: + { int temp=zzStartRead; addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); addHyperlinkToken(temp,zzMarkedPos-1, Token.COMMENT_MULTILINE); start = zzMarkedPos; + } case 49: break; - case 13: - { addToken(Token.ERROR_NUMBER_FORMAT); - } + case 13: + { addToken(Token.ERROR_NUMBER_FORMAT); + } case 50: break; - case 3: - { addToken(Token.LITERAL_NUMBER_DECIMAL_INT); - } + case 3: + { addToken(Token.LITERAL_NUMBER_DECIMAL_INT); + } case 51: break; - case 4: - { addToken(Token.OPERATOR); - } + case 4: + { addToken(Token.OPERATOR); + } case 52: break; - case 10: - { - } + case 10: + { + } case 53: break; - case 11: - { addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); return firstToken; - } + case 11: + { addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); return firstToken; + } case 54: break; - default: + default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; switch (zzLexicalState) { - case EOL_COMMENT: { - addToken(start,zzStartRead-1, Token.COMMENT_EOL); addNullToken(); return firstToken; + case EOL_COMMENT: { + addToken(start,zzStartRead-1, Token.COMMENT_EOL); addNullToken(); return firstToken; + } + case 944: break; + case YYINITIAL: { + addNullToken(); return firstToken; + } + case 945: break; + case MLC: { + addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); return firstToken; + } + case 946: break; + default: + return null; } - case 888: break; - case YYINITIAL: { - addNullToken(); return firstToken; - } - case 889: break; - case MLC: { - addToken(start,zzStartRead-1, Token.COMMENT_MULTILINE); return firstToken; - } - case 890: break; - default: - return null; - } - } + } else { zzScanError(ZZ_NO_MATCH); } diff --git a/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java b/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java index 65bec03a8..c9344f5ca 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java @@ -63,7 +63,9 @@ public class JSContentPane extends BasicPane { initFunctionTitle(args); JPanel jsParaPane = createJSParaPane(); - addNewPaneLabel(); + if (needAdvancedEditor()) { + addNewPaneLabel(); + } this.add(jsParaPane, BorderLayout.NORTH); UIScrollPane sp = createContentTextAreaPanel(); @@ -323,4 +325,8 @@ public class JSContentPane extends BasicPane { return provider; } + + protected boolean needAdvancedEditor() { + return true; + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java b/designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java index d60b97d0f..0340fc3de 100644 --- a/designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java +++ b/designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java @@ -1,5 +1,6 @@ package com.fr.design.login.socketio; +import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.login.DesignerLoginType; import com.fr.design.login.bean.BBSAccountLogin; @@ -11,7 +12,11 @@ import com.fr.third.socketio.Configuration; import com.fr.third.socketio.SocketIOClient; import com.fr.third.socketio.SocketIOServer; import com.fr.third.socketio.listener.DataListener; + import java.net.URLDecoder; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; /** * @author Lanlan @@ -19,9 +24,11 @@ import java.net.URLDecoder; * Created by Lanlan on 2021/6/3 */ public class LoginAuthServer { + + private AtomicBoolean started = new AtomicBoolean(false); private SocketIOServer server; - + private static final String HOSTNAME = "localhost"; private static final int PORT = 41925; @@ -47,6 +54,23 @@ public class LoginAuthServer { } public void start() { + + // 只运行一次,不在乎成不成功 + if (started.compareAndSet(false, true)) { + asyncStart(); + } + } + + public void asyncStart() { + + ExecutorService asyncService = Executors.newSingleThreadExecutor(new NamedThreadFactory(LoginAuthServer.class.getName(), true)); + asyncService.submit(this::compatibleStart); + asyncService.shutdown(); + } + + @Deprecated + public void compatibleStart() { + try { server.start(); } catch (Exception e) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java b/designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java index d3cff1ff9..dc36836c1 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java @@ -10,7 +10,7 @@ import javax.swing.JComponent; * Date: 13-7-15 * Time: 上午10:28 */ -public interface BaseJForm extends JTemplateProvider { +public interface BaseJForm extends JTemplateProvider, JDashboard { String XML_TAG = "JForm"; int FORM_TAB = 0; @@ -58,4 +58,9 @@ public interface BaseJForm extends JTemplateProvider { * @param ecContainer ElementCase所在container */ void tabChanged(int index, FormElementCaseContainerProvider ecContainer); + + @Override + default void switchToDashBoardEditor() { + tabChanged(FORM_TAB); + } } \ No newline at end of file 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 d31b5ede0..20c8c580a 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 @@ -220,7 +220,7 @@ public class CenterRegionContainerPane extends JPanel { * * @param plus 工具条中相关信息 */ - protected void resetToolkitByPlus(ToolBarMenuDockPlus plus, ToolBarMenuDock ad) { + protected void resetToolkitByPlus(ToolBarMenuDockPlus plus, ToolBarMenuDock ad, ToolKitConfigStrategy strategy) { resetCombineUpTooBar(ad.resetUpToolBar(plus), plus); @@ -230,28 +230,40 @@ public class CenterRegionContainerPane extends JPanel { // 颜色,字体那些按钮的工具栏 toolbarPane.add(toolbarComponent = ad.resetToolBar(toolbarComponent, plus), BorderLayout.CENTER); - - if (plus.hasToolBarPane()) { + if (strategy.hasToolBarPane(plus)) { this.add(toolbarPane, BorderLayout.NORTH); } else { this.remove(toolbarPane); } + if (strategy.hasTemplateTabPane(plus)) { + eastCenterPane.add(templateTabPane, BorderLayout.CENTER); + } else { + eastCenterPane.remove(templateTabPane); + } + + if (strategy.hasCombineUp(plus)) { + eastCenterPane.add(combineUp, BorderLayout.NORTH); + } else { + eastCenterPane.remove(combineUp); + } resetByDesignMode(); } private void resetByDesignMode() { if (DesignModeContext.isDuchampMode()) { eastPane.remove(largeToolbar); - eastCenterPane.remove(templateTabPane); - centerTemplateCardPane.refresh(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()); + //移除新建模板按钮 + templateTabPane.remove(newWorkBookPane); } else { eastPane.add(largeToolbar, BorderLayout.WEST); - eastCenterPane.add(templateTabPane, BorderLayout.CENTER); - } + templateTabPane.add(newWorkBookPane, BorderLayout.WEST); + } } + + JComponent getToolbarComponent() { return this.toolbarComponent; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java b/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java new file mode 100644 index 000000000..305c44aa2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java @@ -0,0 +1,21 @@ +package com.fr.design.mainframe; + +import com.fr.design.base.mode.DesignModeContext; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; + +public class DefaultToolKitConfig implements ToolKitConfigStrategy { + @Override + public boolean hasTemplateTabPane(ToolBarMenuDockPlus plus) { + return !DesignModeContext.isDuchampMode(); + } + + @Override + public boolean hasCombineUp(ToolBarMenuDockPlus plus) { + return plus.hasToolBarPane(); + } + + @Override + public boolean hasToolBarPane(ToolBarMenuDockPlus plus) { + return plus.hasToolBarPane(); + } +} 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 2534de526..812cb86b1 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 @@ -4,6 +4,7 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; +import com.fr.base.OptimizeUtil; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; @@ -42,6 +43,7 @@ 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.ConfigToPropMigrator; import com.fr.exit.DesignerExiter; import com.fr.file.FILE; import com.fr.file.FILEFactory; @@ -369,7 +371,12 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta public void fireDesignerOpened() { for (DesignerOpenedListener listener : designerOpenedListenerList) { - listener.designerOpened(); + // 捕获下异常 避免造成启动过程监听触发异常导致设计器闪退 + try { + listener.designerOpened(); + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } } designerOpened = true; @@ -614,6 +621,10 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta * @param plus 工具条中相关信息 */ public void resetToolkitByPlus(ToolBarMenuDockPlus plus) { + resetToolkitByPlus(plus, new DefaultToolKitConfig()); + } + + public void resetToolkitByPlus(ToolBarMenuDockPlus plus, ToolKitConfigStrategy strategy) { if (plus == null) { plus = ToolBarMenuDock.NULLAVOID; @@ -621,7 +632,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta NorthRegionContainerPane.getInstance().resetToolkitByPlus(plus, ad); - CenterRegionContainerPane.getInstance().resetToolkitByPlus(plus, ad); + CenterRegionContainerPane.getInstance().resetToolkitByPlus(plus, ad, strategy); this.checkToolbarMenuEnable(); this.validate(); @@ -1071,6 +1082,10 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta DesignerEnvManager.getEnvManager().setLastEastRegionContainerWidth( EastRegionContainerPane.getInstance().getContainerWidth()); + OptimizeUtil.open(() -> { + ConfigToPropMigrator.getInstance().execute(); + }); + DesignerEnvManager.getEnvManager().saveXMLFile(); } 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 2b7a321a8..ab30582dd 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 @@ -11,6 +11,7 @@ import com.fr.design.actions.UpdateAction; 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.management.search.TableDataTreeSearchManager; import com.fr.design.data.tabledata.ResponseDataSourceChange; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.file.FileOperations; @@ -244,6 +245,9 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt DesignModelAdapter.setCurrentModelAdapter(jt.getModel()); fireDSChanged(); + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); HistoryTemplateListPane.getInstance().setCurrentEditingTemplate(jt); //处理自动新建的模板 diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java b/designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java new file mode 100644 index 000000000..d2b45f4ea --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java @@ -0,0 +1,10 @@ +package com.fr.design.mainframe; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2022/3/1 + */ +public interface JDashboard { + void switchToDashBoardEditor(); +} 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 6c9406a8b..aacbd2fbf 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 @@ -65,6 +65,7 @@ import com.fr.design.write.submit.DBManipulationPane; import com.fr.event.EventDispatcher; import com.fr.file.FILE; import com.fr.file.FILEChooserPane; +import com.fr.file.FileFILE; import com.fr.file.MemFILE; import com.fr.file.StashedFILE; import com.fr.form.ui.NoneWidget; @@ -1010,8 +1011,11 @@ public abstract class JTemplate> if (WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(getEditingFILE().getPath())) { throw new UnLockedException(); } - // 校验锁定信息是否一致 - if (getEditingFILE().exists() && !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath())) { + // 过滤掉本地文件 + boolean localFile = getEditingFILE() instanceof FileFILE; + boolean inconsistent = !localFile && getEditingFILE().exists() + && !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath()); + if (inconsistent) { throw new InconsistentLockException(); } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java b/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java new file mode 100644 index 000000000..67b1409b3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java @@ -0,0 +1,27 @@ +package com.fr.design.mainframe; + +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; + +public interface ToolKitConfigStrategy { + + /** + * 展示tabpane + * @param plus + * @return + */ + boolean hasTemplateTabPane(ToolBarMenuDockPlus plus); + + /** + * 展示模板操作按钮(复制、粘贴、保存等) + * @param plus + * @return + */ + boolean hasCombineUp(ToolBarMenuDockPlus plus); + + /** + * 展示工具栏pane + * @param plus + * @return + */ + boolean hasToolBarPane(ToolBarMenuDockPlus plus); +} 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 index 6bac51876..570593586 100644 --- 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 @@ -77,7 +77,7 @@ public class ChartTitleAndBackgroundStylePane extends AbstractChartStylePane { private void initList() { paneList = new ArrayList<>(); paneList.add(new NullBackgroundQuickPane()); - paneList.add(new ColorBackgroundQuickPane()); + paneList.add(new ColorBackgroundQuickPane(true)); paneList.add(new ImageBackgroundQuickPane(false)); paneList.add(new VanChartGradientPane()); } 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 index 67be5cc9a..64aaeb9c0 100644 --- 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 @@ -3,6 +3,7 @@ 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.base.mode.DesignModeContext; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.mainframe.JTemplate; import com.fr.report.cell.DefaultTemplateCellElement; @@ -37,7 +38,7 @@ public class DefaultThemedTemplateCellElementCase { ThemedCellStyle themedCellStyle = theme.getCellStyleList().getUse4Default(); if (themedCellStyle != null) { NameStyle nameStyle = NameStyle.getPassiveInstance(themedCellStyle.getName(), themedCellStyle.getStyle()); - cellElement.setStyle(nameStyle); + cellElement.setStyle(DesignModeContext.isDuchampMode() ? nameStyle.getRealStyle() : nameStyle); } } return cellElement; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java index 5ce099c91..5b04ef014 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java @@ -23,7 +23,7 @@ public class AccessibleTreeModelEditor extends UneditableAccessibleEditor { @Override protected void showEditorPane() { if (treeSettingPane == null) { - treeSettingPane = new TreeSettingPane(false); + treeSettingPane = new TreeSettingPane(); } BasicDialog dlg = treeSettingPane.showWindow(SwingUtilities.getWindowAncestor(this)); treeSettingPane.populate(getValue()); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java index 8a2489407..00171f3fb 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java @@ -6,8 +6,7 @@ import com.fr.data.impl.TreeNodeWrapper; import com.fr.design.Exception.ValidationException; import com.fr.design.designer.properties.Decoder; import com.fr.design.designer.properties.Encoder; - -import com.fr.general.NameObject; +import com.fr.form.ui.tree.LayerConfig; import com.fr.stable.StringUtils; public class TreeModelWrapper implements Encoder, Decoder { @@ -22,7 +21,7 @@ public class TreeModelWrapper implements Encoder, Decoder { } else if (v instanceof TreeNodeWrapper) { TreeNodeAttr[] treeNodeAttrs = ((TreeNodeWrapper) v).getTreeNodeAttrs(); return TemplateUtils.render(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Total_N_Grade"), new String[]{"N"}, new String[]{treeNodeAttrs.length + ""}); - } else if (v instanceof NameObject) { + } else if (v instanceof LayerConfig[]) { return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DataTable_Build"); } else { return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Auto_Build"); diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java new file mode 100644 index 000000000..2397f0548 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java @@ -0,0 +1,45 @@ +package com.fr.design.record.analyzer; + +import com.fr.design.record.analyzer.advice.TimeAdvice; +import com.fr.design.record.analyzer.advice.TrackAdvice; +import com.fr.record.analyzer.AnalyzerConfiguration; +import com.fr.record.analyzer.AnalyzerUnit; +import com.fr.record.analyzer.Assistant; +import com.fr.record.analyzer.Metrics; +import com.fr.record.analyzer.Track; +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.stable.ArrayUtils; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.description.type.TypeDescription; +import com.fr.third.net.bytebuddy.dynamic.DynamicType; +import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import com.fr.third.net.bytebuddy.utility.JavaModule; + +/** + * created by Harrison on 2022/03/08 + **/ +public class DesignerAnalyzer { + + private static final AnalyzerUnit ANALYZER = new AnalyzerUnit(); + + public static synchronized void init(AnalyzerAssemblyFactory factory, AnalyzerConfiguration... configurations) { + + AnalyzerAssemblyFactory redefineFactory = factory.prepare(DesignerAssemblyFactory.getInstance()); + + AnalyzerConfiguration defaultConfiguration = AnalyzerConfiguration.create(new Assistant() { + @Override + public DynamicType.Builder supply(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) { + return builder + .visit(Advice.to(TimeAdvice.class).on(ElementMatchers.isAnnotatedWith(Metrics.class))) + .visit(Advice.to(TrackAdvice.class).on(ElementMatchers.isAnnotatedWith(Track.class))); + } + }); + AnalyzerConfiguration[] allConfigurations = ArrayUtils.add(configurations, defaultConfiguration); + + // 准备监听 + ANALYZER.setAgentListener(new DesignerAnalyzerListener()); + + ANALYZER.init(redefineFactory, allConfigurations); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java new file mode 100644 index 000000000..0a83d81c2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -0,0 +1,131 @@ +package com.fr.design.record.analyzer; + +import com.fr.base.OptimizeUtil; +import com.fr.concurrent.NamedThreadFactory; +import com.fr.design.constants.DesignerLaunchStatus; +import com.fr.design.record.analyzer.advice.DBMonitorAdvice; +import com.fr.design.record.analyzer.advice.FaultToleranceAdvice; +import com.fr.design.record.analyzer.advice.FocusAdvice; +import com.fr.design.record.analyzer.advice.MonitorAdvice; +import com.fr.design.record.analyzer.advice.PerformancePointAdvice; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.event.Null; +import com.fr.intelli.metrics.Compute; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.PerformancePoint; +import com.fr.module.Activator; +import com.fr.module.extension.Prepare; +import com.fr.record.analyzer.AnalyzerConfiguration; +import com.fr.record.analyzer.AnalyzerKey; +import com.fr.record.analyzer.DBMetrics; +import com.fr.record.analyzer.FineAnalyzer; +import com.fr.record.analyzer.advice.AnalyzerAdviceKey; +import com.fr.record.analyzer.advice.FineAdviceAssistant; +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory; +import com.fr.stable.collections.CollectionUtils; +import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import com.fr.tolerance.FaultTolerance; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.concurrent.ExecutorService; + +/** + * created by Harrison on 2022/03/04 + **/ +public class DesignerAnalyzerActivator extends Activator implements Prepare { + + @Override + public void start() { + + OptimizeUtil.open(() -> { + + AnalyzerAssemblyFactory basicFactory = createBasicFactory(); + + // 兼容逻辑 + List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); + if (!CollectionUtils.isEmpty(backwardsConfigurations)) { + // 直接初始化,不添加默认值,防止和下面的冲突 + FineAnalyzer.initDirectly(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); + } + + // 等页面完全打开后,再进行 retransform, 别影响了启动速度 + EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { + + @Override + public void on(Event event, Null param) { + + ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); + try { + // 加入 retransform 部分的逻辑 + List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); + + if (!CollectionUtils.isEmpty(adviceConfigurations)) { + AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); + es.submit(() -> { + DesignerAnalyzer.init(basicFactory, configurations); + }); + } + } finally { + es.shutdown(); + } + } + }); + }); + } + + @NotNull + private AnalyzerConfiguration[] convertConfigurations(List list) { + + return list.stream() + .map(AnalyzerConfiguration::create) + .toArray(AnalyzerConfiguration[]::new); + } + + @Override + public void stop() { + + } + + @Override + public void prepare() { + + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( + ElementMatchers.isAnnotatedWith(Focus.class), + FocusAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( + ElementMatchers.isAnnotatedWith(Compute.class), + MonitorAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( + ElementMatchers.isAnnotatedWith(DBMetrics.class), + DBMonitorAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( + ElementMatchers.isAnnotatedWith(PerformancePoint.class), + PerformancePointAdvice.class + )); + + addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create( + ElementMatchers.isAnnotatedWith(FaultTolerance.class), + FaultToleranceAdvice.class + )); + + } + + + private AnalyzerAssemblyFactory createBasicFactory() { + + AnalyzerAssemblyFactory factory = findSingleton(AnalyzerAssemblyFactory.class); + FineAnalyzerAssemblyFactory basicFactory = new FineAnalyzerAssemblyFactory(); + basicFactory.prepare(factory); + return basicFactory; + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java new file mode 100644 index 000000000..301634aa6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java @@ -0,0 +1,12 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.advice.AnalyzerAdvice; + +/** + * 仅作为标志 + * 没有方法 + * + * created by Harrison on 2022/03/04 + **/ +public interface DesignerAnalyzerAdvice extends AnalyzerAdvice { +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java new file mode 100644 index 000000000..8db3a395f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java @@ -0,0 +1,23 @@ +package com.fr.design.record.analyzer; + +import com.fr.log.FineLoggerFactory; +import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder; +import com.fr.third.net.bytebuddy.description.type.TypeDescription; +import com.fr.third.net.bytebuddy.dynamic.DynamicType; +import com.fr.third.net.bytebuddy.utility.JavaModule; + +/** + * created by Harrison on 2022/03/08 + **/ +public class DesignerAnalyzerListener extends AgentBuilder.Listener.Adapter { + + @Override + public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) { + FineLoggerFactory.getLogger().debug("Designer-Analyzer transform successfully:{}", typeDescription); + } + + @Override + public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) { + FineLoggerFactory.getLogger().error("Designer-Analyzer transform error:" + typeName); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java new file mode 100644 index 000000000..2e5fdc408 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java @@ -0,0 +1,91 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder; + +import java.util.List; +import java.util.Map; + +/** + * 装配 Agent 为后置启动 + *

必须在一个线程中处理 retransform 的事务,否则会阻塞整个的线程,导致效果不佳

+ * + * created by Harrison on 2022/03/07 + **/ +public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory { + + /** + * 每次执行 1 个 class 的 retransform + */ + private static final int FIXED_SIZE = 1; + + /** + * 单位 ms + * 每次间隔 500 ms, 执行一次 + */ + private static final int DELAY_INTERVAL = 500; + + private final AgentBuilder.RedefinitionStrategy.BatchAllocator batchAllocator = AgentBuilder.RedefinitionStrategy.BatchAllocator.ForFixedSize.ofSize(FIXED_SIZE); + + private final AgentBuilder.RedefinitionStrategy.Listener redefinitionListener = new DelayListener(DELAY_INTERVAL); + + public static DesignerAssemblyFactory getInstance() { + return DesignerAssemblyFactoryHolder.INSTANCE; + } + + private static class DesignerAssemblyFactoryHolder { + private static final DesignerAssemblyFactory INSTANCE = new DesignerAssemblyFactory(); + } + + @Override + public AnalyzerAssemblyFactory prepare(Void material) { + + return this; + } + + @Override + public AgentBuilder assembly(AgentBuilder raw) { + + return raw.disableClassFormatChanges() + .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) + // 每次只 transform 一部分否则会导致 UI 变慢 + .with(batchAllocator) + .with(redefinitionListener) + .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE) + .with(AgentBuilder.TypeStrategy.Default.REDEFINE); + } + + private class DelayListener implements AgentBuilder.RedefinitionStrategy.Listener { + + /** + * 单位 ms + */ + private final int interval; + + public DelayListener(int interval) { + this.interval = interval; + } + + /** + * 执行完后,等待一段时间再执行。 + */ + @Override + public void onBatch(int index, List> batch, List> types) { + + try { + Thread.sleep(interval); + } catch (Exception ignore) { + } + } + + @Override + public Iterable>> onError(int index, List> batch, Throwable throwable, List> types) { + return null; + } + + @Override + public void onComplete(int amount, List> types, Map>, Throwable> failures) { + + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java new file mode 100644 index 000000000..aba2c2bdf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java @@ -0,0 +1,23 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.general.data.DataModel; +import com.fr.measure.DBMeterFactory; +import com.fr.measure.metric.DBMetric; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +/** + * created by Harrison on 2022/03/07 + **/ +public class DBMonitorAdvice implements DesignerAnalyzerAdvice { + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args) { + + if (args.length > 1 && args[1] instanceof DataModel) { + DBMetric meter = ((DataModel) args[1]).getMetric(); + DBMeterFactory.getMeter().record(meter); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java new file mode 100644 index 000000000..4f40ef943 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java @@ -0,0 +1,46 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.record.analyzer.advice.AdviceContext; +import com.fr.record.analyzer.advice.DefaultAdviceCallable; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; +import com.fr.tolerance.FaultTolerance; +import com.fr.tolerance.FaultToleranceFactory; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +/** + * created by Harrison on 2022/03/07 + **/ +public class FaultToleranceAdvice implements DesignerAnalyzerAdvice { + + @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) + public static boolean onMethodEnter(@Advice.Local("context") AdviceContext adviceContext) throws Exception { + + adviceContext = AdviceContext + .builder() + .onAdviceCall() + .build(); + // 如果是切面调用,则忽视当前方法 + return adviceContext.isOnAdviceCall(); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, + @Advice.Local("context")AdviceContext adviceContext) throws Exception { + + // 如果是切面调用,则忽视不继续 exit + if (adviceContext != null && adviceContext.isOnAdviceCall()) { + return; + } + + FaultTolerance faultTolerance = method.getAnnotation(FaultTolerance.class); + Callable callable = new DefaultAdviceCallable<>(self, method, args); + result = FaultToleranceFactory.getInstance().getScene(faultTolerance.scene()).getProcessor().execute(self, callable, args); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java new file mode 100644 index 000000000..7bc79cc6c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java @@ -0,0 +1,31 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.FocusPoint; +import com.fr.intelli.record.FocusPolicy; +import com.fr.log.counter.DefaultLimitedMetric; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class FocusAdvice implements DesignerAnalyzerAdvice { + + private static final String FOCUS_POINT_ID_PREFIX = "function_"; + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Origin Method method, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception { + + if (FocusPolicy.IGNORE == result) { + return; + } + Focus focus = method.getAnnotation(Focus.class); + String id = FOCUS_POINT_ID_PREFIX + focus.id(); + DefaultLimitedMetric.INSTANCE.submit(FocusPoint.create(id, focus.text(), focus.source()), id); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java new file mode 100644 index 000000000..68f8c8508 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java @@ -0,0 +1,155 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.general.GeneralUtils; +import com.fr.intelli.measure.Estimator; +import com.fr.intelli.metrics.Compute; +import com.fr.intelli.metrics.MessageRecorderFactory; +import com.fr.intelli.metrics.SupervisoryConfig; +import com.fr.intelli.record.Measurable; +import com.fr.intelli.record.MeasureObject; +import com.fr.intelli.record.MeasureUnit; +import com.fr.log.FineLoggerFactory; +import com.fr.measure.DBMeterFactory; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.web.Session; +import com.fr.stable.web.SessionProvider; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; +import com.fr.web.core.SessionPoolManager; +import com.fr.web.session.SessionLocalManager; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * created by Harrison on 2022/03/07 + **/ +public class MonitorAdvice implements DesignerAnalyzerAdvice { + + private static final Pattern P = Pattern.compile("-?\\d+"); + private static final int MIN_ERROR_CODE = 10000000; + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Local("startTime") Long startTime, + @Advice.Local("registeredSession") Boolean registeredSession) { + + startTime = (System.currentTimeMillis()); + registeredSession = (findSessionAnnotation(method, args)); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e, + @Advice.Local("startTime") Long startTime, + @Advice.Local("registeredSession") Boolean registeredSession) throws Exception { + + String error = StringUtils.EMPTY; + + try { + + if (e != null) { + try { + error = getErrorContent(e); + } catch (Exception ignore) { + } + } + } finally { + try { + if (self instanceof Measurable) { + long consume = System.currentTimeMillis() - startTime; + Compute once = method.getAnnotation(Compute.class); + Measurable measurable = (Measurable) self; + MeasureObject measureObject = MeasureObject.create(); + recordMemory(once, measurable, measureObject); + recordSQL(once, measureObject); + measureObject.consume(consume); + measureObject.error(error); + String id = UUID.randomUUID().toString(); + List newArgs = new ArrayList<>(Arrays.asList(args)); + newArgs.add(id); + recordSQLDetail(id); + Object message = null; + try { + message = measurable.durableEntity(measureObject, newArgs.toArray()); + } catch (Throwable throwable) { + FineLoggerFactory.getLogger().error(throwable.getMessage(), throwable); + } + if (measurable instanceof Estimator) { + MessageRecorderFactory.getInstance().asyncSubmit(message); + } else { + MessageRecorderFactory.getInstance().syncSubmit(message); + } + } + } catch (Exception ignore) { + //埋点信息入库失败应该不能影响业务流程 + } finally { + if (registeredSession) { + // 如果上面记录了,这里就要释放 + SessionLocalManager.releaseSession(); + } + } + } + } + + public static String getErrorContent(Exception e) { + int errorCode = GeneralUtils.objectToNumber( + extractCodeFromString(e.getMessage()) + ).intValue(); + // 提取字符串中的第一个数字,最小的错误码为10000000 + return e.getClass().getName() + ":" + (errorCode >= MIN_ERROR_CODE ? errorCode : StringUtils.EMPTY); + } + + public static String extractCodeFromString(String errorMsg) { + Matcher m = P.matcher(errorMsg); + if (m.find()) { + return m.group(); + } + return StringUtils.EMPTY; + } + + public static void recordSQLDetail(String uuid) { + DBMeterFactory.getMeter().submit(uuid); + } + + public static void recordSQL(Compute once, MeasureObject measureObject) { + if (SupervisoryConfig.getInstance().isEnableMeasureSql() && once.computeSql()) { + measureObject.sqlTime(SessionLocalManager.getSqlTime()); + measureObject.sql(SessionLocalManager.getSql()); + } + } + + public static void recordMemory(Compute once, Measurable measurable, MeasureObject measureObject) { + if (SupervisoryConfig.getInstance().isEnableMeasureMemory() && once.computeMemory()) { + MeasureUnit unit = measurable.measureUnit(); + measureObject.memory(unit.measureMemory()); + } + } + + public static boolean findSessionAnnotation(Method method, Object[] args) { + Annotation[][] all = method.getParameterAnnotations(); + int len = ArrayUtils.getLength(args); + for (int i = 0; i < len; i++) { + Annotation[] current = all[i]; + for (Annotation annotation : current) { + if (annotation.annotationType().equals(Session.class)) { + SessionLocalManager.setSession( + SessionPoolManager.getSessionIDInfor(GeneralUtils.objectToString(args[i]), SessionProvider.class)); + return true; + } + } + } + return false; + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java new file mode 100644 index 000000000..5b54f6653 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java @@ -0,0 +1,49 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.intelli.record.ConsumePoint; +import com.fr.intelli.record.MetricRegistry; +import com.fr.intelli.record.PerformancePoint; +import com.fr.intelli.record.PerformancePointRecord; +import com.fr.stable.StringUtils; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * created by Harrison on 2022/03/07 + **/ +public class PerformancePointAdvice implements DesignerAnalyzerAdvice { + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Local("startTime") Long startTime) { + + startTime = (System.currentTimeMillis()); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Local("startTime") Long startTime) { + + PerformancePoint point = method.getAnnotation(PerformancePoint.class); + String id = point.id(); + long endTime = System.currentTimeMillis(); + long consume = endTime - startTime; + if (self instanceof PerformancePointRecord) { + PerformancePointRecord measurable = (PerformancePointRecord) self; + List newArgs = new ArrayList(Arrays.asList(args)); + ConsumePoint consumePoint = ConsumePoint.create(id, startTime, endTime, consume, point.source()); + MetricRegistry.getMetric().submit(measurable.recordPoint(consumePoint, newArgs.toArray())); + } else { + if (StringUtils.isNotEmpty(id)) { + MetricRegistry.getMetric().submit(ConsumePoint.create(id, consume, point.source())); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java new file mode 100644 index 000000000..b60b5c2d3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java @@ -0,0 +1,36 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.design.record.analyzer.DesignerAnalyzerAdvice; +import com.fr.log.FineLoggerFactory; +import com.fr.record.analyzer.Metrics; +import com.fr.third.net.bytebuddy.asm.Advice; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/08 + **/ +public class TimeAdvice implements DesignerAnalyzerAdvice { + + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Local("startTime") Long startTime) { + + startTime = (System.currentTimeMillis()); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Origin Method method, + @Advice.Local("startTime") Long startTime) { + + Metrics metrics = method.getAnnotation(Metrics.class); + Object prefix; + String description = metrics.description(); + if ("".equals(description)) { + prefix = method.getDeclaringClass().getName() + "#" + method.getName(); + } else { + prefix = description; + } + FineLoggerFactory.getLogger().info("{} took {} ms.", prefix, System.currentTimeMillis() - startTime); + } +} diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java new file mode 100644 index 000000000..bdebecc60 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java @@ -0,0 +1,25 @@ +package com.fr.design.record.analyzer.advice; + +import com.fr.intelli.record.MetricRegistry; +import com.fr.third.javax.persistence.Entity; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.util.List; + +/** + * created by Harrison on 2022/03/08 + **/ +public class TrackAdvice { + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) { + + if (result != null) { + Class clazz = result.getClass(); + if (clazz.getAnnotation(Entity.class) != null || result instanceof List) { + MetricRegistry.getMetric().submit(result); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java b/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java index 5402032f9..b23969889 100644 --- a/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java +++ b/designer-base/src/main/java/com/fr/design/startup/Install4jStartupNotificationProvider.java @@ -22,14 +22,22 @@ public class Install4jStartupNotificationProvider implements FineStartupNotifica @Override public void registerStartupListener(Listener listener) { - Class StartupNotificationListenerClass = Reflect.on("com.install4j.api.launcher.StartupNotification$Listener").type(); + Class StartupNotificationListenerClass = null; + try { + StartupNotificationListenerClass = Reflect.on("com.install4j.api.launcher.StartupNotification$Listener").type(); + } catch (Exception ignored) { + } + if (StartupNotificationListenerClass == null) { return; } ListenerHandler mHandler = new ListenerHandler(listener); Object listenerCallbackInstance = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { StartupNotificationListenerClass }, mHandler); - Reflect.on("com.install4j.api.launcher.StartupNotification").call("registerStartupListener", listenerCallbackInstance); + try { + Reflect.on("com.install4j.api.launcher.StartupNotification").call("registerStartupListener", listenerCallbackInstance); + } catch (Exception ignored) { + } } private static class ListenerHandler implements InvocationHandler { @@ -48,4 +56,13 @@ public class Install4jStartupNotificationProvider implements FineStartupNotifica return null; } } + + public static void main(String[] args) { + Install4jStartupNotificationProvider.getInstance().registerStartupListener(new Listener() { + @Override + public void startupPerformed(String parameters) { + + } + }); + } } 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 ad99b9083..f5ff739fa 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,6 +1,7 @@ package com.fr.design.style.color; import com.fr.base.BaseUtils; +import com.fr.chart.base.ChartConstants; import com.fr.design.DesignerEnvManager; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; @@ -12,8 +13,6 @@ import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.util.ArrayList; -import java.util.List; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; @@ -23,6 +22,8 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; /** * 配色方案选择组合色之后,可以调整颜色的组件 @@ -33,18 +34,7 @@ import java.awt.image.BufferedImage; */ public class ColorAdjustPane extends JPanel implements UIObserver { - public static final Color[] DEFAULT_COLORS = { - new Color(99, 178, 238), - new Color(118, 218, 145), - new Color(248, 203, 127), - new Color(248, 149, 136), - new Color(124, 214, 207), - new Color(145, 146, 171), - new Color(120, 152, 225), - new Color(239, 166, 102), - new Color(237, 221, 134), - new Color(153, 135, 206), - }; + public static final Color[] DEFAULT_COLORS = ChartConstants.NEW_FEATURES; private static final int COUNT_OF_ROW = 8; diff --git a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java index 09fa2bbc0..5a0ead41e 100644 --- a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java +++ b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java @@ -203,6 +203,10 @@ public class ModernUIPane extends BasicPane { this.pane = new ModernUIPane<>(browserType); } + public Builder(ModernUIPane pane) { + this.pane = pane; + } + public Builder prepare(ScriptContextListener contextListener) { pane.browser.addScriptContextListener(contextListener); return this; diff --git a/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java b/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java index 0b56fc0ad..59df782cd 100644 --- a/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java +++ b/designer-base/src/main/java/com/fr/design/ui/compatible/NewModernUIPane.java @@ -182,7 +182,7 @@ public class NewModernUIPane extends ModernUIPane { public void disposeBrowser() { if (browser != null) { - browser.close(); + browser.engine().close(); browser = null; } @@ -206,6 +206,10 @@ public class NewModernUIPane extends ModernUIPane { private NewModernUIPane pane = new NewModernUIPane<>(); + public Builder() { + super((ModernUIPane)null); + } + public NewModernUIPane.Builder prepare(InjectJsCallback callback) { pane.browser.set(InjectJsCallback.class, callback); return this; diff --git a/designer-base/src/main/java/com/fr/design/ui/util/GraphicsConfig.java b/designer-base/src/main/java/com/fr/design/ui/util/GraphicsConfig.java deleted file mode 100644 index 316b6ac24..000000000 --- a/designer-base/src/main/java/com/fr/design/ui/util/GraphicsConfig.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fr.design.ui.util; - -import org.jetbrains.annotations.NotNull; - -import java.awt.*; -import java.util.Map; - -/** - * 图形渲染配置 - * - * @author vito - * @version 10.0 - * Created by vito on 2019/9/18 - */ -public class GraphicsConfig { - private final Graphics2D myG; - private final Map myHints; - private final Composite myComposite; - private final Stroke myStroke; - - public GraphicsConfig(@NotNull Graphics g) { - myG = (Graphics2D) g; - myHints = (Map) myG.getRenderingHints().clone(); - myComposite = myG.getComposite(); - myStroke = myG.getStroke(); - } - - public GraphicsConfig setAntialiasing(boolean on) { - myG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, on ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); - return this; - } - - public GraphicsConfig setAlpha(float alpha) { - myG.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); - return this; - } - - public GraphicsConfig setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { - myG.setRenderingHint(hintKey, hintValue); - return this; - } - - public Graphics2D getG() { - return myG; - } - - public GraphicsConfig setComposite(Composite composite) { - myG.setComposite(composite); - return this; - } - - public GraphicsConfig setStroke(Stroke stroke) { - myG.setStroke(stroke); - return this; - } - - public GraphicsConfig setupAAPainting() { - return setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) - .setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); - } - - public GraphicsConfig disableAAPainting() { - return setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF) - .setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); - } - - public GraphicsConfig paintWithAlpha(float alpha) { - assert 0.0f <= alpha && alpha <= 1.0f : "alpha should be in range 0.0f .. 1.0f"; - return setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); - } - - public void restore() { - myG.setRenderingHints(myHints); - myG.setComposite(myComposite); - myG.setStroke(myStroke); - } -} diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java index 9ea734e73..950d76d7b 100644 --- a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java +++ b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java @@ -15,6 +15,7 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { private static DesignerPushUpdateConfigManager singleton; private boolean autoPushUpdateEnabled = true; // 是否开启自动推送更新 + private boolean cloudAnalyticsDelay = false; // 是否云端运维模块延迟启动 private String lastIgnoredVersion = StringUtils.EMPTY; // 最近一次跳过的更新版本 private DesignerPushUpdateConfigManager() { @@ -32,6 +33,7 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { if (reader.isAttr()) { this.setAutoPushUpdateEnabled(reader.getAttrAsBoolean("autoPushUpdateEnabled", true)); this.setLastIgnoredVersion(reader.getAttrAsString("lastIgnoredVersion", StringUtils.EMPTY)); + this.setCloudAnalyticsDelay(reader.getAttrAsBoolean("cloudAnalyticsDelay", false)); } } @@ -40,6 +42,7 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { writer.startTAG(XML_TAG); writer.attr("autoPushUpdateEnabled", autoPushUpdateEnabled); writer.attr("lastIgnoredVersion", lastIgnoredVersion); + writer.attr("cloudAnalyticsDelay", cloudAnalyticsDelay); writer.end(); } @@ -58,4 +61,12 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { public void setLastIgnoredVersion(String lastIgnoredVersion) { this.lastIgnoredVersion = lastIgnoredVersion; } + + public boolean isCloudAnalyticsDelay() { + return cloudAnalyticsDelay; + } + + public void setCloudAnalyticsDelay(boolean cloudAnalyticsDelay) { + this.cloudAnalyticsDelay = cloudAnalyticsDelay; + } } diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java b/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java index f3284c11e..576c5a9b9 100644 --- a/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java +++ b/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java @@ -1,6 +1,6 @@ package com.fr.design.upm; -import com.fr.base.FRContext; +import com.fr.decision.webservice.v10.plugin.helper.category.impl.BaseResourceLoader; import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.UIDialog; @@ -12,8 +12,11 @@ import com.fr.design.update.ui.dialog.UpdateMainDialog; import com.fr.event.Event; import com.fr.event.EventDispatcher; import com.fr.event.Listener; +import com.fr.general.CommonIOUtils; import com.fr.general.GeneralContext; +import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; +import com.fr.plugin.PluginStoreConstants; import com.fr.stable.StableUtils; import com.fr.workspace.Workspace; import com.fr.workspace.WorkspaceEvent; @@ -33,7 +36,7 @@ public class UpmFinder { private static final String MAIN_RESOURCE_PATH = UPM_DIR + "/plugin_design.html"; private static final String JXBROWSER = "com.teamdev.jxbrowser.browser.Browser"; - public static String installHome = FRContext.getCommonOperator().getWebRootPath(); + public static String installHome = PluginStoreConstants.getLocalInstallHome(); private static UIDialog dialog = null; @@ -41,7 +44,8 @@ public class UpmFinder { EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener() { @Override public void on(Event event, Workspace param) { - installHome = FRContext.getCommonOperator().getWebRootPath(); + installHome = PluginStoreConstants.getLocalInstallHome(); + UpmResourceLoader.INSTANCE.checkOldShopFile(); } }); } @@ -75,24 +79,24 @@ public class UpmFinder { } private static void showUpmPane() { - if (!checkUPMResourcesExist()){ + if (!checkUPMResourcesExist()) { // upm下载 int val = FineJOptionPane.showConfirmDialog(null, Toolkit.i18nText("Fine-Design_Basic_Plugin_Shop_Need_Install"), Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE); - if (val == JOptionPane.OK_OPTION){ + if (val == JOptionPane.OK_OPTION) { try { UpmResourceLoader.INSTANCE.download(); - UpmResourceLoader.INSTANCE.install(); + installUpmResource(); + FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_Plugin_Shop_Installed"), Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE); - } catch (Exception e){ + } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Updater_Download_Failed"), Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE); } } - } - else { + } else { UpmShowPane upmPane = new UpmShowPane(); if (dialog == null) { dialog = new UpmShowDialog(DesignerContext.getDesignerFrame(), upmPane); @@ -102,6 +106,15 @@ public class UpmFinder { } } + private static void installUpmResource() { + String installHome = PluginStoreConstants.getLocalInstallHome(); + File scriptZip = new File(BaseResourceLoader.SCRIPT_DOWNLOAD_PATH); + if (scriptZip.exists()) { + IOUtils.unzip(scriptZip, installHome); + CommonIOUtils.deleteFile(scriptZip); + } + } + private static void showUpdatePane() { JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Update_Info_Plugin_Message")); if (!GeneralContext.getLocale().equals(Locale.JAPANESE) && !GeneralContext.getLocale().equals(Locale.JAPAN) diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java b/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java index 0384b5c29..23a712508 100644 --- a/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java +++ b/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java @@ -32,23 +32,14 @@ public class UpmShowPane extends BasicPane { UpmShowPane() { setLayout(new BorderLayout()); - modernUIPane = ModernUIPaneFactory.modernUIPaneBuilder() - .prepareForV6(new ScriptContextAdapter() { + modernUIPane = new ModernUIPane.Builder<>() + .prepare(new ScriptContextAdapter() { @Override public void onScriptContextCreated(ScriptContextEvent event) { - // 6.x JSValue window = event.getBrowser().executeJavaScriptAndReturnValue("window"); window.asObject().setProperty("PluginHelper", UpmBridge.getBridge(event.getBrowser())); } }) - .prepareForV7(params -> { - // 7.x - JsObject window = params.frame().executeJavaScript("window"); - if (window != null) { - window.putProperty("PluginHelper", NewUpmBridge.getBridge(window)); - } - return InjectJsCallback.Response.proceed(); - }) .withURL(UpmFinder.getMainResourcePath(), UpmUtils.renderMap()) .build(); EventDispatcher.listen(DownloadEvent.UPDATE, new Listener() { @@ -57,6 +48,12 @@ public class UpmShowPane extends BasicPane { modernUIPane.redirect(UpmFinder.getMainResourcePath(), UpmUtils.renderMap()); } }); + EventDispatcher.listen(DownloadEvent.UPDATE, new Listener() { + @Override + public void on(Event event, String param) { + modernUIPane.redirect(UpmFinder.getMainResourcePath(), UpmUtils.renderMap()); + } + }); add(modernUIPane, BorderLayout.CENTER); } } 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 c717ce6ea..9bc431636 100644 --- a/designer-base/src/main/java/com/fr/env/HelpLink.java +++ b/designer-base/src/main/java/com/fr/env/HelpLink.java @@ -24,6 +24,8 @@ public class HelpLink { 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); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_NetWork_Connection_Error_Solution"), link); + map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Redirect_Solution"), link); + map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_NetWork_Config_Solution"), link); return map.get(solution); } diff --git a/designer-base/src/main/java/com/fr/env/utils/WorkspaceUtils.java b/designer-base/src/main/java/com/fr/env/utils/WorkspaceUtils.java new file mode 100644 index 000000000..3979b4eee --- /dev/null +++ b/designer-base/src/main/java/com/fr/env/utils/WorkspaceUtils.java @@ -0,0 +1,27 @@ +package com.fr.env.utils; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.env.DesignerWorkspaceInfo; +import com.fr.design.env.LocalDesignerWorkspaceInfo; +import com.fr.stable.StringUtils; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/3/10 + */ +public class WorkspaceUtils { + + private static final String SPECIFY_WORKSPACE = "fr.designer.workspace"; + + public static DesignerWorkspaceInfo getWorkspaceInfo() { + String workspacePath; + String current = DesignerEnvManager.getEnvManager().getCurEnvName(); + if (StringUtils.isNotEmpty(workspacePath = System.getProperty(SPECIFY_WORKSPACE))) { + return LocalDesignerWorkspaceInfo.create(StringUtils.EMPTY, workspacePath); + } else { + return DesignerEnvManager.getEnvManager().getWorkspaceInfo(current); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java b/designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java new file mode 100644 index 000000000..909768bee --- /dev/null +++ b/designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java @@ -0,0 +1,111 @@ +package com.fr.exit; + +import com.fr.config.dao.PropertiesConstants; +import com.fr.design.DesignerEnvManager; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.CommonUtils; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.workspace.WorkContext; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.sql.Blob; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; + +/** + * 设计器关闭前的配置缓存一份到Properties + * + * @author hades + * @version 11.0 + * Created by hades on 2022/3/1 + */ +public class ConfigToPropMigrator { + + private static final String SELECT_FOR_ENTITY = "select id, value from fine_conf_entity"; + + private static final String SELECT_FOR_CLASSNAME = "select id, classname from fine_conf_classname"; + + private static final String SELECT_FOR_XML_ENTITY = "select id, value from fine_conf_xmlentity"; + + private static final ConfigToPropMigrator INSTANCE = new ConfigToPropMigrator(); + + public static ConfigToPropMigrator getInstance() { + return INSTANCE; + } + + public void execute() { + + if (WorkContext.getCurrent().isLocal()) { + + String url = "jdbc:hsqldb:file://" + WorkContext.getCurrent().getPath() + "/" + ProjectConstants.EMBED_DB_DIRECTORY + "/finedb/db;hsqldb.tx=mvcc"; + + try { + Class.forName("com.fr.third.org.hsqldb.jdbcDriver"); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return ; + } + + initDirectory(); + + try (Connection c = DriverManager.getConnection(url); + FileOutputStream entityOut = new FileOutputStream(PropertiesConstants.ENTITY_PROP_PATH); + FileOutputStream classHelperOut = new FileOutputStream(PropertiesConstants.CLASS_NAME_PROP_PATH); + FileOutputStream xmlEntityOut = new FileOutputStream(PropertiesConstants.XML_ENTITY_PROP_PATH)) { + + processClassOrEntity(c, new Properties(), SELECT_FOR_ENTITY, entityOut); + processClassOrEntity(c, new Properties(), SELECT_FOR_CLASSNAME, classHelperOut); + processXmlEntity(c, new Properties(), xmlEntityOut); + DesignerEnvManager.getEnvManager().setPropertiesUsable(true); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + deletePropertiesCache(); + } + } + } + + private void initDirectory() { + File directory = new File(StableUtils.pathJoin(WorkContext.getCurrent().getPath(), ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.PROPERTIES_CACHE_FOR_CONFIG)); + if (!directory.exists()) { + directory.mkdir(); + } + } + + private void processClassOrEntity(Connection c, Properties map, String sql, FileOutputStream outputStream) throws SQLException, IOException { + PreparedStatement query = c.prepareStatement(sql); + ResultSet resultSet = query.executeQuery(); + while (resultSet.next()) { + String id = resultSet.getString(1); + String value = resultSet.getString(2); + if (id != null && value != null) { + map.setProperty(id, value); + } + } + map.store(outputStream, null); + } + + private void processXmlEntity(Connection c, Properties map, FileOutputStream outputStream) throws SQLException, IOException { + PreparedStatement query = c.prepareStatement(SELECT_FOR_XML_ENTITY); + ResultSet resultSet = query.executeQuery(); + while (resultSet.next()) { + String id = resultSet.getString(1); + Blob value = resultSet.getBlob(2); + byte[] bytes = value.getBytes(1L, (int) value.length()); + map.setProperty(id, new String(bytes)); + } + map.store(outputStream, null); + } + + public void deletePropertiesCache() { + CommonUtils.deleteFile(new File(PropertiesConstants.ENTITY_PROP_PATH)); + CommonUtils.deleteFile(new File(PropertiesConstants.XML_ENTITY_PROP_PATH)); + CommonUtils.deleteFile(new File(PropertiesConstants.CLASS_NAME_PROP_PATH)); + } + +} 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 30f55d7ef..6dfb29443 100644 --- a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java +++ b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java @@ -202,10 +202,11 @@ public class FILEChooserPane extends BasicPane { return INSTANCE; } - public static FILEChooserPane getInstanceWithDesignatePath(String path, FILEFilter filter) { + public static FILEChooserPane getInstanceWithDesignatePath(String path, FILEFilter filter, String topPath) { INSTANCE.showLoc = false; INSTANCE.showEnv = false; INSTANCE.showWebReport = false; + INSTANCE.setTopPath(topPath); INSTANCE.setDesignateModel(path); INSTANCE.removeAllFilter(); INSTANCE.addChooseFILEFilter(filter, 0); @@ -633,6 +634,9 @@ public class FILEChooserPane extends BasicPane { this.filterList.clear(); } + public void removeTopPath() { + this.setTopPath(StringUtils.EMPTY); + } /** * 设置filter,刷新右侧subFileList中的items @@ -1045,9 +1049,14 @@ public class FILEChooserPane extends BasicPane { if (placesList == null) { return; } + setPlaceListModel(new DesignateRemotePlaceListModel(path)); } + private void setTopPath(String path) { + this.locationBtnPane.setTopPath(path); + } + private void setMultiPlaceListModel() { if (placesList == null) { @@ -1385,6 +1394,8 @@ public class FILEChooserPane extends BasicPane { private List buttonList = new ArrayList<>(); private int pathIndex = 0; private int maxPathIndex = 0; + // 对顶层目录进行的限制 + private String topPath; public LocationButtonPane() { this.setLayout(FRGUIPaneFactory.createBoxFlowLayout()); @@ -1430,6 +1441,10 @@ public class FILEChooserPane extends BasicPane { }); } + public void setTopPath(String path) { + this.topPath = path; + } + public void highLightButton(FILE dir) { for (int i = 0; i < this.buttonList.size(); i++) { this.buttonList.get(i).setForeground(null); @@ -1471,6 +1486,7 @@ public class FILEChooserPane extends BasicPane { } Matcher matcher = SEPARATOR_PATTERN.matcher(path); int node_start = 0; + boolean needTopPath = !StringUtils.isEmpty(topPath); while (matcher.find()) { int start = matcher.start(); String btn_text = path.substring(node_start, start); @@ -1478,11 +1494,14 @@ public class FILEChooserPane extends BasicPane { if (StringUtils.isBlank(btn_text) && isWebAppNamePath) { btn_text = webAppName; } + node_start = matcher.end(); + if (needTopPath && topPath.equals(btn_text)) { + needTopPath = false; + } this.buttonList.add(createBlankButton((new SetDirectoryAction(btn_text + '/', // alex:dir.prefix不和btn_path一起参与pathJoin,因为btn_path是否以/打头在unix,linux // OS中意义很不一样 - FILEFactory.createFolder(dir.prefix() + StableUtils.pathJoin(btn_path, "/")))))); - node_start = matcher.end(); + FILEFactory.createFolder(dir.prefix() + StableUtils.pathJoin(btn_path, "/")), !needTopPath)))); } maxPathIndex = calculateMaxPathIndex(); @@ -1583,6 +1602,7 @@ public class FILEChooserPane extends BasicPane { private class SetDirectoryAction extends UpdateAction { private FILE dir; + private boolean response = true; public SetDirectoryAction(String name) { this.setName(name); @@ -1594,9 +1614,15 @@ public class FILEChooserPane extends BasicPane { this.dir = file; } + public SetDirectoryAction(String name, FILE file, boolean response) { + this.setName(name); + this.dir = file; + this.response = response; + } + @Override public void actionPerformed(ActionEvent evt) { - if (dir != null) { + if (dir != null && response) { setSelectedDirectory(dir); } } 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 index 0b1a65657..df0303a65 100644 --- 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 @@ -3,7 +3,9 @@ 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.FineBook; import com.fr.main.TemplateWorkBook; +import com.fr.report.core.ReportUtils; import com.fr.report.report.Report; import com.fr.report.stable.LayerReportAttr; import com.fr.report.worksheet.WorkSheet; @@ -30,7 +32,7 @@ public class CptAndCptxCompatibilityUtil { } /** - * 判断是不是cptx模板或者开启了的新引擎的cpt模板的另存为操作 + * 判断是不是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))); @@ -40,7 +42,7 @@ public class CptAndCptxCompatibilityUtil { * cptx另存为cpt需要修改报表引擎属性 **/ private static boolean setFrEngineAttr(JTemplate jTemplate){ - WorkSheet workSheet = gainWorkSheet(jTemplate.getTarget()); + WorkSheet workSheet = getFirstWorkSheet(jTemplate.getTarget()); if (workSheet == null){ return false; }else { @@ -49,8 +51,7 @@ public class CptAndCptxCompatibilityUtil { layerReportAttr = new LayerReportAttr(); workSheet.setLayerReportAttr(layerReportAttr); } - layerReportAttr.setClientPaging(true); - layerReportAttr.setEngineState(0); + layerReportAttr.enableEngineX(); return true; } } @@ -60,29 +61,17 @@ public class CptAndCptxCompatibilityUtil { * 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; + if (workBook == null || !(workBook instanceof FineBook)){ + return false; } + return ReportUtils.hasEngineXReport4Template((FineBook) workBook) || FileExtension.CPTX.matchExtension(fileName); } - private static WorkSheet gainWorkSheet(Object workBook){ + private static WorkSheet getFirstWorkSheet(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/start/BaseDesigner.java b/designer-base/src/main/java/com/fr/start/BaseDesigner.java index 6165ff7f7..360e9cdfa 100644 --- a/designer-base/src/main/java/com/fr/start/BaseDesigner.java +++ b/designer-base/src/main/java/com/fr/start/BaseDesigner.java @@ -3,6 +3,7 @@ */ package com.fr.start; +import com.fr.base.extension.FileExtension; import com.fr.common.report.ReportState; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; @@ -32,7 +33,9 @@ import com.fr.process.engine.core.CarryMessageEvent; import com.fr.process.engine.core.FineProcessContext; import com.fr.stable.OperatingSystem; +import com.fr.start.event.LazyStartupEvent; import com.fr.workspace.base.WorkspaceStatus; + import java.awt.Window; import java.io.File; import java.lang.reflect.Method; @@ -86,6 +89,7 @@ public abstract class BaseDesigner extends ToolBarMenuDock { eventPipe.fire(new CarryMessageEvent(ReportState.STOP.getValue())); } EventDispatcher.fire(WorkspaceStatus.Prepared); + EventDispatcher.asyncFire(LazyStartupEvent.INSTANCE); collectUserInformation(); } }); @@ -119,14 +123,7 @@ public abstract class BaseDesigner extends ToolBarMenuDock { } File f = new File(arg); String path = f.getAbsolutePath(); - boolean pathends1 = path.endsWith(".cpt") - || path.endsWith(".xls"); - boolean pathends2 = path.endsWith(".xlsx") - || path.endsWith(".frm"); - boolean pathends3 = path.endsWith(".form") - || path.endsWith(".cht"); - boolean pathends4 = pathends1 || pathends2 || pathends3; - if (pathends4 || path.endsWith(".chart")) { + if (isAcceptFilePathEnd(path)) { file = new FileFILE(f); } } @@ -146,6 +143,21 @@ public abstract class BaseDesigner extends ToolBarMenuDock { } } + private boolean isAcceptFilePathEnd(String path) { + FileExtension[] acceptFileExtensions = new FileExtension[]{ + FileExtension.CPT, FileExtension.XLS, FileExtension.XLSX, FileExtension.FRM, FileExtension.CHT, FileExtension.VIS + }; + for (FileExtension acceptFileExtension : acceptFileExtensions) { + String[] extensions = acceptFileExtension.getExtensions(); + for (String extension : extensions) { + if (path.endsWith("." + extension)) { + return true; + } + } + } + return false; + } + private boolean openFile(final DesignerFrame df, boolean isException, FILE file) { //启动时打开指定文件的接口 diff --git a/designer-base/src/main/java/com/fr/start/event/LazyStartupEvent.java b/designer-base/src/main/java/com/fr/start/event/LazyStartupEvent.java new file mode 100644 index 000000000..fcef2ffc1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/start/event/LazyStartupEvent.java @@ -0,0 +1,14 @@ +package com.fr.start.event; + +import com.fr.event.Event; +import com.fr.event.Null; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/3/7 + */ +public enum LazyStartupEvent implements Event { + + INSTANCE +} diff --git a/designer-base/src/main/resources/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex b/designer-base/src/main/resources/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex index f73852366..aa2c854da 100644 --- a/designer-base/src/main/resources/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex +++ b/designer-base/src/main/resources/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex @@ -584,7 +584,31 @@ FunctionNames = "ABS"| "QUERY"| "query"| "WEBIMAGE"| - "webimage" + "webimage"| + "ACCSUM"| + "accsum"| + "COUNTIFS"| + "countifs"| + "SUMIFS"| + "sumifs"| + "ENDOFMONTH"| + "endofmonth"| + "NUMTOZH"| + "numtozh"| + "MIDCHAR"| + "midchar"| + "ISWORKDAY"| + "isworkday"| + "ENBYSTRNUM"| + "enbystrnum"| + "TEXTGETNUM"| + "textgetnum"| + "GETCHARNUM"| + "getcharnum"| + "GCD"| + "gcd"| + "LCM"| + "lcm" %state MLC 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 aa4a83f3e..f4840b71a 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 @@ -14,4 +14,8 @@ 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 com.fr.design.lock.LockInfoDialog=500*180 -com.fr.design.mainframe.ForbiddenPane.refreshButton=75*24 \ No newline at end of file +com.fr.design.mainframe.ForbiddenPane.refreshButton=75*24 +com.fr.design.cell.expand.sort.pane=257*185 +com.fr.design.sort.rule.item=125*20 +com.fr.design.ds.column.sort.pane=250*180 +com.fr.design.sort.expand.header.pane=95*10 \ 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 96558262f..fb0ecfb3d 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 @@ -13,4 +13,8 @@ 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 com.fr.design.lock.LockInfoDialog=500*180 -com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 \ No newline at end of file +com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 +com.fr.design.cell.expand.sort.pane=257*170 +com.fr.design.sort.rule.item=125*20 +com.fr.design.ds.column.sort.pane=250*165 +com.fr.design.sort.expand.header.pane=95*10 \ 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 05e20c7aa..19bb7e97a 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 @@ -13,4 +13,8 @@ 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 com.fr.design.lock.LockInfoDialog=500*180 -com.fr.design.mainframe.ForbiddenPane.refreshButton=80*24 \ No newline at end of file +com.fr.design.mainframe.ForbiddenPane.refreshButton=80*24 +com.fr.design.cell.expand.sort.pane=267*165 +com.fr.design.sort.rule.item=125*20 +com.fr.design.ds.column.sort.pane=250*180 +com.fr.design.sort.expand.header.pane=95*10 \ 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 a4b2993e6..3c398efc0 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 @@ -14,4 +14,8 @@ 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 com.fr.design.lock.LockInfoDialog=400*160 -com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 \ No newline at end of file +com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 +com.fr.design.cell.expand.sort.pane=227*155 +com.fr.design.sort.rule.item=80*20 +com.fr.design.ds.column.sort.pane=220*150 +com.fr.design.sort.expand.header.pane=108*10 \ 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 5813cd96c..7130938c7 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 @@ -13,4 +13,8 @@ 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 com.fr.design.lock.LockInfoDialog=400*160 -com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 \ No newline at end of file +com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24 +com.fr.design.cell.expand.sort.pane=227*155 +com.fr.design.sort.rule.item=80*20 +com.fr.design.ds.column.sort.pane=220*150 +com.fr.design.sort.expand.header.pane=108*10 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/buttonicon/ds_column_summary.png b/designer-base/src/main/resources/com/fr/design/images/buttonicon/ds_column_summary.png new file mode 100644 index 000000000..1d7e13aa4 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/buttonicon/ds_column_summary.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg new file mode 100644 index 000000000..ed225a99b --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg new file mode 100644 index 000000000..c81b5419a --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg new file mode 100644 index 000000000..23d8c5da5 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg new file mode 100644 index 000000000..13f924d88 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/data/back_normal.svg b/designer-base/src/main/resources/com/fr/design/images/data/back_normal.svg new file mode 100644 index 000000000..8b22bc182 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/data/back_normal.svg @@ -0,0 +1,9 @@ + + + icon_返回_normal + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/data/clear_normal.svg b/designer-base/src/main/resources/com/fr/design/images/data/clear_normal.svg new file mode 100644 index 000000000..11f60a553 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/data/clear_normal.svg @@ -0,0 +1,10 @@ + + + icon_关闭_normal + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/data/search_normal.svg b/designer-base/src/main/resources/com/fr/design/images/data/search_normal.svg new file mode 100644 index 000000000..dc036ac53 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/data/search_normal.svg @@ -0,0 +1,9 @@ + + + icon_搜索_normal + + + + diff --git a/designer-base/src/test/java/com/fr/design/data/MapCompareUtilsTest.java b/designer-base/src/test/java/com/fr/design/data/MapCompareUtilsTest.java new file mode 100644 index 000000000..1f1e60e2b --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/data/MapCompareUtilsTest.java @@ -0,0 +1,57 @@ +package com.fr.design.data; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2022/3/28 + */ +public class MapCompareUtilsTest { + + @Test + public void contrastMapEntries() { + + + Map orig = new LinkedHashMap<>(); + + orig.put("aaa", "aaa"); + orig.put("bbb", "bbb"); + orig.put("ccc", "ccc"); + orig.put("ddd", "ddd"); + + + Map other = new LinkedHashMap<>(); + + other.put("aaa", "111"); + other.put("bbb", "bbb"); + other.put("ccc", "ccc"); + other.put("eee", "eee"); + + + MapCompareUtils.contrastMapEntries(orig, other, new MapCompareUtils.EventHandler() { + @Override + public void on(MapCompareUtils.EntryEventKind entryEventKind, String s, String s2) { + switch (entryEventKind) { + case UPDATED: + Assert.assertEquals(s, "aaa"); + Assert.assertEquals(s2, "111"); + break; + case REMOVED: + Assert.assertEquals(s, "ddd"); + break; + case ADDED: + Assert.assertEquals(s, "eee"); + Assert.assertEquals(s2, "eee"); + break; + default: + Assert.fail(); + } + } + }); + } +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboardTest.java b/designer-base/src/test/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboardTest.java new file mode 100644 index 000000000..98871158d --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboardTest.java @@ -0,0 +1,43 @@ +package com.fr.design.data.datapane.management.clip; + +import com.fr.data.impl.EmbeddedTableData; +import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Yvan + */ +public class TableDataTreeClipboardTest extends TestCase { + + public void testAddAndTake() { + Map testMap = new HashMap<>(); + testMap.put("ds1", new TemplateTableDataWrapper(new EmbeddedTableData())); + testMap.put("ds2", new TemplateTableDataWrapper(new EmbeddedTableData())); + + Map anotherTestMap = new HashMap<>(); + anotherTestMap.put("ds3", new TemplateTableDataWrapper(new EmbeddedTableData())); + + Map clip; + TableDataTreeClipboard.getInstance().addToClip(testMap); + clip = TableDataTreeClipboard.getInstance().takeFromClip(); + Assert.assertEquals(2, clip.size()); + Assert.assertTrue(clip.containsKey("ds1")); + Assert.assertTrue(clip.containsKey("ds2")); + + // 验证多次取出 + clip = TableDataTreeClipboard.getInstance().takeFromClip(); + Assert.assertEquals(2, clip.size()); + Assert.assertTrue(clip.containsKey("ds1")); + Assert.assertTrue(clip.containsKey("ds2")); + + TableDataTreeClipboard.getInstance().addToClip(anotherTestMap); + clip = TableDataTreeClipboard.getInstance().takeFromClip(); + Assert.assertEquals(1, clip.size()); + Assert.assertTrue(clip.containsKey("ds3")); + } +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtilsTest.java b/designer-base/src/test/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtilsTest.java new file mode 100644 index 000000000..2435f363f --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtilsTest.java @@ -0,0 +1,201 @@ +package com.fr.design.data.tabledata.paste; + +import com.fr.base.TableData; +import com.fr.data.Dictionary; +import com.fr.data.TableDataSource; +import com.fr.data.impl.EmbeddedTableData; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.form.data.DataBinding; +import com.fr.form.data.DataTableConfig; +import com.fr.form.ui.AbstractDataControl; +import com.fr.form.ui.DictionaryContainer; +import com.fr.form.ui.Widget; +import com.fr.form.ui.WidgetValue; +import com.fr.report.cell.tabledata.ElementUsedTableDataProvider; +import com.fr.script.Calculator; +import com.fr.stable.script.CalculatorProvider; +import com.fr.stable.script.NameSpace; +import com.fr.web.core.TemplateSessionIDInfo; +import junit.framework.TestCase; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Yvan + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({DesignTableDataManager.class}) +public class TableDataFollowingPasteUtilsTest extends TestCase { + + @Before + public void beforeTest() { + Map templateDataMap = new LinkedHashMap(); + Map serverDataMap = new LinkedHashMap(); + Map storeProcedureMap = new LinkedHashMap(); + templateDataMap.put("ds1", new TemplateTableDataWrapper(new EmbeddedTableData())); + templateDataMap.put("ds2", new TemplateTableDataWrapper(new EmbeddedTableData())); + templateDataMap.put("ds3", new TemplateTableDataWrapper(new EmbeddedTableData())); + templateDataMap.put("ds4", new TemplateTableDataWrapper(new EmbeddedTableData())); + templateDataMap.put("ds5", new TemplateTableDataWrapper(new EmbeddedTableData())); + + List> list = new ArrayList>(); + list.add(templateDataMap); + list.add(serverDataMap); + list.add(storeProcedureMap); + + TableDataSource tableDataSource = EasyMock.mock(TableDataSource.class); + PowerMock.mockStatic(DesignTableDataManager.class); + EasyMock.expect(DesignTableDataManager.getEditingTableDataSource()).andReturn(tableDataSource).anyTimes(); + EasyMock.expect(DesignTableDataManager.getEditingDataSet(tableDataSource)).andReturn(list).anyTimes(); + PowerMock.replayAll(); + } + + public void testTransferProvider2TableDataMap() { + ElementUsedTableDataProvider[] providers = generateElementUsedTableDataProvider(); + Map tableDataMap = TableDataFollowingPasteUtils.transferProvider2TableDataMap(providers); + Assert.assertEquals(2, tableDataMap.size()); + Assert.assertTrue(tableDataMap.containsKey("ds1")); + Assert.assertTrue(tableDataMap.containsKey("ds2")); + } + + private ElementUsedTableDataProvider[] generateElementUsedTableDataProvider() { + ElementUsedTableDataProvider elementUsedTableDataProvider1 = new ElementUsedTableDataProvider() { + @Override + public Set getElementUsedTableDataNames() { + Set set = new HashSet<>(); + set.add("ds1"); + return set; + } + }; + ElementUsedTableDataProvider elementUsedTableDataProvider2 = new ElementUsedTableDataProvider() { + @Override + public Set getElementUsedTableDataNames() { + Set set = new HashSet<>(); + set.add("ds2"); + return set; + } + }; + return new ElementUsedTableDataProvider[]{elementUsedTableDataProvider1, elementUsedTableDataProvider2}; + } + + public void testTransferWidgetArray2TableDataMap() { + Widget[] widgets = generateWidgetArray(); + Map tableDataMap = TableDataFollowingPasteUtils.transferWidgetArray2TableDataMap(widgets); + Assert.assertEquals(3, tableDataMap.size()); + Assert.assertTrue(tableDataMap.containsKey("ds3")); + Assert.assertTrue(tableDataMap.containsKey("ds4")); + Assert.assertTrue(tableDataMap.containsKey("ds5")); + } + + private Widget[] generateWidgetArray() { + Set set = new HashSet<>(); + set.add("ds3"); + MockWidget widget1 = EasyMock.mock(MockWidget.class); + EasyMock.expect(widget1.getUsedTableDataSets()).andReturn(set).anyTimes(); + EasyMock.replay(widget1); + + DataBinding dataBinding = new DataBinding("ds4", ""); + WidgetValue widgetValue2 = new WidgetValue(); + widgetValue2.setValue(dataBinding); + AbstractDataControl widget2 = EasyMock.mock(AbstractDataControl.class); + EasyMock.expect(widget2.getWidgetValue()).andReturn(widgetValue2).anyTimes(); + EasyMock.replay(widget2); + + DataTableConfig dataTableConfig = EasyMock.mock(DataTableConfig.class); + EasyMock.expect(dataTableConfig.getTableDataName()).andReturn("ds5").anyTimes(); + WidgetValue widgetValue3 = new WidgetValue(); + widgetValue3.setValue(dataTableConfig); + AbstractDataControl widget3 = EasyMock.mock(AbstractDataControl.class); + EasyMock.expect(widget3.getWidgetValue()).andReturn(widgetValue3).anyTimes(); + EasyMock.replay(dataTableConfig, widget3); + + Widget[] widgets = new Widget[3]; + widgets[0] = widget1; + widgets[1] = widget2; + widgets[2] = widget3; + return widgets; + } + + private class MockWidget extends Widget implements DictionaryContainer { + + @Override + public String[] supportedEvents() { + return new String[0]; + } + + @Override + public void setDictionary(Dictionary model) { + + } + + @Override + public Dictionary getDictionary() { + return null; + } + + @Override + public Object getViewValue(Object value, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req) { + return null; + } + + @Override + public Object getModuleValue(Object text, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req) { + return null; + } + + @Override + public Object getViewValue(Object value, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req, NameSpace dependenceNameSpace) { + return null; + } + + @Override + public Object getModuleValue(Object text, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req, NameSpace dependenceNameSpace) { + return null; + } + + @Override + public boolean isValueAllInDictionary(Object value, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req, NameSpace dependenceNameSpace) { + return false; + } + + @Override + public String getXType() { + return null; + } + + @Override + public boolean isEditor() { + return false; + } + + @Override + public void setDependenceMap(Map dependenceMap) { + + } + + @Override + public Map getDependenceMap() { + return null; + } + + @Override + public String[] dependence(CalculatorProvider calculatorProvider) { + return new String[0]; + } + } +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java b/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java new file mode 100644 index 000000000..837c2bd5b --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java @@ -0,0 +1,139 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.ByteBuddy; +import com.fr.third.net.bytebuddy.agent.ByteBuddyAgent; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.dynamic.loading.ClassReloadingStrategy; +import com.fr.third.net.bytebuddy.matcher.ElementMatchers; +import com.fr.third.org.apache.commons.lang3.time.StopWatch; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.TimeUnit; + +/** + * 测试一下,通过 redefine 去处理代码时 + * 相应的 advice 应该怎么写 + */ +public class BytebuddyRedefineTest { + + /** + * 测试一下是否可以直接抛出异常 + */ + @Test + public void testThrowException() { + + try { + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestThrowExceptionAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + testClass.testPrint(); + } catch (Throwable throwable) { + Assert.assertNotNull("expected throw exception", throwable); + } + } + + /** + * 测试是否可以直接传值 + */ + @Test + public void testTransferValue() { + + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestTransferValueAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + String print = testClass.testPrint(); + + Assert.assertEquals(10, TestTransferValueAdvice.intField); + Assert.assertEquals("[test]stringField", TestTransferValueAdvice.stringField); + Assert.assertEquals("[test]objectField", TestTransferValueAdvice.objectField); + + } + + /** + * 测试是否可以改变返回值 + */ + @Test + public void testModifyReturn() { + + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestModifyReturnAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + String print = testClass.testPrint(); + + Assert.assertEquals("[test]Modify Return Value", print); + + } + + @Test + public void testCallable() throws Exception { + + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestCallableAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + TestClass testClass = new TestClass(); + String print = testClass.testPrint(); + + Assert.assertEquals("[test]Callable", print); + } + + @Test + public void testCallablePerformance() throws Exception { + + // 千 + int loop = 1000; + StopWatch stopWatch = new StopWatch(); + + stopWatch.start(); + TestClass rawClass = new TestClass(); + for (int i = 0; i < loop; i++) { + rawClass.testPrint(); + } + System.out.printf("raw class run %s cost %s ms \n", loop, stopWatch.getTime(TimeUnit.MILLISECONDS)); + + + ByteBuddyAgent.install(); + + new ByteBuddy() + .redefine(TestClass.class) + .visit(Advice.to(TestCallableAdvice.class).on(ElementMatchers.named("testPrint"))) + .make() + .load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()); + + stopWatch.reset(); + stopWatch.start(); + + TestClass retransformClass = new TestClass(); + for (int i = 0; i < loop; i++) { + retransformClass.testPrint(); + } + + System.out.printf("retransformClass class run %s cost %s ms \n", loop, stopWatch.getTime(TimeUnit.MILLISECONDS)); + + Assert.assertEquals("[test]Callable", retransformClass.testPrint()); + } + +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableAdvice.java new file mode 100644 index 000000000..f98cedcde --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableAdvice.java @@ -0,0 +1,50 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.advice.AdviceCallable; +import com.fr.record.analyzer.advice.AdviceContext; +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; +import com.fr.tolerance.FaultTolerance; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +/** + * created by Harrison on 2022/03/09 + **/ +public class TestCallableAdvice { + + @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) + public static boolean onMethodEnter(@Advice.Local("context")AdviceContext adviceContext) { + + adviceContext = AdviceContext + .builder() + .onAdviceCall() + .build(); + // 如果是切面调用,则忽视当前方法 + return adviceContext.isOnAdviceCall(); + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result, + @Advice.Local("context") AdviceContext adviceContext) throws Exception { + + // 如果是切面调用,则忽视不继续 exit + if (adviceContext != null && adviceContext.isOnAdviceCall()) { + return; + } + + FaultTolerance faultTolerance = method.getAnnotation(FaultTolerance.class); + Callable callable = new AdviceCallable() { + @Override + public Object call() throws Exception { + return method.invoke(self, args); + } + }; + result = TestCallableHelper.test(callable); + } + +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableHelper.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableHelper.java new file mode 100644 index 000000000..4e99bb703 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableHelper.java @@ -0,0 +1,15 @@ +package com.fr.design.record.analyzer; + +import java.util.concurrent.Callable; + +/** + * created by Harrison on 2022/03/09 + **/ +public class TestCallableHelper { + + public static String test(Callable callable) throws Exception { + + callable.call(); + return "[test]Callable"; + } +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java new file mode 100644 index 000000000..e1a2761aa --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java @@ -0,0 +1,11 @@ +package com.fr.design.record.analyzer; + +/** + * created by Harrison on 2022/03/04 + **/ +public class TestClass { + + public String testPrint() { + return ""; + } +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java new file mode 100644 index 000000000..7c2dae455 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java @@ -0,0 +1,29 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class TestModifyReturnAdvice { + + @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) + public static int onMethodEnter() throws Exception { + + return 0; + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self, + @Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args, + @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception { + + result = "[test]Modify Return Value"; + + } + +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java new file mode 100644 index 000000000..53c54c28d --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java @@ -0,0 +1,19 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.asm.Advice; +import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner; + +import java.lang.reflect.Method; + +/** + * created by Harrison on 2022/03/07 + **/ +public class TestThrowExceptionAdvice { + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Origin Method method, + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments, + @Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e) throws Exception { + throw new RuntimeException("[test] throw exception in advice"); + } +} diff --git a/designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java b/designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java new file mode 100644 index 000000000..fa0bf6f09 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java @@ -0,0 +1,37 @@ +package com.fr.design.record.analyzer; + +import com.fr.third.net.bytebuddy.asm.Advice; + +/** + * created by Harrison on 2022/03/07 + **/ +public class TestTransferValueAdvice { + + public static int intField; + + public static String stringField; + + public static Object objectField; + + @Advice.OnMethodEnter + public static void onMethodEnter(@Advice.Local("int") int intField, + @Advice.Local("string") String stringField, + @Advice.Local("Object") Object objectField) { + + intField = 10; + stringField = "[test]stringField"; + objectField = "[test]objectField"; + } + + @Advice.OnMethodExit(onThrowable = Exception.class) + public static void onMethodExit(@Advice.Local("int") int intField, + @Advice.Local("string") String stringField, + @Advice.Local("Object") Object objectField) throws Exception { + + TestTransferValueAdvice.intField = intField; + TestTransferValueAdvice.stringField = stringField; + TestTransferValueAdvice.objectField = objectField; + + } + +} diff --git a/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java b/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java index 2d54fc818..b7c9c474e 100644 --- a/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java +++ b/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java @@ -111,6 +111,8 @@ public class ChartTypeInterfaceManager implements ExtraChartDesignClassManagerPr public static final String TYPE_PANE_DEFAULT_TITLE = "DEFAULT_NAME"; + public static final String GEO_LAND_CHART_ID = "UGeoLandChart"; + public synchronized static ChartTypeInterfaceManager getInstance() { return classManager; diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartDataHelper.java b/designer-chart/src/main/java/com/fr/design/chart/ChartDataHelper.java new file mode 100644 index 000000000..e8371a3c1 --- /dev/null +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartDataHelper.java @@ -0,0 +1,69 @@ +package com.fr.design.chart; + +import com.fr.base.TableData; +import com.fr.base.chart.chartdata.TopDefinitionProvider; +import com.fr.chart.chartattr.Chart; +import com.fr.chart.chartattr.Plot; +import com.fr.chart.chartdata.MoreNameCDDefinition; +import com.fr.chart.chartdata.OneValueCDDefinition; +import com.fr.data.TableDataSource; +import com.fr.design.DesignModelAdapter; +import com.fr.design.data.DesignTableDataManager; +import com.fr.general.ComparatorUtils; +import com.fr.plugin.chart.custom.CustomDefinition; +import com.fr.plugin.chart.custom.type.CustomPlotType; +import com.fr.van.chart.designer.PlotFactory; +import java.util.Map; + +public class ChartDataHelper { + public static String[] getCommonChartFieldNames(Chart chart) { + if (chart == null) { + return null; + } + Plot plot = chart.getPlot(); + if (plot == null) { + return null; + } + + if (!PlotFactory.plotSupportAddTableField(plot)) { + return null; + } + TopDefinitionProvider definition = chart.getFilterDefinition(); + return getFieldNames(definition); + } + + public static String[] getCustomChartTableFieldNames(Chart chart, CustomPlotType plotType) { + if (chart == null || plotType == null) { + return null; + } + + TopDefinitionProvider filterDefinition = chart.getFilterDefinition(); + if (filterDefinition instanceof CustomDefinition) { + CustomDefinition customDefinition = (CustomDefinition) filterDefinition; + Map definitionProviderMap = customDefinition.getDefinitionProviderMap(); + return getFieldNames(definitionProviderMap.get(plotType)); + } + return null; + } + + private static String[] getFieldNames(TopDefinitionProvider definition) { + if (definition == null) { + return null; + } + DesignModelAdapter adapter = DesignModelAdapter.getCurrentModelAdapter(); + TableDataSource tableDataSource = adapter == null ? null : adapter.getBook(); + TableData tableData = null; + if (ComparatorUtils.equals(definition.getDataDefinitionType(), OneValueCDDefinition.DEFINITION_TYPE)) { + OneValueCDDefinition oneValueCDDefinition = (OneValueCDDefinition) definition; + tableData = oneValueCDDefinition.getTableData(); + } else if (ComparatorUtils.equals(definition.getDataDefinitionType(), MoreNameCDDefinition.DEFINITION_TYPE)) { + MoreNameCDDefinition moreNameCDDefinition = (MoreNameCDDefinition) definition; + tableData = moreNameCDDefinition.getTableData(); + } + if (tableData == null) { + return null; + } + return DesignTableDataManager.getSelectedColumnNames(tableDataSource, tableData.getName()); + } + +} 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 1408b6a77..c34fcce65 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 @@ -8,11 +8,13 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chartx.attr.ChartProvider; import com.fr.design.ChartTypeInterfaceManager; +import com.fr.design.base.mode.DesignModeContext; import com.fr.design.gui.ilable.UILabel; 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.stable.ArrayUtils; import com.fr.van.chart.config.DefaultStyleHelper4Van; import javax.swing.BorderFactory; @@ -45,6 +47,11 @@ public class ChartTypePane extends ChartCommonWizardPane implements CallbackEven DefaultListModel defaultListModel = new DefaultListModel(); mainTypeList = new JList(defaultListModel); + if (DesignModeContext.isDuchampMode() + && ArrayUtils.contains(chartIDs, ChartTypeInterfaceManager.GEO_LAND_CHART_ID)) { + chartIDs = ArrayUtils.removeElement(chartIDs, ChartTypeInterfaceManager.GEO_LAND_CHART_ID); + } + for (int i = 0; i < chartIDs.length; i++) { defaultListModel.insertElementAt(ChartTypeInterfaceManager.getInstance().getName(chartIDs[i]), i); } diff --git a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ChartConditionPane.java b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ChartConditionPane.java index af44b6331..4085c7f10 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ChartConditionPane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ChartConditionPane.java @@ -7,6 +7,7 @@ import com.fr.design.beans.BasicBeanPane; import com.fr.design.condition.LiteConditionPane; import com.fr.design.editor.ValueEditorPane; import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.editor.editor.Editor; import com.fr.design.formula.CustomVariableResolver; import com.fr.design.formula.VariableResolver; import com.fr.design.gui.icombobox.UIComboBox; @@ -17,6 +18,7 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.general.ComparatorUtils; import com.fr.plugin.chart.type.ConditionKeyType; +import com.fr.stable.ArrayUtils; import com.fr.stable.StringUtils; import javax.swing.DefaultComboBoxModel; @@ -79,7 +81,10 @@ public class ChartConditionPane extends LiteConditionPane { return this; } }); - conditionValuePane = ValueEditorPaneFactory.createAllValueEditorPane(); + Editor[] editors = ValueEditorPaneFactory.allEditors(); + ColSelectedWithSummaryMethodEditor colSelectedWithSummaryMethodEditor = new ColSelectedWithSummaryMethodEditor(); + Editor[] allEditors = ArrayUtils.add(editors,colSelectedWithSummaryMethodEditor); + conditionValuePane = ValueEditorPaneFactory.createValueEditorPane(allEditors,StringUtils.EMPTY,StringUtils.EMPTY); conditionKeyComboBox.setPreferredSize(new Dimension(175, conditionKeyComboBox.getPreferredSize().height)); conditionOPComboBox.setPreferredSize(new Dimension(80, 20)); Component[][] components = { diff --git a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java new file mode 100644 index 000000000..6b6fe08cc --- /dev/null +++ b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java @@ -0,0 +1,89 @@ +package com.fr.design.chart.series.SeriesCondition; + +import com.fr.chart.chartattr.Chart; +import com.fr.data.DSColumnWithSummaryMethod; +import com.fr.design.chart.ChartDataHelper; +import com.fr.design.data.datapane.SummaryMethodComboBox; +import com.fr.design.editor.editor.Editor; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.plugin.chart.custom.type.CustomPlotType; +import java.awt.Dimension; +import javax.swing.DefaultComboBoxModel; + +public class ColSelectedWithSummaryMethodEditor extends Editor { + private UIComboBox columnNameComboBox = new UIComboBox(); + private SummaryMethodComboBox summaryMethodComboBox; + private static DefaultComboBoxModel columnNameComboBoxModel = new DefaultComboBoxModel<>(); + private static DefaultComboBoxModel summaryMethodComboBoxModel = new DefaultComboBoxModel<>(SummaryMethodComboBox.CALCULATE_ARRAY); + + public ColSelectedWithSummaryMethodEditor() { + this.setName(Toolkit.i18nText("Fine-Design_Chart_Summary_Array")); + this.setLayout(FRGUIPaneFactory.createLeftZeroLayout()); + if (columnNameComboBox == null) { + columnNameComboBox = new UIComboBox(); + } + columnNameComboBox.setPreferredSize(new Dimension(82, 20)); + this.add(columnNameComboBox); + summaryMethodComboBox = new SummaryMethodComboBox(); + summaryMethodComboBox.setModel(summaryMethodComboBoxModel); + summaryMethodComboBox.setPreferredSize(new Dimension(82, 20)); + this.add(summaryMethodComboBox); + columnNameComboBox.setModel(columnNameComboBoxModel); + } + + public static void refreshCommonChartFieldNames(Chart chart) { + String[] columnNames = ChartDataHelper.getCommonChartFieldNames(chart); + refreshComboBoxModel(columnNames); + } + + public static void refreshCustomChartTableFieldNames(Chart chart, CustomPlotType plotType) { + String[] columnNames = ChartDataHelper.getCustomChartTableFieldNames(chart, plotType); + refreshComboBoxModel(columnNames); + } + + private static void refreshComboBoxModel(String[] columnNames) { + if (columnNames != null) { + columnNameComboBoxModel.removeAllElements(); + for (String columnName : columnNames) { + columnNameComboBoxModel.addElement(columnName); + } + for (String method : SummaryMethodComboBox.CALCULATE_ARRAY) { + summaryMethodComboBoxModel.addElement(method); + } + } else { + columnNameComboBoxModel.removeAllElements(); + summaryMethodComboBoxModel.removeAllElements(); + } + } + + public String getIconName() { + return "ds_column_summary"; + } + + @Override + public DSColumnWithSummaryMethod getValue() { + if (columnNameComboBox.getSelectedItem() == null || summaryMethodComboBox.getSelectedItem() == null) { + return null; + } + DSColumnWithSummaryMethod dsColumnWithSummaryMethod = new DSColumnWithSummaryMethod(); + dsColumnWithSummaryMethod.setFieldName(columnNameComboBox.getSelectedItem().toString()); + dsColumnWithSummaryMethod.setDataFunction(summaryMethodComboBox.updateBean()); + return dsColumnWithSummaryMethod; + } + + @Override + public void setValue(DSColumnWithSummaryMethod value) { + if (value != null) { + columnNameComboBox.setSelectedItem(value.getFieldName()); + summaryMethodComboBox.setSelectedItem(value.getDataFunction()); + } + } + + @Override + public boolean accept(Object object) { + return object instanceof DSColumnWithSummaryMethod; + } + +} diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java index 6b75dff69..6064ef89d 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java @@ -29,6 +29,7 @@ import com.fr.log.FineLoggerFactory; import com.fr.plugin.chart.custom.VanChartCustomPlot; import com.fr.plugin.chart.vanchart.VanChart; +import com.fr.van.chart.drillmap.designer.data.VanChartDrillMapDataPane; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -148,7 +149,12 @@ public class ChartEditPane extends BasicPane implements AttributeChange, Prepare ChartInfoCollector.getInstance().updateChartPropertyTime(collection.getSelectedChartProvider(ChartProvider.class)); selectedPane.update(collection); - + for (int i = 0; i < paneList.size(); i++) { + if (paneList.get(i) instanceof VanChartDrillMapDataPane && i != tabsHeaderIconPane.getSelectedIndex()) { + paneList.get(i).populateBean(collection); + break; + } + } if (!ComparatorUtils.equals(collection, lastCollection)) { VanChart vanChart = collection.getSelectedChartProvider(VanChart.class); if (vanChart != null) { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartOtherPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartOtherPane.java index 4bc363306..36bc56d6b 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartOtherPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartOtherPane.java @@ -5,6 +5,7 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.chart.chartattr.Plot; import com.fr.chartx.config.info.constant.ConfigType; import com.fr.design.beans.BasicBeanPane; +import com.fr.design.chart.series.SeriesCondition.ColSelectedWithSummaryMethodEditor; import com.fr.design.dialog.BasicPane; import com.fr.design.mainframe.chart.AbstractChartAttrPane; import com.fr.design.mainframe.chart.ChartEditPane; @@ -112,6 +113,7 @@ public class ChartOtherPane extends AbstractChartAttrPane { interactivePane.populateBean(chart); if (ChartOtherPane.this.isHaveCondition()) { VanChartRichEditorPane.refreshCommonChartFieldNames(chart); + ColSelectedWithSummaryMethodEditor.refreshCommonChartFieldNames(chart); conditionAttrPane.populateBean(chart); } } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java index 2eea49f16..bd94ff561 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java @@ -19,7 +19,6 @@ import com.fr.design.mainframe.chart.gui.item.FlexibleComboBox; import com.fr.design.mainframe.chart.gui.item.ItemEventType; import com.fr.design.mainframe.chart.gui.type.AbstractChartTypePane; import com.fr.design.mainframe.chart.mode.ChartEditContext; -import com.fr.design.mainframe.chart.mode.ChartEditMode; import com.fr.design.module.DesignModuleFactory; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; @@ -27,11 +26,6 @@ import com.fr.stable.AssistUtils; import com.fr.stable.StringUtils; import javax.swing.JPanel; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.event.ActionEvent; @@ -40,6 +34,11 @@ 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.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * 图表 属性表, 类型选择 界面. @@ -55,6 +54,7 @@ public class ChartTypePane extends AbstractChartAttrPane { private ActionListener autoButtonListener; private boolean inForm; + @Override protected JPanel createContentPane() { initButtonListener(); @@ -291,13 +291,20 @@ public class ChartTypePane extends AbstractChartAttrPane { String plotID = entry.getKey(); if (ignore || ChartTypeManager.enabledChart(plotID)) { if (ChartTypeManager.getInstance().isShowInDesigner(plotID)) { - cards.add(entry.getValue()); + if (notGeoLandInDuchampCPT(plotID)) { + cards.add(entry.getValue()); + } } } } } + public boolean notGeoLandInDuchampCPT(String plotID) { + return !(DesignModeContext.isDuchampMode() + && ChartTypeInterfaceManager.GEO_LAND_CHART_ID.equals(plotID)); + } + private void addOnePlotIDCards(int priority, String plotID) { cards.add(allChartTypePane.get(priority).get(plotID)); } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/CalculateComboBox.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/CalculateComboBox.java index a1ad22312..61a906a3f 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/CalculateComboBox.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/CalculateComboBox.java @@ -1,17 +1,6 @@ package com.fr.design.mainframe.chart.gui.data; -import com.fr.data.util.function.AbstractDataFunction; -import com.fr.data.util.function.AverageFunction; -import com.fr.data.util.function.CountFunction; -import com.fr.data.util.function.MaxFunction; -import com.fr.data.util.function.MinFunction; -import com.fr.data.util.function.NoneFunction; -import com.fr.data.util.function.SumFunction; -import com.fr.design.gui.icombobox.UIComboBox; -import com.fr.design.i18n.Toolkit; -import com.fr.general.ComparatorUtils; -import com.fr.log.FineLoggerFactory; -import com.fr.plugin.chart.base.FirstFunction; +import com.fr.design.data.datapane.SummaryMethodComboBox; /** @@ -20,53 +9,11 @@ import com.fr.plugin.chart.base.FirstFunction; * @author kunsnat E-mail:kunsnat@gmail.com * @version 创建时间:2013-1-8 上午09:52:15 */ -public class CalculateComboBox extends UIComboBox { - - public static final String[] CALCULATE_ARRAY = {Toolkit.i18nText("Fine-Design_Chart_Data_Function_First"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Last"), - Toolkit.i18nText("Fine-Design_Chart_Data_Function_Sum"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Average"), - Toolkit.i18nText("Fine-Design_Chart_Data_Function_Max"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Min"), - Toolkit.i18nText("Fine-Design_Chart_Data_Function_Count")}; - public static final Class[] CLASS_ARRAY = {FirstFunction.class, NoneFunction.class, SumFunction.class, AverageFunction.class, - MaxFunction.class, MinFunction.class, CountFunction.class}; +public class CalculateComboBox extends SummaryMethodComboBox { + public static final String[] CALCULATE_ARRAY = SummaryMethodComboBox.CALCULATE_ARRAY; + public static final Class[] CLASS_ARRAY = SummaryMethodComboBox.CLASS_ARRAY; public CalculateComboBox() { - super(CALCULATE_ARRAY); - setSelectedIndex(2); - } - - public void reset() { - this.setSelectedItem(Toolkit.i18nText("Fine-Design_Chart_Data_Function_Sum")); - } - - /** - * 更新公式选择. - */ - public void populateBean(AbstractDataFunction function) { - for (int i = 0; i < CLASS_ARRAY.length; i++) { - if (function != null && ComparatorUtils.equals(function.getClass(), CLASS_ARRAY[i])) { - setSelectedIndex(i); - break; - } - } - } - - /** - * 返回当前选择的公式 - */ - public AbstractDataFunction updateBean() { - try { - int selectIndex = getSelectedIndex(); - if (selectIndex >= 0 && selectIndex < CLASS_ARRAY.length) { - return (AbstractDataFunction) CLASS_ARRAY[selectIndex].newInstance(); - } - } catch (InstantiationException e) { - FineLoggerFactory.getLogger().error("Function Error"); - return null; - } catch (IllegalAccessException e) { - FineLoggerFactory.getLogger().error("Function Error"); - return null; - } - - return null; + super(); } } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/ChartDataHelper.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/ChartDataHelper.java new file mode 100644 index 000000000..0ff5b275f --- /dev/null +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/ChartDataHelper.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.chart.gui.data; + +import com.fr.base.chart.chartdata.TopDefinitionProvider; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartattr.Plot; +import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.attr.axis.VanChartAxisLabelStyle; +import com.fr.plugin.chart.attr.plot.VanChartAxisPlot; +import com.fr.van.chart.config.DefaultStyleHelper4Van; + +/** + * @author shine + * @version 10.0 + * Created by shine on 2022/4/6 + */ +public class ChartDataHelper { + + /** + * 在update数据集分类的时候,需要联动update一下样式-坐标轴里面的分层样式设置,来自CHART-22873 + */ + public static void updateAxisCategoryStyles(ChartCollection chartCollection) { + TopDefinitionProvider definition = chartCollection.getSelectedChart().getFilterDefinition(); + int size = definition == null ? 1 : definition.getMoreCateSize() + 1; + + Plot plot = chartCollection.getSelectedChart().getPlot(); + if (plot instanceof VanChartAxisPlot) { + for (VanChartAxis axis : ((VanChartAxisPlot) plot).getXAxisList()) { + axis.clearCategoryStyles(); + for (int i = 0; i < size; i++) { + axis.addCategoryStyle(DefaultStyleHelper4Van.dealAxisCheckTheme(new VanChartAxisLabelStyle())); + } + } + } + } +} diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java index 54c3bd33d..427e241e6 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java @@ -13,6 +13,7 @@ import com.fr.design.formula.TinyFormulaPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.mainframe.chart.gui.ChartDataPane; import com.fr.design.mainframe.chart.gui.data.ChartDataFilterPane; +import com.fr.design.mainframe.chart.gui.data.ChartDataHelper; import com.fr.stable.StringUtils; import com.fr.van.chart.designer.TableLayout4VanChartHelper; @@ -190,10 +191,9 @@ public class CategoryPlotMoreCateReportDataContentPane extends CategoryPlotRepor Plot plot = collection.getSelectedChart().getPlot(); if (definition instanceof NormalReportDataDefinition) { NormalReportDataDefinition reportDefinition = (NormalReportDataDefinition) definition; - reportDefinition.clearMoreCate(); updateMoreCate(reportDefinition, plot); - collection.updateAxisCategoryStyles(); + ChartDataHelper.updateAxisCategoryStyles(collection); } } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java index 4c809e64f..7432dfcce 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java @@ -13,6 +13,7 @@ import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.BoldFontTextLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.mainframe.chart.gui.ChartDataPane; +import com.fr.design.mainframe.chart.gui.data.ChartDataHelper; import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.BorderFactory; @@ -246,7 +247,7 @@ public class CategoryPlotMoreCateTableDataContentPane extends CategoryPlotTableD normal.clearMoreCate(); updateMoreCate(normal, plot); } - collection.updateAxisCategoryStyles(); + ChartDataHelper.updateAxisCategoryStyles(collection); } protected void updateMoreCate(NormalTableDataDefinition normal, Plot plot) { @@ -257,5 +258,4 @@ public class CategoryPlotMoreCateTableDataContentPane extends CategoryPlotTableD } } } - } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartHyperlinkGroup.java b/designer-chart/src/main/java/com/fr/design/module/ChartHyperlinkGroup.java index 378e6a0d7..e0112f186 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartHyperlinkGroup.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartHyperlinkGroup.java @@ -59,7 +59,7 @@ public class ChartHyperlinkGroup extends BaseHyperlinkGroup { return false; } - if (template.isJWorkBook() || DesignModeContext.isDuchampMode()) { + if (template.isJWorkBook()) { // 如果是普通报表单元格,那么没有 FormHyperlink 选项 FormHyperlinkProvider formHyperlink = StableFactory.getMarkedInstanceObjectFromClass(FormHyperlinkProvider.XML_TAG, FormHyperlinkProvider.class); //返回true表示可用,返回false表示不可用 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 8421492fa..b3bfca329 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 @@ -5,6 +5,7 @@ import com.fr.base.ChartPreStyleConfig; import com.fr.chart.base.AttrBorder; import com.fr.chart.base.AttrFillStyle; import com.fr.chart.base.ChartConstants; +import com.fr.chart.base.ChartThemeStyleProvider; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.ConditionAttr; import com.fr.chart.chartglyph.DataSheet; @@ -14,6 +15,7 @@ import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.plugin.chart.PiePlot4VanChart; import com.fr.plugin.chart.attr.axis.VanChartAlertValue; import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.attr.axis.VanChartAxisLabelStyle; import com.fr.plugin.chart.attr.plot.VanChartPlot; import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot; import com.fr.plugin.chart.base.AttrLabel; @@ -24,6 +26,10 @@ import com.fr.plugin.chart.map.VanChartMapPlot; import com.fr.plugin.chart.type.GaugeStyle; import com.fr.plugin.chart.vanchart.VanChart; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * @author shine * @version 10.0 @@ -82,7 +88,28 @@ public class DefaultStyleHelper4Van { } + private static void dealAxisCheckTheme(VanChartAxis axis) { + if (!ChartEditContext.supportTheme()) { + List chartThemeStyleProviders = new ArrayList<>(); + VanChartRectanglePlot.getAxisChartPreStyleProvider(axis, chartThemeStyleProviders); + for (ChartThemeStyleProvider themeStyleProvider : chartThemeStyleProviders) { + themeStyleProvider.setThemeCustom(); + } + } + } + + public static VanChartAxisLabelStyle dealAxisCheckTheme(VanChartAxisLabelStyle labelStyle) { + if (!ChartEditContext.supportTheme()) { + labelStyle.getTextAttr().setThemeCustom(); + } + return labelStyle; + } + + public static VanChartAxis dealAxisDefault(VanChartAxis axis) { + + dealAxisCheckTheme(axis); + if (!duchampMode()) { return axis; } @@ -140,22 +167,28 @@ public class DefaultStyleHelper4Van { private static void dealChartColor(VanChartPlot vanChartPlot) { ChartPreStyleConfig manager = ChartPreStyleConfig.getInstance(); Object preStyle = manager.getPreStyle(DefaultStyleConstants.COLORS); + ColorFillStyle colorFillStyle = new ColorFillStyle(); 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()); + } else { + //服务器上没有图表配色 + //需要指定配色属性为自定义组合色,否则会被兼容成跟随主题 + // com.fr.plugin.chart.attr.plot.VanChartPlot.compatibleFillStyle + colorFillStyle.setColorStyle(ChartConstants.COLOR_ACC); + colorFillStyle.setColorList(Arrays.asList(ChartConstants.NEW_FEATURES)); + } - AttrFillStyle plotFillStyle = vanChartPlot.getPlotFillStyle(); - if (plotFillStyle == null) { - plotFillStyle = new AttrFillStyle(); - vanChartPlot.setPlotFillStyle(plotFillStyle); - } - plotFillStyle.setColorFillStyle(colorFillStyle); + AttrFillStyle plotFillStyle = vanChartPlot.getPlotFillStyle(); + if (plotFillStyle == null) { + plotFillStyle = new AttrFillStyle(); + vanChartPlot.setPlotFillStyle(plotFillStyle); } + plotFillStyle.setColorFillStyle(colorFillStyle); } private static void dealBorder(VanChartPlot vanChartPlot) { diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java index b5efad3b6..f3a19a41e 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java @@ -150,17 +150,19 @@ public class VanChartHyperLinkPane extends VanChartUIListControlPane { //安装平台内打开插件时,添加相应按钮 Set providers = ExtraDesignClassManager.getInstance().getArray(HyperlinkProvider.XML_TAG); - for (HyperlinkProvider provider : providers) { - NameableCreator nc = provider.createHyperlinkCreator(); - paneMap.put(nc.getHyperlink(), nc.getUpdatePane()); - } - java.util.List list = refreshList(paneMap); - NameObjectCreator[] creators = new NameObjectCreator[list.size()]; - for (int i = 0; list != null && i < list.size(); i++) { + int size = list.size(); + NameObjectCreator[] creators = new NameObjectCreator[size + providers.size()]; + for (int i = 0; i < size; i++) { UIMenuNameableCreator uiMenuNameableCreator = list.get(i); creators[i] = new NameObjectCreator(uiMenuNameableCreator.getName(), uiMenuNameableCreator.getObj().getClass(), uiMenuNameableCreator.getPaneClazz()); - + } + for (HyperlinkProvider provider : providers) { + NameableCreator creator = provider.createHyperlinkCreator(); + if (creator != null) { + creators[size] = new NameObjectCreator(creator.menuName(), creator.getHyperlink(), creator.getUpdatePane()); + size++; + } } refreshNameableCreator(creators); diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/other/VanChartCustomPlotConditionAttrTabPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/other/VanChartCustomPlotConditionAttrTabPane.java index 4cb5c652f..8c2056857 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/other/VanChartCustomPlotConditionAttrTabPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/other/VanChartCustomPlotConditionAttrTabPane.java @@ -1,6 +1,7 @@ package com.fr.van.chart.custom.other; import com.fr.chart.chartattr.Chart; +import com.fr.design.chart.series.SeriesCondition.ColSelectedWithSummaryMethodEditor; import com.fr.design.dialog.BasicPane; import com.fr.plugin.chart.attr.plot.VanChartPlot; import com.fr.plugin.chart.custom.CustomPlotFactory; @@ -91,6 +92,7 @@ public class VanChartCustomPlotConditionAttrTabPane extends VanChartCustomPlotTa CustomPlotType plotType = CustomPlotFactory.getCustomType(chartPlot); VanChartRichEditorPane.refreshCustomChartTableFieldNames(chart, plotType); + ColSelectedWithSummaryMethodEditor.refreshCustomChartTableFieldNames(chart,plotType); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomStylePane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomStylePane.java index da4fa2534..234f2ee1d 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomStylePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/style/VanChartCustomStylePane.java @@ -1,6 +1,7 @@ package com.fr.van.chart.custom.style; import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.chart.series.SeriesCondition.ColSelectedWithSummaryMethodEditor; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.frpane.AttributeChangeListener; import com.fr.design.mainframe.chart.gui.style.series.ChartSeriesPane; @@ -75,6 +76,7 @@ public class VanChartCustomStylePane extends VanChartStylePane { public void refreshTableFieldNames(VanChartPlot plot) { CustomPlotType plotType = CustomPlotFactory.getCustomType(plot); VanChartRichEditorPane.refreshCustomChartTableFieldNames(getChart(), plotType); + ColSelectedWithSummaryMethodEditor.refreshCustomChartTableFieldNames(getChart(), plotType); } public void refreshTableFieldNames() { diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java index ce8253b98..823012f58 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java @@ -128,7 +128,7 @@ public abstract class VanChartUIListControlPane extends UIListControlPane implem public void populate(Nameable[] nameableArray) { //特殊处理,使用instanceof判断,弹出不同的面板 - if (SwingUtilities.getWindowAncestor(this) instanceof JDialog) { + if (SwingUtilities.getWindowAncestor(this) instanceof PopupEditDialog) { popupEditDialog = new HyperDialog(cardPane); } super.populate(nameableArray); @@ -136,7 +136,7 @@ public abstract class VanChartUIListControlPane extends UIListControlPane implem protected void popupEditDialog(Point mousePos) { //特殊处理,处理连续弹窗情况,弹出面板定为方式不同 - if (SwingUtilities.getWindowAncestor(this) instanceof JDialog) { + if (SwingUtilities.getWindowAncestor(this) instanceof PopupEditDialog) { GUICoreUtils.centerWindow(popupEditDialog); popupEditDialog.setVisible(true); return; diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/background/VanChartBackgroundPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/background/VanChartBackgroundPane.java index c51ac0fe9..f3de5d17f 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/background/VanChartBackgroundPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/background/VanChartBackgroundPane.java @@ -148,7 +148,7 @@ public class VanChartBackgroundPane extends BasicPane { protected void initList() { paneList.add(new NullBackgroundQuickPane()); - paneList.add(new ColorBackgroundQuickPane()); + paneList.add(new ColorBackgroundQuickPane(true)); paneList.add(new ImageBackgroundQuickPane(false)); paneList.add(new VanChartGradientPane()); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartStylePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartStylePane.java index 7ca77a9fc..603b5af0a 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartStylePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartStylePane.java @@ -1,6 +1,7 @@ package com.fr.van.chart.designer.style; import com.fr.chart.chartattr.Plot; +import com.fr.design.chart.series.SeriesCondition.ColSelectedWithSummaryMethodEditor; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.frpane.AttributeChangeListener; import com.fr.design.mainframe.chart.ChartEditPane; @@ -88,6 +89,7 @@ public class VanChartStylePane extends ChartStylePane { public void refreshTableFieldNames() { VanChartRichEditorPane.refreshCommonChartFieldNames(getChart()); + ColSelectedWithSummaryMethodEditor.refreshCommonChartFieldNames(getChart()); } public void registerChartEditPane(ChartEditPane currentEditPane) { diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java index 5deb49831..dde467226 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisStyleSettingPane.java @@ -13,6 +13,7 @@ import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.FRWidgetFactory; import com.fr.plugin.chart.attr.axis.VanChartAxisLabelStyle; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.style.axis.component.AxisLabelDisplayComboBox; @@ -125,6 +126,7 @@ public class VanChartAxisStyleSettingPane extends BasicBeanPane { private VanChartAxisLabelStyle getAxisLabelStyle(VanChartAxis axis) { VanChartAxisLabelStyle style = new VanChartAxisLabelStyle(); + DefaultStyleHelper4Van.dealAxisCheckTheme(style); style.setLabelDisplay(axis.getLabelDisplay()); style.setTextAttr(axis.getTextAttr()); style.setAutoLabelGap(axis.isAutoLabelGap()); @@ -663,6 +665,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { style = axis.getCategoryStyle(index); } else { style = new VanChartAxisLabelStyle(); + DefaultStyleHelper4Van.dealAxisCheckTheme(style); axis.addCategoryStyle(style); } return style; diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java index acc87572f..79e4aad9b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/component/VanChartCategoryStylePaneWithCheckBox.java @@ -1,7 +1,7 @@ package com.fr.van.chart.designer.style.axis.component; import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; -import com.fr.design.gui.frpane.UIBubbleFloatPane; +import com.fr.design.gui.frpane.ClosableBubbleFloatPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.i18n.Toolkit; @@ -68,7 +68,7 @@ public class VanChartCategoryStylePaneWithCheckBox extends JPanel { Point comPoint = settingButton.getLocationOnScreen(); Point arrowPoint = new Point(comPoint.x +settingButton.getWidth() - 25, comPoint.y + settingButton.getHeight()); Dimension size = settingPane.getPreferredSize(); - UIBubbleFloatPane pane = new UIBubbleFloatPane(Constants.LEFT, arrowPoint, settingPane, size.width, 230) { + ClosableBubbleFloatPane pane = new ClosableBubbleFloatPane(Constants.LEFT, arrowPoint, settingPane, size.width, 240) { @Override public void updateContentPane() { diff --git a/designer-form/src/main/java/com/fr/design/actions/FormECParallelCalAction.java b/designer-form/src/main/java/com/fr/design/actions/FormECParallelCalAction.java new file mode 100644 index 000000000..5874398c2 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/actions/FormECParallelCalAction.java @@ -0,0 +1,81 @@ +package com.fr.design.actions; + +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.UIDialog; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JForm; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.widget.ui.designer.FormECParallelCalSettingPane; +import com.fr.form.main.Form; +import com.fr.form.main.parallel.FormECParallelCalAttr; + +import javax.swing.KeyStroke; +import java.awt.Dimension; +import java.awt.event.ActionEvent; + +/** + * @author fly.li + * @version 10.0 + * Created on 2022/03/18 + */ +public class FormECParallelCalAction extends JTemplateAction { + + private static final MenuKeySet FORM_PARALLEL_SETTING = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'P'; + } + + @Override + public String getMenuName() { + return Toolkit.i18nText("Fine-Design_Form_Calculate_Setting"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + + + private void initMenuStyle() { + this.setMenuKeySet(FORM_PARALLEL_SETTING); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon("com/fr/design/form/images/parallel.png"); + } + + public FormECParallelCalAction(JForm jForm) { + super(jForm); + initMenuStyle(); + } + + @Override + public void actionPerformed(ActionEvent e) { + final JForm jf = getEditingComponent(); + if (jf == null) { + return; + } + showParallelSettingDialog(jf); + } + + private void showParallelSettingDialog(JForm jf) { + FormECParallelCalSettingPane attrPane = new FormECParallelCalSettingPane(); + Form form = jf.getTarget(); + FormECParallelCalAttr parallelAttr = form.getParallelAttr(); + attrPane.populateBean(parallelAttr); + UIDialog dialog = attrPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + fireEditingOk(jf, form, attrPane.updateBean()); + } + }, new Dimension(600, 600)); + dialog.setVisible(true); + } + + private void fireEditingOk(JForm jForm, Form form, FormECParallelCalAttr parallelAttr){ + form.setParallelAttr(parallelAttr); + jForm.fireTargetModified(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java index 5bdfe3c29..5fb1025f3 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java @@ -4,6 +4,7 @@ import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; import com.fr.design.designer.beans.models.DraggingModel; +import com.fr.design.designer.beans.models.StateModel; import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter; import com.fr.design.designer.creator.*; import com.fr.design.designer.properties.BoundsGroupModel; @@ -353,7 +354,10 @@ public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { public void dragging(DraggingModel model) { FormDesigner designer = model.getDesigner(); MouseEvent dragEvent = model.getCurrentDragEvent(); - designer.getStateModel().dragging(dragEvent); + StateModel stateModel = designer.getStateModel(); + if (stateModel.dragable()) { + stateModel.dragging(dragEvent); + } } @Override diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java index 31bb62531..997af89c7 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java @@ -3,6 +3,7 @@ package com.fr.design.designer.beans.models; import com.fr.common.inputevent.InputEventBaseOnOS; import com.fr.design.ExtraDesignClassManager; import com.fr.design.base.clipboard.ClipboardFilter; +import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.events.DesignerEvent; @@ -188,12 +189,18 @@ public class SelectionModel { //已选 selectedPaste(); } + // 粘贴剪切板控件中的数据集 + pasteTableDataFromWidget(pasteSelection); } else { Toolkit.getDefaultToolkit().beep(); } return false; } + private void pasteTableDataFromWidget(FormSelection pasteSelection) { + TableDataFollowingPasteUtils.paste(pasteSelection.getSelectionUsedTablaData()); + } + public FormSelection getSelection() { return selection; } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java b/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java index bde83a176..872a1e97d 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java @@ -41,7 +41,7 @@ public class XTreeEditor extends XWidgetCreator { new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Value")).setEditorClass(WidgetValueEditor.class) .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Fine-Design_Basic_Advanced"), - new CRPropertyDescriptor("model", this.data.getClass(), "getNodeOrDict", "setNodeOrDict").setI18NName( + new CRPropertyDescriptor("model", this.data.getClass(), "getBuildModelConfig", "setBuildModelConfig").setI18NName( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_DS_Dictionary")).setEditorClass(TreeModelEditor.class).setRendererClass( TreeModelRenderer.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Fine-Design_Basic_Advanced"), new CRPropertyDescriptor("allowBlank", this.data.getClass()).setI18NName( @@ -55,7 +55,7 @@ public class XTreeEditor extends XWidgetCreator { new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Value")).setEditorClass(WidgetValueEditor.class) .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Fine-Design_Basic_Advanced"), - new CRPropertyDescriptor("model", this.data.getClass(), "getNodeOrDict", "setNodeOrDict").setI18NName( + new CRPropertyDescriptor("model", this.data.getClass(), "getBuildModelConfig", "setBuildModelConfig").setI18NName( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_DS_Dictionary")).setEditorClass(TreeModelEditor.class).setRendererClass( TreeModelRenderer.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Fine-Design_Basic_Advanced"), new CRPropertyDescriptor("allowBlank", this.data.getClass()).setI18NName( diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java index 8307e945f..1f3a7caf5 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java @@ -224,6 +224,9 @@ public class FormDesignerUI extends ComponentUI { } XCreator creator = draggingModel.getCreator(); + if (!creator.isSupportDrag()) { + return false; + } int leftTopX = draggingModel.getCreatorLeftTopX(); int leftTopY = draggingModel.getCreatorLeftTopY(); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java b/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java index bf047a3be..1230e0fae 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java @@ -2,6 +2,7 @@ package com.fr.design.mainframe; import com.fr.base.Parameter; import com.fr.base.TableData; +import com.fr.base.param.ParameterSource; import com.fr.data.TableDataSource; import com.fr.design.DesignModelAdapter; import com.fr.design.file.HistoryTemplateListPane; @@ -14,8 +15,8 @@ import com.fr.script.Calculator; import com.fr.stable.EmbParaFilter; import com.fr.stable.ParameterProvider; import com.fr.stable.js.WidgetName; - import com.fr.util.ParameterApplyHelper; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -55,7 +56,7 @@ public class FormModelAdapter extends DesignModelAdapter> Map map = new HashMap<>(); addGlobalParameters(map); updateTableDataParameters(oldName, tdName, tableData, map, parameterProvider -> !EmbParaFilter.isFRLayerTypePara(parameterProvider)); - ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters()); + ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters(), null, ParameterSource.DEFAULT_SOURCE); parameters = map.values().toArray(new Parameter[0]); jTemplate.populateParameter(); } @@ -158,7 +159,7 @@ public class FormModelAdapter extends DesignModelAdapter> addTableDataParameters(map, parameterProvider -> !EmbParaFilter.isFRLayerTypePara(parameterProvider)); - ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters()); + ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters(), null, ParameterSource.DEFAULT_SOURCE); return map.values().toArray(new Parameter[0]); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java b/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java index ee7918e50..e7b0390e0 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java @@ -1,5 +1,7 @@ package com.fr.design.mainframe; +import com.fr.base.TableData; +import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter; @@ -7,12 +9,10 @@ import com.fr.design.designer.beans.location.Direction; import com.fr.design.designer.creator.XComponent; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XElementCase; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.designer.creator.XWFitLayout; import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.designer.creator.XWTitleLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.creator.cardlayout.XWCardTagLayout; import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; @@ -22,11 +22,12 @@ import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.ui.Widget; import com.fr.log.FineLoggerFactory; -import java.awt.Component; import java.awt.LayoutManager; import java.awt.Rectangle; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; public class FormSelection { @@ -35,6 +36,7 @@ public class FormSelection { private ArrayList recs = new ArrayList(); // 选中的组件外层嵌套的tab块 head->tail 由内向外 private LinkedList tabList = new LinkedList<>(); + private Map selectionUsedTablaData = new HashMap<>(); public FormSelection() { selection = new ArrayList(); @@ -51,6 +53,7 @@ public class FormSelection { ((XWCardMainBorderLayout) xCreator).setShowOuterShadowBorder(false); } selection.clear(); + selectionUsedTablaData.clear(); } /** @@ -362,8 +365,13 @@ public class FormSelection { public void cut2ClipBoard(FormSelection clipBoard) { clipBoard.reset(); clipBoard.selection.addAll(selection); - for (XCreator creator : selection) { + try { + // 剪切时,添加剪切组件的数据集到usedTablaDataMap中 + clipBoard.addUsedTablaData((Widget) creator.toData().clone()); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } removeCreatorFromContainer(creator); } reset(); @@ -382,15 +390,26 @@ public class FormSelection { continue; } try { - XCreator creator = XCreatorUtils.createXCreator((Widget) root.toData().clone()); + Widget clone = (Widget) root.toData().clone(); + XCreator creator = XCreatorUtils.createXCreator(clone); creator.setBounds(root.getBounds()); clipBoard.selection.add(creator); + // 复制时,添加复制组件的数据集到usedTablaDataMap中 + clipBoard.addUsedTablaData(clone); } catch (CloneNotSupportedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } } } + private void addUsedTablaData(Widget widget) { + this.selectionUsedTablaData.putAll(TableDataFollowingPasteUtils.transferWidgetArray2TableDataMap(widget)); + } + + public Map getSelectionUsedTablaData() { + return selectionUsedTablaData; + } + public LinkedList getTabList() { return tabList; } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java index 449aa5190..493a7fa74 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java @@ -15,6 +15,7 @@ import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.DesignerEnvManager; import com.fr.design.actions.FormMobileAttrAction; +import com.fr.design.actions.FormECParallelCalAction; import com.fr.design.actions.TemplateParameterAction; import com.fr.design.actions.core.WorkBookSupportable; import com.fr.design.actions.file.export.EmbeddedFormExportExportAction; @@ -588,9 +589,9 @@ public class JForm extends JTemplate implements BaseJForm tabChangeListeners; private OnlineEmbedFilterShowPane embedFilterShowPane; private OnlineWidgetPackagesShowPane widgetPackagesShowPane; @@ -57,8 +58,6 @@ public class OnlineWidgetTabPane extends JPanel { this.cardLayout = new CardLayout(); this.centerPane = new JPanel(cardLayout); - this.centerPane.add(new OnlineWidgetShowPane(sharableWidgets), COMPONENT); - this.centerPane.add( embedFilterShowPane = new OnlineEmbedFilterShowPane(new OnlineWidgetShowPane(sharableWidgets, OnlineWidgetSortType.SALES)), COMPONENT_EMBED); //延迟组件包面板的初始化,防止组件面板里组件的缩略图和组件包面板里组件的缩略图一起加载 this.headGroup = new UITabGroup(new String[]{COMPONENT_PACKAGE, COMPONENT}) { public void tabChanged(int newSelectedIndex) { @@ -66,6 +65,12 @@ public class OnlineWidgetTabPane extends JPanel { changeListener.tabChange(newSelectedIndex); } if (newSelectedIndex == COMPONENT_TAB_INDEX) { + //延迟组件包面板的初始化,防止组件面板里组件和缩略图和组件包面板里组件的缩略图一起加载 + if (!componentPaneCreated) { + centerPane.add(new OnlineWidgetShowPane(sharableWidgets), COMPONENT); + centerPane.add( embedFilterShowPane = new OnlineEmbedFilterShowPane(new OnlineWidgetShowPane(sharableWidgets, OnlineWidgetSortType.SALES)), COMPONENT_EMBED); + componentPaneCreated = true; + } cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT); } else { ComponentShareUtil.completeEmbedFilter(); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java index be2d72466..bb600674b 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java @@ -1,15 +1,13 @@ package com.fr.design.mainframe.share.ui.online.mini; -import com.fr.base.ScreenResolution; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.stable.Constants; -import com.fr.stable.unit.FU; -import com.fr.stable.unit.UNIT; import javax.swing.JFrame; import java.awt.Container; +import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; import java.awt.Window; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; @@ -36,10 +34,11 @@ public class MiniComponentShopDialog { final JFrame frame = new JFrame(); final MiniComponentShopPane shopPane = new MiniComponentShopPane(); - final UNIT width = FU.getInstance(900 * Constants.FU_PER_OLD_PIX); - final UNIT height = FU.getInstance(600 * Constants.FU_PER_OLD_PIX); - int resolution = ScreenResolution.getScreenResolution(); - frame.setSize(width.toPixI(resolution), height.toPixI(resolution)); + GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment(); + Rectangle rect =ge.getMaximumWindowBounds(); + int width = (int) (rect.width * 0.8); + int height = (int) (rect.height * 0.9); + frame.setSize(width, height); frame.setTitle(Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Window_Title")); frame.add(shopPane); frame.setResizable(false); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java index e6a4f720c..4cb985b5a 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java @@ -254,9 +254,9 @@ public class NativeProductBridge { MiniComponentShopDialog.getInstance().getContentPane(), Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Component_Tip"), "", - FineJOptionPane.YES_NO_OPTION + FineJOptionPane.OK_CANCEL_OPTION ); - allowedDownload = result == JOptionPane.YES_OPTION; + allowedDownload = result == JOptionPane.OK_OPTION; } if (allowedDownload) { fireStartEvent(null); @@ -353,33 +353,14 @@ public class NativeProductBridge { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - boolean allowedDownload; - OnlineShareWidget[] childrenWidgets = OnlineShopUtils.getPackageWidgets(widget, false); - boolean isCompatibleWithCurrentEnv = true; - for (OnlineShareWidget children: childrenWidgets) { - if (!children.isCompatibleWithCurrentEnv()) { - isCompatibleWithCurrentEnv = false; - break; - } - } - int result; - if (!isCompatibleWithCurrentEnv) { - result = FineJOptionPane.showConfirmDialog( - MiniComponentShopDialog.getInstance().getContentPane(), - Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Components_Package_Tip", childrenCount), - "", - FineJOptionPane.YES_NO_OPTION - ); - } else { - result = FineJOptionPane.showConfirmDialog( - MiniComponentShopDialog.getInstance().getContentPane(), - Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Components_Package_Tip", childrenCount), - "", - FineJOptionPane.YES_NO_OPTION - ); - } - allowedDownload = result == JOptionPane.YES_OPTION; - if (allowedDownload) { + OnlineShareWidget[] childrenWidgets = OnlineShopUtils.getPackageWidgets(widget, true); + int result = FineJOptionPane.showConfirmDialog( + MiniComponentShopDialog.getInstance().getContentPane(), + Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Components_Package_Tip", childrenWidgets.length), + "", + FineJOptionPane.OK_CANCEL_OPTION + ); + if (result == JOptionPane.OK_OPTION) { fireStartEvent(null); action.install(); } else { diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/OnlineResourceManager.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/OnlineResourceManager.java index b29ea11db..ecdea13fe 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/OnlineResourceManager.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/OnlineResourceManager.java @@ -1,8 +1,8 @@ package com.fr.design.mainframe.share.ui.online.resource; import javax.swing.SwingWorker; -import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; import java.util.function.Predicate; /** @@ -24,7 +24,7 @@ public class OnlineResourceManager { private SwingWorker swingWorker; - private final BlockingQueue loaderBlockingQueue = new ArrayBlockingQueue(100); + private final BlockingQueue loaderBlockingQueue = new LinkedBlockingQueue<>(); public void cancelLoad(Object key) { if (swingWorker != null) { @@ -39,11 +39,7 @@ public class OnlineResourceManager { } public void addLoader(ResourceLoader loader) { - try { - this.loaderBlockingQueue.put(loader); - } catch (InterruptedException e) { - e.printStackTrace(); - } + this.loaderBlockingQueue.add(loader); } public void loadImage() { diff --git a/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java b/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java index 3793da7ea..910b466f7 100644 --- a/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java @@ -32,11 +32,11 @@ import com.fr.design.widget.ui.designer.AbstractDataModify; import com.fr.design.widget.ui.designer.component.UIBoundSpinner; import com.fr.form.ui.container.WParameterLayout; import com.fr.general.Background; - import com.fr.report.stable.FormConstants; import javax.swing.BorderFactory; import javax.swing.Icon; +import javax.swing.JCheckBox; import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Component; @@ -52,6 +52,7 @@ public class RootDesignDefinePane extends AbstractDataModify { private UISpinner paraHeight; private UICheckBox displayReport; private UICheckBox useParamsTemplate; + private JCheckBox fireAfterEditor; private AccessibleBackgroundEditor background; private UIButtonGroup hAlignmentPane; private UITextField labelNameTextField; @@ -121,8 +122,8 @@ public class RootDesignDefinePane extends AbstractDataModify { } /** - * @Description: 获取的非新决策报表AdvancePane * @param + * @Description: 获取的非新决策报表AdvancePane * @return: * @Author: Henry.Wang * @date: 2020/11/05 15:36 @@ -133,6 +134,16 @@ public class RootDesignDefinePane extends AbstractDataModify { displayReport = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Display_Nothing_Before_Query")); UIComponentUtils.setLineWrap(displayReport); useParamsTemplate = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Use_Params_Template")); + fireAfterEditor = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("触发编辑结束事件")); + fireAfterEditor.setEnabled(false); + fireAfterEditor.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); + useParamsTemplate.addChangeListener(e -> { + boolean isSelected = ((UICheckBox) e.getSource()).isSelected(); + fireAfterEditor.setEnabled(isSelected); + if (!isSelected) { + fireAfterEditor.setSelected(false); + } + }); background = new AccessibleBackgroundEditor(); Icon[] hAlignmentIconArray = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), @@ -143,14 +154,15 @@ public class RootDesignDefinePane extends AbstractDataModify { , com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right")}); double f = TableLayout.FILL; double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p, p, p}; + double[] rowSize = {p, p, p, p, p, p}; double[] columnSize = {p, f}; - int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; Component[][] components = new Component[][]{ new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField}, new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_Background")), background}, new Component[]{displayReport, null}, new Component[]{useParamsTemplate, null}, + new Component[]{fireAfterEditor, null}, new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Display_Position")), hAlignmentPane} }; JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1); @@ -165,8 +177,8 @@ public class RootDesignDefinePane extends AbstractDataModify { } /** - * @Description: 获取新决策报表的AdvancePane * @param + * @Description: 获取新决策报表的AdvancePane * @return: * @Author: Henry.Wang * @date: 2020/11/05 15:36 @@ -177,18 +189,29 @@ public class RootDesignDefinePane extends AbstractDataModify { displayReport = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Display_Nothing_Before_Query")); UIComponentUtils.setLineWrap(displayReport); useParamsTemplate = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Use_Params_Template")); + fireAfterEditor = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("触发编辑结束事件")); + fireAfterEditor.setEnabled(false); + fireAfterEditor.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); + useParamsTemplate.addChangeListener(e -> { + boolean isSelected = ((UICheckBox) e.getSource()).isSelected(); + fireAfterEditor.setEnabled(isSelected); + if (!isSelected) { + fireAfterEditor.setSelected(false); + } + }); background = new AccessibleBackgroundEditor(); double f = TableLayout.FILL; double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p, p}; + double[] rowSize = {p, p, p, p, p}; double[] columnSize = {p, f}; - int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; Component[][] components = new Component[][]{ new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField}, new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_Background")), background}, new Component[]{displayReport, null}, - new Component[]{useParamsTemplate, null} + new Component[]{useParamsTemplate, null}, + new Component[]{fireAfterEditor, null}, }; JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1); panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); @@ -209,6 +232,8 @@ public class RootDesignDefinePane extends AbstractDataModify { background.setValue(ob.getBackground()); displayReport.setSelected(ob.isDelayDisplayContent()); useParamsTemplate.setSelected(ob.isUseParamsTemplate()); + fireAfterEditor.setEnabled(ob.isUseParamsTemplate()); + fireAfterEditor.setSelected(ob.isParamsFireStopEdit()); if (newForm) { FormDesigner designer = TemplateTool.getCurrentEditingNewJForm().getFormDesign(); paraHeight.setValue(designer.getParaHeight()); @@ -233,8 +258,8 @@ public class RootDesignDefinePane extends AbstractDataModify { } /** - * @Description: 更新非新决策报表的bean * @param + * @Description: 更新非新决策报表的bean * @return: * @Author: Henry.Wang * @date: 2020/11/05 15:36 @@ -249,6 +274,7 @@ public class RootDesignDefinePane extends AbstractDataModify { } wParameterLayout.setDelayDisplayContent(displayReport.isSelected()); wParameterLayout.setUseParamsTemplate(useParamsTemplate.isSelected()); + wParameterLayout.setParamsFireStopEdit(fireAfterEditor.isSelected()); JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected()); wParameterLayout.setBackground((Background) background.getValue()); @@ -257,8 +283,8 @@ public class RootDesignDefinePane extends AbstractDataModify { } /** - * @Description: 更新新决策报表的bean * @param + * @Description: 更新新决策报表的bean * @return: * @Author: Henry.Wang * @date: 2020/11/05 15:36 @@ -269,6 +295,7 @@ public class RootDesignDefinePane extends AbstractDataModify { wParameterLayout.setDelayDisplayContent(displayReport.isSelected()); wParameterLayout.setUseParamsTemplate(useParamsTemplate.isSelected()); + wParameterLayout.setParamsFireStopEdit(fireAfterEditor.isSelected()); JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected()); wParameterLayout.setBackground((Background) background.getValue()); diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java index e43e567f4..2d459bd1b 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java @@ -15,6 +15,8 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.widget.component.DateValuePane; import com.fr.design.widget.component.UIComboBoxNoArrow; import com.fr.design.widget.ui.designer.component.FormWidgetValuePane; +import com.fr.design.widget.ui.designer.date.DateFormatCheckManager; +import com.fr.design.widget.ui.designer.date.DateFormatCheckResult; import com.fr.form.ui.DateEditor; import com.fr.stable.ArrayUtils; @@ -172,13 +174,9 @@ public class DateEditorDefinePane extends DirectWriteEditorDefinePane 0) { try { simpleDateFormat = new SimpleDateFormat(text); - this.currentSamplelabel.setText(simpleDateFormat.format(new Date())); } catch (Exception exp) { simpleDateFormat = new SimpleDateFormat(""); } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FormECParallelCalSettingPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FormECParallelCalSettingPane.java new file mode 100644 index 000000000..312526ff3 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FormECParallelCalSettingPane.java @@ -0,0 +1,131 @@ +package com.fr.design.widget.ui.designer; + +import com.fr.design.beans.BasicBeanPane; +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.utils.gui.GUICoreUtils; +import com.fr.form.main.parallel.FormECParallelCalAttr; +import com.fr.report.core.config.FormParallelCalConfig; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +/** + * @author fly.li + * @version 10.0 + * Created on 2022/03/18 + */ +public class FormECParallelCalSettingPane extends BasicBeanPane { + private static final String[] CHOOSE_ITEM = new String[] { + Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single"), + Toolkit.i18nText("Fine-Design_Form_Using_Server_Report_View_Settings") + }; + protected static final int SINGLE_SET = 0; + protected static final int SERVER_SET = 1; + //并行设置范围的下拉框(服务器设置还是模板设置) + UIComboBox parallelSettingScope; + //并行计算开关 + UICheckBox parallelSwitch; + + public FormECParallelCalSettingPane(){ + initPane(); + } + + private void initPane(){ + JPanel calSettingOutPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Form_Block_Calculate_Setting")); + calSettingOutPane.setPreferredSize(new Dimension(550,110)); + calSettingOutPane.add(getCalSettingPane()); + this.add(calSettingOutPane); + } + + private JPanel getCalSettingPane() { + JPanel calSettingPane = new JPanel(); + calSettingPane.setLayout(new BorderLayout()); + UILabel belowSetLabel = new UILabel(Toolkit.i18nText("Fine-Design_Setting_Mode")); + belowSetLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 20)); + JPanel parallelSettingScopePane = GUICoreUtils.createFlowPane(new Component[] { + belowSetLabel, getParallelSettingScope()}, FlowLayout.LEFT, 0, 0); + calSettingPane.add(parallelSettingScopePane, BorderLayout.NORTH); + calSettingPane.add(getSwitchPane(Toolkit.i18nText("Fine-Design_Enable_Form_Block_Parallel_Calculate")), BorderLayout.CENTER); + return calSettingPane; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Form_Calculate_Setting"); + } + + private UIComboBox getParallelSettingScope() { + if (this.parallelSettingScope == null){ + parallelSettingScope = new UIComboBox(CHOOSE_ITEM); + parallelSettingScope.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + if (isUsingServerSettings()) { + populateServerSettings(); + parallelSwitch.setEnabled(false); + } else { + parallelSwitch.setEnabled(true); + } + } + } + }); + } + return this.parallelSettingScope; + } + + private JPanel getSwitchPane(String tip){ + JPanel innerPane = new JPanel(); + innerPane.setLayout(new BorderLayout()); + innerPane.setPreferredSize(new Dimension(500, 30)); + innerPane.setBorder(BorderFactory.createEmptyBorder(10, 70, 5, 10)); + innerPane.add(getParallelSwitch(tip)); + return innerPane; + } + + private UICheckBox getParallelSwitch(String tip){ + if (parallelSwitch == null){ + parallelSwitch = new UICheckBox(tip); + } + return parallelSwitch; + } + + private boolean isUsingServerSettings(){ + return parallelSettingScope.getSelectedIndex() == SERVER_SET; + } + + @Override + public void populateBean(FormECParallelCalAttr formParallelAttr){ + if (formParallelAttr == null){ + formParallelAttr = FormECParallelCalAttr.getDefaultParallelAttr(); + } + parallelSettingScope.setSelectedIndex(formParallelAttr.isUseServerSetting() ? SERVER_SET : SINGLE_SET); + if (formParallelAttr.isUseServerSetting()){ + populateServerSettings(); + } else { + populateSingleTemplateSetting(formParallelAttr); + } + } + + private void populateServerSettings(){ + parallelSwitch.setSelected(FormParallelCalConfig.getInstance().isParallelCal()); + } + + private void populateSingleTemplateSetting(FormECParallelCalAttr parallelAttr){ + parallelSwitch.setSelected(parallelAttr.isParallelCal()); + } + + public FormECParallelCalAttr updateBean(){ + return new FormECParallelCalAttr(isUsingServerSettings(), parallelSwitch.isSelected()); + } +} diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java index 3c7158f82..e4d99802c 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java @@ -76,7 +76,7 @@ public class TreeEditorDefinePane extends CustomWritableRepeatEditorPane CHECKS = new ArrayList<>(); + + static { + // 顺序执行 + CHECKS.add(DateFormatFrontCheck.KEY); + CHECKS.add(DateFormatCustomCheck.KEY); + } + + @NotNull + public static DateFormatCheckResult check(String date, String format) { + for (DateFormatCheck check : CHECKS) { + if (!check.accept(date, format)) { + return check.result(date); + } + } + return DateFormatCheckResult.create(date); + } +} diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/DateFormatCheckResult.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/DateFormatCheckResult.java new file mode 100644 index 000000000..3dc786ba3 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/DateFormatCheckResult.java @@ -0,0 +1,43 @@ +package com.fr.design.widget.ui.designer.date; + +import java.awt.Color; + +/** + * @author Lucian.Chen + * @version 11.0 + * Created by Lucian.Chen on 2022/4/8 + */ +public class DateFormatCheckResult { + + private String sample; + private Color color; + + public static DateFormatCheckResult create(String sample) { + return create(sample, Color.BLACK); + } + + public static DateFormatCheckResult create(String sample, Color color) { + return new DateFormatCheckResult(sample, color); + } + + DateFormatCheckResult(String sample, Color color) { + this.sample = sample; + this.color = color; + } + + public String getSample() { + return sample; + } + + public void setSample(String sample) { + this.sample = sample; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } +} diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/check/DateFormatCustomCheck.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/check/DateFormatCustomCheck.java new file mode 100644 index 000000000..b8aaa2d9b --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/check/DateFormatCustomCheck.java @@ -0,0 +1,35 @@ +package com.fr.design.widget.ui.designer.date.check; + +import com.fr.data.core.FormatField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.widget.ui.designer.date.DateFormatCheck; +import com.fr.design.widget.ui.designer.date.DateFormatCheckResult; +import com.fr.stable.ArrayUtils; + +import java.awt.Color; + +/** + * 自定义格式校验 + * @author Lucian.Chen + * @version 11.0 + * Created by Lucian.Chen on 2022/4/8 + */ +public class DateFormatCustomCheck implements DateFormatCheck { + + public static final DateFormatCustomCheck KEY = new DateFormatCustomCheck(); + + /** + * 不是自定义格式 + */ + @Override + public boolean accept(String date, String format) { + return ArrayUtils.contains(FormatField.getInstance().getDateFormatArray(), format); + } + + @Override + public DateFormatCheckResult result(String sample) { + sample += " " + Toolkit.i18nText("Fine-Design_Basic_DateFormat_Custom_Warning"); + return DateFormatCheckResult.create(sample, Color.red); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/check/DateFormatFrontCheck.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/check/DateFormatFrontCheck.java new file mode 100644 index 000000000..165a900ad --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/date/check/DateFormatFrontCheck.java @@ -0,0 +1,94 @@ +package com.fr.design.widget.ui.designer.date.check; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.widget.ui.designer.date.DateFormatCheck; +import com.fr.design.widget.ui.designer.date.DateFormatCheckResult; +import com.fr.stable.AssistUtils; +import com.fr.stable.StringUtils; + +import java.awt.Color; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 前端的解析方案检测 + * FR.str2Date + * @author Lucian.Chen + * @version 11.0 + * Created by Lucian.Chen on 2022/4/7 + */ +public class DateFormatFrontCheck implements DateFormatCheck { + + private static final Pattern YEAR_PATTERN_1 = Pattern.compile("y{4,}"); //yyyy + private static final Pattern YEAR_PATTERN_2 = Pattern.compile("y{2,}"); //yy + private static final Pattern MONTH_PATTERN_1 = Pattern.compile("M{4,}"); //MMMM + private static final Pattern MONTH_PATTERN_2 = Pattern.compile("M{3}"); //MMM + private static final Pattern MONTH_PATTERN_3 = Pattern.compile("M{2}"); //MM + private static final Pattern MONTH_PATTERN_4 = Pattern.compile("M"); //M + private static final Pattern MONTH_PATTERN_5 = Pattern.compile("a"); + private static final Pattern DAY_PATTERN_1 = Pattern.compile("d{2,}"); //dd + private static final Pattern DAY_PATTERN_2 = Pattern.compile("d"); //d + private static final Pattern HOUR_PATTERN_1 = Pattern.compile("h+"); //hh、h + private static final Pattern HOUR_PATTERN_2 = Pattern.compile("H+"); //HH、H + private static final Pattern MINUTE_PATTERN = Pattern.compile("m{2,}"); //mm + private static final Pattern SECOND_PATTERN = Pattern.compile("s{2,}"); //ss + private static final Pattern FMT_PATTERN = Pattern.compile("%."); + + public static final DateFormatFrontCheck KEY = new DateFormatFrontCheck(); + + /** + * 前端支持的格式 + */ + @Override + public boolean accept(String date, String format) { + if (StringUtils.isBlank(date) || StringUtils.isBlank(format)) { + return false; + } + + String fmt = parseFmt(format); + int fmtCount = 0; + Matcher matcher = FMT_PATTERN.matcher(fmt); + while (matcher.find()) { + fmtCount ++; + } + String[] dates = date.split("\\W+"); + + return dates.length == fmtCount || isSpecialFmt(fmt); + } + + @Override + public DateFormatCheckResult result(String sample) { + return DateFormatCheckResult.create(Toolkit.i18nText("Fine-Design_Basic_DateFormat_Not_Support"), Color.red); + } + + private boolean isSpecialFmt(String fmt) { + return AssistUtils.equals(fmt, "%Y%X") || AssistUtils.equals(fmt, "%Y%X%d"); + } + + private String parseFmt(String fmt) { + //年 + fmt = YEAR_PATTERN_1.matcher(fmt).replaceAll("%Y"); + fmt = YEAR_PATTERN_2.matcher(fmt).replaceAll("%y"); + //月 + fmt = MONTH_PATTERN_1.matcher(fmt).replaceAll("%b"); + fmt = MONTH_PATTERN_2.matcher(fmt).replaceAll("%B"); + fmt = MONTH_PATTERN_3.matcher(fmt).replaceAll("%X"); + fmt = MONTH_PATTERN_4.matcher(fmt).replaceAll("%x"); + fmt = MONTH_PATTERN_5.matcher(fmt).replaceAll("%p"); + //天 + Matcher dayMatcher = DAY_PATTERN_1.matcher(fmt); + if (dayMatcher.find()) { + fmt = dayMatcher.replaceAll("%d"); + } else { + fmt = DAY_PATTERN_2.matcher(fmt).replaceAll("%e"); + } + //时 + fmt = HOUR_PATTERN_1.matcher(fmt).replaceAll("%I"); + fmt = HOUR_PATTERN_2.matcher(fmt).replaceAll("%H"); + //分 + fmt = MINUTE_PATTERN.matcher(fmt).replaceAll("%M"); + //秒 + fmt = SECOND_PATTERN.matcher(fmt).replaceAll("%S"); + return fmt; + } +} diff --git a/designer-form/src/main/resources/com/fr/design/form/images/parallel.png b/designer-form/src/main/resources/com/fr/design/form/images/parallel.png new file mode 100644 index 000000000..2eff0f4ee Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/parallel.png differ diff --git a/designer-form/src/test/java/com/fr/design/widget/ui/designer/date/check/DateFormatFrontCheckTest.java b/designer-form/src/test/java/com/fr/design/widget/ui/designer/date/check/DateFormatFrontCheckTest.java new file mode 100644 index 000000000..d69728441 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/widget/ui/designer/date/check/DateFormatFrontCheckTest.java @@ -0,0 +1,27 @@ +package com.fr.design.widget.ui.designer.date.check; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Lucian.Chen + * @version 10.0 + * Created by Lucian.Chen on 2022/4/18 + */ +public class DateFormatFrontCheckTest { + + @Test + public void testAccept() { + Assert.assertTrue(DateFormatFrontCheck.KEY.accept("20220101", "yyyyMMdd")); + Assert.assertTrue(DateFormatFrontCheck.KEY.accept("202201", "yyyyMM")); + Assert.assertTrue(DateFormatFrontCheck.KEY.accept("2022-01-01", "yyyy-MM-dd")); + Assert.assertTrue(DateFormatFrontCheck.KEY.accept("22/01/01", "yy/MM/dd")); + Assert.assertTrue(DateFormatFrontCheck.KEY.accept("2022年01月01日", "yyyy年MM月dd日")); + Assert.assertTrue(DateFormatFrontCheck.KEY.accept("2022/01/01 12:30:00", "yyyy/MM/dd HH:mm:ss")); + + Assert.assertFalse(DateFormatFrontCheck.KEY.accept("220101", "yyMMdd")); + Assert.assertFalse(DateFormatFrontCheck.KEY.accept("20221", "yyyyM")); + Assert.assertFalse(DateFormatFrontCheck.KEY.accept("20220101123000", "yyyyMMddHHmmss")); + Assert.assertFalse(DateFormatFrontCheck.KEY.accept("2022-01-01", "YYYY-MM-dd")); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java b/designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java index 8bc66e172..b54c871e0 100644 --- a/designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java +++ b/designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java @@ -3,7 +3,9 @@ */ package com.fr.design.cell.clipboard; +import com.fr.base.TableData; import com.fr.design.base.clipboard.ClipboardHelper; +import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils; import com.fr.grid.selection.CellSelection; import com.fr.log.FineLoggerFactory; import com.fr.report.cell.CellElement; @@ -17,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Map; /** * The clip of CellElement. @@ -27,6 +30,7 @@ public class CellElementsClip implements Cloneable, java.io.Serializable { private FU[] columnWidth; private FU[] rowHeight; private TemplateCellElement[] clips; + private Map elementUsedTableDatas; public CellElementsClip(int columnSpan, int rowSpan, FU[] columnWidth, FU[] rowHeight, TemplateCellElement[] clips) { this.columnSpan = columnSpan; @@ -34,12 +38,14 @@ public class CellElementsClip implements Cloneable, java.io.Serializable { this.columnWidth = columnWidth; this.rowHeight = rowHeight; this.clips = clips; + this.elementUsedTableDatas = TableDataFollowingPasteUtils.transferProvider2TableDataMap(clips); } public CellElementsClip(int columnSpan, int rowSpan, TemplateCellElement[] clips) { this.columnSpan = columnSpan; this.rowSpan = rowSpan; this.clips = clips; + this.elementUsedTableDatas = TableDataFollowingPasteUtils.transferProvider2TableDataMap(clips); } public int getColumnSpan() { @@ -136,6 +142,8 @@ public class CellElementsClip implements Cloneable, java.io.Serializable { if (this.columnWidth != null && this.rowHeight != null) { pasteWidthAndHeight(ec, column, row, columnSpan, rowSpan); } + // 粘贴数据集 + TableDataFollowingPasteUtils.paste(elementUsedTableDatas); return new CellSelection(column, row, columnSpan, rowSpan); } @@ -163,6 +171,8 @@ public class CellElementsClip implements Cloneable, java.io.Serializable { } ec.addCellElement(cellElement); + // 跟随粘贴数据集 + TableDataFollowingPasteUtils.paste(elementUsedTableDatas); } } @@ -182,4 +192,4 @@ public class CellElementsClip implements Cloneable, java.io.Serializable { return cloned; } -} \ No newline at end of file +} diff --git a/designer-realize/src/main/java/com/fr/design/cell/clipboard/FloatElementsClip.java b/designer-realize/src/main/java/com/fr/design/cell/clipboard/FloatElementsClip.java index 7dc7fd80b..3c1f54e33 100644 --- a/designer-realize/src/main/java/com/fr/design/cell/clipboard/FloatElementsClip.java +++ b/designer-realize/src/main/java/com/fr/design/cell/clipboard/FloatElementsClip.java @@ -3,7 +3,9 @@ */ package com.fr.design.cell.clipboard; +import com.fr.base.TableData; import com.fr.design.cell.FloatElementsProvider; +import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils; import com.fr.general.ComparatorUtils; import com.fr.grid.selection.FloatSelection; import com.fr.log.FineLoggerFactory; @@ -14,21 +16,25 @@ import com.fr.stable.unit.FU; import com.fr.stable.unit.OLDPIX; import java.util.Iterator; +import java.util.Map; /** * The clip of Float Element. */ -public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatElementsProvider { +public class FloatElementsClip implements Cloneable, java.io.Serializable, FloatElementsProvider { private FloatElement floatEl; - public FloatElementsClip(FloatElement floatEl) { - this.floatEl = floatEl; - } - - /** - * 悬浮元素的粘贴 - * - * @param ec 单元格 + private Map elementUsedTableDatas; + + public FloatElementsClip(FloatElement floatEl) { + this.floatEl = floatEl; + this.elementUsedTableDatas = TableDataFollowingPasteUtils.transferProvider2TableDataMap(floatEl); + } + + /** + * 悬浮元素的粘贴 + * + * @param ec 单元格 * @return 粘贴的悬浮元素 */ public FloatSelection pasteAt(TemplateElementCase ec) { @@ -46,7 +52,7 @@ public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatE while (ec.getFloatElement(ret.getName()) != null) { ret.setName(ret.getName() + "-Copy"); } - + while (true) { if (isContainSameBoundFloatElement(ec, ret)) { ret.setTopDistance(FU.getInstance(ret.getTopDistance().toFU() + new OLDPIX(50).toFU())); @@ -55,11 +61,12 @@ public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatE break; } } - + ec.addFloatElement(ret); - + // 跟随粘贴数据集 + TableDataFollowingPasteUtils.paste(elementUsedTableDatas); return new FloatSelection(ret.getName()); - } + } /** * Contain same location and bounds FloatElement. @@ -100,4 +107,4 @@ public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatE return cloned; } -} \ No newline at end of file +} diff --git a/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java b/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java index 32818de9f..91c8fa292 100644 --- a/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java +++ b/designer-realize/src/main/java/com/fr/design/dscolumn/DSColumnAdvancedPane.java @@ -1,16 +1,14 @@ package com.fr.design.dscolumn; import com.fr.base.BaseFormula; -import com.fr.data.util.SortOrder; import com.fr.design.border.UITitledBorder; -import com.fr.design.constants.LayoutConstants; import com.fr.design.data.DesignTableDataManager; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.formula.CustomVariableResolver; import com.fr.design.formula.FormulaFactory; -import com.fr.design.formula.SortFormulaPane; import com.fr.design.formula.UIFormula; +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; @@ -30,11 +28,19 @@ import com.fr.report.cell.cellattr.CellExpandAttr; import com.fr.report.cell.cellattr.core.group.DSColumn; import com.fr.report.cell.cellattr.core.group.SelectCount; -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.Arrays; import static com.fr.report.cell.cellattr.core.group.FilterTypeEnum.BOTTOM; import static com.fr.report.cell.cellattr.core.group.FilterTypeEnum.SPECIFY; @@ -512,11 +518,12 @@ public class DSColumnAdvancedPane extends BasicPane { } } - public static class FormatAttrPane extends TextFormatPane { + + public static class ReLayoutTextFormatPane extends TextFormatPane { protected void initLayout() { - JComponent[][] components = new JComponent[][]{{typeComboBox, textField, roundingBox}}; - double[] rowSize = new double[]{TableLayout.FILL}; + JComponent[][] components = new JComponent[][] { {typeComboBox, textField, roundingBox} }; + double[] rowSize = new double[] { TableLayout.FILL }; double[] columnSize = {TableLayout.PREFERRED, 200, TableLayout.PREFERRED}; JPanel settingPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 4, 0); @@ -542,6 +549,44 @@ public class DSColumnAdvancedPane extends BasicPane { } } + public static class FormatAttrPane extends AbstractAttrNoScrollPane { + private TextFormatPane formatPane; + + @Override + protected JPanel createContentPane() { + this.formatPane = new ReLayoutTextFormatPane(); + return this.formatPane; + } + + @Override + public Dimension getPreferredSize() { + if (formatPane == null) { + return super.getPreferredSize(); + } + return formatPane.getPreferredSize(); + } + + protected void initContentPane() { + leftContentPane = createContentPane(); + if (leftContentPane != null) { + leftContentPane.setBorder(BorderFactory.createEmptyBorder()); + this.add(leftContentPane, BorderLayout.CENTER); + } + } + + public void populate(CellElement cellElement) { + if (cellElement != null && formatPane != null) { + formatPane.populateBean(cellElement.getStyle()); + } + } + + public void update(CellElement cellElement) { + if (cellElement != null && formatPane != null) { + cellElement.setStyle(formatPane.update(cellElement.getStyle())); + } + } + } + private void checkButtonEnabled() { if (useMultiplyNumCheckBox.isSelected()) { multiNumSpinner.setEnabled(true); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java b/designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java index d90b7e8ec..b3bbaf1df 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java @@ -18,6 +18,7 @@ import com.fr.report.cell.FloatElement; import com.fr.report.elementcase.TemplateElementCase; import com.fr.stable.Constants; +import javax.swing.event.ListDataEvent; import java.awt.Color; /** @@ -86,7 +87,12 @@ public class HyperlinkGroupPaneActionImpl implements HyperlinkGroupPaneActionPro frFont = frFont.applyForeground(AdjustWorkBookDefaultStyleUtils.adjustCellElementFontForeground(Color.black)); frFont = frFont.applyUnderline(Constants.LINE_NONE); } - editCellElement.setStyle(elementStyle.deriveFRFont(frFont)); + + // 首次添加超链接,将文字样式默认改为蓝色下划线 + if (editCellElement.getNameHyperlinkGroup() == null && hyperlinkGroupPane.getCurrentEvent() != null && hyperlinkGroupPane.getCurrentEvent().getType() == ListDataEvent.INTERVAL_ADDED) { + editCellElement.setStyle(elementStyle.deriveFRFont(frFont)); + } + try { editCellElement.setNameHyperlinkGroup((NameJavaScriptGroup) updateNameHyperlinks.clone()); } catch (CloneNotSupportedException e) { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/WorkBookModelAdapter.java b/designer-realize/src/main/java/com/fr/design/mainframe/WorkBookModelAdapter.java index 53f193be7..6cbc0142e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/WorkBookModelAdapter.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/WorkBookModelAdapter.java @@ -2,6 +2,7 @@ package com.fr.design.mainframe; import com.fr.base.Parameter; import com.fr.base.TableData; +import com.fr.base.param.ParameterSource; import com.fr.data.TableDataSource; import com.fr.design.DesignModelAdapter; import com.fr.design.bridge.DesignToolbarProvider; @@ -17,8 +18,8 @@ import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; import com.fr.stable.bridge.StableFactory; import com.fr.stable.js.WidgetName; - import com.fr.util.ParameterApplyHelper; + import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -139,7 +140,7 @@ public class WorkBookModelAdapter extends DesignModelAdapter HOT_SEARCH_SET = new LinkedHashSet<>( + Arrays.asList( + Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_ONE"), + Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_TWO"), + Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_THREE") + ) + ); + + public static final ArrayList CONJUNCTION = new ArrayList() {{ add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_HE")); add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_YU")); add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_DE")); }}; + public static final String LOADING = "loading"; + + public static final String NETWORK_ERROR = "network error"; + + public static final String TITLE = "AlphaFine"; + + public static final int DEFAULT_CLICK_COUNT = 1; } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineHelper.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineHelper.java index dd5a01349..441bd03ac 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineHelper.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineHelper.java @@ -2,12 +2,11 @@ package com.fr.design.mainframe.alphafine; import com.fr.design.DesignerEnvManager; import com.fr.design.actions.help.alphafine.AlphaFineConfigManager; -import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; import com.fr.design.mainframe.alphafine.cell.model.MoreModel; import com.fr.design.mainframe.alphafine.cell.model.NoResultModel; import com.fr.design.mainframe.alphafine.cell.model.RobotModel; -import com.fr.design.mainframe.alphafine.component.AlphaFineDialog; +import com.fr.design.mainframe.alphafine.component.AlphaFineFrame; import com.fr.design.mainframe.alphafine.model.SearchResult; import com.fr.design.mainframe.alphafine.search.manager.impl.DocumentSearchManager; import com.fr.design.mainframe.alphafine.search.manager.impl.HotIssuesManager; @@ -25,6 +24,7 @@ import com.fr.json.JSONFactory; import com.fr.json.JSONObject; import com.fr.stable.StringUtils; +import java.awt.Frame; import java.util.List; /** @@ -32,7 +32,7 @@ import java.util.List; */ public class AlphaFineHelper { public static final NoResultModel NO_CONNECTION_MODEL = new NoResultModel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Connection_Failed")); - private static AlphaFineDialog alphaFineDialog; + private static AlphaFineFrame alphaFineDialog; private static final String URL_FOR_TEST_NETWORK = "https://www.baidu.com"; private AlphaFineHelper() { @@ -62,17 +62,30 @@ public class AlphaFineHelper { return; } if (alphaFineDialog == null) { - alphaFineDialog = new AlphaFineDialog(DesignerContext.getDesignerFrame(), forceOpen); + alphaFineDialog = new AlphaFineFrame(); alphaFineDialog.setVisible(true); final AlphaFineConfigManager manager = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager(); manager.setNeedRemind(false); } else { - alphaFineDialog.setVisible(!alphaFineDialog.isVisible()); + alphaFineDialog.setVisible(true); + // check 如果最小化 点击悬浮按钮后 恢复 + if ((alphaFineDialog.getExtendedState() & Frame.ICONIFIED) != 0) { + // 从最小化恢复 + alphaFineDialog.setExtendedState(Frame.NORMAL); + } + alphaFineDialog.toFront(); } } + public static void resetAlphaFineDialog() { + alphaFineDialog = null; + } + + public static AlphaFineFrame getAlphaFineDialog() { + return alphaFineDialog; + } /** * 获取文件名上级目录 diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineUtil.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineUtil.java new file mode 100644 index 000000000..0d23a6fc9 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineUtil.java @@ -0,0 +1,61 @@ +package com.fr.design.mainframe.alphafine; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; +import com.fr.stable.StringUtils; +import java.util.Set; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/20 + */ +public class AlphaFineUtil { + + public static String highLightModelName(String modelName, String[] strings) { + if (strings == null) { + return modelName; + } + for (String string : strings) { + String primaryStr = getReplacedString(modelName, string); + if (StringUtils.isNotEmpty(primaryStr)) { + modelName = modelName.replaceAll("(?i)" + primaryStr, "|" + primaryStr + "|"); + } + } + modelName = "" + modelName.replaceAll("\\|", StringUtils.EMPTY) + ""; + return modelName; + } + + + private static String getReplacedString(String modelName, String string) { + //需要考虑modelName有空格的情况 + //比如现在是work boo k 搜索词是workb,应该要替换的部分是work b + //先去掉已经匹配替换过的部分,因为考虑到分词的情况,可能会进行多次替换 + final String regex = "\\|\\|"; + modelName = modelName.replaceAll(regex, StringUtils.EMPTY); + //再去掉空格进行匹配 + String noBlackName = modelName.replaceAll(StringUtils.BLANK, StringUtils.EMPTY).toLowerCase(); + int index = noBlackName.indexOf(string.toLowerCase()); + if (index == -1) { + return StringUtils.EMPTY; + } + StringBuilder result = new StringBuilder(); + int count = 0; + while (count < string.length()) { + char pos = modelName.charAt(index++); + result.append(pos); + count += pos == ' ' ? 0 : 1; + } + return result.toString(); + } + + public static boolean unread() { + Set readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); + Set idSet = ProductNewsSearchManager.getInstance().getIdSet(); + return !idSet.isEmpty() && !readSet.containsAll(idSet); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/CellType.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/CellType.java index 3d533e47b..c558ee584 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/CellType.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/CellType.java @@ -1,15 +1,49 @@ package com.fr.design.mainframe.alphafine; +import com.fr.stable.StringUtils; + /** * Created by XiaXiang on 2017/4/27. */ public enum CellType { - RECOMMEND(0), ACTION(1), DOCUMENT(2), FILE(3), PLUGIN(4), REUSE(5), NO_RESULT(6), MORE(7), RECOMMEND_ROBOT(8), BOTTOM(9), ROBOT(10); + RECOMMEND(0), + ACTION(1, "action", "actionResult", false), + DOCUMENT(2, "document", "documentResult", true), + FILE(3, "file", "fileResult", false), + PLUGIN(4, "plugin", "pluginResult", true), + REUSE(5), + NO_RESULT(6, "noResult", StringUtils.EMPTY, false), + MORE(7), + RECOMMEND_ROBOT(8), + BOTTOM(9), + ROBOT(10), + PRODUCT_NEWS(11, "productNews", "productNewsResult", true); private int typeValue; - CellType(int type) { + /** + * 标志位 索引无搜索结果面板 + * + * 空字符表示不涉及索引该项 + */ + private String flagStr4None; + + /** + * 标志位 索引有搜索结果面板 + */ + private String flagStr4Result; + + private boolean needNetWork = true; + + CellType(int type, String flagStr4None, String flagStr4Result, boolean needNetWork) { this.typeValue = type; + this.flagStr4None = flagStr4None; + this.flagStr4Result = flagStr4Result; + this.needNetWork = needNetWork; + } + + CellType(int type) { + this(type, StringUtils.EMPTY, StringUtils.EMPTY, true); } public static CellType parse(int typeValue) { @@ -29,5 +63,17 @@ public enum CellType { public void setTypeValue(int typeValue) { this.typeValue = typeValue; } + + public String getFlagStr4None() { + return flagStr4None; + } + + public String getFlagStr4Result() { + return flagStr4Result; + } + + public boolean isNeedNetWork() { + return needNetWork; + } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java index 47c2e6c7e..e6e924570 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java @@ -435,7 +435,7 @@ public class AlphaFineDialog extends UIDialog { */ private void removeLeftPane() { if (searchListModel.isEmpty() && defaultPane == null) { - defaultPane = new NoResultPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_NO_Result"), AlphaFineConstants.IMAGE_URL + "no_result.png"); + defaultPane = new NoResultPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_NO_Result"), AlphaFineConstants.NO_RESULT_ICON); searchResultPane.remove(leftSearchResultPane); searchResultPane.add(defaultPane, BorderLayout.WEST); refreshContainer(); @@ -661,7 +661,7 @@ public class AlphaFineDialog extends UIDialog { break; case ACTION: rightSearchResultPane.removeAll(); - rightSearchResultPane.add(new NoResultPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_No_Result"), AlphaFineConstants.IMAGE_URL + "noresult.png")); + rightSearchResultPane.add(new NoResultPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_No_Result"), AlphaFineConstants.NO_RESULT_ICON)); validate(); repaint(); break; diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineFrame.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineFrame.java new file mode 100644 index 000000000..28300c9b2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineFrame.java @@ -0,0 +1,792 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.base.svg.IconUtils; +import com.fr.base.svg.SVGLoader; +import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.help.alphafine.AlphaFineConfigManager; +import com.fr.design.actions.help.alphafine.AlphaFineShortCutUtil; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.borders.UITextFieldBorder; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.CellType; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import com.fr.design.mainframe.alphafine.preview.DefaultProductNewsPane; +import com.fr.design.mainframe.alphafine.preview.HelpDocumentNoResultPane; +import com.fr.design.mainframe.alphafine.preview.LoadingRightSearchResultPane; +import com.fr.design.mainframe.alphafine.preview.NetWorkFailedPane; +import com.fr.design.mainframe.alphafine.preview.NoResultPane; +import com.fr.design.mainframe.alphafine.preview.NoResultWithLinkPane; +import com.fr.design.mainframe.alphafine.preview.SearchLoadingPane; +import com.fr.design.mainframe.alphafine.preview.SimpleRightSearchResultPane; +import com.fr.design.mainframe.alphafine.question.QuestionWindow; +import com.fr.design.mainframe.alphafine.search.ProductNewsSearchWorkerManager; +import com.fr.design.mainframe.alphafine.search.SearchTextBean; +import com.fr.design.mainframe.alphafine.search.SearchWorkerManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.ActionSearchManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.DocumentSearchManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.FileSearchManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.PluginSearchManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; +import com.fr.design.mainframe.alphafine.search.manager.impl.SegmentationManager; +import com.fr.design.utils.DesignUtils; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +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.Insets; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.Window; +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.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.Timer; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/04/06 + */ +public class AlphaFineFrame extends JFrame { + + private static final String ADVANCED_SEARCH_MARK = "k:"; + + private static final int TIMER_DELAY = 300; + + private static final String PLACE_HOLDER = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine"); + + private static final String SETTING = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set"); + + private static final String NO_RESULT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_No_Result"); + + private static final String SKILLS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Skills"); + + private static final String SEARCH_TERM = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Search_Term"); + + private static final String SEARCH = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Search"); + + private static final String GO_FORUM = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Go_Forum"); + + private static final String TEMPLATES = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Templates"); + + public static final String PRODUCT_NEWS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News"); + + private static final String HELP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help"); + + private static final String PLUGIN = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon"); + + private static final String ONE_CLICK_READ = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_One_Click_Read"); + + private static final String NO_SEARCH_RESULT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_NO_Result"); + + private static final String PRODUCT_DYNAMICS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_Dynamics"); + + private static final Image SEARCH_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/search.svg"); + + private static final Color BORDER_COLOR = new Color(232, 232, 233); + + private final CardLayout cardLayout = new CardLayout(); + + private final JPanel resultPane = new JPanel(cardLayout); + + private String storeText; + + private String[] segmentationResult; + + private UILabel useTipLabel; + + private UILabel tipIconLabel; + + private AlphaFineTextField searchTextField; + + private AlphaFineList searchResultList; + + private SearchLoadingPane searchLoadingPane; + + private JPanel searchTextFieldWrapperPane; + + private UILabel clearLabel; + + private CellType selectedType; + + private String beforeSearchStr = StringUtils.EMPTY; + + private SearchWorkerManager settingSearchWorkerManager; + + private SearchWorkerManager fileSearchWorkerManager; + + private SearchWorkerManager documentWorkerManager; + + private SearchWorkerManager pluginSearchWorkerManager; + + private SearchWorkerManager currentSearchWorkerManager; + + private ProductNewsSearchWorkerManager productNewsSearchWorkerManager; + + public AlphaFineFrame() { + this.setTitle(AlphaFineConstants.TITLE); + setUndecorated(true); + setSize(AlphaFineConstants.FIELD_SIZE); + initComponents(); + centerWindow(this); + initSearchManager(); + } + + private void initSearchManager() { + + this.productNewsSearchWorkerManager = new ProductNewsSearchWorkerManager( + CellType.PRODUCT_NEWS, + searchTextBean -> { + return ProductNewsSearchManager.getInstance().getSearchResult(searchTextBean.getSegmentation()); + }, + this + ); + + this.settingSearchWorkerManager = new SearchWorkerManager( + CellType.ACTION, + searchTextBean -> { + ActionSearchManager.getInstance().getLessSearchResult(searchTextBean.getSegmentation()); + return ActionSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText()); + }, + this, + new SimpleRightSearchResultPane(new NoResultPane(NO_RESULT, AlphaFineConstants.NO_RESULT_ICON)) + ); + fileSearchWorkerManager = new SearchWorkerManager( + CellType.FILE, + searchTextBean -> { + FileSearchManager.getInstance().getLessSearchResult(searchTextBean.getSearchText(), searchTextBean.getSegmentation()); + return FileSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText()); + }, + this, + new LoadingRightSearchResultPane() + ); + documentWorkerManager = new SearchWorkerManager( + CellType.DOCUMENT, + searchTextBean -> { + DocumentSearchManager.getInstance().getLessSearchResult(searchTextBean.getSegmentation()); + return DocumentSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText()); + }, + this, + new SimpleRightSearchResultPane(new JPanel()) + ); + + pluginSearchWorkerManager = new SearchWorkerManager( + CellType.PLUGIN, + searchTextBean -> { + PluginSearchManager.getInstance().getLessSearchResult(searchTextBean.getSegmentation()); + return PluginSearchManager.getInstance().getMoreSearchResult(searchTextBean.getSearchText()); + }, + this, + new LoadingRightSearchResultPane() + ); + + } + + /** + * 初始化全部组件 + */ + private void initComponents() { + + add(createTopPane(), BorderLayout.NORTH); + initSearchTextField(); + add(createSearchPane(), BorderLayout.CENTER); + add(createShowPane(), BorderLayout.SOUTH); + this.getContentPane().setBackground(Color.WHITE); + this.setIconImage(SEARCH_IMAGE); + this.setSize(AlphaFineConstants.FULL_SIZE); + } + + private JPanel createTopPane() { + JPanel topPane = new JPanel(new BorderLayout()); + topPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + topPane.setBackground(Color.WHITE); + JPanel topLeftPane = new JPanel(new FlowLayout(FlowLayout.LEFT)); + topLeftPane.setBackground(Color.WHITE); + UILabel alphaFineLabel = new UILabel(AlphaFineConstants.TITLE); + alphaFineLabel.setFont(new Font("Arial Black", Font.PLAIN, 20)); + alphaFineLabel.setForeground(UIConstants.FLESH_BLUE); + topLeftPane.add(alphaFineLabel); + topPane.add(topLeftPane, BorderLayout.WEST); + + JPanel topRightPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 10)); + topRightPane.setBackground(Color.WHITE); + JPanel tipPane = new JPanel(new BorderLayout()); + tipPane.setBackground(Color.WHITE); + String toolTip = AlphaFineShortCutUtil.getDisplayShortCut(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Short_Cut", DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getShortcuts())); + tipIconLabel = new UILabel(AlphaFineConstants.BULB_ICON); + tipIconLabel.addMouseListener(tipMouseListener); + tipIconLabel.setToolTipText(toolTip); + useTipLabel = new UILabel(SKILLS); + useTipLabel.addMouseListener(tipMouseListener); + useTipLabel.setToolTipText(toolTip); + useTipLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); + tipPane.add(tipIconLabel, BorderLayout.WEST); + tipPane.add(useTipLabel, BorderLayout.CENTER); + topRightPane.add(tipPane); + UIButton minimizeButton = createButton(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/minimize.svg")); + minimizeButton.addActionListener(e -> AlphaFineFrame.this.setExtendedState(JFrame.ICONIFIED)); + topRightPane.add(minimizeButton); + UIButton closeButton = createButton(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/close.svg")); + closeButton.addActionListener(e -> AlphaFineFrame.this.dispose()); + topRightPane.add(closeButton); + topPane.add(topRightPane, BorderLayout.EAST); + return topPane; + } + + private MouseAdapter tipMouseListener = new MouseAdapter() { + + @Override + public void mouseEntered(MouseEvent e) { + useTipLabel.setForeground(UIConstants.FLESH_BLUE); + tipIconLabel.setIcon(AlphaFineConstants.BLUE_BULB_ICON); + } + + @Override + public void mouseExited(MouseEvent e) { + useTipLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); + tipIconLabel.setIcon(AlphaFineConstants.BULB_ICON); + } + }; + + private JPanel createSearchPane() { + JPanel searchPane = new JPanel(new BorderLayout()); + searchPane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20)); + searchTextFieldWrapperPane = new JPanel(new BorderLayout()) { + @Override + protected void paintBorder(Graphics g) { + g.setColor(BORDER_COLOR); + g.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 5, 5); + } + }; + searchTextFieldWrapperPane.setBorder(new UITextFieldBorder(new Insets(2, 3, 2, 3))); + searchTextFieldWrapperPane.setBackground(Color.WHITE); + searchTextFieldWrapperPane.add(searchTextField, BorderLayout.CENTER); + clearLabel = new UILabel(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/clear.svg")); + clearLabel.setVisible(false); + clearLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + searchTextField.setText(StringUtils.EMPTY); + clearLabel.setVisible(false); + } + }); + searchTextFieldWrapperPane.add(clearLabel, BorderLayout.EAST); + searchPane.add(searchTextFieldWrapperPane, BorderLayout.CENTER); + JButton searchButton = new JButton(SEARCH) { + @Override + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setColor(UIConstants.FLESH_BLUE); + g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 4, 4); + super.paintComponent(g2d); + } + }; + searchButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + fireSearch(); + } + }); + searchButton.setPreferredSize(new Dimension(70, 60)); + searchButton.setForeground(Color.WHITE); + searchButton.setBorderPainted(false); + searchButton.setContentAreaFilled(false); + searchPane.add(searchButton, BorderLayout.EAST); + searchPane.setBackground(Color.WHITE); + return searchPane; + } + + private JPanel createShowPane() { + JPanel showPane = new JPanel(new BorderLayout()); + resultPane.add(new DefaultProductNewsPane(), CellType.PRODUCT_NEWS.getFlagStr4None()); + resultPane.add(new NoResultWithLinkPane(GO_FORUM, AlphaFineConstants.NO_RESULT_ICON), CellType.NO_RESULT.getFlagStr4None()); + resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.ACTION.getFlagStr4None()); + resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.FILE.getFlagStr4None()); + resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.PLUGIN.getFlagStr4None()); + resultPane.add(new HelpDocumentNoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.DOCUMENT.getFlagStr4None()); + resultPane.add(new NetWorkFailedPane(this::reSearch), AlphaFineConstants.NETWORK_ERROR); + + JPanel labelPane = new JPanel(new BorderLayout()); + labelPane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20)); + labelPane.setBackground(Color.WHITE); + JPanel labelContentPane = new JPanel(new BorderLayout()); + UILabel tabLabel = new UILabel(PRODUCT_DYNAMICS); + tabLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); + tabLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + tabLabel.setPreferredSize(new Dimension(100, 30)); + JPanel westPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + westPane.add(tabLabel); + labelContentPane.add(westPane, BorderLayout.WEST); + JPanel eastPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0)); + UILabel readLabel = new UILabel(ONE_CLICK_READ); + readLabel.setHorizontalAlignment(SwingConstants.RIGHT); + readLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));; + readLabel.setPreferredSize(new Dimension(100, 30)); + readLabel.setForeground(UIConstants.FLESH_BLUE); + readLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + fireOneClickRead(); + showPane.repaint(); + } + }); + eastPane.add(readLabel); + labelContentPane.add(eastPane, BorderLayout.EAST); + labelContentPane.setBackground(new Color(245, 245, 247)); + labelPane.add(labelContentPane); + labelPane.setPreferredSize(new Dimension(AlphaFineConstants.FULL_SIZE.width, 30)); + + JPanel tabPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 10)); + tabPane.setBackground(Color.WHITE); + List selectedLabelList = new ArrayList<>(); + AlphaFineConfigManager alphaFineConfigManager = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager(); + if (alphaFineConfigManager.isProductDynamics()) { + selectedLabelList.add(new SelectedLabel(PRODUCT_NEWS, CellType.PRODUCT_NEWS, true)); + } + if (alphaFineConfigManager.isContainAction()) { + selectedLabelList.add(new SelectedLabel(SETTING, CellType.ACTION)); + } + if (alphaFineConfigManager.isContainFileContent() || alphaFineConfigManager.isContainTemplate()) { + selectedLabelList.add(new SelectedLabel(TEMPLATES, CellType.FILE)); + } + if (alphaFineConfigManager.isContainDocument()) { + selectedLabelList.add(new SelectedLabel(HELP, CellType.DOCUMENT)); + } + if (alphaFineConfigManager.isContainPlugin()) { + selectedLabelList.add(new SelectedLabel(PLUGIN, CellType.PLUGIN)); + } + selectedType = selectedLabelList.get(0).getCellType(); + for (SelectedLabel selectedLabel : selectedLabelList) { + + selectedLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + for (SelectedLabel label : selectedLabelList) { + label.setSelected(false); + label.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); + } + selectedLabel.setSelected(true); + // 处理产品动态 tab与下方文字展示不一致 + if (ComparatorUtils.equals(selectedLabel.getText().trim(), PRODUCT_NEWS)) { + tabLabel.setText(PRODUCT_DYNAMICS); + } else { + tabLabel.setText(selectedLabel.getText()); + } + readLabel.setVisible(false); + tabPane.repaint(); + switch (selectedLabel.getCellType()) { + case PRODUCT_NEWS: + readLabel.setVisible(true); + switchType(CellType.PRODUCT_NEWS); + break; + case ACTION: + currentSearchWorkerManager = settingSearchWorkerManager; + switchType(CellType.ACTION); + break; + case FILE: + currentSearchWorkerManager = fileSearchWorkerManager; + switchType(CellType.FILE); + break; + case DOCUMENT: + currentSearchWorkerManager = documentWorkerManager; + switchType(CellType.DOCUMENT); + break; + case PLUGIN: + currentSearchWorkerManager = pluginSearchWorkerManager; + switchType(CellType.PLUGIN); + break; + } + if (currentSearchWorkerManager != null) { + AlphaFineList alphaFineList = currentSearchWorkerManager.getSearchResultList(); + if (alphaFineList != null) { + alphaFineList.setSelectedIndex(0); + } + } + } + + private Color defaultColor; + + @Override + public void mouseEntered(MouseEvent e) { + defaultColor = selectedLabel.getForeground(); + selectedLabel.setForeground(AlphaFineConstants.SUSPENDED_COLOR); + } + + @Override + public void mouseExited(MouseEvent e) { + selectedLabel.setForeground(defaultColor); + } + }); + tabPane.add(selectedLabel); + } + showPane.add(tabPane, BorderLayout.NORTH); + showPane.add(labelPane, BorderLayout.CENTER); + showPane.add(resultPane, BorderLayout.SOUTH); + return showPane; + } + + private void fireOneClickRead() { + List productNewsList = ProductNewsSearchManager.getInstance().getCachedProductNewsList(); + Set readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); + for (ProductNews productNews : productNewsList) { + readSet.add(productNews.getId()); + } + } + + private void switchType(CellType cellType) { + this.selectedType = cellType; + if (StringUtils.isEmpty(searchTextField.getText())) { + cardLayout.show(resultPane, cellType.getFlagStr4None()); + } else { + // 当前搜索未结束 不切换loading + if (!checkSearchLoading()) { + return; + } + // 所有都搜索都结束 移除loading + if (isAllSearchOver()) { + resultPane.remove(searchLoadingPane); + } + + // 网络异常 + if (checkNetworkError()) { + return; + } + + cardLayout.show(resultPane, cellType.getFlagStr4Result()); + checkSearchResult(); + } + + } + + private boolean checkNetworkError() { + boolean networkError; + if (selectedType == CellType.PRODUCT_NEWS) { + networkError = productNewsSearchWorkerManager.isNetWorkError(); + } else { + networkError = currentSearchWorkerManager.isNetWorkError(); + } + cardLayout.show(resultPane, AlphaFineConstants.NETWORK_ERROR); + return networkError; + } + + private boolean checkSearchLoading() { + boolean searchOver; + if (selectedType == CellType.PRODUCT_NEWS) { + searchOver = productNewsSearchWorkerManager.isSearchOver(); + } else { + searchOver = currentSearchWorkerManager.isSearchOver(); + } + cardLayout.show(resultPane, AlphaFineConstants.LOADING); + return searchOver; + } + + private boolean isAllSearchOver() { + return productNewsSearchWorkerManager.isSearchOver() + && pluginSearchWorkerManager.isSearchOver() + && fileSearchWorkerManager.isSearchOver() + && settingSearchWorkerManager.isSearchOver() + && documentWorkerManager.isSearchOver(); + } + + private void checkSearchResult() { + if (currentSearchWorkerManager == null) { + return; + } + searchResultList = currentSearchWorkerManager.getSearchResultList(); + if (searchResultList != null) { + searchResultList.requestFocus(); + } + boolean hasSearchResult = true; + if (selectedType == CellType.PRODUCT_NEWS) { + hasSearchResult = productNewsSearchWorkerManager.hasSearchResult(); + } else { + hasSearchResult = currentSearchWorkerManager.hasSearchResult(); + } + + if (!hasSearchResult) { + cardLayout.show(resultPane, CellType.NO_RESULT.getFlagStr4None()); + } + + } + + private void initSearchTextField() { + searchTextField = new AlphaFineTextField(PLACE_HOLDER); + initTextFieldListener(); + searchTextField.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); + searchTextField.setBackground(Color.WHITE); + searchTextField.setPreferredSize(new Dimension(300, 60)); + searchTextField.setBorder(null); + } + + + private void initTextFieldListener() { + searchTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + // 搜索提示框 + if (StringUtils.isNotEmpty(searchTextField.getText())) { + clearLabel.setVisible(true); + SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); + } + AlphaFineToolTipList alphaFineToolTipList = SearchTooltipPopup.getInstance().getAlphaFineToolTipList(); + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + if (!alphaFineToolTipList.isSelectionEmpty()) { + fireSearch(alphaFineToolTipList.getSelectedValue()); + return; + } + fireSearch(); + } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + if (alphaFineToolTipList.getSelectedIndex() == alphaFineToolTipList.getModel().getSize() - 1) { + alphaFineToolTipList.setSelectedIndex(0); + } + alphaFineToolTipList.setSelectedIndex(alphaFineToolTipList.getSelectedIndex() + 1); + } else if (e.getKeyCode() == KeyEvent.VK_UP) { + alphaFineToolTipList.setSelectedIndex(alphaFineToolTipList.getSelectedIndex() - 1); + } + + } + }); + + searchTextField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + if (StringUtils.isNotEmpty(searchTextField.getText())) { + SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); + } + } + + @Override + public void focusLost(FocusEvent e) { + if (e.getOppositeComponent() != SearchTooltipPopup.getInstance().getAlphaFineToolTipList()) { + SearchTooltipPopup.getInstance().hide(); + } + } + }); + + startSearchTextFieldTimer(); + + } + + private void startSearchTextFieldTimer() { + Timer timer = new Timer(TIMER_DELAY, e -> { + // 坑 isShowing返回false 即使textField有内容 getText返回的也是空 + if (searchTextField.isShowing() && StringUtils.isEmpty(searchTextField.getText())) { + SearchTooltipPopup.getInstance().hide(); + clearLabel.setVisible(false); + switchType(selectedType); + } else if (searchTextField.hasFocus()) { + clearLabel.setVisible(true); + SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); + } + + }); + timer.start(); + } + + public void fireSearch(String text) { + searchTextField.setText(text); + fireSearch(); + } + + private void fireSearch() { + // 焦点转移 + AlphaFineFrame.this.requestFocus(); + if (ComparatorUtils.equals(beforeSearchStr, searchTextField.getText())) { + return; + } + if (StringUtils.isEmpty(searchTextField.getText())) { + beforeSearchStr = StringUtils.EMPTY; + return; + } + if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isNeedSegmentationCheckbox()) { + //是高级搜索 + if (searchTextField.getText().toLowerCase().startsWith(ADVANCED_SEARCH_MARK)) { + segmentationResult = SegmentationManager.getInstance().startSegmentation(getStoreText(searchTextField.getText().toLowerCase())); + } + //是普通搜索 + else { + segmentationResult = SegmentationManager.getInstance().startSegmentation(searchTextField.getText().toLowerCase()); + } + } else { + if (StringUtils.isEmpty(getRealSearchText(searchTextField.getText()))) { + segmentationResult = null; + } else { + segmentationResult = new String[]{getRealSearchText(searchTextField.getText())}; + } + } + DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getHistorySearch().push(searchTextField.getText()); + doSearch(searchTextField.getText().toLowerCase()); + beforeSearchStr = searchTextField.getText(); + SearchTooltipPopup.getInstance().hide(); + } + + private void dealWithSearchResult() { + final AlphaCellModel model = searchResultList.getSelectedValue(); + if (model != null) { + model.doAction(); + } + } + + public void showResult(String flag) { + cardLayout.show(resultPane, flag); + } + + public void addResult(JPanel panel, String flag) { + resultPane.add(panel, flag); + } + + + + private void doSearch(String text) { + initSearchLoadingPane(); + SearchTextBean searchTextBean = new SearchTextBean(text, segmentationResult); + this.productNewsSearchWorkerManager.doSearch(searchTextBean); + this.settingSearchWorkerManager.doSearch(searchTextBean); + this.fileSearchWorkerManager.doSearch(searchTextBean); + this.documentWorkerManager.doSearch(searchTextBean); + this.pluginSearchWorkerManager.doSearch(searchTextBean); + } + + /** + * 仅搜索依赖网络的搜索项 + * + */ + private void reSearch() { + String text = this.searchTextField.getText().toLowerCase(); + if (StringUtils.isEmpty(text)) { + return; + } + searchLoadingPane = new SearchLoadingPane(); + SearchTextBean searchTextBean = new SearchTextBean(text, segmentationResult); + this.productNewsSearchWorkerManager.doSearch(searchTextBean); + this.documentWorkerManager.doSearch(searchTextBean); + this.pluginSearchWorkerManager.doSearch(searchTextBean); + } + + private void initSearchLoadingPane() { + if (searchLoadingPane == null) { + searchLoadingPane = new SearchLoadingPane(); + } + resultPane.add(searchLoadingPane, AlphaFineConstants.LOADING); + cardLayout.show(resultPane, AlphaFineConstants.LOADING); + } + + public String getSearchText() { + return searchTextField.getText(); + } + + + public CellType getSelectedType() { + return selectedType; + } + + public void setStoreText(String storeText) { + this.storeText = storeText; + } + + /** + * 截取字符串中关键词 + * + * @param searchText + * @return + */ + private String getStoreText(String searchText) { + //这里也需要先做一个去除不需要空格的处理 + setStoreText((searchText.substring(searchText.indexOf(StringUtils.BLANK) + 1)).replaceAll(StringUtils.BLANK, StringUtils.EMPTY)); + return storeText; + } + + + /** + * 去除特殊字符,空格等 + */ + private String getRealSearchText(String searchText) { + searchText = searchText.toLowerCase(); + Pattern p = Pattern.compile(AlphaFineConstants.SPECIAL_CHARACTER_REGEX); + Matcher m = p.matcher(searchText); + searchText = m.replaceAll(StringUtils.EMPTY).trim().replaceAll(StringUtils.BLANK, StringUtils.EMPTY); + if (searchText.length() == 0) { + return null; + } + return searchText; + } + + private UIButton createButton(Icon icon) { + UIButton button = new UIButton() { + @Override + public void paintComponent(Graphics g) { + g.setColor(Color.WHITE); + g.fillRect(0, 0, getSize().width, getSize().height); + super.paintComponent(g); + } + }; + button.setPreferredSize(new Dimension(20, 20)); + button.setIcon(icon); + button.set4ToolbarButton(); + button.setBorderPainted(false); + button.setRolloverEnabled(false); + return button; + } + + /** + * 设置面板位置 + * + * @param win + */ + private void centerWindow(Window win) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + Dimension winSize = win.getSize(); + + if (winSize.height > screenSize.height) { + winSize.height = screenSize.height; + } + if (winSize.width > screenSize.width) { + winSize.width = screenSize.width; + } + //这里设置位置:水平居中,竖直偏上 + win.setLocation((screenSize.width - winSize.width) / 2, (screenSize.height - winSize.height) / AlphaFineConstants.SHOW_SIZE); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + QuestionWindow.getInstance().setVisible(!b); + } + + @Override + public void dispose() { + super.dispose(); + AlphaFineHelper.resetAlphaFineDialog(); + QuestionWindow.getInstance().setVisible(true); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineList.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineList.java new file mode 100644 index 000000000..b58a3e51b --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineList.java @@ -0,0 +1,76 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import com.fr.design.mainframe.alphafine.preview.ResultShowPane; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JList; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/18 + */ +public class AlphaFineList extends JList { + + private ResultShowPane resultShowPane; + + public AlphaFineList() { + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + AlphaCellModel selectedValue = getSelectedValue(); + if (e.getClickCount() == AlphaFineConstants.DEFAULT_CLICK_COUNT && selectedValue.hasAction()) { + // 点击搜索结果 主页面移动到后面 + AlphaFineHelper.getAlphaFineDialog().toBack(); + dealWithSearchResult(); + } + } + }); + + addListSelectionListener(e -> { + if (!e.getValueIsAdjusting() && getSelectedValue() != null) { + if (resultShowPane != null) { + resultShowPane.showResult(getSelectedValue()); + } + } + }); + + + addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + dealWithSearchResult(); + } + } + }); + } + + public void setResultShowPane(ResultShowPane resultShowPane) { + this.resultShowPane = resultShowPane; + } + + @Override + public void setSelectedIndex(int index) { + super.setSelectedIndex(index); + AlphaCellModel alphaCellModel = getSelectedValue(); + if (resultShowPane != null && alphaCellModel != null) { + resultShowPane.showResult(getSelectedValue()); + } + ensureIndexIsVisible(getSelectedIndex()); + } + + private void dealWithSearchResult() { + final AlphaCellModel model = this.getSelectedValue(); + if (model != null) { + model.doAction(); + } + } + + +} \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFinePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFinePane.java index 74c4d6d34..06c9ff0c1 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFinePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFinePane.java @@ -31,7 +31,7 @@ public class AlphaFinePane extends BasicPane { setLayout(new BorderLayout()); UIButton refreshButton = new UIButton(); refreshButton.setIcon(IOUtils.readIcon(("/com/fr/design/mainframe/alphafine/images/smallsearch.png"))); - refreshButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine")); + refreshButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Learn_More_About")); refreshButton.set4ToolbarButton(); refreshButton.setRolloverEnabled(false); this.add(refreshButton); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineTextField.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineTextField.java index ba4d279fb..b745b0de9 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineTextField.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineTextField.java @@ -1,8 +1,7 @@ package com.fr.design.mainframe.alphafine.component; import com.fr.design.gui.itextfield.UITextField; -import com.fr.report.web.button.Image; - +import com.fr.design.mainframe.alphafine.AlphaFineConstants; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; @@ -13,9 +12,10 @@ import java.awt.RenderingHints; */ public class AlphaFineTextField extends UITextField { + private static final int PLACE_HOLDER_GAP = 3; + private String placeHolder; - private Image image; public AlphaFineTextField(String placeHolder) { this.placeHolder = placeHolder; @@ -36,16 +36,13 @@ public class AlphaFineTextField extends UITextField { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setColor(super.getDisabledTextColor()); - g2.drawString(placeHolder, getInsets().left, g.getFontMetrics().getMaxAscent() + getInsets().top + 15); + g2.setColor(AlphaFineConstants.FOREGROUND_COLOR_5); + g2.drawString(placeHolder, getInsets().left, g.getFontMetrics().getMaxAscent() + getInsets().top + PLACE_HOLDER_GAP); } - public Image getImage() { - return image; - } - - public void setImage(Image image) { - this.image = image; + @Override + protected void paintBorder(Graphics g) { + // do nothing } public String getPlaceHolder() { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineToolTipContentCellRender.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineToolTipContentCellRender.java new file mode 100644 index 000000000..1b439f1a8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineToolTipContentCellRender.java @@ -0,0 +1,68 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.base.svg.IconUtils; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineUtil; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class AlphaFineToolTipContentCellRender implements ListCellRenderer { + + private static final Color SELECTED_COLOR = new Color(65, 155, 249, 26); + + private static final Icon HOT_SEARCH_ICON = IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/hot_search.svg"); + + private static final Icon SEARCH_ICON = IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/search.svg"); + + private static final Icon HISTORY_SEARCH_ICON = IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/history_search.svg"); + + + @Override + public Component getListCellRendererComponent(JList list, String value, int index, + boolean isSelected, boolean cellHasFocus) { + + if (StringUtils.isEmpty(value)) { + return new LineCellRender().getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + + JPanel panel = new JPanel(new BorderLayout()); + panel.setBackground(null); + + UILabel iconLabel = new UILabel(); + iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 5, 0)); + iconLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); + iconLabel.setText(value); + if (ComparatorUtils.equals(value, AlphaFineConstants.HOT_SEARCH)) { + iconLabel.setIcon(HOT_SEARCH_ICON); + } else if (AlphaFineConstants.HOT_SEARCH_SET.contains(value)) { + iconLabel.setIcon(SEARCH_ICON); + } else { + iconLabel.setIcon(HISTORY_SEARCH_ICON); + } + + if (isSelected && !ComparatorUtils.equals(value, AlphaFineConstants.HOT_SEARCH)) { + iconLabel.setText(AlphaFineUtil.highLightModelName(value, new String[]{value})); + panel.setBackground(SELECTED_COLOR); + } + panel.add(iconLabel, BorderLayout.WEST); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + panel.setPreferredSize(new Dimension(640, 32)); + + return panel; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineToolTipList.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineToolTipList.java new file mode 100644 index 000000000..3d3333772 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineToolTipList.java @@ -0,0 +1,42 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.general.ComparatorUtils; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JList; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class AlphaFineToolTipList extends JList { + + public AlphaFineToolTipList() { + addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + AlphaFineHelper.getAlphaFineDialog().fireSearch(getSelectedValue()); + } + } + }); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + if (ComparatorUtils.equals(getSelectedValue(), AlphaFineConstants.HOT_SEARCH)) { + return; + } + AlphaFineHelper.getAlphaFineDialog().fireSearch(getSelectedValue()); + } + } + }); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaSearchTooltipPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaSearchTooltipPane.java new file mode 100644 index 000000000..b07d506b8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaSearchTooltipPane.java @@ -0,0 +1,63 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.stable.StringUtils; +import java.awt.Color; +import java.awt.Dimension; +import java.util.Stack; +import javax.swing.DefaultListModel; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class AlphaSearchTooltipPane extends JPanel { + + private AlphaFineToolTipList alphaFineToolTipList; + + public AlphaSearchTooltipPane() { + alphaFineToolTipList = new AlphaFineToolTipList(); + alphaFineToolTipList.setCellRenderer(new AlphaFineToolTipContentCellRender()); + alphaFineToolTipList.setModel(getDefaultListModel()); + UIScrollPane scrollPane = new UIScrollPane(alphaFineToolTipList); + scrollPane.setBorder(null); + scrollPane.setBackground(Color.WHITE); + this.add(scrollPane); + this.setPreferredSize(new Dimension(640, 250)); + this.setBackground(Color.WHITE); + } + + public AlphaFineToolTipList getAlphaFineToolTipList() { + return alphaFineToolTipList; + } + + private DefaultListModel getDefaultListModel() { + DefaultListModel defaultListModel = new DefaultListModel<>(); + defaultListModel.addElement(AlphaFineConstants.HOT_SEARCH); + for (String content : AlphaFineConstants.HOT_SEARCH_SET) { + defaultListModel.addElement(content); + } + return defaultListModel; + } + + public void refreshHistory() { + Stack stack = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getHistorySearch(); + if (stack.isEmpty()) { + return; + } + DefaultListModel defaultListModel = new DefaultListModel<>(); + for (int i = stack.size() - 1; i >= 0; i--) { + defaultListModel.addElement(stack.get(i)); + } +// defaultListModel.addElement(StringUtils.EMPTY); + defaultListModel.addElement(AlphaFineConstants.HOT_SEARCH); + for (String content : AlphaFineConstants.HOT_SEARCH_SET) { + defaultListModel.addElement(content); + } + alphaFineToolTipList.setModel(defaultListModel); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/LineCellRender.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/LineCellRender.java new file mode 100644 index 000000000..9158cb045 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/LineCellRender.java @@ -0,0 +1,32 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import javax.swing.BorderFactory; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class LineCellRender implements ListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, String value, int index, + boolean isSelected, boolean cellHasFocus) { + JPanel panel = new JPanel(new BorderLayout()); + UILabel splitLabel = new UILabel(); + panel.setBackground(null); + splitLabel.setBackground(UIConstants.BARNOMAL); + splitLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 5,0)); + panel.setPreferredSize(new Dimension(640, 1)); + panel.add(splitLabel); + return panel; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsContentCellRender.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsContentCellRender.java new file mode 100644 index 000000000..c6b5983d6 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsContentCellRender.java @@ -0,0 +1,100 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineUtil; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import com.fr.design.utils.DesignUtils; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.text.SimpleDateFormat; +import javax.swing.BorderFactory; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/19 + */ +public class ProductNewsContentCellRender implements ListCellRenderer { + + private static final String FINE_REPORT = "FineReport"; + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd"); + + /** + * 透明灰色背景 Y方向偏移 + */ + private static final int GRAY_BACKGROUND_Y_GAP = 39; + + /** + * 透明灰色背景 高度 + */ + private static final int GRAY_BACKGROUND_HEIGHT = 23; + + /** + * 单行产品动态的高度与宽度尺寸 + */ + private static final Dimension DEFAULT_DIMENSION = new Dimension(500, 100); + + private String[] segmentationResult; + + private ProductNewsList productNewsList; + + public ProductNewsContentCellRender(String[] segmentationResult, ProductNewsList productNewsList) { + this.segmentationResult = segmentationResult; + this.productNewsList = productNewsList; + } + + public ProductNewsContentCellRender(ProductNewsList productNewsList) { + this(null, productNewsList); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + ProductNews productNews = (ProductNews) value; + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); + panel.setBackground(Color.WHITE); + + panel.add(new ProductNewsImagePanel(productNews), BorderLayout.WEST); + JPanel textPane = new JPanel(new BorderLayout()); + textPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 0)); + UILabel titleLabel = new UILabel(AlphaFineUtil.highLightModelName(productNews.getTitle(), segmentationResult)); + titleLabel.setFont(DesignUtils.getDefaultGUIFont().applySize(20)); + if (productNewsList.getHoverIndex() == index) { + titleLabel.setForeground(UIConstants.FLESH_BLUE); + } + + textPane.add(titleLabel, BorderLayout.NORTH); + JPanel infoPane = new JPanel(new BorderLayout()); + UILabel productLabel = new UILabel(FINE_REPORT) { + @Override + protected void paintComponent(Graphics g) { + g.setColor(AlphaFineConstants.BACKGROUND_COLOR); + g.fillRect(0, getHeight() - GRAY_BACKGROUND_Y_GAP, getWidth(), GRAY_BACKGROUND_HEIGHT); + super.paintComponent(g); + } + }; + productLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); + infoPane.add(productLabel, BorderLayout.WEST); + + UILabel dateLabel = new UILabel(DATE_FORMAT.format(productNews.getPushDate())); + dateLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); + dateLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + infoPane.setBackground(Color.WHITE); + infoPane.add(dateLabel, BorderLayout.CENTER); + textPane.setBackground(Color.WHITE); + textPane.add(infoPane, BorderLayout.CENTER); + panel.add(textPane, BorderLayout.CENTER); + panel.setPreferredSize(DEFAULT_DIMENSION); + return panel; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsImagePanel.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsImagePanel.java new file mode 100644 index 000000000..e87b6f199 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsImagePanel.java @@ -0,0 +1,76 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.base.GraphHelper; +import com.fr.base.svg.SVGLoader; +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; + +import java.awt.RenderingHints; +import java.util.Set; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/15 + */ +public class ProductNewsImagePanel extends JPanel { + + private static final Image NEW_TIP_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/new_tip.svg"); + + private static final int BACKGROUND_HEIGHT = 20; + + private static final Color BACKGROUND_COLOR = new Color(116, 181, 249); + + private static final Color COVER_COLOR = new Color(116, 181, 249, 26); + + private ProductNews productNews; + + private int width = 200; + private int height = 150; + + public ProductNewsImagePanel(ProductNews productNews) { + this.productNews = productNews; + } + + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + Color defaultColor = g2.getColor(); + + Image image = productNews.getImage(); + if (image != null) { + g2.drawImage(productNews.getImage(), 0, 0, getWidth(), getHeight(), this); + } else { + g2.setColor(COVER_COLOR); + g2.fillRect(0, 0, getWidth(), getHeight()); + } + Set readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); + if (!readSet.contains(productNews.getId())) { + g2.drawImage(NEW_TIP_IMAGE, 0, 0, this); + } + + g2.setColor(BACKGROUND_COLOR); + g2.fillRect(0, getHeight() - BACKGROUND_HEIGHT, getWidth(), BACKGROUND_HEIGHT); + g2.setColor(Color.WHITE); + int x = (getWidth() - GraphHelper.getWidth(productNews.getTag().getDesc(), g2.getFont())) / 2; + g2.drawString(productNews.getTag().getDesc(), x, getHeight() - 5); + g2.setColor(defaultColor); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(width, height); + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsList.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsList.java new file mode 100644 index 000000000..9e4d1c402 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsList.java @@ -0,0 +1,78 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import com.fr.log.FineLoggerFactory; + +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.net.URI; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.ListModel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/21 + */ +public class ProductNewsList extends JList { + + private int hoverIndex = -1; + + public ProductNewsList(ListModel dataModel) { + super(dataModel); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == AlphaFineConstants.DEFAULT_CLICK_COUNT) { + dealWithClick(); + } + } + + @Override + public void mouseExited(MouseEvent e) { + hoverIndex = -1; + ProductNewsList.this.repaint(); + } + }); + + addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + Point p = new Point(e.getX(), e.getY()); + int index = ProductNewsList.this.locationToIndex(p); + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + if (index != hoverIndex) { + hoverIndex = index; + ProductNewsList.this.repaint(); + } + } + }); + } + + public ProductNewsList() { + this(new DefaultListModel<>()); + } + + private void dealWithClick() { + ProductNews productNews = getSelectedValue(); + try { + Desktop.getDesktop().browse(new URI(productNews.getUrl())); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet().add(productNews.getId()); + AlphaFineHelper.getAlphaFineDialog().repaint(); + } + + public int getHoverIndex() { + return hoverIndex; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsSearchResultPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsSearchResultPane.java new file mode 100644 index 000000000..b3fd4dc95 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/ProductNewsSearchResultPane.java @@ -0,0 +1,37 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.BorderFactory; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/21 + */ +public class ProductNewsSearchResultPane extends JPanel { + + private ProductNewsList productNewsList; + + public ProductNewsSearchResultPane(String[] segmentationResult) { + + productNewsList = new ProductNewsList(); + UIScrollPane scrollPane = new UIScrollPane(productNewsList); + scrollPane.setBackground(Color.WHITE); + scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 20)); + productNewsList.setCellRenderer(new ProductNewsContentCellRender(segmentationResult, productNewsList)); + this.setLayout(new BorderLayout()); + this.setBackground(Color.WHITE); + this.add(scrollPane); + this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); + } + + public ProductNewsList getProductNewsList() { + return productNewsList; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchListModel.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchListModel.java new file mode 100644 index 000000000..f6948a57d --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchListModel.java @@ -0,0 +1,126 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import com.fr.design.mainframe.alphafine.model.SearchResult; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/18 + */ +public class SearchListModel extends DefaultListModel { + + private static final int MAX_SHOW_SIZE = 12; + private static final long serialVersionUID = 7230585307439551228L; + + + private SearchResult myDelegate; + + /** + * 第一有效的项是否被选中 + */ + private boolean isValidSelected; + + private UIScrollPane leftSearchResultPane; + + private AlphaFineList searchResultList; + + public SearchListModel(SearchResult searchResult, AlphaFineList searchResultList, UIScrollPane leftSearchResultPane) { + this.myDelegate = searchResult; + this.searchResultList = searchResultList; + this.leftSearchResultPane = leftSearchResultPane; + } + + @Override + public void addElement(AlphaCellModel element) { + AlphaFineHelper.checkCancel(); + int index = myDelegate.size(); + myDelegate.add(element); + fireContentsChanged(this, index, index); + fireSelectedStateChanged(element, index); + + } + + @Override + protected void fireContentsChanged(Object source, int index0, int index1) { + if (myDelegate.size() > MAX_SHOW_SIZE) { + leftSearchResultPane.getVerticalScrollBar().setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0)); + leftSearchResultPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 2)); + } else { + leftSearchResultPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + } + super.fireContentsChanged(source, index0, index1); + } + + /** + * 触发选中第一有效的项 + * + * @param element + * @param index + */ + private void fireSelectedStateChanged(AlphaCellModel element, int index) { + if (element.hasAction() && !isValidSelected()) { + searchResultList.setSelectedIndex(index); + setValidSelected(true); + } + } + + @Override + public AlphaCellModel getElementAt(int index) { + return myDelegate.get(index); + } + + @Override + public void add(int index, AlphaCellModel element) { + myDelegate.add(index, element); + fireIntervalAdded(this, index, index); + } + + @Override + public AlphaCellModel remove(int index) { + AlphaCellModel object = myDelegate.get(index); + myDelegate.remove(object); + fireContentsChanged(this, index, index); + return object; + } + + @Override + public int getSize() { + return this.myDelegate.size(); + } + + @Override + public void removeAllElements() { + this.myDelegate.clear(); + } + + /** + * 重置选中状态 + */ + public void resetSelectedState() { + setValidSelected(false); + } + + private boolean isValidSelected() { + return isValidSelected; + } + + private void setValidSelected(boolean selected) { + isValidSelected = selected; + } + + @Override + public boolean isEmpty() { + return myDelegate.isEmpty(); + } + + public void resetState() { + for (int i = 0; i < getSize(); i++) { + getElementAt(i).resetState(); + } + } +} \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchResultContentCellRender.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchResultContentCellRender.java new file mode 100644 index 000000000..dd65d36a2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchResultContentCellRender.java @@ -0,0 +1,83 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineUtil; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import com.fr.general.IOUtils; +import com.fr.stable.StringUtils; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import javax.swing.BorderFactory; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/19 + */ +public class SearchResultContentCellRender implements ListCellRenderer { + + private static final int OFFSET = 45; + private static final String SELECTED_PATH = AlphaFineConstants.IMAGE_URL + "selected"; + private static final String CELL_PATH = AlphaFineConstants.IMAGE_URL + "alphafine"; + private static final String SUFFIX = ".png"; + + private String[] segmentationResult; + + public SearchResultContentCellRender(String[] segmentationResult) { + this.segmentationResult = segmentationResult; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + + + AlphaCellModel model = (AlphaCellModel) value; + JPanel panel = new JPanel(new BorderLayout()); + panel.setBackground(null); + panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + // 图标icon 样式 + UILabel iconLabel = new UILabel(); + if (isSelected) { + iconLabel.setText(StringUtils.BLANK + model.getName()); + String iconUrl = SELECTED_PATH + model.getType().getTypeValue() + SUFFIX; + panel.setBackground(AlphaFineConstants.BLUE); + iconLabel.setForeground(Color.WHITE); + iconLabel.setIcon(IOUtils.readIcon(iconUrl)); + } else { + iconLabel.setText(AlphaFineUtil.highLightModelName(model.getName(), segmentationResult)); + String iconUrl = CELL_PATH + model.getType().getTypeValue() + SUFFIX; + iconLabel.setIcon(IOUtils.readIcon(iconUrl)); + } + iconLabel.setFont(AlphaFineConstants.MEDIUM_FONT); + + + // 内容详情label 样式 + UILabel detailLabel = new UILabel(); + String description = model.getDescription(); + if (StringUtils.isNotBlank(description)) { + detailLabel.setText("-" + description); + detailLabel.setForeground(AlphaFineConstants.LIGHT_GRAY); + panel.add(detailLabel, BorderLayout.CENTER); + int width = (int) (iconLabel.getPreferredSize().getWidth() + detailLabel.getPreferredSize().getWidth()); + if (width > AlphaFineConstants.LEFT_WIDTH - OFFSET) { + int nameWidth = (int) (AlphaFineConstants.LEFT_WIDTH - detailLabel.getPreferredSize().getWidth() - OFFSET); + iconLabel.setPreferredSize(new Dimension(nameWidth, AlphaFineConstants.CELL_HEIGHT)); + } + } else { + iconLabel.setPreferredSize(new Dimension(AlphaFineConstants.LEFT_WIDTH - OFFSET, AlphaFineConstants.CELL_HEIGHT)); + } + + panel.add(iconLabel, BorderLayout.WEST); + panel.setPreferredSize(new Dimension(list.getFixedCellWidth(), AlphaFineConstants.CELL_HEIGHT)); + return panel; + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchResultPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchResultPane.java new file mode 100644 index 000000000..d4f6c1802 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchResultPane.java @@ -0,0 +1,51 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.model.SearchResult; +import com.fr.design.mainframe.alphafine.preview.ResultShowPane; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class SearchResultPane extends JPanel { + + private AlphaFineList searchResultList; + + private SearchListModel searchListModel; + + private UIScrollPane leftSearchResultPane; + + + public SearchResultPane(String[] segmentationResult, ResultShowPane rightSearchResultPane) { + searchResultList = new AlphaFineList(); + searchResultList.setFixedCellHeight(AlphaFineConstants.CELL_HEIGHT); + leftSearchResultPane = new UIScrollPane(searchResultList); + leftSearchResultPane.setBorder(null); + leftSearchResultPane.setBackground(Color.WHITE); + leftSearchResultPane.setPreferredSize(new Dimension(AlphaFineConstants.LEFT_WIDTH, AlphaFineConstants.CONTENT_HEIGHT)); + searchListModel = new SearchListModel(new SearchResult(), searchResultList, leftSearchResultPane); + searchResultList.setModel(searchListModel); + searchResultList.setCellRenderer(new SearchResultContentCellRender(segmentationResult)); + searchResultList.setResultShowPane(rightSearchResultPane); + this.setPreferredSize(AlphaFineConstants.CONTENT_SIZE); + this.setLayout(new BorderLayout()); + this.add(leftSearchResultPane, BorderLayout.WEST); + this.add(rightSearchResultPane, BorderLayout.EAST); + this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); + } + + public AlphaFineList getSearchResultList() { + return searchResultList; + } + + public UIScrollPane getLeftSearchResultPane() { + return leftSearchResultPane; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchTooltipPopup.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchTooltipPopup.java new file mode 100644 index 000000000..b3aaa8170 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SearchTooltipPopup.java @@ -0,0 +1,58 @@ +package com.fr.design.mainframe.alphafine.component; + +import java.awt.Component; +import java.awt.Point; +import javax.swing.Popup; +import javax.swing.PopupFactory; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class SearchTooltipPopup { + + private static final SearchTooltipPopup INSTANCE = new SearchTooltipPopup(); + + public static SearchTooltipPopup getInstance() { + return INSTANCE; + } + + private AlphaSearchTooltipPane alphaSearchTooltipPane; + + private SearchTooltipPopup() { + alphaSearchTooltipPane = new AlphaSearchTooltipPane(); + } + + private boolean showPopup; + + private Popup popup; + + public void show(Component owner) { + if (popup == null || !showPopup) { + PopupFactory pf = PopupFactory.getSharedInstance(); + Point point = owner.getLocationOnScreen(); + alphaSearchTooltipPane.refreshHistory(); + popup = pf.getPopup(owner, alphaSearchTooltipPane, point.x, point.y + owner.getHeight()); + } + if (!showPopup) { + alphaSearchTooltipPane.repaint(); + popup.show(); + getAlphaFineToolTipList().clearSelection(); + showPopup = true; + } + } + + public AlphaFineToolTipList getAlphaFineToolTipList() { + return alphaSearchTooltipPane.getAlphaFineToolTipList(); + } + + public void hide() { + if (popup != null) { + popup.hide(); + } + showPopup = false; + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SelectedLabel.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SelectedLabel.java new file mode 100644 index 000000000..9bf151adc --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/SelectedLabel.java @@ -0,0 +1,81 @@ +package com.fr.design.mainframe.alphafine.component; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineUtil; +import com.fr.design.mainframe.alphafine.CellType; + +import javax.swing.BorderFactory; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/07 + */ +public class SelectedLabel extends UILabel { + + private static final int WIDTH = 4; + private static final int HEIGHT = 4; + private static final int GAP = 0; + private static final int BORDER_RIGHT = 5; + private static final int BORDER_TOP = 2; + + private boolean selected; + private CellType cellType; + + public SelectedLabel(String text, CellType cellType, boolean selected) { + super(text); + this.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); + this.setBorder(BorderFactory.createEmptyBorder(BORDER_TOP, 0, 0, BORDER_RIGHT)); + this.selected = selected; + this.cellType = cellType; + } + + public SelectedLabel(String text, CellType cellType) { + this(text, cellType, false); + } + + @Override + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + if (selected) { + g2d.setColor(UIConstants.FLESH_BLUE); + setForeground(UIConstants.FLESH_BLUE); + g2d.drawLine(0, this.getHeight() - 1, this.getWidth() - BORDER_RIGHT, this.getHeight() - 1); + } + super.paintComponent(g); + } + + + @Override + protected void paintBorder(Graphics g) { + super.paintBorder(g); + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + if (cellType == CellType.PRODUCT_NEWS && AlphaFineUtil.unread()) { + Color oldColor = g.getColor(); + g2d.setColor(Color.RED); + g2d.fillOval(getWidth() - WIDTH, GAP, WIDTH, HEIGHT); + g2d.setColor(oldColor); + } + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + public CellType getCellType() { + return cellType; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/exception/AlphaFineNetworkException.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/exception/AlphaFineNetworkException.java new file mode 100644 index 000000000..c8fec04e0 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/exception/AlphaFineNetworkException.java @@ -0,0 +1,14 @@ +package com.fr.design.mainframe.alphafine.exception; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/27 + */ +public class AlphaFineNetworkException extends RuntimeException { + + public AlphaFineNetworkException() { + super("NetWork Error"); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/ProductNews.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/ProductNews.java new file mode 100644 index 000000000..aea152da2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/model/ProductNews.java @@ -0,0 +1,200 @@ +package com.fr.design.mainframe.alphafine.model; + +import com.fr.design.i18n.Toolkit; +import java.awt.Image; +import java.util.Date; + +/** + * 产品动态 + * + * @author hades + * @version 11.0 + * Created by hades on 2022/4/05 + */ +public class ProductNews { + + private long id; + private String title; + + private Tag tag; + private Target target; + + private Status status; + private String url; + private Image image; + + + private Date pushDate; + + /** + * 创建cid的用户 + */ + private int creator; + + public long getId() { + return id; + } + + public ProductNews setId(long id) { + this.id = id; + return this; + } + + public String getTitle() { + return title; + } + + public ProductNews setTitle(String title) { + this.title = title; + return this; + } + + public Tag getTag() { + return tag; + } + + public ProductNews setTag(Tag tag) { + this.tag = tag; + return this; + } + + public Target getTarget() { + return target; + } + + public ProductNews setTarget(Target target) { + this.target = target; + return this; + } + + public Status getStatus() { + return status; + } + + public ProductNews setStatus(Status status) { + this.status = status; + return this; + } + + public String getUrl() { + return url; + } + + public ProductNews setUrl(String url) { + this.url = url; + return this; + } + + public Image getImage() { + return image; + } + + public ProductNews setImage(Image image) { + this.image = image; + return this; + } + + public Date getPushDate() { + return pushDate; + } + + public ProductNews setPushDate(Date pushDate) { + this.pushDate = pushDate; + return this; + } + + public int getCreator() { + return creator; + } + + public ProductNews setCreator(int creator) { + this.creator = creator; + return this; + } + + interface CodeParser { + int getCode(); + } + + public enum Status implements CodeParser { + STOP(0), START(1); + + private final int code; + + Status(int code) { + this.code = code; + } + + @Override + public int getCode() { + return code; + } + + public static Status parseCode(int code) { + for (Status status : values()) { + if (code == status.code) { + return status; + } + } + throw new IllegalArgumentException(); + } + } + + public enum Tag { + SOLUTION(1, Toolkit.i18nText("Fine-Design_Report_AlphaFine_Solution")), + MATERIAL(2, Toolkit.i18nText("Fine-Design_Report_AlphaFine_Material")), + NEW_PRODUCT(3, Toolkit.i18nText("Fine-Design_Report_AlphaFine_New_Product")); + + private final int code; + + private final String desc; + + Tag(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public static Tag parseCode(int code) { + for (Tag tag :values()) { + if (tag.code == code) { + return tag; + } + } + throw new IllegalArgumentException(); + } + + public int getCode() { + return code; + } + + public String getDesc() { + return desc; + } + } + + public enum Target { + ALL_USER(0); + + private final int code; + + Target(int code) { + this.code = code; + } + + public int getCode() { + return code; + } + + public static Target parseCode(int code) { + for (Target target : values()) { + if (target.code == code) { + return target; + } + } + throw new IllegalArgumentException(); + } + + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/DefaultProductNewsPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/DefaultProductNewsPane.java new file mode 100644 index 000000000..d70e37ec0 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/DefaultProductNewsPane.java @@ -0,0 +1,121 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.component.ProductNewsContentCellRender; +import com.fr.design.mainframe.alphafine.component.ProductNewsList; +import com.fr.design.mainframe.alphafine.exception.AlphaFineNetworkException; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; +import com.fr.design.utils.DesignUtils; +import com.fr.log.FineLoggerFactory; +import java.awt.BorderLayout; +import java.awt.Color; +import java.util.List; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.SwingWorker; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/14 + */ +public class DefaultProductNewsPane extends JPanel { + + + private static final String LOADING = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Loading"); + private static final ImageIcon LOADING_ICON = new ImageIcon(DefaultProductNewsPane.class.getResource("/com/fr/web/images/loading-local.gif")); + + private SwingWorker, Void> worker; + + public DefaultProductNewsPane() { + + setLayout(new BorderLayout()); + this.add(createLoadingPane()); + this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); + this.worker = createWorker(); + this.worker.execute(); + } + + + private JPanel createLoadingPane() { + JPanel loadingPane = new JPanel(new BorderLayout()); + UILabel loadingLabel = new UILabel(LOADING); + loadingLabel.setForeground(AlphaFineConstants.MEDIUM_GRAY); + loadingLabel.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); + loadingLabel.setBorder(BorderFactory.createEmptyBorder(0, 280, 0, 0)); + UILabel loadingIconLabel = new UILabel(LOADING_ICON); + loadingIconLabel.setBorder(BorderFactory.createEmptyBorder(100, 0, 0, 0)); + loadingPane.add(loadingIconLabel, BorderLayout.NORTH); + loadingPane.add(loadingLabel, BorderLayout.CENTER); + loadingPane.setBackground(Color.WHITE); + return loadingPane; + } + + private SwingWorker, Void> createWorker() { + if (this.worker != null && !this.worker.isDone()) { + this.worker.cancel(true); + this.worker = null; + } + return new SwingWorker, Void>() { + + @Override + protected List doInBackground() throws Exception { + if (!AlphaFineHelper.isNetworkOk()) { + throw new AlphaFineNetworkException(); + } + return ProductNewsSearchManager.getInstance().getProductNewsList(); + } + + @Override + protected void done() { + DefaultProductNewsPane.this.removeAll(); + try { + DefaultProductNewsPane.this.add(createContentPane(get())); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + if (e.getCause() instanceof AlphaFineNetworkException) { + DefaultProductNewsPane.this.add(new NetWorkFailedPane(() -> { + DefaultProductNewsPane.this.removeAll(); + add(createLoadingPane()); + refresh(); + worker = createWorker(); + worker.execute(); + })); + } + } + refresh(); + } + }; + + } + + private void refresh() { + this.validate(); + this.repaint(); + if (AlphaFineHelper.getAlphaFineDialog() != null) { + AlphaFineHelper.getAlphaFineDialog().repaint(); + } + } + + private UIScrollPane createContentPane(List productNewsList) { + DefaultListModel productNewsDefaultListModel = new DefaultListModel<>(); + for (ProductNews productNews : productNewsList) { + productNewsDefaultListModel.addElement(productNews); + } + ProductNewsList productNewsJList = new ProductNewsList(productNewsDefaultListModel); + productNewsJList.setBackground(Color.WHITE); + productNewsJList.setCellRenderer(new ProductNewsContentCellRender(productNewsJList)); + UIScrollPane scrollPane = new UIScrollPane(productNewsJList); + scrollPane.setBackground(Color.WHITE); + scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 20)); + return scrollPane; + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/HelpDocumentNoResultPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/HelpDocumentNoResultPane.java new file mode 100644 index 000000000..961d490e5 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/HelpDocumentNoResultPane.java @@ -0,0 +1,167 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.utils.BrowseUtils; +import com.fr.design.utils.DesignUtils; +import com.fr.json.JSON; +import com.fr.json.JSONArray; +import com.fr.json.JSONFactory; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.SwingConstants; +import javax.swing.SwingWorker; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/13 + */ +public class HelpDocumentNoResultPane extends JPanel { + + private static final String RECOMMEND = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Recommend_For_You"); + + private static final Color DOT_COLOR = new Color(200, 201, 205); + + private SwingWorker worker; + + private String title; + + private Icon icon; + + private Map linkMap; + + public HelpDocumentNoResultPane(String title, Icon icon) { + this.title = title; + this.icon = icon; + this.linkMap = generateMap(); + setLayout(new BorderLayout()); + worker = createWorker(); + worker.execute(); + } + + private SwingWorker createWorker() { + if (this.worker != null && !this.worker.isDone()) { + this.worker.cancel(true); + this.worker = null; + } + return new SwingWorker() { + + @Override + protected Boolean doInBackground() throws Exception { + return AlphaFineHelper.isNetworkOk(); + } + + @Override + protected void done() { + HelpDocumentNoResultPane.this.removeAll(); + try { + if (get()) { + add(new NoResultPane(title, icon, 150), BorderLayout.CENTER); + add(createRecommendPane(linkMap), BorderLayout.EAST); + } else { + add(new NetWorkFailedPane(() -> { + worker = createWorker(); + worker.execute(); + })); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + refresh(); + } + }; + } + + + private void refresh() { + this.validate(); + this.repaint(); + } + + + private Map generateMap() { + JSONArray jsonArray = JSONFactory.createJSON(JSON.ARRAY, AlphaFineConstants.ALPHA_HELP_RECOMMEND); + Map linkMap = new LinkedHashMap<>(); + for (int i = 0, len = jsonArray.size(); i < len; i++) { + JSONObject json = jsonArray.getJSONObject(i); + linkMap.put(json.getString("name"), json.getString("link")); + } + return linkMap; + } + + private JPanel createRecommendPane(Map linkMap) { + JPanel wrapRecommendPane = new JPanel(new BorderLayout()); + wrapRecommendPane.setPreferredSize(new Dimension(200, 305)); + JPanel recommendPane = new JPanel(); + recommendPane.setLayout(new GridLayout(0, 1)); + recommendPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 130, 0)); + recommendPane.setBackground(Color.WHITE); + recommendPane.add(new UILabel(RECOMMEND)); + for (Map.Entry entry : linkMap.entrySet()) { + recommendPane.add(createListLabel(entry.getKey(), entry.getValue())); + } + // 分割线 + JSeparator sep = new JSeparator(); + sep.setOrientation(JSeparator.VERTICAL); + sep.setLayout(new GridLayout(0, 1)); + sep.setPreferredSize(new Dimension(1, 285)); + sep.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + sep.add(new UILabel()); + wrapRecommendPane.add(sep, BorderLayout.WEST); + wrapRecommendPane.add(recommendPane, BorderLayout.CENTER); + return wrapRecommendPane; + } + + private JPanel createListLabel(String text, String link) { + UILabel listLabel = new UILabel(String.format("%s", text)); + listLabel.setForeground(UIConstants.FLESH_BLUE); + listLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + listLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + responseClick(link); + } + }); + listLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + + JPanel listPane = new JPanel(new BorderLayout()); + listPane.setBackground(Color.WHITE); + UILabel dotLabel = new UILabel("·"); + dotLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + dotLabel.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); + dotLabel.setHorizontalAlignment(SwingConstants.LEADING); + dotLabel.setForeground(DOT_COLOR); + listPane.add(dotLabel, BorderLayout.WEST); + listPane.add(listLabel, BorderLayout.CENTER); + listPane.setPreferredSize(new Dimension(100, 20)); + return listPane; + } + + /** + * 方便记录埋点 + * + * @param link + */ + private void responseClick(String link) { + BrowseUtils.browser(link); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/LoadingRightSearchResultPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/LoadingRightSearchResultPane.java new file mode 100644 index 000000000..6201c25e5 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/LoadingRightSearchResultPane.java @@ -0,0 +1,167 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.CellType; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import com.fr.design.mainframe.alphafine.cell.model.FileModel; +import com.fr.design.mainframe.alphafine.cell.model.PluginModel; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.project.ProjectConstants; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.exporter.LocalExportOperator; +import com.fr.workspace.server.exporter.TemplateExportOperator; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import java.util.concurrent.ExecutionException; +import javax.imageio.ImageIO; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.SwingWorker; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/20 + */ +public class LoadingRightSearchResultPane extends ResultShowPane { + + private SwingWorker showWorker; + + public LoadingRightSearchResultPane() { + + this.setBackground(Color.WHITE); + this.setPreferredSize(new Dimension(AlphaFineConstants.RIGHT_WIDTH - 1, AlphaFineConstants.CONTENT_HEIGHT)); + initLoadingLabel(); + + } + + private void initLoadingLabel() { + UILabel label = new UILabel(new ImageIcon(getClass().getResource("/com/fr/design/mainframe/alphafine/images/opening.gif"))); + label.setBorder(BorderFactory.createEmptyBorder(120, 0, 0, 0)); + this.add(label, BorderLayout.CENTER); + } + + private void showDefaultPreviewPane() { + this.removeAll(); + initLoadingLabel(); + validate(); + repaint(); + revalidate(); + } + + @Override + public void showResult(AlphaCellModel selectedValue) { + showDefaultPreviewPane(); + checkWorker(); + if (selectedValue.getType() == CellType.FILE) { + fileShowWorker(selectedValue); + } + + if (selectedValue.getType() == CellType.PLUGIN) { + pluginShowWorker(selectedValue); + } + this.showWorker.execute(); + } + + private void fileShowWorker(AlphaCellModel selectedValue) { + this.showWorker = new SwingWorker() { + @Override + protected BufferedImage doInBackground() throws Exception { + final String fileName = ((FileModel) selectedValue).getFilePath().substring(ProjectConstants.REPORTLETS_NAME.length() + 1); + if (fileName.endsWith(ProjectConstants.FRM_SUFFIX)) { + return frmToImage(fileName); + } else if (fileName.endsWith(ProjectConstants.CPT_SUFFIX)) { + return cptToImage(fileName); + } else { + return null; + } + } + + @Override + protected void done() { + if (!isCancelled()) { + LoadingRightSearchResultPane.this.removeAll(); + try { + LoadingRightSearchResultPane.this.add(new FilePreviewPane(get())); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + validate(); + repaint(); + } + } + }; + } + + private void pluginShowWorker(AlphaCellModel selectedValue) { + this.showWorker = new SwingWorker() { + @Override + protected BufferedImage doInBackground() { + BufferedImage bufferedImage = null; + try { + bufferedImage = ImageIO.read(new URL(((PluginModel) selectedValue).getImageUrl())); + } catch (IOException e) { + try { + bufferedImage = ImageIO.read(getClass().getResource("/com/fr/design/mainframe/alphafine/images/default_product.png")); + } catch (IOException e1) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + return bufferedImage; + } + + @Override + protected void done() { + try { + if (!isCancelled()) { + LoadingRightSearchResultPane.this.removeAll(); + LoadingRightSearchResultPane.this.add(new PluginPreviewPane((selectedValue).getName(), get(), ((PluginModel) selectedValue).getVersion(), ((PluginModel) selectedValue).getJartime(), ((PluginModel) selectedValue).getType(), ((PluginModel) selectedValue).getPrice())); + validate(); + repaint(); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + }; + } + + + private BufferedImage frmToImage(String fileName) throws Exception { + byte[] bytes = null; + try { + bytes = WorkContext.getCurrent().get(TemplateExportOperator.class).exportFormAsImageData(fileName); + } catch (Exception ignored) { + // 兼容下老版本 + bytes = new LocalExportOperator().exportFormAsImageData(fileName); + } + return TemplateExportOperator.byteDataToImage(bytes); + } + + + private BufferedImage cptToImage(String fileName) throws Exception { + byte[] bytes = null; + try { + bytes = WorkContext.getCurrent().get(TemplateExportOperator.class).exportWorkBookAsImageData(fileName); + } catch (Exception ignored) { + // 兼容下老版本 + bytes = new LocalExportOperator().exportWorkBookAsImageData(fileName); + } + return TemplateExportOperator.byteDataToImage(bytes); + } + + + private void checkWorker() { + if (this.showWorker != null && !this.showWorker.isDone()) { + this.showWorker.cancel(true); + this.showWorker = null; + } + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NetWorkFailedPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NetWorkFailedPane.java new file mode 100644 index 000000000..eb4c107c4 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NetWorkFailedPane.java @@ -0,0 +1,69 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.share.ui.base.MouseClickListener; +import com.fr.general.IOUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.FlowLayout; +import java.awt.event.MouseEvent; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/28 + */ +public class NetWorkFailedPane extends JPanel { + + private Runnable reload; + + public NetWorkFailedPane() { + this(() -> {}); + } + + public NetWorkFailedPane(Runnable reload) { + this.reload = reload; + this.setLayout(new BorderLayout()); + this.add(createInternetErrorPane()); + this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); + this.setBackground(Color.WHITE); + } + + private JPanel createInternetErrorPane() { + JPanel panel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5); + panel.setBackground(Color.WHITE); + UILabel imagePanel = new UILabel(IOUtils.readIcon("/com/fr/base/images/share/internet_error.png")); + imagePanel.setBorder(BorderFactory.createEmptyBorder(50, 280, 0, 0)); + panel.add(imagePanel); + UILabel uiLabel = tipLabel(Toolkit.i18nText("Fine-Design_Share_Internet_Connect_Failed")); + uiLabel.setBorder(BorderFactory.createEmptyBorder(0, 300, 0, 0)); + uiLabel.setForeground(Color.decode("#8F8F92")); + UILabel reloadLabel = tipLabel(Toolkit.i18nText("Fine-Design_Share_Online_Reload")); + reloadLabel.setBorder(BorderFactory.createEmptyBorder(0, 310, 0, 0)); + reloadLabel.setForeground(Color.decode("#419BF9")); + reloadLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + reloadLabel.addMouseListener(new MouseClickListener() { + @Override + public void mousePressed(MouseEvent e) { + reload.run(); + } + }); + panel.add(uiLabel); + panel.add(reloadLabel); + return panel; + } + + private UILabel tipLabel(String text) { + UILabel tipLabel = new UILabel(text); + tipLabel.setHorizontalAlignment(SwingConstants.CENTER); + return tipLabel; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultPane.java index 29a8c1e08..db9282118 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultPane.java @@ -5,7 +5,9 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.mainframe.alphafine.AlphaFineConstants; import com.fr.design.utils.DesignUtils; +import java.awt.Component; import javax.swing.BorderFactory; +import javax.swing.Icon; import javax.swing.JPanel; import javax.swing.SwingConstants; import java.awt.BorderLayout; @@ -16,21 +18,29 @@ import java.awt.Dimension; * Created by XiaXiang on 2017/8/14. */ public class NoResultPane extends JPanel { - public NoResultPane(String title, String iconUrl) { + public NoResultPane(String title, Icon icon) { + this(title, icon, AlphaFineConstants.LEFT_WIDTH); + } + + public NoResultPane(String title, Icon icon, int width) { setLayout(new BorderLayout()); setBackground(Color.white); - setPreferredSize(new Dimension(AlphaFineConstants.LEFT_WIDTH, AlphaFineConstants.CONTENT_HEIGHT)); + setPreferredSize(new Dimension(width, 305)); UILabel image = new UILabel(); image.setPreferredSize(new Dimension(150, 111)); image.setHorizontalAlignment(SwingConstants.CENTER); - image.setIcon(IconLoader.getIcon(iconUrl)); - image.setBorder(BorderFactory.createEmptyBorder(100, 0, 0, 0)); + image.setIcon(icon); + image.setBorder(BorderFactory.createEmptyBorder(30, 0, 0, 0)); + add(image, BorderLayout.CENTER); + add(generateDescription(title), BorderLayout.SOUTH); + } + + protected Component generateDescription(String title) { UILabel description = new UILabel(title); description.setForeground(AlphaFineConstants.MEDIUM_GRAY); description.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); description.setBorder(BorderFactory.createEmptyBorder(0, 0, 135, 0)); description.setHorizontalAlignment(SwingConstants.CENTER); - add(image, BorderLayout.CENTER); - add(description, BorderLayout.SOUTH); + return description; } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultWithLinkPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultWithLinkPane.java new file mode 100644 index 000000000..3dc4a44b2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/NoResultWithLinkPane.java @@ -0,0 +1,63 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.dialog.link.MessageWithLink; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.utils.BrowseUtils; +import com.fr.design.utils.DesignUtils; +import java.awt.Color; +import java.awt.Component; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; + +/** + * 带跳转链接的无结果面板 + * + * @author hades + * @version 11.0 + * Created by hades on 2022/4/12 + */ +public class NoResultWithLinkPane extends NoResultPane { + + private static final String TAG_A_START = ""; + private static final String TAG_A_END = ""; + + public NoResultWithLinkPane(String title, Icon icon) { + super(title, icon); + } + + @Override + protected Component generateDescription(String title) { + String[] para1 = title.split(TAG_A_START); + String[] para2 = para1[1].split(TAG_A_END); + + MessageWithLink messageWithLink = new MessageWithLink(para1[0], para2[0], AlphaFineConstants.ALPHA_GO_TO_FORUM, para2[1], Color.WHITE, DesignUtils.getDefaultGUIFont().applySize(14), AlphaFineConstants.MEDIUM_GRAY) { + @Override + protected void initListener(String link) { + + addHyperlinkListener(new HyperlinkListener() { + @Override + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { + jumpToForum(link); + } + } + }); + } + }; + messageWithLink.setBorder(BorderFactory.createEmptyBorder(0, AlphaFineConstants.LEFT_WIDTH - 30, 135, 0)); + return messageWithLink; + } + + + /** + * 方便记录埋点 + * + * @param link + */ + private void jumpToForum(String link) { + BrowseUtils.browser(link); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/ResultShowPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/ResultShowPane.java new file mode 100644 index 000000000..7e82fc047 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/ResultShowPane.java @@ -0,0 +1,14 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public abstract class ResultShowPane extends JPanel { + + public abstract void showResult(AlphaCellModel selectedValue); +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/SearchLoadingPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/SearchLoadingPane.java new file mode 100644 index 000000000..e694708e8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/SearchLoadingPane.java @@ -0,0 +1,28 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.ImageIcon; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/21 + */ +public class SearchLoadingPane extends JPanel { + + private static final ImageIcon LOADING_ICON = new ImageIcon(SearchLoadingPane.class.getResource("/com/fr/design/mainframe/alphafine/images/opening.gif")); + + public SearchLoadingPane() { + setLayout(new BorderLayout()); + this.add(new UILabel(LOADING_ICON)); + this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); + this.setBackground(Color.WHITE); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/SimpleRightSearchResultPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/SimpleRightSearchResultPane.java new file mode 100644 index 000000000..6d94bd9ed --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/preview/SimpleRightSearchResultPane.java @@ -0,0 +1,32 @@ +package com.fr.design.mainframe.alphafine.preview; + +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.CellType; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/20 + */ +public class SimpleRightSearchResultPane extends ResultShowPane { + + public SimpleRightSearchResultPane(JPanel contentPane) { + this.add(contentPane); + this.setBackground(Color.WHITE); + this.setPreferredSize(new Dimension(AlphaFineConstants.RIGHT_WIDTH - 1, AlphaFineConstants.CONTENT_HEIGHT)); + } + + @Override + public void showResult(AlphaCellModel selectedValue) { + if (selectedValue.getType() == CellType.DOCUMENT) { + this.removeAll(); + this.add(new DocumentPreviewPane((selectedValue).getName(), (selectedValue).getContent())); + validate(); + repaint(); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionPane.java new file mode 100644 index 000000000..2726824b7 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionPane.java @@ -0,0 +1,51 @@ +package com.fr.design.mainframe.alphafine.question; + +import com.fr.base.svg.SVGLoader; +import com.fr.design.mainframe.alphafine.AlphaFineUtil; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import javax.swing.JPanel; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/15 + */ +public class QuestionPane extends JPanel { + + private static final Image NEW_MESSAGE_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/group_new.svg"); + + private static final Image QUESTION_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/group.svg"); + + private static final Image QUESTION_BACKGROUND_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/groupbackgroud.svg"); + + + public QuestionPane() { + this.setBackground(new Color(0, 0, 0, 0)); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + if (AlphaFineUtil.unread()) { + g2.drawImage(NEW_MESSAGE_IMAGE, 0, 0, getWidth(), getHeight(), this); + } else { + g2.drawImage(QUESTION_BACKGROUND_IMAGE, 0, 0, getWidth(), getHeight(), this); + } + g2.drawImage(QUESTION_IMAGE, (getWidth() - QUESTION_IMAGE.getWidth(this)) / 2, (getHeight() - QUESTION_IMAGE.getHeight(this)) / 2, this); + } + + + @Override + public Dimension getPreferredSize() { + return new Dimension(40, 40); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionWindow.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionWindow.java new file mode 100644 index 000000000..dc78c22ab --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/question/QuestionWindow.java @@ -0,0 +1,75 @@ +package com.fr.design.mainframe.alphafine.question; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JWindow; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/15 + */ +public class QuestionWindow extends JWindow { + + private static final QuestionWindow INSTANCE = new QuestionWindow(); + private final QuestionPane questionPane = new QuestionPane(); + private int pressX; + private int pressY; + private QuestionWindow() { + this.setBackground(new Color(0, 0, 0, 0)); + questionPane.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + AlphaFineHelper.showAlphaFineDialog(true); + } + + @Override + public void mousePressed(MouseEvent e) { + pressX = e.getX(); + pressY = e.getY(); + } + }); + questionPane.addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseDragged(MouseEvent e) { + int left = getLocation().x; + int top = getLocation().y; + setLocation(left + e.getX() - pressX, top + e.getY() - pressY); + } + }); + + DesignerContext.getDesignerFrame().addWindowListener(new WindowAdapter() { + + @Override + public void windowActivated(WindowEvent e) { + QuestionWindow.getInstance().setVisible(true); + } + + @Override + public void windowDeactivated(WindowEvent e) { + QuestionWindow.getInstance().setVisible(false); + } + + }); + questionPane.setToolTipText(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Learn_More_About")); + this.setContentPane(questionPane); + this.setSize(new Dimension(40, 40)); + // 这个地方可以设置alwaysOnTop 弹窗会跟随主页面失去激活状态而隐藏 不会与其他弹窗冲突 + this.setAlwaysOnTop(true); + this.setLocation(DesignerContext.getDesignerFrame().getWidth() - 100, + DesignerContext.getDesignerFrame().getHeight() - 100); + } + + public static QuestionWindow getInstance() { + return INSTANCE; + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/ProductNewsSearchWorkerManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/ProductNewsSearchWorkerManager.java new file mode 100644 index 000000000..0c230844b --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/ProductNewsSearchWorkerManager.java @@ -0,0 +1,126 @@ +package com.fr.design.mainframe.alphafine.search; + +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.CellType; +import com.fr.design.mainframe.alphafine.component.AlphaFineFrame; +import com.fr.design.mainframe.alphafine.component.ProductNewsSearchResultPane; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import com.fr.log.FineLoggerFactory; +import java.util.List; +import java.util.function.Function; +import javax.swing.DefaultListModel; +import javax.swing.SwingWorker; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/22 + */ +public class ProductNewsSearchWorkerManager implements SearchManager { + + private final CellType cellType; + + private SwingWorker, Void> searchWorker; + + private Function> searchFunction; + + private ProductNewsSearchResultPane searchResultPane; + + private AlphaFineFrame alphaFineFrame; + + private volatile boolean hasSearchResult = true; + + private volatile boolean searchOver = false; + + private volatile boolean networkError = false; + + public ProductNewsSearchWorkerManager(CellType cellType, Function> searchFunction, AlphaFineFrame alphaFineFrame) { + this.cellType = cellType; + this.searchFunction = searchFunction; + this.alphaFineFrame = alphaFineFrame; + } + + + + @Override + public void doSearch(SearchTextBean searchTextBean) { + checkSearchWork(); + searchOver = false; + networkError = false; + if (searchResultPane == null) { + searchResultPane = new ProductNewsSearchResultPane(searchTextBean.getSegmentation()); + alphaFineFrame.addResult(searchResultPane, cellType.getFlagStr4Result()); + } + + this.searchWorker = new SwingWorker, Void>() { + @Override + protected DefaultListModel doInBackground() throws Exception { + DefaultListModel productNewsDefaultListModel = new DefaultListModel<>(); + if (!AlphaFineHelper.isNetworkOk() && cellType.isNeedNetWork()) { + networkError = true; + FineLoggerFactory.getLogger().warn("alphaFine network error"); + return productNewsDefaultListModel; + } + List productNewsList = searchFunction.apply(searchTextBean); + for (ProductNews productNews : productNewsList) { + productNewsDefaultListModel.addElement(productNews); + } + return productNewsDefaultListModel; + } + + @Override + protected void done() { + searchOver = true; + if (!isCancelled()) { + try { + if (networkError) { + alphaFineFrame.showResult(AlphaFineConstants.NETWORK_ERROR); + return; + } + DefaultListModel productNewsDefaultListModel = get(); + hasSearchResult = !productNewsDefaultListModel.isEmpty(); + searchResultPane.getProductNewsList().setModel(get()); + if (alphaFineFrame.getSelectedType() == cellType) { + if (!hasSearchResult) { + alphaFineFrame.showResult(CellType.NO_RESULT.getFlagStr4None()); + return; + } + alphaFineFrame.showResult(cellType.getFlagStr4Result()); + searchResultPane.getProductNewsList().setSelectedIndex(0); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + }; + this.searchWorker.execute(); + } + + public ProductNewsSearchResultPane getSearchResultPane() { + return searchResultPane; + } + + @Override + public boolean hasSearchResult() { + return hasSearchResult; + } + + @Override + public boolean isSearchOver() { + return searchOver; + } + + private void checkSearchWork() { + if (this.searchWorker != null && !this.searchWorker.isDone()) { + this.searchWorker.cancel(true); + this.searchWorker = null; + } + } + + @Override + public boolean isNetWorkError() { + return networkError; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchManager.java new file mode 100644 index 000000000..f9f789395 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchManager.java @@ -0,0 +1,17 @@ +package com.fr.design.mainframe.alphafine.search; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/17 + */ +public interface SearchManager { + + void doSearch(SearchTextBean searchTextBean); + + boolean hasSearchResult(); + + boolean isSearchOver(); + + boolean isNetWorkError(); +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchTextBean.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchTextBean.java new file mode 100644 index 000000000..f7148363c --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchTextBean.java @@ -0,0 +1,37 @@ +package com.fr.design.mainframe.alphafine.search; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/17 + */ +public class SearchTextBean { + + private String searchText; + + /** + * 分词搜索 + */ + private String[] segmentation; + + public SearchTextBean(String searchText, String[] segmentation) { + this.searchText = searchText; + this.segmentation = segmentation; + } + + public String getSearchText() { + return searchText; + } + + public void setSearchText(String searchText) { + this.searchText = searchText; + } + + public String[] getSegmentation() { + return segmentation; + } + + public void setSegmentation(String[] segmentation) { + this.segmentation = segmentation; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchWorkerManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchWorkerManager.java new file mode 100644 index 000000000..7aa86b84a --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/SearchWorkerManager.java @@ -0,0 +1,145 @@ +package com.fr.design.mainframe.alphafine.search; + +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.CellType; +import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; +import com.fr.design.mainframe.alphafine.component.AlphaFineFrame; +import com.fr.design.mainframe.alphafine.component.AlphaFineList; +import com.fr.design.mainframe.alphafine.component.SearchListModel; +import com.fr.design.mainframe.alphafine.component.SearchResultPane; +import com.fr.design.mainframe.alphafine.model.SearchResult; +import com.fr.design.mainframe.alphafine.preview.ResultShowPane; +import com.fr.log.FineLoggerFactory; +import java.util.function.Function; +import javax.swing.SwingWorker; +import org.jetbrains.annotations.Nullable; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/16 + */ +public class SearchWorkerManager implements SearchManager { + + private final CellType cellType; + + private SwingWorker searchWorker; + + private Function searchResultFunction; + + private SearchResultPane searchResultPane; + + private AlphaFineFrame alphaFineFrame; + + private ResultShowPane resultShowPane; + + private volatile boolean hasSearchResult = true; + + private volatile boolean searchOver = false; + + private volatile boolean networkError = false; + + public SearchWorkerManager(CellType cellType, Function function, AlphaFineFrame alphaFineFrame, ResultShowPane resultShowPane) { + this.cellType = cellType; + this.searchResultFunction = function; + this.alphaFineFrame = alphaFineFrame; + this.resultShowPane = resultShowPane; + } + + private void initSearchResult(SearchTextBean searchTextBean) { + if (searchResultPane == null) { + searchResultPane = new SearchResultPane(searchTextBean.getSegmentation(), resultShowPane); + alphaFineFrame.addResult(searchResultPane, cellType.getFlagStr4Result()); + } + + } + + private void checkSearchWork() { + if (this.searchWorker != null && !this.searchWorker.isDone()) { + this.searchWorker.cancel(true); + this.searchWorker = null; + } + } + + private void initSearchWorker(SearchTextBean searchTextBean) { + this.searchOver = false; + this.networkError = false; + this.searchWorker = new SwingWorker() { + @Override + protected SearchListModel doInBackground() throws Exception { + SearchListModel searchListModel = new SearchListModel(new SearchResult(), searchResultPane.getSearchResultList(), searchResultPane.getLeftSearchResultPane()); + if (!AlphaFineHelper.isNetworkOk() && cellType.isNeedNetWork()) { + networkError = true; + FineLoggerFactory.getLogger().warn("alphaFine network error"); + return searchListModel; + } + SearchResult searchResult = searchResultFunction.apply(searchTextBean); + for (AlphaCellModel object : searchResult) { + AlphaFineHelper.checkCancel(); + searchListModel.addElement(object); + } + return searchListModel; + } + + @Override + protected void done() { + searchOver = true; + if (!isCancelled()) { + try { + if (networkError) { + alphaFineFrame.showResult(AlphaFineConstants.NETWORK_ERROR); + return; + } + SearchListModel searchListModel = get(); + hasSearchResult = !searchListModel.isEmpty(); + searchResultPane.getSearchResultList().setModel(get()); + if (alphaFineFrame.getSelectedType() == cellType) { + if (!hasSearchResult) { + alphaFineFrame.showResult(CellType.NO_RESULT.getFlagStr4None()); + return; + } + alphaFineFrame.showResult(cellType.getFlagStr4Result()); + searchResultPane.getSearchResultList().setSelectedIndex(0); + searchResultPane.getSearchResultList().requestFocus(); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + }; + } + + @Override + public void doSearch(SearchTextBean searchTextBean) { + initSearchResult(searchTextBean); + checkSearchWork(); + initSearchWorker(searchTextBean); + this.searchWorker.execute(); + } + + @Override + public boolean hasSearchResult() { + return hasSearchResult; + } + + @Override + public boolean isSearchOver() { + return searchOver; + } + + @Override + public boolean isNetWorkError() { + return networkError; + } + + @Nullable + public AlphaFineList getSearchResultList() { + if (searchResultPane != null) { + return searchResultPane.getSearchResultList(); + } + return null; + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java new file mode 100644 index 000000000..205735ab3 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/search/manager/impl/ProductNewsSearchManager.java @@ -0,0 +1,124 @@ +package com.fr.design.mainframe.alphafine.search.manager.impl; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.design.mainframe.alphafine.AlphaFineConstants; +import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.model.ProductNews; +import com.fr.general.http.HttpToolbox; +import com.fr.json.JSON; +import com.fr.json.JSONArray; +import com.fr.json.JSONFactory; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import org.jetbrains.annotations.Nullable; + +import java.awt.Image; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.imageio.ImageIO; + +public class ProductNewsSearchManager { + + private static final ProductNewsSearchManager INSTANCE = new ProductNewsSearchManager(); + private static final int TIME_GAP = 12; + private List productNewsResultList; + + private List productNewsList = new ArrayList<>(); + + /** + * 单独记录一份cid的唯一id 用来判断是否已读 + */ + private Set idSet = new HashSet<>(); + + + private ScheduledExecutorService service; + + private ProductNewsSearchManager() { + service = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("ProductNewsSearchManager", true)); + service.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + getProductNewsList(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + }, TIME_GAP, TIME_GAP, TimeUnit.HOURS); + } + + public static ProductNewsSearchManager getInstance() { + return INSTANCE; + } + + public List getSearchResult(String[] searchText) { + productNewsResultList = new ArrayList<>(); + try { + List productNewsList = getProductNewsList(); + for (ProductNews productNews : productNewsList) { + for (String str : searchText) { + if (productNews.getTitle().contains(str)) { + productNewsResultList.add(productNews); + break; + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return productNewsResultList; + } + + + public List getProductNewsList() throws Exception { + productNewsList = new ArrayList<>(); + idSet = new HashSet<>(); + String jsonStr = HttpToolbox.get(AlphaFineConstants.ALPHA_CID); + AlphaFineHelper.checkCancel(); + JSONObject cidJSON = JSONFactory.createJSON(JSON.OBJECT, jsonStr); + JSONArray jsonArray = cidJSON.getJSONArray("data"); + for (int i = 0, size = jsonArray.size(); i < size; i++) { + JSONObject obj = jsonArray.getJSONObject(i); + ProductNews productNews = new ProductNews(). + setId(obj.getLong("id")).setTitle(obj.getString("title")). + setImage(getCoverImage(obj.getString("pic"))). + setUrl(obj.getString("url")).setTag(ProductNews.Tag.parseCode(obj.getInt("tag"))). + setStatus(ProductNews.Status.parseCode(obj.getInt("status"))).setTarget( + ProductNews.Target.parseCode(obj.getInt("target"))). + setCreator(obj.getInt("creator")).setPushDate(new Date(obj.getLong("push_time"))); + Date currentDate = new Date(System.currentTimeMillis()); + // 推送时间check + if (productNews.getPushDate().before(currentDate)) { + productNewsList.add(productNews); + idSet.add(productNews.getId()); + } + } + return productNewsList; + } + + public List getCachedProductNewsList() { + return productNewsList; + } + + public Set getIdSet() { + return idSet; + } + + @Nullable + private Image getCoverImage(String url) { + try { + return ImageIO.read(new URL(url)); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn("get image failed from {}", url); + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + } + return null; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java index efab3fc66..eeaf8f920 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java @@ -12,8 +12,10 @@ import com.fr.design.gui.ibutton.UIRadioButton; 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.ispinner.UISpinner; 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.design.layout.VerticalFlowLayout; @@ -58,6 +60,8 @@ public class CellOtherSetPane extends AbstractCellAttrPane { private static final int HEAD_HEIGTH = 24; private static final int COMBO_WIDTH = 154; private static final int BUTTON_GROUP_WIDTH = 140; + private static final double f = TableLayout.FILL; + private static final double p = TableLayout.PREFERRED; // normal private UIButtonGroup autoshrik; @@ -67,8 +71,20 @@ public class CellOtherSetPane extends AbstractCellAttrPane { private UIComboBox showContent; + //内容提示 + private UIButtonGroup tooltipButtonGroup; + private CardLayout tooltipLayout; + private JPanel tooltipPane; private UITextField tooltipTextField; + //文本超出时隐藏 + private UICheckBox textOverflowCheckBox; + private UIComboBox showPartComboBox; + private CardLayout showPartLayout; + private JPanel showPartPane; + private UISpinner showCharNums; + private UIComboBox textOverflowTypeComboBox; + private UITextField fileNameTextField; // 分页 @@ -214,17 +230,16 @@ public class CellOtherSetPane extends AbstractCellAttrPane { private JPanel seniorUpPane() { JPanel pane = new JPanel(new BorderLayout()); // TODO: 方法之间的耦合还比较严重。现在必须先执行 createShowContentPane,再执行 createSeniorCheckPane。否则出现 npe。 + pane.add(createTextOverflowPane(), BorderLayout.SOUTH); pane.add(createShowContentPane(), BorderLayout.CENTER); pane.add(createSeniorCheckPane(), BorderLayout.NORTH); return pane; } private JPanel createShowContentPane() { - double f = TableLayout.FILL; - double p = TableLayout.PREFERRED; - double[] rowSize = {p, p, p}; + double[] rowSize = {p, p, p, p}; double[] colSize = {f, COMBO_WIDTH}; - int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}}; JPanel fileNamePane = createNormal(); fileNamePane.setBorder(BorderFactory.createEmptyBorder(0,12,0,0)); @@ -233,21 +248,96 @@ public class CellOtherSetPane extends AbstractCellAttrPane { UIComponentUtils.setLineWrap(showContentLabel); UILabel toolTipLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip")); - JPanel toolTipTextFieldWrapper = new JPanel(new BorderLayout()); - toolTipTextFieldWrapper.add(tooltipTextField, BorderLayout.NORTH); + tooltipLayout = new CardLayout(); + tooltipPane = new JPanel(tooltipLayout); + tooltipPane.add(new JPanel(), "none"); + tooltipPane.add(tooltipTextField, "content"); + tooltipPane.setPreferredSize(new Dimension(0, 0)); + tooltipButtonGroup = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_Custom"), Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_CellValue")}); + tooltipButtonGroup.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (tooltipButtonGroup.getSelectedIndex() == 0) { + tooltipPane.setPreferredSize(new Dimension(154, 20)); + tooltipLayout.show(tooltipPane, "content"); + } else { + tooltipLayout.show(tooltipPane, "none"); + tooltipPane.setPreferredSize(new Dimension(0, 0)); + } + } + }); Component[][] components = new Component[][]{ new Component[]{showContentLabel, UIComponentUtils.wrapWithBorderLayoutPane(showContent)}, new Component[]{fileNamePane, null}, // 选择"用下载连接显示二进制内容"时,会显示这一行的面板 - new Component[]{toolTipLabel, toolTipTextFieldWrapper} + new Component[]{toolTipLabel, tooltipButtonGroup}, // “自定义”or"单元格值" + new Component[]{null, tooltipPane} // 选择“自定义”时显示这一行 }; JPanel showContentPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, colSize, rowCount, LayoutConstants.VGAP_LARGE, LayoutConstants.VGAP_MEDIUM); - showContentPane.setBorder(BorderFactory.createEmptyBorder(6, 0, 12, 0)); + showContentPane.setBorder(BorderFactory.createEmptyBorder(6, 0, 6, 0)); return showContentPane; } + private JPanel createTextOverflowPane() { + showPartLayout = new CardLayout(); + showPartPane = new JPanel(showPartLayout); + showCharNums = new UISpinner(0, Integer.MAX_VALUE, 1, 10); + JPanel showPartNumPane = new JPanel(new BorderLayout(4, 0)); + showPartNumPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Nums")), BorderLayout.WEST); + showPartNumPane.add(showCharNums, BorderLayout.CENTER); + showPartPane.add(new JPanel(), "none"); + showPartPane.add(showPartNumPane, "content"); + showPartComboBox = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_CharNum"), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_CellWidth")}); + showPartComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (showPartComboBox.getSelectedIndex() == 0) { + showPartPane.setPreferredSize(new Dimension(70, 20)); + showPartLayout.show(showPartPane, "content"); + } else { + showPartLayout.show(showPartPane, "none"); + showPartPane.setPreferredSize(new Dimension(0, 0)); + } + } + }); + + textOverflowTypeComboBox = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Ellipsis"), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_NoneSymbol")}); + UILabel showPartLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_ShowPart") + ":"); + UILabel hideTypeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideType") + ":"); + Component[][] textOverflowComponents = new Component[][]{ + new Component[]{showPartLabel, showPartComboBox, showPartPane}, + new Component[]{hideTypeLabel, textOverflowTypeComboBox, null} + }; + JPanel textOverflowComPane = TableLayoutHelper.createTableLayoutPane(textOverflowComponents, new double[]{p, p}, new double[]{p, f, p}); + textOverflowComPane.setVisible(false); + textOverflowCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideWhenOverflow")); + textOverflowCheckBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + textOverflowComPane.setVisible(e.getStateChange() == ItemEvent.SELECTED); + if (e.getStateChange() == ItemEvent.SELECTED) { + if (showPartComboBox.getSelectedIndex() == 0) { + showPartPane.setPreferredSize(new Dimension(70, 20)); + showPartLayout.show(showPartPane, "content"); + } else { + showPartLayout.show(showPartPane, "none"); + showPartPane.setPreferredSize(new Dimension(0, 0)); + } + noAutoRadioButton.setSelected(true); + } + } + }); + JPanel dynamicPaneWrapper = FRGUIPaneFactory.createBorderLayout_S_Pane(); + dynamicPaneWrapper.add(textOverflowComPane); + JPanel textOverflowPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + textOverflowPane.add(textOverflowCheckBox, BorderLayout.NORTH); + textOverflowPane.add(dynamicPaneWrapper, BorderLayout.CENTER); + textOverflowPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); + return textOverflowPane; + } + private JPanel createSeniorCheckPane() { previewCellContent.setBorder(UIConstants.CELL_ATTR_ZEROBORDER); printAndExportContent.setBorder(UIConstants.CELL_ATTR_ZEROBORDER); @@ -371,6 +461,11 @@ public class CellOtherSetPane extends AbstractCellAttrPane { insertRowPolicyButtonGroup.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_InsertRow_Policy")); valueEditor.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_InsertRow_Policy")); pageFixedRowDataCheckBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_Page_Fixed_Row_Cell")); + tooltipButtonGroup.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_Button_Group")); + textOverflowCheckBox.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideWhenOverflow")); + showPartComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_ShowPart")); + showCharNums.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Nums")); + textOverflowTypeComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideType")); } @@ -429,7 +524,40 @@ public class CellOtherSetPane extends AbstractCellAttrPane { } else { showContent.setSelectedItem(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Default")); } - tooltipTextField.setText(cellGUIAttr.getTooltipText()); + if (cellGUIAttr.isCustomTooltip()) { + tooltipButtonGroup.setSelectedIndex(0); + tooltipTextField.setText(cellGUIAttr.getTooltipText()); + } else { + tooltipButtonGroup.setSelectedIndex(1); + } + if (tooltipButtonGroup.getSelectedIndex() == 0) { + tooltipPane.setPreferredSize(new Dimension(100, 20)); + tooltipLayout.show(tooltipPane, "content"); + } else { + tooltipLayout.show(tooltipPane, "none"); + tooltipPane.setPreferredSize(new Dimension(0, 0)); + } + tooltipPane.setVisible(true); + if (cellGUIAttr.isHideTextWhenOverflow()) { + textOverflowCheckBox.setSelected(true); + if (cellGUIAttr.isShowCharNum()) { + showPartComboBox.setSelectedIndex(0); + showCharNums.setValue(cellGUIAttr.getShowCharNums()); + } else { + showPartComboBox.setSelectedIndex(1); + } + showPartPane.setVisible(true); + if (cellGUIAttr.isTextOverflowEllipsis()) { + textOverflowTypeComboBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Ellipsis")); + } else { + textOverflowTypeComboBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_NoneSymbol")); + } + } else { + showPartComboBox.setSelectedIndex(cellGUIAttr.isShowCharNum() ? 0 : 1); + showCharNums.setValue(cellGUIAttr.getShowCharNums()); + textOverflowTypeComboBox.setSelectedIndex(cellGUIAttr.isTextOverflowEllipsis() ? 0 : 1); + textOverflowCheckBox.setSelected(false); + } CellPageAttr cellPageAttr = cellElement.getCellPageAttr(); // 分页 if (cellPageAttr == null) { cellPageAttr = new CellPageAttr(); @@ -521,7 +649,18 @@ public class CellOtherSetPane extends AbstractCellAttrPane { cellGUIAttr.setFileName(fileNameTextField.getText()); } } - + if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_Button_Group"))) { + cellGUIAttr.setCustomTooltip(tooltipButtonGroup.getSelectedIndex() == 0); + if (tooltipButtonGroup.getSelectedIndex() == 0) { + if (tooltipTextField.getText() == null || tooltipTextField.getText().trim().length() <= 0) { + cellGUIAttr.setTooltipText(fieldName); + } else { + cellGUIAttr.setTooltipText(tooltipTextField.getText()); + } + } else if (tooltipButtonGroup.getSelectedIndex() == 1) { + cellGUIAttr.setTooltipText("=$$$"); + } + } if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip"))) { if (tooltipTextField.getText() == null || tooltipTextField.getText().trim().length() <= 0) { cellGUIAttr.setTooltipText(fieldName); @@ -529,6 +668,18 @@ public class CellOtherSetPane extends AbstractCellAttrPane { cellGUIAttr.setTooltipText(tooltipTextField.getText()); } } + if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideWhenOverflow"))) { + cellGUIAttr.setHideTextWhenOverflow(textOverflowCheckBox.isSelected()); + } + if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_ShowPart"))) { + cellGUIAttr.setShowCharNum(showPartComboBox.getSelectedIndex() == 0); + } + if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Nums"))) { + cellGUIAttr.setShowCharNums((int) showCharNums.getValue()); + } + if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideType"))) { + cellGUIAttr.setTextOverflowEllipsis(textOverflowTypeComboBox.getSelectedIndex() == 0); + } // 如果与默认的CellGUIAttr相同,就不用保存这个属性了 if (ComparatorUtils.equals(cellGUIAttr, CellGUIAttr.DEFAULT_CELLGUIATTR)) { cellElement.setCellGUIAttr(cellNullGUIAttr); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java index 3bdd034c6..8e57415a7 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java @@ -118,7 +118,7 @@ public class CellStylePane extends AbstractCellAttrPane { elementCase.addCellElement(cellElement); } Format format = cellElement.getStyle().getFormat(); - Style style = stylePane.updateBean(); + Style style = stylePane.mergeBean(cellElement.getStyle()); // 格式不能通过样式面板中的配置项修改,因此需要保留 style = style.deriveFormat(format); cellElement.setStyle(style); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java index 7f382ed44..9c9523e13 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java @@ -251,6 +251,14 @@ public class StylePane extends BasicPane implements UIObserver { followingThemePane.setVisible(AdjustWorkBookDefaultStyleUtils.supportTheme()); } + public Style mergeBean(Style style) { + if (isFollowingTheme()) { + return updateBean(); + } else { + return customStylePane.updateStyle(style); + } + } + private void fireStateChanged() { for (UIObserverListener listener: observerListeners) { listener.doChange(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java index 481ab540b..71d34ff44 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java @@ -30,6 +30,7 @@ import com.fr.design.selection.SelectableElement; import com.fr.design.selection.Selectedable; import com.fr.design.selection.SelectionListener; import com.fr.form.FormElementCaseProvider; +import com.fr.form.fit.common.LightTool; import com.fr.form.main.Form; import com.fr.grid.Grid; import com.fr.grid.selection.CellSelection; @@ -69,8 +70,12 @@ public class FormElementCaseDesigner } public FormElementCaseDesigner(T sheet, Form form) { + this(sheet, form.getFormMobileAttr().isMobileOnly(), LightTool.containNewFormFlag(form)); + } + + public FormElementCaseDesigner(T sheet, boolean isMobileOnly, boolean isNewForm) { super(sheet); - elementCasePane = initElementCasePane(sheet, form); + elementCasePane = initElementCasePane(sheet, isMobileOnly, isNewForm); this.setLayout(FRGUIPaneFactory.createBorderLayout()); elementCasePane.setSelection(getDefaultSelectElement()); this.add(elementCasePane, BorderLayout.CENTER); @@ -84,8 +89,8 @@ public class FormElementCaseDesigner } - protected FormElementCasePaneDelegate initElementCasePane(T sheet, Form form){ - return new FormElementCasePaneDelegate((FormElementCase) sheet, form); + protected FormElementCasePaneDelegate initElementCasePane(T sheet, boolean isMobileOnly, boolean isNewForm){ + return new FormElementCasePaneDelegate((FormElementCase) sheet, isMobileOnly, isNewForm); } @Override diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java index 5961700e2..cd46f9de1 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java @@ -9,6 +9,7 @@ import com.fr.design.actions.form.FormECFrozenAction; import com.fr.design.designer.creator.XElementCase; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fit.NewUIModeCellElementPainter; import com.fr.design.fit.common.FormDesignerUtil; import com.fr.design.gui.frpane.HyperlinkGroupPane; @@ -40,13 +41,16 @@ import java.awt.Rectangle; */ public class FormElementCasePaneDelegate extends ElementCasePane{ - public FormElementCasePaneDelegate(FormElementCase sheet, Form form) { + this(sheet, form.getFormMobileAttr().isMobileOnly(), LightTool.containNewFormFlag(form)); + } + + public FormElementCasePaneDelegate(FormElementCase sheet, boolean isMobileOnly, boolean isNewForm) { super(sheet); - this.getGrid().setPaginateLineShowType(form.getFormMobileAttr().isMobileOnly() + this.getGrid().setPaginateLineShowType(isMobileOnly ? Grid.SINGLE_HORIZONTAL_PAGINATE_LINE : Grid.NO_PAGINATE_LINE); - if (LightTool.containNewFormFlag(form)){ + if (isNewForm){ this.getGrid().setCellElementPainter(new NewUIModeCellElementPainter()); } this.addSelectionChangeListener(new SelectionListener() { @@ -68,8 +72,17 @@ public class FormElementCasePaneDelegate extends ElementCasePane template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (!(template instanceof JForm)) { + return rectangle; + } + + FormDesigner designer = ((JForm) template).getFormDesign(); + if (designer == null) { + return rectangle; + } + XElementCase xElementCase = FormDesignerUtil.getXelementCase(designer.getRootComponent(), (FormElementCase) elementCase); if (xElementCase != null) { rectangle.setBounds(xElementCase.getBounds()); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormReportComponentComposite.java b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormReportComponentComposite.java index 05c3b13ec..5fdc4b011 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormReportComponentComposite.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormReportComponentComposite.java @@ -2,7 +2,6 @@ package com.fr.design.mainframe.form; import com.fr.base.DynamicUnitList; import com.fr.base.ScreenResolution; -import com.fr.common.inputevent.InputEventBaseOnOS; import com.fr.design.cell.bar.DynamicScrollBar; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; @@ -11,9 +10,11 @@ import com.fr.design.mainframe.BaseJForm; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerUIModeConfig; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.JDashboard; +import com.fr.design.mainframe.JForm; import com.fr.design.mainframe.JFormSliderPane; -import com.fr.design.mainframe.ReportComponent; -import com.fr.design.mainframe.ReportComponentCompositeMouseWheelHandler; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.JTemplateProvider; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.form.FormElementCaseContainerProvider; import com.fr.form.FormElementCaseProvider; @@ -24,11 +25,11 @@ import com.fr.report.worksheet.FormElementCase; import com.fr.stable.AssistUtils; import com.fr.stable.Constants; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.*; -import java.awt.event.*; +import java.awt.BorderLayout; /** * 整个FormElementCase编辑区域 包括滚动条、中间的grid或者聚合块、下面的sheetTab @@ -40,19 +41,19 @@ public class FormReportComponentComposite extends JComponent implements TargetMo private static final int MIN = 10; private static final int DIR = 10; private static final double MIN_TIME = 0.4; - public FormElementCaseDesigner elementCaseDesigner; - private BaseJForm jForm; + public final FormElementCaseDesigner elementCaseDesigner; + private final JTemplateProvider jTemplate; - private FormTabPane sheetNameTab; + private final FormTabPane sheetNameTab; private JPanel hbarContainer; private JFormSliderPane jSliderContainer; - public FormReportComponentComposite(BaseJForm jform, FormElementCaseDesigner elementCaseDesign, FormElementCaseContainerProvider ecContainer) { - this.jForm = jform; + public FormReportComponentComposite(JTemplateProvider jTemplate, JDashboard jDashboard, FormElementCaseDesigner elementCaseDesign, String ecContainerName) { + this.jTemplate = jTemplate; this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.elementCaseDesigner = elementCaseDesign; this.add(elementCaseDesigner, BorderLayout.CENTER); - sheetNameTab = new FormTabPane(ecContainer, jform); + sheetNameTab = new FormTabPane(ecContainerName, jDashboard); this.add(createSouthControlPane(), BorderLayout.SOUTH); jSliderContainer.addValueChangeListener(showValSpinnerChangeListener); this.elementCaseDesigner.elementCasePane.getGrid().addMouseWheelListener(new FormReportComponentCompositeMouseWheelHandler(this)); @@ -60,6 +61,10 @@ public class FormReportComponentComposite extends JComponent implements TargetMo this.jSliderContainer.setShowValue((ScreenResolution.getScreenResolution() * HUND) / Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION); } + public FormReportComponentComposite(BaseJForm jform, FormElementCaseDesigner elementCaseDesign, FormElementCaseContainerProvider ecContainer) { + this(jform, jform, elementCaseDesign, ecContainer.getElementCaseContainerName()); + } + ChangeListener showValSpinnerChangeListener = new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { @@ -167,7 +172,7 @@ public class FormReportComponentComposite extends JComponent implements TargetMo } public void setComposite() { - DesignerContext.getDesignerFrame().resetToolkitByPlus((ToolBarMenuDockPlus) jForm); + DesignerContext.getDesignerFrame().resetToolkitByPlus((ToolBarMenuDockPlus) jTemplate); this.validate(); this.repaint(40); } @@ -182,7 +187,7 @@ public class FormReportComponentComposite extends JComponent implements TargetMo * 模板更新 */ public void fireTargetModified() { - jForm.fireTargetModified(); + jTemplate.fireTargetModified(); } public JFormSliderPane getSliderContainer() { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormTabPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormTabPane.java index f158b3936..dca702904 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormTabPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormTabPane.java @@ -5,6 +5,7 @@ import com.fr.base.GraphHelper; import com.fr.design.constants.UIConstants; import com.fr.design.mainframe.BaseJForm; +import com.fr.design.mainframe.JDashboard; import com.fr.form.FormElementCaseContainerProvider; @@ -27,8 +28,8 @@ public class FormTabPane extends JComponent implements MouseListener, MouseMotio private static final int GAP = 5; //间隔 - private BaseJForm form; - private FormElementCaseContainerProvider elementCase; + private JDashboard jDashboard; + private final String elementCaseContainerName; //选了30度和60度的特殊角度的x,y作为经过的两个点的坐标 private double specialLocation1 = 2.5; @@ -48,8 +49,12 @@ public class FormTabPane extends JComponent implements MouseListener, MouseMotio private int selectedIndex = -1; public FormTabPane(FormElementCaseContainerProvider elementCase, BaseJForm form){ - this.elementCase = elementCase; - this.form = form; + this(elementCase.getElementCaseContainerName(), form); + } + + public FormTabPane(String elementCaseContainerName, JDashboard jDashboard){ + this.elementCaseContainerName = elementCaseContainerName; + this.jDashboard = jDashboard; this.setLayout(new BorderLayout(0, 0)); this.addMouseListener(this); this.addMouseMotionListener(this); @@ -57,12 +62,16 @@ public class FormTabPane extends JComponent implements MouseListener, MouseMotio this.setForeground(new Color(99, 99, 99)); } + public String getElementCaseContainerName() { + return elementCaseContainerName; + } + public void paintComponent(Graphics g){ super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; calculateECWidth(); paintFormTab(g2d, 0, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Form"), POLY_SHEET_ICON); - paintECTab(g2d, formTabWidth, elementCase.getElementCaseContainerName(), WORK_SHEET_ICON); + paintECTab(g2d, formTabWidth, getElementCaseContainerName(), WORK_SHEET_ICON); } /** @@ -165,7 +174,7 @@ public class FormTabPane extends JComponent implements MouseListener, MouseMotio private void calculateECWidth() { FontMetrics fm = GraphHelper.getFontMetrics(this.getFont()); int charWidth = fm.charWidth('M'); - String ECName = elementCase.getElementCaseContainerName(); + String ECName = getElementCaseContainerName(); ecTabWidth = Math.max(ecTabWidth,fm.stringWidth(ECName) + charWidth * 2 + ADD_WIDTH_BY_SHEETNAME) ; } @@ -177,7 +186,7 @@ public class FormTabPane extends JComponent implements MouseListener, MouseMotio public void mouseClicked(MouseEvent e) { selectedIndex = getTabIndex(e.getX()); if (selectedIndex == FORM_INDEX) { - form.tabChanged(FORM_INDEX); + jDashboard.switchToDashBoardEditor(); } repaint(); } diff --git a/designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java b/designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java new file mode 100644 index 000000000..d32c006a6 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java @@ -0,0 +1,242 @@ +package com.fr.design.report; + +import com.fr.base.extension.FileExtension; +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.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.io.attr.ImageExportAttr; +import com.fr.io.attr.ReportExportAttr; +import com.fr.report.ReportConfigManager; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.BorderLayout; + +/** + * 导出图片配置 + * + * @author vito + * @date 2015/7/6 0006 + */ +public class ImageExportPane extends AbstractExportPane { + + private UIRadioButton globalResolutionBtnS; + private UIRadioButton globalResolutionBtnM; + private UIRadioButton globalResolutionBtnL; + + private UIRadioButton globalRenderSpeed; + private UIRadioButton globalRenderQuality; + + private UIRadioButton globalFormatJpg; + private UIRadioButton globalFormatPng; + + private UIRadioButton previewResolutionBtnS; + private UIRadioButton previewResolutionBtnM; + + private UIRadioButton previewRenderSpeed; + private UIRadioButton previewRenderQuality; + + private static final int RESOLUTION_S = 96; + private static final int RESOLUTION_M = 192; + private static final int RESOLUTION_L = 300; + + private static final int DPI_SCALE_S = 1; + private static final int DPI_SCALE_M = 2; + + private static final int GAP = 20; + + public static final String GLOBAL_CONF = Toolkit.i18nText("Fine-Design_Image_Export_Global_Configuration"); + + + private ReportExportAttr reportExportAttr; + + public ImageExportPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + JPanel globalTitlePane = FRGUIPaneFactory.createTitledBorderPane(GLOBAL_CONF); + JPanel previewSetting = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Preview")); + this.add(globalTitlePane, BorderLayout.NORTH); + this.add(previewSetting, BorderLayout.CENTER); + initGlobalSettings(); + + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JComponent[][] comps = { + {new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Resolution") + ":"), this.globalResolutionBtnS, this.globalResolutionBtnM, this.globalResolutionBtnL}, + {new UILabel(Toolkit.i18nText("Fine-Design_Report_Format") + ":"), this.globalFormatJpg, null, this.globalFormatPng}, + {new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Rendering_Quality") + ":"), this.globalRenderQuality, null, this.globalRenderSpeed}, + }; + centerPane.add( + TableLayoutHelper.createCommonTableLayoutPane( + comps, + new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, + new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, + GAP), + BorderLayout.CENTER); + globalTitlePane.add(centerPane, BorderLayout.CENTER); + JPanel templateCenterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JComponent[][] templateComps = { + {new UILabel(Toolkit.i18nText("Fine-Design_Report_Engine_Enlarge_Or_Reduce") + ":"), this.previewResolutionBtnS, this.previewResolutionBtnM}, + {new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Rendering_Quality") + ":"), this.previewRenderQuality, this.previewRenderSpeed}, + }; + templateCenterPane.add( + TableLayoutHelper.createCommonTableLayoutPane( + templateComps, + new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, + new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, + GAP), + BorderLayout.CENTER); + + previewSetting.add(templateCenterPane, BorderLayout.CENTER); + + + } + + + private void initGlobalSettings() { + globalResolutionBtnS = new UIRadioButton("96dpi", true); + globalResolutionBtnM = new UIRadioButton("192dpi"); + globalResolutionBtnL = new UIRadioButton("300dpi"); + ButtonGroup globalResolutionBtnGroup = new ButtonGroup(); + globalResolutionBtnGroup.add(globalResolutionBtnS); + globalResolutionBtnGroup.add(globalResolutionBtnM); + globalResolutionBtnGroup.add(globalResolutionBtnL); + + globalFormatJpg = new UIRadioButton("jpg", true); + globalFormatPng = new UIRadioButton("png"); + ButtonGroup globalFormatGroup = new ButtonGroup(); + globalFormatGroup.add(globalFormatJpg); + globalFormatGroup.add(globalFormatPng); + + globalRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First"), true); + globalRenderSpeed = new UIRadioButton(Toolkit.i18nText(("Fine-Design_Image_Export_Speed_Priority"))); + ButtonGroup globalRenderGroup = new ButtonGroup(); + globalRenderGroup.add(globalRenderQuality); + globalRenderGroup.add(globalRenderSpeed); + + previewResolutionBtnS = new UIRadioButton("100%", true); + previewResolutionBtnM = new UIRadioButton("200%"); + ButtonGroup previewResolutionBtnGroup = new ButtonGroup(); + previewResolutionBtnGroup.add(previewResolutionBtnS); + previewResolutionBtnGroup.add(previewResolutionBtnM); + + previewRenderSpeed = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Speed_Priority")); + previewRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First")); + ButtonGroup previewRenderGroup = new ButtonGroup(); + previewRenderGroup.add(previewRenderQuality); + previewRenderGroup.add(previewRenderSpeed); + } + + + /** + * 展示界面 + */ + @Override + public void populate(Object exportAttr) { + populateBean(exportAttr); + } + + /** + * 提交数据 + * + * @return 界面上的更新数据 + */ + @Override + public void update(Object exportAttr) { + updateBean(); + } + + private ImageExportAttr getGlobalImageExportAttr() { + return ReportConfigManager.getProviderInstance().getImageExportAttr(); + } + + /** + * 标题 + * + * @return 标题 + */ + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Image_Export_Export_Image_Setting"); + } + + @Override + public void populateBean(Object exportAttr) { + ImageExportAttr attr = getGlobalImageExportAttr(); + switch (attr.getResolution()) { + case 192: + globalResolutionBtnM.setSelected(true); + break; + case 300: + globalResolutionBtnL.setSelected(true); + break; + default: + globalResolutionBtnS.setSelected(true); + } + if (FileExtension.PNG.getExtension().equals(attr.getFormat())) { + globalFormatPng.setSelected(true); + } else { + globalFormatJpg.setSelected(true); + } + if (attr.getRenderQuality() == ImageExportAttr.RENDER_SPEED) { + globalRenderSpeed.setSelected(true); + } else { + globalRenderQuality.setSelected(true); + } + + if (attr.getPreviewRenderQuality() == ImageExportAttr.RENDER_SPEED) { + previewRenderSpeed.setSelected(true); + } else { + previewRenderQuality.setSelected(true); + } + + if (attr.getPreviewResolutionScale() == DPI_SCALE_S) { + previewResolutionBtnS.setSelected(true); + } else { + previewResolutionBtnM.setSelected(true); + } + + } + + @Override + public void updateBean(Object exportAttr) { + ImageExportAttr attr = getGlobalImageExportAttr(); + if (globalResolutionBtnS.isSelected()) { + attr.setResolution(RESOLUTION_S); + } else if (globalResolutionBtnM.isSelected()) { + attr.setResolution(RESOLUTION_M); + } else { + attr.setResolution(RESOLUTION_L); + } + if (globalFormatPng.isSelected()) { + attr.setFormat(FileExtension.PNG.getExtension()); + } else { + attr.setFormat(FileExtension.JPG.getExtension()); + } + if (globalRenderSpeed.isSelected()) { + attr.setRenderQuality(ImageExportAttr.RENDER_SPEED); + } else { + attr.setRenderQuality(ImageExportAttr.RENDER_QUALITY); + } + + if (previewRenderSpeed.isSelected()) { + attr.setPreviewRenderQuality(ImageExportAttr.RENDER_SPEED); + } else { + attr.setPreviewRenderQuality(ImageExportAttr.RENDER_QUALITY); + } + if (previewResolutionBtnS.isSelected()) { + attr.setPreviewResolutionScale(DPI_SCALE_S); + } else { + attr.setPreviewResolutionScale(DPI_SCALE_M); + } + } + + @Override + public String getTitle() { + return "Image"; + } +} \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java b/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java index 1ac27cc88..a284764d2 100644 --- a/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java +++ b/designer-realize/src/main/java/com/fr/design/report/ReportExportAttrPane.java @@ -14,13 +14,14 @@ import java.util.Set; public class ReportExportAttrPane extends BasicPane { + UITabbedPane uiTabbedPane; private ExcelExportPane excelExportPane; private PDFExportPane pdfExportPane; private WordExportPane wordExportPane; private List> paneList; public ReportExportAttrPane() { - UITabbedPane uiTabbedPane = new UITabbedPane(); + uiTabbedPane = new UITabbedPane(); this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); excelExportPane = new ExcelExportPane(); @@ -31,6 +32,7 @@ public class ReportExportAttrPane extends BasicPane { uiTabbedPane.addTab("Word", wordExportPane); Set providers = ExtraDesignClassManager.getInstance().getArray(ExportAttrTabProvider.XML_TAG); paneList = new ArrayList<>(); + initPane(new ImageExportPane()); for (ExportAttrTabProvider provider : providers) { BasicStorePane storePane = provider.toServiceComponent(); uiTabbedPane.addTab(storePane.getTitle(), storePane); @@ -39,6 +41,11 @@ public class ReportExportAttrPane extends BasicPane { this.add(uiTabbedPane); } + private void initPane(BasicStorePane exportPane) { + uiTabbedPane.addTab(exportPane.getTitle(), exportPane); + paneList.add(exportPane); + } + @Override protected String title4PopupWindow() { return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_ReportD_Excel_Export"); diff --git a/designer-realize/src/main/java/com/fr/design/sort/celldscolumn/CellDSColumnSortPane.java b/designer-realize/src/main/java/com/fr/design/sort/celldscolumn/CellDSColumnSortPane.java index b5175e7fa..584ff05b4 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/celldscolumn/CellDSColumnSortPane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/celldscolumn/CellDSColumnSortPane.java @@ -1,20 +1,17 @@ package com.fr.design.sort.celldscolumn; -import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.sort.common.AbstractSortPane; import com.fr.general.data.TableDataColumn; import com.fr.report.cell.TemplateCellElement; import com.fr.report.cell.cellattr.core.group.DSColumn; import com.fr.report.core.sort.common.CellSortAttr; -import javax.swing.*; - public class CellDSColumnSortPane extends AbstractSortPane { public CellDSColumnSortPane() { - super(220, 150); - //this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + super(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.ds.column.sort.pane")); } @Override diff --git a/designer-realize/src/main/java/com/fr/design/sort/cellexpand/CellExpandSortPane.java b/designer-realize/src/main/java/com/fr/design/sort/cellexpand/CellExpandSortPane.java index 5bfc20eea..e8045b283 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/cellexpand/CellExpandSortPane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/cellexpand/CellExpandSortPane.java @@ -1,6 +1,7 @@ package com.fr.design.sort.cellexpand; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.mainframe.cell.settingpane.CellExpandAttrPane; import com.fr.design.sort.common.AbstractSortPane; import com.fr.report.cell.TemplateCellElement; @@ -14,7 +15,7 @@ public class CellExpandSortPane extends AbstractSortPane { CellExpandAttrPane cellExpandAttrPane; public CellExpandSortPane(CellExpandAttrPane cellExpandAttrPane) { - super(227, 155); + super(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.cell.expand.sort.pane")); this.cellExpandAttrPane = cellExpandAttrPane; this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); } diff --git a/designer-realize/src/main/java/com/fr/design/sort/common/AbstractSortPane.java b/designer-realize/src/main/java/com/fr/design/sort/common/AbstractSortPane.java index 227708e7a..281b365ac 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/common/AbstractSortPane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/common/AbstractSortPane.java @@ -26,6 +26,10 @@ public abstract class AbstractSortPane extends JPanel { protected String selfSortArea; protected String defaultHeaderArea; + public AbstractSortPane(Dimension dimension) { + this(dimension.width, dimension.height); + } + public AbstractSortPane(int sortPaneWidth, int sortPaneRightWidth) { this.sortPaneWidth = sortPaneWidth; this.sortPaneRightWidth = sortPaneRightWidth; @@ -101,12 +105,12 @@ public abstract class AbstractSortPane extends JPanel { } public static UILabel createIntervalUILabel() { - return createIntervalUILabel(PANE_COMPONENT_H_GAP); + return createIntervalUILabel(new Dimension(PANE_COMPONENT_H_GAP, 10)); } - public static UILabel createIntervalUILabel(int vGap) { + public static UILabel createIntervalUILabel(Dimension dimension) { UILabel uiLabel = new UILabel(); - uiLabel.setPreferredSize(new Dimension(vGap, 10)); + uiLabel.setPreferredSize(dimension); return uiLabel; } } diff --git a/designer-realize/src/main/java/com/fr/design/sort/common/SortUIExpandablePane.java b/designer-realize/src/main/java/com/fr/design/sort/common/SortUIExpandablePane.java index eef21bb06..42a135298 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/common/SortUIExpandablePane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/common/SortUIExpandablePane.java @@ -6,6 +6,7 @@ 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.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import javax.swing.*; @@ -85,7 +86,7 @@ public class SortUIExpandablePane extends JPanel { this.add(iconUiLabel); tipUILabel = new UILabel(Toolkit.i18nText("Fine-Design_Sort_Second_Sort")); this.add(tipUILabel); - this.add(AbstractSortPane.createIntervalUILabel(108)); + this.add(AbstractSortPane.createIntervalUILabel( DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.sort.expand.header.pane"))); closeButton = new UILabel(IconUtils.readIcon("/com/fr/design/images/control/close.png")); closeButton.setPreferredSize(new Dimension(16, 20)); diff --git a/designer-realize/src/main/java/com/fr/design/sort/header/HeaderAreaPane.java b/designer-realize/src/main/java/com/fr/design/sort/header/HeaderAreaPane.java index 25641340c..d7c9aab40 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/header/HeaderAreaPane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/header/HeaderAreaPane.java @@ -208,7 +208,9 @@ public class HeaderAreaPane extends JPanel { if (isNotSelectables(headerColumnRow)) { SortHeader sortHeader = templateCellElement.getCellExpandAttr().getCellSortAttr().getSortHeader(); headerColumnRow = ColumnRow.ERROR; - sortHeader.setHeaderArea(headerColumnRow.toString()); + if (sortHeader != null) { + sortHeader.setHeaderArea(headerColumnRow.toString()); + } } else { handleDisableHeaderCell(templateCellElement); } diff --git a/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSettingPane.java b/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSettingPane.java index f31c40929..114300e66 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSettingPane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSettingPane.java @@ -4,12 +4,14 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.sort.common.AbstractSortPane; +import com.fr.general.GeneralContext; import com.fr.report.core.sort.header.SortHeader; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; +import java.util.Locale; public class HeaderSettingPane extends JPanel { protected int headerSettingPaneWidth; @@ -36,6 +38,7 @@ public class HeaderSettingPane extends JPanel { emptyUILabel.setPreferredSize(new Dimension(10, 10)); uiCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Sort_Allow_User_Click_Sort_Order")); + addToolTipText(); uiCheckBox.setPreferredSize(new Dimension(headerSettingPaneRightWidth - 10, AbstractSortPane.PANE_COMPONENT_HEIGHT)); uiCheckBox.addChangeListener(new ChangeListener() { @Override @@ -49,6 +52,12 @@ public class HeaderSettingPane extends JPanel { this.add(jPanel); } + private void addToolTipText() { + if (!Locale.CHINA.equals(GeneralContext.getLocale())) { + uiCheckBox.setToolTipText(Toolkit.i18nText("Fine-Design_Sort_Allow_User_Click_Sort_Order")); + } + } + void initHeaderSortRulePane() { headerSortRulePane = new HeaderSortRulePane(); this.add(headerSortRulePane); diff --git a/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSortRulePane.java b/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSortRulePane.java index 27c03e9e0..01021ed09 100644 --- a/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSortRulePane.java +++ b/designer-realize/src/main/java/com/fr/design/sort/header/HeaderSortRulePane.java @@ -7,6 +7,7 @@ import com.fr.design.event.UIObserverListener; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ipoppane.PopupHider; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.style.color.ColorControlWindow; @@ -32,6 +33,7 @@ public class HeaderSortRulePane extends JPanel { UICheckBox desUICheckBox; UICheckBox nosortUICheckBox; Color defaultColor = new Color(33, 33, 34); + public static final int ICON_LENGTH = 20; HeaderSortRulePane() { initComponents(); @@ -57,8 +59,9 @@ public class HeaderSortRulePane extends JPanel { new Component[]{desUICheckBox = new UICheckBox(SortRule.DES.getDescription()), desIconButton = new IconButton(SortRule.DES)}, new Component[]{nosortUICheckBox = new UICheckBox(SortRule.NO_SORT.getDescription()), nosortIconButton = new IconButton(SortRule.NO_SORT)}, }; - double[] rowSize = {HeaderIconBuilder.ICON_LENGTH + 10, HeaderIconBuilder.ICON_LENGTH + 10, HeaderIconBuilder.ICON_LENGTH + 10}; - double[] columnSize = {80, HeaderIconBuilder.ICON_LENGTH + 10}; + double[] rowSize = {ICON_LENGTH + 10, ICON_LENGTH + 10, ICON_LENGTH + 10}; + double[] columnSize = + {DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.sort.rule.item").getWidth(), ICON_LENGTH + 10}; JPanel sortRuleItem = TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, 0); this.add(sortRuleItem, BorderLayout.CENTER); initUICheckBoxChange(ascUICheckBox, ascIconButton); @@ -116,10 +119,10 @@ public class HeaderSortRulePane extends JPanel { jLayeredPane = new JLayeredPane(); iconLabel = getIconLabel(); borderUiLabel = new UILabel(); - borderUiLabel.setSize(HeaderIconBuilder.ICON_LENGTH, HeaderIconBuilder.ICON_LENGTH); + borderUiLabel.setSize(ICON_LENGTH, ICON_LENGTH); borderUiLabel.setOpaque(true); borderUiLabel.setBackground(Color.WHITE); - iconLabel.setSize(HeaderIconBuilder.ICON_LENGTH, HeaderIconBuilder.ICON_LENGTH); + iconLabel.setSize(ICON_LENGTH, ICON_LENGTH); iconLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -128,7 +131,7 @@ public class HeaderSortRulePane extends JPanel { } } }); - jLayeredPane.setPreferredSize(new Dimension(HeaderIconBuilder.ICON_LENGTH, HeaderIconBuilder.ICON_LENGTH)); + jLayeredPane.setPreferredSize(new Dimension(ICON_LENGTH, ICON_LENGTH)); jLayeredPane.add(iconLabel, JLayeredPane.POPUP_LAYER); jLayeredPane.add(borderUiLabel, JLayeredPane.MODAL_LAYER); this.add(jLayeredPane); @@ -142,7 +145,7 @@ public class HeaderSortRulePane extends JPanel { Icon getIcon(FineColor fineColor) { BufferedImage bufferedImage = HeaderIconBuilder.getIcon(sortRule, fineColor); - Icon icon = new ImageIcon(bufferedImage); + Icon icon = new SVGIcon(bufferedImage); return icon; } diff --git a/designer-realize/src/main/java/com/fr/design/webattr/WriteToolBarPane.java b/designer-realize/src/main/java/com/fr/design/webattr/WriteToolBarPane.java index 06b167167..a2e0c53c2 100644 --- a/designer-realize/src/main/java/com/fr/design/webattr/WriteToolBarPane.java +++ b/designer-realize/src/main/java/com/fr/design/webattr/WriteToolBarPane.java @@ -161,6 +161,7 @@ public class WriteToolBarPane extends AbstractEditToolBarPane { colorButton.setColor(webWrite.getSelectedColor()); } else { colorBox.setSelected(false); + colorButton.setEnabled(false); } if (webWrite.getSheetPosition() == Constants.TOP) { diff --git a/designer-realize/src/main/java/com/fr/design/webattr/WriteWebSettingPane.java b/designer-realize/src/main/java/com/fr/design/webattr/WriteWebSettingPane.java index 3db3da6d7..527acb4c4 100644 --- a/designer-realize/src/main/java/com/fr/design/webattr/WriteWebSettingPane.java +++ b/designer-realize/src/main/java/com/fr/design/webattr/WriteWebSettingPane.java @@ -109,6 +109,7 @@ public class WriteWebSettingPane extends WebSettingPane { protected void setDefault() { super.setDefault(); colorBox.setSelected(false); + colorButton.setEnabled(false); bottomRadioButton.setSelected(true); leftRadioButton.setSelected(true); unloadCheck.setSelected(true); @@ -126,6 +127,7 @@ public class WriteWebSettingPane extends WebSettingPane { colorButton.setColor(webWrite.getSelectedColor()); } else { colorBox.setSelected(false); + colorButton.setEnabled(false); } if (webWrite.getSheetPosition() == Constants.TOP) { diff --git a/designer-realize/src/main/java/com/fr/design/widget/WidgetPane.java b/designer-realize/src/main/java/com/fr/design/widget/WidgetPane.java index d746c4066..3a50c3870 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/WidgetPane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/WidgetPane.java @@ -20,8 +20,11 @@ import com.fr.form.ui.*; import com.fr.general.ComparatorUtils; import com.fr.stable.ArrayUtils; +import com.fr.stable.AssistUtils; import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -198,6 +201,7 @@ public class WidgetPane extends AbstractAttrNoScrollPane implements ItemListener } }); this.setPreferredSize(new Dimension(100, 20)); + this.initPopupMenuListener(userDefined); } public void setSelectedItemByWidgetClass(Class clazz) { @@ -218,7 +222,7 @@ public class WidgetPane extends AbstractAttrNoScrollPane implements ItemListener super.setSelectedItem(anObject); } - private Vector getWidgetsName(boolean userDefined) { + private Vector getWidgetsName(boolean userDefined) { WidgetOption[] reportWidgetInstance = getWidgetOptions(); Vector items = new Vector(); @@ -262,7 +266,45 @@ public class WidgetPane extends AbstractAttrNoScrollPane implements ItemListener } private WidgetOption[] getWidgetOptions() { - return (WidgetOption[]) ArrayUtils.addAll(WidgetOption.getReportWidgetInstance(), ExtraDesignClassManager.getInstance().getCellWidgetOptions()); + return ArrayUtils.addAll(WidgetOption.getReportWidgetInstance(), ExtraDesignClassManager.getInstance().getCellWidgetOptions()); + } + + private void initPopupMenuListener(boolean userDefined) { + this.addPopupMenuListener(new PopupMenuListener() { + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + // 下拉刷新下列表 + Vector widgetsName = getWidgetsName(userDefined); + if (modelChanged(widgetsName)) { + refreshBoxItems(widgetsName); + } + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + + } + }); + } + + private boolean modelChanged(Vector widgetsName) { + DefaultComboBoxModel model = (DefaultComboBoxModel) getModel(); + int modelSize = model.getSize(); + if (modelSize != widgetsName.size()) { + return true; + } + for (int i = 0; i < modelSize; i++) { + if (!AssistUtils.equals(model.getElementAt(i), widgetsName.elementAt(i))) { + return true; + } + } + return false; } } diff --git a/designer-realize/src/main/java/com/fr/design/widget/ui/DateEditorDefinePane.java b/designer-realize/src/main/java/com/fr/design/widget/ui/DateEditorDefinePane.java index c29407b8e..0a3f3d288 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/ui/DateEditorDefinePane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/ui/DateEditorDefinePane.java @@ -13,6 +13,8 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.widget.component.DateValuePane; import com.fr.design.widget.component.UIComboBoxNoArrow; +import com.fr.design.widget.ui.designer.date.DateFormatCheckManager; +import com.fr.design.widget.ui.designer.date.DateFormatCheckResult; import com.fr.form.ui.DateEditor; import com.fr.stable.ArrayUtils; @@ -164,13 +166,9 @@ public class DateEditorDefinePane extends DirectWriteEditorDefinePane 0) { try { simpleDateFormat = new SimpleDateFormat(text); - this.currentSamplelabel.setText(simpleDateFormat.format(new Date())); } catch (Exception exp) { simpleDateFormat = new SimpleDateFormat(""); } diff --git a/designer-realize/src/main/java/com/fr/design/widget/ui/TreeComboBoxEditorDefinePane.java b/designer-realize/src/main/java/com/fr/design/widget/ui/TreeComboBoxEditorDefinePane.java index 881e832fb..f8ddeeca2 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/ui/TreeComboBoxEditorDefinePane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/ui/TreeComboBoxEditorDefinePane.java @@ -48,7 +48,7 @@ public class TreeComboBoxEditorDefinePane extends CustomWritableRepeatEditorPane } - + @Override protected String title4PopupWindow() { return "treecombobox"; @@ -56,20 +56,20 @@ public class TreeComboBoxEditorDefinePane extends CustomWritableRepeatEditorPane @Override protected void populateSubCustomWritableRepeatEditorBean(TreeEditor e) { - treeSettingPane.setValue(e.getNodeOrDict()); + treeSettingPane.setValue(e.getBuildModelConfig()); treeRootPane.populate(e.getTreeAttr()); } @Override protected TreeComboBoxEditor updateSubCustomWritableRepeatEditorBean() { TreeComboBoxEditor editor = new TreeComboBoxEditor(); - editor.setNodeOrDict(treeSettingPane.getValue()); + editor.setBuildModelConfig(treeSettingPane.getValue()); editor.setTreeAttr(treeRootPane.update()); return editor; } - @Override - public DataCreatorUI dataUI() { - return null; - } + @Override + public DataCreatorUI dataUI() { + return null; + } } \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/widget/ui/TreeEditorDefinePane.java b/designer-realize/src/main/java/com/fr/design/widget/ui/TreeEditorDefinePane.java index 6d6e1d4a8..89e54cdc8 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/ui/TreeEditorDefinePane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/ui/TreeEditorDefinePane.java @@ -25,12 +25,12 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane { private UICheckBox removeRepeatCheckBox; public TreeEditorDefinePane(){ - this.initComponents(); + this.initComponents(); } @Override protected void populateSubFieldEditorBean(TreeEditor e) { - this.accessibleTreeModelEditor.setValue(e.getNodeOrDict()); + this.accessibleTreeModelEditor.setValue(e.getBuildModelConfig()); treeRootPane.populate(e.getTreeAttr()); if (this.removeRepeatCheckBox != null) { this.removeRepeatCheckBox.setSelected(e.isRemoveRepeat()); @@ -40,7 +40,7 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane { @Override protected TreeEditor updateSubFieldEditorBean() { TreeEditor editor = new TreeEditor(); - editor.setNodeOrDict(accessibleTreeModelEditor.getValue()); + editor.setBuildModelConfig(accessibleTreeModelEditor.getValue()); editor.setTreeAttr(treeRootPane.update()); if (this.removeRepeatCheckBox != null) { editor.setRemoveRepeat(this.removeRepeatCheckBox.isSelected()); @@ -50,8 +50,8 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane { @Override protected JPanel setFirstContentPane() { - return this.setSecondContentPane(); - } + return this.setSecondContentPane(); + } protected JPanel setSecondContentPane() { accessibleTreeModelEditor = new AccessibleTreeModelEditor(); @@ -80,14 +80,14 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane { content.add(treeRootPane, BorderLayout.NORTH); return content; } - + @Override protected String title4PopupWindow() { return "tree"; } - @Override - public DataCreatorUI dataUI() { - return null; - } + @Override + public DataCreatorUI dataUI() { + return null; + } } \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/grid/Grid.java b/designer-realize/src/main/java/com/fr/grid/Grid.java index d1f388138..fb18ac07f 100644 --- a/designer-realize/src/main/java/com/fr/grid/Grid.java +++ b/designer-realize/src/main/java/com/fr/grid/Grid.java @@ -1095,6 +1095,7 @@ public class Grid extends BaseGridComponent { TemplateCellElement cellElement = (TemplateCellElement) newValue; editingCellElement.setValue(cellElement.getValue()); editingCellElement.setCellExpandAttr(cellElement.getCellExpandAttr()); + editingCellElement.setStyle(cellElement.getStyle()); return true; } else if (newValue instanceof CellImage) { CellImage cellImage = (CellImage) newValue; diff --git a/designer-realize/src/main/java/com/fr/grid/GridUI.java b/designer-realize/src/main/java/com/fr/grid/GridUI.java index c6ed5e416..6234acc95 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridUI.java +++ b/designer-realize/src/main/java/com/fr/grid/GridUI.java @@ -406,7 +406,7 @@ public class GridUI extends ComponentUI { rowHeight = gridRange.rowHeightList.get(i); paperYAxisSumSize = paperYAxisSumSize.add(rowHeight); if (showGridLine) { - UNIT columnWidth, xAxisSumSize = FU.getInstance(0); + UNIT columnWidth, xAxisSumSize = FU.getInstance(0); for (int j = gridRange.xBeginIndex; j <= gridRange.xEndIndex; j++) { columnWidth = gridRange.columnWidthList.get(j); if (!mergeCellElementTable.get(CellPosition.value(i - 1, j)).contains(CellPosition.BOTTOM)) { @@ -1018,7 +1018,7 @@ public class GridUI extends ComponentUI { g2d.translate(floatX, floatY); - PaintUtils.paintFloatElement(g2d, tmpFloatElement, + PaintUtils.paintFloatElementWithBackgroundAndBorder(g2d, tmpFloatElement, tmpFloatElement.getWidth().toPixI(resolution), tmpFloatElement.getHeight().toPixI(resolution), resolution); @@ -1220,8 +1220,8 @@ public class GridUI extends ComponentUI { Stroke oldStroke = g2d.getStroke(); g2d.setPaint(Color.black); g2d.setStroke(GraphDrawHelper.getStroke(Constants.LINE_DASH_DOT)); - g2d.drawLine( 0, height, width, height); - g2d.drawLine( width, 0, width, height); + g2d.drawLine(0, height, width, height); + g2d.drawLine(width, 0, width, height); g2d.setPaint(oldPaint); g2d.setStroke(oldStroke); } diff --git a/designer-realize/src/main/java/com/fr/poly/creator/ECBlockPane.java b/designer-realize/src/main/java/com/fr/poly/creator/ECBlockPane.java index 33bcda20a..d18e52110 100644 --- a/designer-realize/src/main/java/com/fr/poly/creator/ECBlockPane.java +++ b/designer-realize/src/main/java/com/fr/poly/creator/ECBlockPane.java @@ -62,7 +62,7 @@ public class ECBlockPane extends PolyElementCasePane { @Override public void selectionChanged(SelectionEvent e) { - if (!isEditable() && !DesignModeContext.isAuthorityEditing()) { + if (!isEditable()) { return; } if (DesignModeContext.isAuthorityEditing()) { diff --git a/designer-realize/src/main/java/com/fr/quickeditor/cellquick/CellDSColumnEditor.java b/designer-realize/src/main/java/com/fr/quickeditor/cellquick/CellDSColumnEditor.java index 23015e9d0..1c50499f7 100644 --- a/designer-realize/src/main/java/com/fr/quickeditor/cellquick/CellDSColumnEditor.java +++ b/designer-realize/src/main/java/com/fr/quickeditor/cellquick/CellDSColumnEditor.java @@ -282,7 +282,7 @@ public class CellDSColumnEditor extends CellQuickEditor { private void initComponents(){ dataPane = new SelectedDataColumnPane(true, true); groupPane = new ResultSetGroupDockingPane(); - + initListener(); double[] rowSize = {P}, columnSize = {60, F}; UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Report_Filter_Conditions")); condition = new DSColumnConditionAction(); @@ -299,6 +299,35 @@ public class CellDSColumnEditor extends CellQuickEditor { conditionPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, HGAP, VGAP); this.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); } + + + private void initListener() { + dataPane.setListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + dataPane.update(cellElement); + fireTargetModified(); + } + } + }); + groupPane.setListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e == null) { + //分组-高级-自定义点确定的时候传进来null的e,但是这时候应该触发保存 + groupPane.update(); + fireTargetModified(); + return; + } + if (e.getStateChange() == ItemEvent.DESELECTED) { + groupPane.update(); + fireTargetModified(); + } + } + }); + } + @Override protected AttributeChangeListener getAttributeChangeListener() { return new AttributeChangeListener() { @@ -442,6 +471,7 @@ public class CellDSColumnEditor extends CellQuickEditor { @Override public void attributeChange() { update(); + checkButtonEnabled(); fireTargetModified(); } }; diff --git a/designer-realize/src/main/java/com/fr/start/MainDesigner.java b/designer-realize/src/main/java/com/fr/start/MainDesigner.java index e29a4e804..f60003c9a 100644 --- a/designer-realize/src/main/java/com/fr/start/MainDesigner.java +++ b/designer-realize/src/main/java/com/fr/start/MainDesigner.java @@ -16,6 +16,7 @@ import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.fun.MenuHandler; +import com.fr.design.fun.OemProcessor; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIPreviewButton; import com.fr.design.gui.ibutton.UISaveForbiddenButton; @@ -42,6 +43,7 @@ import com.fr.design.module.DesignModuleFactory; import com.fr.design.monitor.DesignerLifecycleMonitorContext; import com.fr.design.notification.ui.NotificationCenterPane; import com.fr.design.share.SharableManager; +import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.concurrent.ThreadFactoryBuilder; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.env.utils.DesignerInteractionHistory; @@ -59,6 +61,7 @@ import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.stable.lifecycle.FineLifecycleFatalError; import com.fr.stable.xml.XMLTools; +import com.fr.start.common.SplashCommon; import com.fr.start.module.StartupArgs; import com.fr.start.server.ServerTray; import com.fr.third.org.apache.commons.lang3.time.StopWatch; @@ -106,7 +109,8 @@ public class MainDesigner extends BaseDesigner { * @param args 参数 */ public static void main(String[] args) { - + + showSplash(); DeepLinkManager.getInstance().start(args); StopWatch watch = new StopWatch(); watch.start(); @@ -136,7 +140,18 @@ public class MainDesigner extends BaseDesigner { FineLoggerFactory.getLogger().info("Designer started.Time used {} ms", watch.getTime()); watch.stop(); } - + + private static void showSplash() { + // 快快显示启动画面 + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + SplashContext.getInstance().registerSplash(createSplash()); + SplashContext.getInstance().show(); + } + }); + } + /** * 创建新建文件的快捷方式数组。 * @@ -528,5 +543,22 @@ public class MainDesigner extends BaseDesigner { DesignerInteractionHistory historyCollector = DesignerInteractionHistory.getInstance(); historyCollector.saveXMLFile(); } - + + private static SplashStrategy createSplash() { + + OemProcessor oemProcessor = OemHandler.findOem(); + if (oemProcessor != null) { + SplashStrategy splashStrategy = null; + try { + splashStrategy = oemProcessor.createSplashStrategy(); + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (splashStrategy != null) { + return splashStrategy; + } + } + + return new SplashCommon(); + } } diff --git a/designer-realize/src/main/java/com/fr/start/SplashContext.java b/designer-realize/src/main/java/com/fr/start/SplashContext.java index d425d726c..cc9eb1933 100644 --- a/designer-realize/src/main/java/com/fr/start/SplashContext.java +++ b/designer-realize/src/main/java/com/fr/start/SplashContext.java @@ -36,7 +36,7 @@ public class SplashContext { private SplashStrategy splashStrategy; - private String moduleId = ""; + private String moduleId = Toolkit.i18nText("Fine-Design_Basic_Initializing"); private int loadingIndex = 0; private String[] loading = new String[]{"..", "....", "......"}; diff --git a/designer-realize/src/main/java/com/fr/start/common/SplashPane.java b/designer-realize/src/main/java/com/fr/start/common/SplashPane.java index 726bdaba4..74500acc3 100644 --- a/designer-realize/src/main/java/com/fr/start/common/SplashPane.java +++ b/designer-realize/src/main/java/com/fr/start/common/SplashPane.java @@ -4,7 +4,7 @@ import com.bulenkov.iconloader.IconLoader; import com.bulenkov.iconloader.util.JBUI; import com.fr.base.GraphHelper; import com.fr.design.locale.impl.SplashMark; -import com.fr.design.ui.util.GraphicsConfig; +import com.fr.stable.GraphicsConfig; import com.fr.general.locale.LocaleCenter; import com.fr.general.locale.LocaleMark; import com.fr.stable.GraphDrawHelper; diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java index eea3360ba..02152beb1 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java @@ -3,6 +3,7 @@ package com.fr.start.module; import com.fr.base.BaseFormula; import com.fr.base.Formula; import com.fr.base.MultiFieldParameter; +import com.fr.base.OptimizeUtil; import com.fr.base.passport.FinePassportListenerAdapter; import com.fr.base.passport.FinePassportManager; import com.fr.base.process.ProcessOperator; @@ -12,6 +13,8 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.config.MarketConfig; import com.fr.config.ServerPreferenceConfig; import com.fr.decision.update.backup.RecoverManager; +import com.fr.decision.webservice.v10.plugin.helper.category.impl.PluginResourceLoader; +import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.NewFormAction; @@ -56,6 +59,8 @@ import com.fr.design.mainframe.JTemplateEvent; import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.mainframe.WidgetToolBarPane; import com.fr.design.mainframe.alphafine.AlphaFineHelper; +import com.fr.design.mainframe.alphafine.question.QuestionWindow; +import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; import com.fr.design.mainframe.bbs.BBSGuestPane; import com.fr.design.mainframe.bbs.UserInfoPane; import com.fr.design.mainframe.form.FormECCompositeProvider; @@ -78,7 +83,10 @@ import com.fr.design.share.ui.generate.ShareGeneratePane; import com.fr.design.update.actions.RecoverForDesigner; import com.fr.design.update.push.DesignerPushUpdateManager; import com.fr.design.widget.ui.btn.FormSubmitButtonDetailPane; +import com.fr.event.Event; import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.event.Null; import com.fr.general.GeneralContext; import com.fr.general.xml.GeneralXMLTools; import com.fr.js.EmailJavaScript; @@ -136,6 +144,7 @@ import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import java.util.Set; +import javax.swing.SwingWorker; /** * Created by juhaoyu on 2018/1/31. @@ -157,6 +166,8 @@ public class DesignerActivator extends Activator implements Prepare { @Override public void start() { + + startLoginAuthServer(); migrateBBSInfoFromFineDB(); FormThemeConfigMigrator.getInstance().upgrade(); ReportThemeConfigMigrator.getInstance().upgrade(); @@ -180,6 +191,8 @@ public class DesignerActivator extends Activator implements Prepare { AlphaFineHelper.switchConfig4Locale(); RecoverManager.register(new RecoverForDesigner()); pushUpdateTask.run(); + PluginResourceLoader.INSTANCE.checkOldShopFile(); + UpmResourceLoader.INSTANCE.checkOldShopFile(); } @Override @@ -484,7 +497,42 @@ public class DesignerActivator extends Activator implements Prepare { @Override public void prepare() { - LoginAuthServer.getInstance().start(); + + OptimizeUtil.close(() -> { + LoginAuthServer.getInstance().compatibleStart(); + }); ContentReplacerCenter.getInstance().register(); + EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { + @Override + public void on(Event event, Null param) { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + // 触发下cid 搜索 + ProductNewsSearchManager.getInstance().getProductNewsList(); + return null; + } + + @Override + protected void done() { + QuestionWindow.getInstance().setVisible(true); + } + }.execute(); + } + }); + } + + private void startLoginAuthServer() { + + OptimizeUtil.open(() -> { + // 设计器启动后启动 + EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { + @Override + public void on(Event event, Null param) { + LoginAuthServer.getInstance().start(); + } + }); + }); } } diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java b/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java index 56af5583f..da8b559e8 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java @@ -1,36 +1,40 @@ package com.fr.start.module; +import com.fr.base.OptimizeUtil; import com.fr.concurrent.NamedThreadFactory; +import com.fr.config.dao.DaoSelectorFactory; +import com.fr.config.dao.PropertiesConstants; +import com.fr.decision.webservice.v10.encryption.EncryptionConstants; import com.fr.design.DesignerEnvManager; import com.fr.design.RestartHelper; import com.fr.design.dialog.TipDialog; -import com.fr.design.fun.OemProcessor; +import com.fr.design.env.DesignerWorkspaceInfo; +import com.fr.design.env.DesignerWorkspaceType; import com.fr.design.fun.impl.GlobalListenerProviderManager; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector; import com.fr.design.mainframe.messagecollect.StartupMessageCollector; import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage; -import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.DesignUtils; import com.fr.design.utils.DesignerPort; +import com.fr.env.utils.WorkspaceUtils; +import com.fr.event.Event; +import com.fr.event.Listener; +import com.fr.event.Null; import com.fr.exit.DesignerExiter; -import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.module.Activator; import com.fr.record.analyzer.EnableMetrics; import com.fr.record.analyzer.Metrics; import com.fr.stable.ArrayUtils; import com.fr.stable.BuildContext; -import com.fr.stable.ProductConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; import com.fr.start.DesignerProcessType; -import com.fr.start.OemHandler; import com.fr.start.ServerStarter; -import com.fr.start.SplashContext; -import com.fr.start.SplashStrategy; -import com.fr.start.common.SplashCommon; +import com.fr.start.event.LazyStartupEvent; import com.fr.start.server.FineEmbedServer; import com.fr.value.NotNullLazyValue; import org.jetbrains.annotations.NotNull; @@ -55,10 +59,9 @@ public class DesignerStartup extends Activator { @Override public void beforeAllStart() { BuildContext.setBuildFilePath("/com/fr/stable/build.properties"); - // 检查是否是-Ddebug = true 启动 并切换对应的端口以及环境配置文件 - checkDebugStart(); - // 都是在启动过程中读取,这边提前初始化xml配置 - DesignerEnvManager.getEnvManager(); + + registerDaoSelector(); + // 初始化look and feel DesignUtils.initLookAndFeel(); if (DesignUtils.isPortOccupied()) { @@ -100,14 +103,6 @@ public class DesignerStartup extends Activator { DesignerExiter.getInstance().execute(); return; } - // 快快显示启动画面 - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - @Override - public void run() { - SplashContext.getInstance().registerSplash(createSplash()); - SplashContext.getInstance().show(); - } - }); } @Override @@ -125,13 +120,21 @@ public class DesignerStartup extends Activator { || FineEmbedServer.isRunning()) { return; } + if (DaoSelectorFactory.getDaoSelector().useCacheDao()) { + listenEvent(LazyStartupEvent.INSTANCE, new Listener(Integer.MIN_VALUE) { + @Override + public void on(Event event, Null param) { + startEmbeddedServer(); + } + }); + } else { + startEmbeddedServer(); + } + } + + private void startEmbeddedServer() { ExecutorService service = newSingleThreadExecutor(new NamedThreadFactory("FineEmbedServerStart")); - service.submit(new Runnable() { - @Override - public void run() { - FineEmbedServer.start(); - } - }); + service.submit(FineEmbedServer::start); service.shutdown(); } @@ -142,23 +145,6 @@ public class DesignerStartup extends Activator { StartupMessageCollector.getInstance().recordStartupLog(); } - private SplashStrategy createSplash() { - OemProcessor oemProcessor = OemHandler.findOem(); - if (oemProcessor != null) { - SplashStrategy splashStrategy = null; - try { - splashStrategy = oemProcessor.createSplashStrategy(); - } catch (Throwable e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - if (splashStrategy != null) { - return splashStrategy; - } - } - - return new SplashCommon(); - } - private void browserDemoIfNeeded() { if (startupArgsValue.getValue().isDemo()) { @@ -166,28 +152,36 @@ public class DesignerStartup extends Activator { } } - /** - * 在VM options里加入-Ddebug=true激活 - */ - private void checkDebugStart() { + private void registerDaoSelector() { + // 注入设计器db cache 是否可用 + DesignerWorkspaceInfo info = WorkspaceUtils.getWorkspaceInfo(); + if (info.getType() == DesignerWorkspaceType.Remote) { + DaoSelectorFactory.registerDaoSelector(() -> false); + } else { + String webInfPath = WorkspaceUtils.getWorkspaceInfo().getPath(); + String dbConfigPath = StableUtils.pathJoin(webInfPath, ProjectConstants.CONFIG_DIRECTORY, + EncryptionConstants.PROPERTY_NAME); + String entityPath = generatePath(webInfPath, PropertiesConstants.ENTITY_PROP); + String xmlEntityPath = generatePath(webInfPath, PropertiesConstants.XML_ENTITY_PROP); + String classNamePath = generatePath(webInfPath, PropertiesConstants.CLASS_NAME_PROP); + // 校验 平台迁移文件/缓存文件 + boolean existPropCache = new File(entityPath).exists() && new File(xmlEntityPath).exists() && new File(classNamePath).exists(); + DaoSelectorFactory.registerDaoSelector(() -> DesignerEnvManager.getEnvManager().isPropertiesUsable() + && OptimizeUtil.isOpen() + && existPropCache + // demo启动时 前后目录可能会不一致 造成读取缓存失败 + && !startupArgsValue.getValue().isDemo() + && !new File(dbConfigPath).exists()); - if (ComparatorUtils.equals("true", System.getProperty("debug"))) { - setDebugEnv(); } } - /** - * 端口改一下,环境配置文件改一下。便于启动两个设计器,进行对比调试 - */ - private void setDebugEnv() { - - DesignUtils.setPort(DesignerPort.getInstance().getDebugMessagePort()); - DesignerEnvManager.setEnvFile(new File(StableUtils.pathJoin( - ProductConstants.getEnvHome(), - ProductConstants.APP_NAME + "Env_debug.xml" - ))); + private String generatePath(String webInfPath, String name) { + return StableUtils.pathJoin(webInfPath, ProjectConstants.EMBED_DB_DIRECTORY, + ProjectConstants.PROPERTIES_CACHE_FOR_CONFIG, name); } + @Override public void stop() { // void diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java b/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java index 724f947c9..de57164bc 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java @@ -9,6 +9,7 @@ import com.fr.design.env.DesignerWorkspaceGenerator; import com.fr.design.env.DesignerWorkspaceInfo; import com.fr.design.env.LocalDesignerWorkspaceInfo; import com.fr.design.versioncheck.VersionCheckUtils; +import com.fr.env.utils.WorkspaceUtils; import com.fr.event.Event; import com.fr.event.EventDispatcher; import com.fr.event.Listener; @@ -28,7 +29,6 @@ import org.jetbrains.annotations.NotNull; */ public class DesignerWorkspaceProvider extends Activator { - private static final String SPECIFY_WORKSPACE = "fr.designer.workspace"; private NotNullLazyValue startupArgs = new NotNullLazyValue() { @NotNull @@ -46,15 +46,10 @@ public class DesignerWorkspaceProvider extends Activator { if (startupArgs.getValue().isDemo()) { DesignerEnvManager.getEnvManager().setCurrentEnv2Default(); } else { - String workspacePath; DesignerWorkspaceInfo workspaceInfo = null; try { String current = DesignerEnvManager.getEnvManager().getCurEnvName(); - if (StringUtils.isNotEmpty(workspacePath = System.getProperty(SPECIFY_WORKSPACE))) { - workspaceInfo = LocalDesignerWorkspaceInfo.create(StringUtils.EMPTY, workspacePath); - } else { - workspaceInfo = DesignerEnvManager.getEnvManager().getWorkspaceInfo(current); - } + workspaceInfo = WorkspaceUtils.getWorkspaceInfo(); Workspace workspace = DesignerWorkspaceGenerator.generate(workspaceInfo); boolean checkValid = workspace != null && workspaceInfo.checkValid(); if (!checkValid) { diff --git a/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java b/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java index 6a3e0415d..65cdc1c30 100644 --- a/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java @@ -2,14 +2,11 @@ package com.fr.start.module; import com.fr.design.DesignerEnvManager; import com.fr.design.RestartHelper; -import com.fr.design.i18n.Toolkit; import com.fr.design.utils.DesignUtils; -import com.fr.event.EventDispatcher; import com.fr.file.TmpFileUtils; import com.fr.general.CloudCenter; import com.fr.general.GeneralContext; import com.fr.module.Activator; -import com.fr.module.ModuleEvent; /** * Created by juhaoyu on 2018/1/8. @@ -21,8 +18,9 @@ public class PreStartActivator extends Activator { //清空临时文件 TmpFileUtils.cleanUpInnerTmpFiles(); RestartHelper.deleteRecordFilesWhenStart(); - //初始化 - EventDispatcher.fire(ModuleEvent.MajorModuleStarting, Toolkit.i18nText("Fine-Design_Basic_Initializing")); + //初始化起始画面放到 SplashContext 里面 + //EventDispatcher.fire(ModuleEvent.MajorModuleStarting, Toolkit.i18nText("Fine-Design_Basic_Initializing")); + // 完成初始化 //noinspection ResultOfMethodCallIgnored CloudCenter.getInstance(); diff --git a/designer-realize/src/main/java/com/fr/start/module/optimized/BaseDBActivator4Designer.java b/designer-realize/src/main/java/com/fr/start/module/optimized/BaseDBActivator4Designer.java new file mode 100644 index 000000000..4c5492651 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/start/module/optimized/BaseDBActivator4Designer.java @@ -0,0 +1,30 @@ +package com.fr.start.module.optimized; + +import com.fr.config.activator.BaseDBActivator; +import com.fr.config.dao.DaoSelectorFactory; +import com.fr.event.Event; +import com.fr.event.Listener; +import com.fr.event.Null; +import com.fr.start.event.LazyStartupEvent; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/3/7 + */ +public class BaseDBActivator4Designer extends BaseDBActivator { + + @Override + public void start() { + if (DaoSelectorFactory.getDaoSelector().useCacheDao()) { + listenEvent(LazyStartupEvent.INSTANCE, new Listener(Integer.MAX_VALUE) { + @Override + public void on(Event event, Null param) { + BaseDBActivator4Designer.super.start(); + } + }); + } else { + super.start(); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/start/module/optimized/ConfigurationActivator4Designer.java b/designer-realize/src/main/java/com/fr/start/module/optimized/ConfigurationActivator4Designer.java new file mode 100644 index 000000000..35863aa48 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/start/module/optimized/ConfigurationActivator4Designer.java @@ -0,0 +1,27 @@ +package com.fr.start.module.optimized; + +import com.fr.config.activator.ConfigurationActivator; +import com.fr.config.dao.DaoContext; +import com.fr.config.dao.DaoSelectorFactory; +import com.fr.config.dao.impl.PropertiesClassHelperDao; +import com.fr.config.dao.impl.PropertiesEntityDao; +import com.fr.config.dao.impl.PropertiesXmlEntityDao; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/3/7 + */ +public class ConfigurationActivator4Designer extends ConfigurationActivator { + + @Override + protected void initLocalDao() { + if (DaoSelectorFactory.getDaoSelector().useCacheDao()) { + DaoContext.setClassHelperDao(new PropertiesClassHelperDao()); + DaoContext.setEntityDao(new PropertiesEntityDao()); + DaoContext.setXmlEntityDao(new PropertiesXmlEntityDao()); + } else { + super.initLocalDao(); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/start/module/optimized/ReportBaseActivator4Designer.java b/designer-realize/src/main/java/com/fr/start/module/optimized/ReportBaseActivator4Designer.java new file mode 100644 index 000000000..31986da01 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/start/module/optimized/ReportBaseActivator4Designer.java @@ -0,0 +1,32 @@ +package com.fr.start.module.optimized; + +import com.fr.config.dao.DaoSelectorFactory; +import com.fr.event.Event; +import com.fr.event.Listener; +import com.fr.event.Null; +import com.fr.report.module.ReportBaseActivator; +import com.fr.start.event.LazyStartupEvent; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/3/16 + */ +public class ReportBaseActivator4Designer extends ReportBaseActivator { + + @Override + protected void vcsInit() { + if (DaoSelectorFactory.getDaoSelector().useCacheDao()) { + listenEvent(LazyStartupEvent.INSTANCE, new Listener() { + @Override + public void on(Event event, Null param) { + ReportBaseActivator4Designer.super.vcsInit(); + } + }); + } else { + super.vcsInit(); + } + + + } +} diff --git a/designer-realize/src/main/java/com/fr/start/module/optimized/TenantDBAdapter4Designer.java b/designer-realize/src/main/java/com/fr/start/module/optimized/TenantDBAdapter4Designer.java new file mode 100644 index 000000000..d45913e1a --- /dev/null +++ b/designer-realize/src/main/java/com/fr/start/module/optimized/TenantDBAdapter4Designer.java @@ -0,0 +1,42 @@ +package com.fr.start.module.optimized; + +import com.fr.config.dao.DaoSelectorFactory; +import com.fr.config.dao.swicter.DaoSwitcher; +import com.fr.design.DesignerEnvManager; +import com.fr.event.Event; +import com.fr.event.Listener; +import com.fr.event.Null; +import com.fr.exit.ConfigToPropMigrator; +import com.fr.stable.db.tenant.TenantDBAdapter; +import com.fr.start.event.LazyStartupEvent; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/3/7 + */ +public class TenantDBAdapter4Designer extends TenantDBAdapter { + + @Override + public void start() { + if (DaoSelectorFactory.getDaoSelector().useCacheDao()) { + listenEvent(LazyStartupEvent.INSTANCE, new Listener() { + @Override + public void on(Event event, Null param) { + TenantDBAdapter4Designer.super.start(); + afterStart(); + } + }); + + } else { + super.start(); + } + } + + private void afterStart() { + DesignerEnvManager.getEnvManager().setPropertiesUsable(false); + DaoSwitcher.executeSwitch(); + ConfigToPropMigrator.getInstance().deletePropertiesCache(); + DesignerEnvManager.getEnvManager().saveXMLFile(); + } +} diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/blue_bulb.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/blue_bulb.svg new file mode 100644 index 000000000..6f8d92a46 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/blue_bulb.svg @@ -0,0 +1,4 @@ + + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bulb.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bulb.svg new file mode 100644 index 000000000..746f1fd61 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/bulb.svg @@ -0,0 +1,4 @@ + + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/clear.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/clear.svg new file mode 100644 index 000000000..815f7c31b --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/clear.svg @@ -0,0 +1,4 @@ + + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/close.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/close.svg new file mode 100644 index 000000000..68259ce14 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group.svg new file mode 100644 index 000000000..2c400e245 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group.svg @@ -0,0 +1,4 @@ + + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group_new.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group_new.svg new file mode 100644 index 000000000..af299d12b --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/group_new.svg @@ -0,0 +1,4 @@ + + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/groupbackgroud.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/groupbackgroud.svg new file mode 100644 index 000000000..4d1989ea6 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/groupbackgroud.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/history_search.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/history_search.svg new file mode 100644 index 000000000..35b5a2e75 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/history_search.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/hot_search.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/hot_search.svg new file mode 100644 index 000000000..35e2a657b --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/hot_search.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/minimize.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/minimize.svg new file mode 100644 index 000000000..76c199416 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/minimize.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/new_tip.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/new_tip.svg new file mode 100644 index 000000000..549e6e50a --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/new_tip.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/search.svg b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/search.svg new file mode 100644 index 000000000..245d4fa59 --- /dev/null +++ b/designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/search.svg @@ -0,0 +1,3 @@ + + +