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 84fd684ae8..24dd314844 100644 --- a/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java +++ b/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java @@ -7,8 +7,11 @@ import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.JTemplateProvider; +import com.fr.form.ui.DataControl; +import com.fr.form.ui.MultiFileEditor; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; import com.fr.stable.js.WidgetName; import java.util.Iterator; @@ -214,6 +217,17 @@ public abstract class DesignModelAdapter getWidgetsName(); + /** + * 判断是否是值编辑器可以设置的控件类型 + * @param widget 控件 + * @return 可以设置返回true,否则返回false + */ + public boolean widgetAccepted(Widget widget) { + return widget != null + && StringUtils.isNotEmpty(widget.getWidgetName()) + && (widget instanceof DataControl || widget instanceof MultiFileEditor); + } + /** * 更新缓存的参数 */ diff --git a/designer-base/src/main/java/com/fr/design/DesignState.java b/designer-base/src/main/java/com/fr/design/DesignState.java index fcc971b7e4..239093d3f1 100644 --- a/designer-base/src/main/java/com/fr/design/DesignState.java +++ b/designer-base/src/main/java/com/fr/design/DesignState.java @@ -1,9 +1,7 @@ package com.fr.design; -import com.fr.base.BaseUtils; import com.fr.base.vcs.DesignerMode; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; -import com.fr.workspace.WorkContext; /** * Created by IntelliJ IDEA. 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 8769454d14..6ebd349cbb 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -145,12 +145,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { //记录当前激活码的在线激活状态. private int activeKeyStatus = -1; private boolean joinProductImprove = true; + + private boolean embedServerLazyStartup = false; //最近使用的颜色 private ColorSelectConfigManager configManager = new ColorSelectConfigManager(); /** * alphafine */ - private AlphaFineConfigManager alphaFineConfigManager = new AlphaFineConfigManager(); + private AlphaFineConfigManager alphaFineConfigManager = AlphaFineConfigManager.getInstance(); private DesignerPushUpdateConfigManager designerPushUpdateConfigManager = DesignerPushUpdateConfigManager.getInstance(); @@ -264,6 +266,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { Thread.sleep(5000); } catch (InterruptedException e) { FineLoggerFactory.getLogger().error("Map Save Error"); + Thread.currentThread().interrupt(); } } } @@ -316,8 +319,9 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } private void createEnvFile(File envFile) { + FileWriter fileWriter = null; try { - FileWriter fileWriter = new FileWriter(envFile); + fileWriter = new FileWriter(envFile); File oldEnvFile = new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "6-1" + "Env.xml"); File envFile80 = new File(getEnvHome(VERSION_80) + File.separator + getEnvFile().getName()); if (oldEnvFile.exists()) { @@ -333,9 +337,17 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { Utils.copyCharTo(stringReader, fileWriter); stringReader.close(); } - fileWriter.close(); + } catch (IOException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + if (null != fileWriter) { + try { + fileWriter.close(); + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } } } @@ -650,9 +662,6 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { */ public void saveXMLFile() { File xmlFile = this.getDesignerEnvFile(); - if (xmlFile == null) { - return; - } if (!xmlFile.getParentFile().exists()) {//建立目录. StableUtils.mkdirs(xmlFile.getParentFile()); } @@ -711,6 +720,24 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { designerPushUpdateConfigManager.setAutoPushUpdateEnabled(autoPushUpdateEnabled); } + /** + * 内置服务器是否使用时启动 + * + * @return 结果 + */ + public boolean isEmbedServerLazyStartup() { + return embedServerLazyStartup; + } + + /** + * 设置内置服务器使用时启动 + * + * @param embedServerLazyStartup 使用时启动 + */ + public void setEmbedServerLazyStartup(boolean embedServerLazyStartup) { + this.embedServerLazyStartup = embedServerLazyStartup; + } + /** * 是否磁盘空间参数 * @@ -1525,7 +1552,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } private void readAlphaFineAttr(XMLableReader reader) { - reader.readXMLObject(this.alphaFineConfigManager = new AlphaFineConfigManager()); + reader.readXMLObject(this.alphaFineConfigManager = AlphaFineConfigManager.getInstance()); } private void readHttpsParas(XMLableReader reader) { @@ -1608,6 +1635,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if ((tmpVal = reader.getAttrAsString("recentSelectedConnection", null)) != null) { this.setRecentSelectedConnection(tmpVal); } + this.setEmbedServerLazyStartup(reader.getAttrAsBoolean("embedServerLazyStartup", false)); } private void readReportPaneAttributions(XMLableReader reader) { @@ -1852,6 +1880,9 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if (this.isTemplateTreePaneExpanded()) { writer.attr("templateTreePaneExpanded", this.isTemplateTreePaneExpanded()); } + if (this.isEmbedServerLazyStartup()) { + writer.attr("embedServerLazyStartup", this.isEmbedServerLazyStartup()); + } writer.end(); } diff --git a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java index 93f2824547..c1c11553f7 100644 --- a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java +++ b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java @@ -102,11 +102,7 @@ public class EnvChangeEntrance { return false; } - //REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录 - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (template != null) { - template.refreshToolArea(); - } + WorkContext.switchTo(workspace, new WorkContextCallback() { @Override public void done() { @@ -119,6 +115,11 @@ public class EnvChangeEntrance { } } }); + //REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录 + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + template.refreshToolArea(); + } } catch (WorkspaceAuthException | RegistEditionException e) { // String title = Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Auth_Failed"); diff --git a/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java b/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java index 77e0eb115c..bd2e50d570 100644 --- a/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java +++ b/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java @@ -5,19 +5,16 @@ package com.fr.design; import com.fr.base.BaseUtils; +import com.fr.common.annotations.Open; import com.fr.design.data.datapane.TableDataNameObjectCreator; -import com.fr.design.fun.CellWidgetOptionProvider; -import com.fr.design.fun.FormWidgetOptionProvider; -import com.fr.design.fun.ParameterWidgetOptionProvider; -import com.fr.design.fun.ServerTableDataDefineProvider; -import com.fr.design.fun.TableDataDefineProvider; -import com.fr.design.fun.ToolbarItemProvider; +import com.fr.design.fun.*; import com.fr.design.gui.core.WidgetOption; import com.fr.design.gui.core.WidgetOptionFactory; import com.fr.design.menu.ShortCut; import com.fr.design.widget.Appearance; import com.fr.design.widget.mobile.WidgetMobilePane; import com.fr.form.ui.Widget; +import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; import com.fr.plugin.AbstractExtraClassManager; import com.fr.plugin.injectable.PluginModule; @@ -39,6 +36,7 @@ import java.util.Set; * @since : 8.0 * 用于设计器扩展的管理类 */ +@Open public class ExtraDesignClassManager extends AbstractExtraClassManager implements ExtraDesignClassManagerProvider { private static ExtraDesignClassManager classManager = new ExtraDesignClassManager(); @@ -220,6 +218,20 @@ public class ExtraDesignClassManager extends AbstractExtraClassManager implement return map; } + public MobileWidgetStyleProvider[] getMobileStyleOfWidget(String xType) { + Set set = getArray(MobileWidgetStyleProvider.XML_TAG); + if (set.isEmpty()) { + return new MobileWidgetStyleProvider[0]; + } + List providers = new ArrayList<>(); + for (MobileWidgetStyleProvider provider: set) { + if(ComparatorUtils.equalsIgnoreCase(provider.xTypeForWidget(), xType)) { + providers.add(provider); + } + } + return providers.toArray(new MobileWidgetStyleProvider[providers.size()]); + } + @Override protected boolean demountSpecific(PluginSingleInjection injection) { 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 6f1b77acb2..cdb4fc532e 100644 --- a/designer-base/src/main/java/com/fr/design/RestartHelper.java +++ b/designer-base/src/main/java/com/fr/design/RestartHelper.java @@ -1,14 +1,17 @@ package com.fr.design; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.os.impl.RestartAction; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; -import com.fr.stable.OperatingSystem; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import com.fr.stable.os.support.OSBasedAction; +import com.fr.workspace.WorkContext; +import javax.swing.*; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -16,8 +19,6 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Properties; @@ -30,7 +31,7 @@ public class RestartHelper { public static final String RECORD_FILE = StableUtils.pathJoin(StableUtils.getInstallHome(), "delete.properties"); public static final String MOVE_FILE = StableUtils.pathJoin(StableUtils.getInstallHome(), "move.properties"); - + private static final OSBasedAction restartAction = new RestartAction(); /** * 把要删除的文件都记录到delete.properties中 @@ -143,6 +144,20 @@ public class RestartHelper { restart(ArrayUtils.EMPTY_STRING_ARRAY); } + public static void restartForUpdate(JFrame frame) { + try { + restartAction.execute(ArrayUtils.EMPTY_STRING_ARRAY); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } finally { + WorkContext.getCurrent().close(); + frame.dispose(); + System.exit(0); + } + } + + + /** * 重启设计器并删除某些特定的文件 * @@ -154,12 +169,12 @@ public class RestartHelper { deleteWhenDebug(); return; } - + RandomAccessFile randomAccessFile = null; try { try { File restartLockFile = new File(StableUtils.pathJoin(StableUtils.getInstallHome(), "restart.lock")); StableUtils.makesureFileExist(restartLockFile); - RandomAccessFile randomAccessFile = new RandomAccessFile(restartLockFile,"rw"); + randomAccessFile = new RandomAccessFile(restartLockFile,"rw"); FileChannel restartLockFC = randomAccessFile.getChannel(); FileLock restartLock = restartLockFC.tryLock(); if(restartLock == null) { @@ -168,39 +183,18 @@ public class RestartHelper { }catch (Exception e){ FineLoggerFactory.getLogger().error(e.getMessage(), e); } - if (OperatingSystem.isMacOS()) { - restartInMacOS(installHome, filesToBeDelete); - } else { - restartInWindows(installHome, filesToBeDelete); - } + restartAction.execute(filesToBeDelete); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } finally { + try { + if (null != randomAccessFile) { + randomAccessFile.close(); + } + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } DesignerContext.getDesignerFrame().exit(); } } - - private static void restartInMacOS(String installHome, String[] filesToBeDelete) throws Exception { - ProcessBuilder builder = new ProcessBuilder(); - List commands = new ArrayList(); - commands.add("open"); - commands.add(installHome + File.separator + "bin" + File.separator + "restart.app"); - if (ArrayUtils.isNotEmpty(filesToBeDelete)) { - commands.add("--args"); - commands.add(StableUtils.join(filesToBeDelete, "+")); - } - builder.command(commands); - builder.start(); - } - - private static void restartInWindows(String installHome, String[] filesToBeDelete) throws Exception { - ProcessBuilder builder = new ProcessBuilder(); - List commands = new ArrayList(); - commands.add(installHome + File.separator + "bin" + File.separator + "restart.exe"); - if (ArrayUtils.isNotEmpty(filesToBeDelete)) { - commands.add(StableUtils.join(filesToBeDelete, "+")); - } - builder.command(commands); - builder.start(); - } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java b/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java index 717537df6f..9a19ef4cc9 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java @@ -10,38 +10,37 @@ import javax.swing.*; import java.awt.event.ActionEvent; -public class QuestionAction extends UpdateAction -{ - - public QuestionAction() - { this.setMenuKeySet(QUESTIONS); - this.setName(getMenuKeySet().getMenuName()); - this.setMnemonic(getMenuKeySet().getMnemonic()); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/bbs/question.png")); - -} - -@Override -public void actionPerformed(ActionEvent arg0) -{ - String url = CloudCenter.getInstance().acquireUrlByKind("bbs.questions"); - BrowseUtils.browser(url); -} - public static final MenuKeySet QUESTIONS = new MenuKeySet() { - @Override - public char getMnemonic() { - return 'Q'; - } - - @Override - public String getMenuName() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Community_Questions"); - } - - @Override - public KeyStroke getKeyStroke() { - return null; - } - }; +public class QuestionAction extends UpdateAction { + + public QuestionAction() { + this.setMenuKeySet(QUESTIONS); + this.setName(getMenuKeySet().getMenuName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/bbs/question.png")); + + } + + @Override + public void actionPerformed(ActionEvent arg0) { + String url = CloudCenter.getInstance().acquireUrlByKind("bbs.questions"); + BrowseUtils.browser(url); + } + + public static final MenuKeySet QUESTIONS = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'Q'; + } + + @Override + public String getMenuName() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Community_Questions"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; } diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 180e5a50e1..43d7391775 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 @@ -1,9 +1,11 @@ package com.fr.design.actions.file; +import com.fr.cluster.ClusterBridge; +import com.fr.cluster.engine.base.FineClusterConfig; import com.fr.config.Configuration; +import com.fr.config.ServerPreferenceConfig; import com.fr.design.DesignerEnvManager; import com.fr.design.RestartHelper; -import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; @@ -17,19 +19,19 @@ import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIDictionaryComboBox; import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.iprogressbar.UIProgressBarUI; 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; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.vcs.VcsConfigManager; import com.fr.design.mainframe.vcs.common.VcsHelper; -import com.fr.design.update.push.DesignerPushUpdateManager; +import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.widget.FRWidgetFactory; -import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.FRFont; import com.fr.general.IOUtils; @@ -37,35 +39,25 @@ import com.fr.general.Inter; import com.fr.general.log.Log4jConfig; import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; +import com.fr.stable.Constants; import com.fr.third.apache.log4j.Level; import com.fr.transaction.Configurations; import com.fr.transaction.Worker; - -import javax.swing.BorderFactory; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Desktop; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; +import com.fr.workspace.server.vcs.git.config.GcConfig; + +import javax.swing.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; import java.io.File; -import java.net.URI; +import java.text.DecimalFormat; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ExecutionException; + +import static com.fr.design.i18n.Toolkit.i18nText; /** * 选项对话框 @@ -111,7 +103,6 @@ public class PreferencePane extends BasicPane { private static final String DISPLAY_EQUALS = "+"; private static final String MINUS = "MINUS"; private static final String DISPLAY_MINUS = "-"; - private static final String PRIVACY_POLICY = "design.privacy"; private static final Level[] LOG = {Level.FATAL, Level.ERROR, Level.WARN, Level.INFO, Level.DEBUG}; @@ -143,20 +134,27 @@ public class PreferencePane extends BasicPane { private IntegerEditor portEditor; private UICheckBox oracleSpace; private UISpinner cachingTemplateSpinner; - private UICheckBox openDebugComboBox; private UICheckBox useOptimizedUPMCheckbox; private UICheckBox useUniverseDBMCheckbox; private UICheckBox joinProductImproveCheckBox; private UICheckBox autoPushUpdateCheckBox; + private UICheckBox embedServerLazyStartupCheckBox; private UICheckBox vcsEnableCheckBox; private UICheckBox saveCommitCheckBox; private UICheckBox useIntervalCheckBox; private IntegerEditor saveIntervalEditor; + private UICheckBox gcEnableCheckBox; + private UIButton gcButton; private UILabel remindVcsLabel; - private UILabel linkLabel; - + private JDialog gcDialog; + private UILabel gcMessage = new UILabel(); + private JPanel gcDialogDownPane = new JPanel(); + private JPanel gcProgressBarPanel = new JPanel(); + private JProgressBar gcProgressBar; + private Timer gcProgressTimer; + private UIButton gcOkButton = new UIButton(i18nText("Fine-Design_Report_OK")); public PreferencePane() { this.initComponents(); @@ -169,9 +167,9 @@ public class PreferencePane extends BasicPane { UITabbedPane jtabPane = new UITabbedPane(); JPanel generalPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); - jtabPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_General"), generalPane); + jtabPane.addTab(i18nText("Fine-Design_Basic_General"), generalPane); JPanel advancePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); - jtabPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Advanced"), advancePane); + jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), advancePane); contentPane.add(jtabPane, BorderLayout.NORTH); createFunctionPane(generalPane); @@ -192,75 +190,66 @@ public class PreferencePane extends BasicPane { createServerPane(advancePane); - JPanel oraclePane = FRGUIPaneFactory.createTitledBorderPane("Oracle" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Oracle_All_Tables")); - oracleSpace = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Show_All_Oracle_Tables")); + JPanel oraclePane = FRGUIPaneFactory.createTitledBorderPane("Oracle" + i18nText("Fine-Design_Basic_Oracle_All_Tables")); + oracleSpace = new UICheckBox(i18nText("Fine-Design_Basic_Show_All_Oracle_Tables")); oraclePane.add(oracleSpace); -// JPanel debuggerPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Develop_Tools")); -// openDebugComboBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Open_Debug_Window")); -// debuggerPane.add(openDebugComboBox, BorderLayout.CENTER); -// advancePane.add(debuggerPane); -// -// JPanel upmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager")); -// useOptimizedUPMCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Use_New_Update_Plugin_Manager")); -// upmSelectorPane.add(useOptimizedUPMCheckbox); -// advancePane.add(upmSelectorPane); -// -// JPanel dbmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Manager")); -// useUniverseDBMCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Use_Universe_Database_Manager")); -// dbmSelectorPane.add(useUniverseDBMCheckbox); -// advancePane.add(dbmSelectorPane); - - JPanel improvePane = FRGUIPaneFactory.createVerticalTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Product_Improve")); - joinProductImproveCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Join_Product_Improve")); - linkLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Privacy_Policy")); - linkLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - linkLabel.setForeground(UIConstants.NORMAL_BLUE); - linkLabel.addMouseListener(new MouseAdapter(){ - @Override - public void mouseClicked(MouseEvent e) { - try { - Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind(PRIVACY_POLICY))); - } catch (Exception e1) { - FineLoggerFactory.getLogger().error(e1.getMessage(), e1); - } - } - }); - double p = TableLayout.PREFERRED; - double rowSize[] = {p}; - double columnSize[] = {p, p}; - Component[][] components = { - {joinProductImproveCheckBox, linkLabel}, - }; - JPanel choosePane = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); - improvePane.add(choosePane); - if (DesignerPushUpdateManager.getInstance().isAutoPushUpdateSupported()) { - autoPushUpdateCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Automatic_Push_Update")); + JPanel upmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Update_Plugin_Manager")); + useOptimizedUPMCheckbox = new UICheckBox(i18nText("Fine-Design_Basic_Use_New_Update_Plugin_Manager")); + upmSelectorPane.add(useOptimizedUPMCheckbox); + advancePane.add(upmSelectorPane); + + JPanel dbmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Database_Manager")); + useUniverseDBMCheckbox = new UICheckBox(i18nText("Fine-Design_Basic_Use_Universe_Database_Manager")); + dbmSelectorPane.add(useUniverseDBMCheckbox); + advancePane.add(dbmSelectorPane); + + JPanel improvePane = FRGUIPaneFactory.createVerticalTitledBorderPane(i18nText("Fine-Design_Basic_Product_Improve")); + joinProductImproveCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Join_Product_Improve")); + improvePane.add(joinProductImproveCheckBox); + + if(SupportOSImpl.AUTOPUSHUPDATE.support()){ + autoPushUpdateCheckBox = new UICheckBox(i18nText("Fine-Design_Automatic_Push_Update")); improvePane.add(autoPushUpdateCheckBox); } + /* + if (DesignerPushUpdateManager.getInstance().isAutoPushUpdateSupported()) { + autoPushUpdateCheckBox = new UICheckBox(i18nText("Fine-Design_Automatic_Push_Update")); + improvePane.add(autoPushUpdateCheckBox); + }*/ JPanel spaceUpPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); spaceUpPane.add(oraclePane, BorderLayout.NORTH); spaceUpPane.add(createMemoryPane(), BorderLayout.CENTER); spaceUpPane.add(improvePane, BorderLayout.SOUTH); advancePane.add(spaceUpPane); + + JPanel embedServerPanel = FRGUIPaneFactory.createVerticalTitledBorderPane(i18nText("Fine-Design_Embed_Server")); + embedServerLazyStartupCheckBox = new UICheckBox(i18nText("Fine-Design_Startup_When_Needed")); + embedServerPanel.add(embedServerLazyStartupCheckBox); + advancePane.add(embedServerPanel); + } private void createVcsSettingPane(JPanel generalPane) { - JPanel vcsPane = FRGUIPaneFactory.createVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Vcs_Title")); + JPanel vcsPane = FRGUIPaneFactory.createVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Title")); generalPane.add(vcsPane); - remindVcsLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Remind")); + remindVcsLabel = new UILabel(i18nText("Fine-Design_Vcs_Remind")); remindVcsLabel.setVisible(!VcsHelper.getInstance().needInit()); - vcsEnableCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Vcs_SaveAuto")); - saveCommitCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Vcs_No_Delete")); + vcsEnableCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_SaveAuto")); + saveCommitCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_No_Delete")); saveIntervalEditor = new IntegerEditor(60); useIntervalCheckBox = new UICheckBox(); + + //gc面板 + JPanel gcControlPane = createGcControlPane(); + JPanel enableVcsPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout()); enableVcsPanel.add(vcsEnableCheckBox); enableVcsPanel.add(remindVcsLabel); JPanel intervalPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout()); - final UILabel everyLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Every")); - final UILabel delayLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Delay")); + final UILabel everyLabel = new UILabel(i18nText("Fine-Design_Vcs_Every")); + final UILabel delayLabel = new UILabel(i18nText("Fine-Design_Vcs_Delay")); intervalPanel.add(useIntervalCheckBox); intervalPanel.add(everyLabel); intervalPanel.add(saveIntervalEditor); @@ -269,7 +258,7 @@ public class PreferencePane extends BasicPane { @Override public void stateChanged(ChangeEvent e) { boolean selected = vcsEnableCheckBox.isSelected(); - if (selected) { + if (selected && vcsEnableCheckBox.isEnabled()) { saveCommitCheckBox.setEnabled(true); saveIntervalEditor.setEnabled(true); useIntervalCheckBox.setEnabled(true); @@ -287,24 +276,55 @@ public class PreferencePane extends BasicPane { vcsPane.add(enableVcsPanel); vcsPane.add(intervalPanel); vcsPane.add(saveCommitCheckBox); + vcsPane.add(gcControlPane); + } + + /** + * 模创建板版本gc 配置操作面板 + * + * @return 面板 + */ + private JPanel createGcControlPane() { + //gc面板 + JPanel gcControlPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + JPanel gcButtonPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 40, 0)); + gcEnableCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_Storage_Optimization")); + gcButton = initGcButton(); + gcButtonPane.add(gcButton); + gcControlPane.add(gcEnableCheckBox); + gcControlPane.add(gcButtonPane); + gcButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + tryGc(); + } + }); + gcEnableCheckBox.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + gcButton.setEnabled(gcEnableCheckBox.isSelected() && gcEnableCheckBox.isEnabled()); + } + }); + return gcControlPane; } private void createFunctionPane(JPanel generalPane) { - JPanel functionPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Function")); + JPanel functionPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Function")); generalPane.add(functionPane); //添加supportUndo选择项 - supportUndoCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Support_Undo")); + supportUndoCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Support_Undo")); functionPane.add(supportUndoCheckBox); //添加maxUndoLimit //String[] undoTimes = {"最大撤销次数","5次","10次","15次","20次","50次"}; - String[] undoTimes = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Max_Undo_Limit"), MAX_UNDO_LIMIT_5 + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_10 + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Time(s)") - , MAX_UNDO_LIMIT_15 + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_20 + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_50 + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Time(s)")}; + String[] undoTimes = {i18nText("Fine-Design_Basic_Max_Undo_Limit"), MAX_UNDO_LIMIT_5 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_10 + i18nText("Fine-Design_Basic_Time(s)") + , MAX_UNDO_LIMIT_15 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_20 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_50 + i18nText("Fine-Design_Basic_Time(s)")}; maxUndoLimit = new UIComboBox(undoTimes); functionPane.add(maxUndoLimit); //不支持撤销则不能选择撤销可缓存,也不能设置最大撤销次数 supportUndoCheckBox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { maxUndoLimit.setEnabled(supportUndoCheckBox.isSelected()); } @@ -313,31 +333,32 @@ public class PreferencePane extends BasicPane { //添加supportDefaultParentCalculate选择项 supportDefaultParentCalculateCheckBox = new UICheckBox( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Support_Default_Parent_Calculate")); + i18nText("Fine-Design_Basic_Preference_Support_Default_Parent_Calculate")); functionPane.add(supportDefaultParentCalculateCheckBox); } private void createEditPane(JPanel generalPane) { //samuel:编辑器设置 - JPanel editPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Editor_Preference")); + JPanel editPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Editor_Preference")); generalPane.add(editPane); //设置是否支持将字符串编辑为公式 - supportStringToFormulaBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Support_String_To_Formula")); + supportStringToFormulaBox = new UICheckBox(i18nText("Fine-Design_Report_Support_String_To_Formula")); editPane.add(supportStringToFormulaBox); //是否默认转化 - defaultStringToFormulaBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Always")); + defaultStringToFormulaBox = new UICheckBox(i18nText("Fine-Design_Basic_Always")); editPane.add(defaultStringToFormulaBox); //不支持转化则不能默认执行 supportStringToFormulaBox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { defaultStringToFormulaBox.setEnabled(supportStringToFormulaBox.isSelected()); } }); JPanel keyStrokePane = new JPanel(new BorderLayout()); - keyStrokePane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Support_Auto_Complete_Shortcut") + ":"), BorderLayout.WEST); + keyStrokePane.add(new UILabel(i18nText("Fine-Design_Basic_Support_Auto_Complete_Shortcut") + ":"), BorderLayout.WEST); shortCutLabel = new UILabel(); keyStrokePane.add(shortCutLabel, BorderLayout.CENTER); editPane.add(keyStrokePane); @@ -367,7 +388,7 @@ public class PreferencePane extends BasicPane { requestFocusInWindow(); label = new UILabel(text); add(GUICoreUtils.createBorderLayoutPane( - new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Support_Current_Auto_Complete_Shortcut") + ":"), + new UILabel(i18nText("Fine-Design_Basic_Support_Current_Auto_Complete_Shortcut") + ":"), BorderLayout.WEST, label, BorderLayout.CENTER), @@ -401,24 +422,24 @@ public class PreferencePane extends BasicPane { private void createGuiOfGridPane(JPanel generalPane) { // GridPane - JPanel guiOfGridPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Setting_Grid")); + JPanel guiOfGridPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Setting_Grid")); generalPane.add(guiOfGridPane); - supportCellEditorDefCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Support_Cell_Editor_Definition")); + supportCellEditorDefCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Support_Cell_Editor_Definition")); guiOfGridPane.add(supportCellEditorDefCheckBox); - isDragPermitedCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Is_Drag_Permited")); + isDragPermitedCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Is_Drag_Permited")); guiOfGridPane.add(isDragPermitedCheckBox); } private void createColorSettingPane(JPanel generalPane) { // Color Setting Pane - JPanel colorSettingPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Setting_Colors")); + JPanel colorSettingPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Setting_Colors")); generalPane.add(colorSettingPane); - new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Grid_Line_Color")); + new UILabel(i18nText("Fine-Design_Basic_Preference_Grid_Line_Color")); - new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Pagination_Line_Color")); + new UILabel(i18nText("Fine-Design_Basic_Preference_Pagination_Line_Color")); gridLineColorTBButton = new UIColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); gridLineColorTBButton.setEnabled(this.isEnabled()); @@ -427,10 +448,10 @@ public class PreferencePane extends BasicPane { paginationLineColorTBButton.setEnabled(this.isEnabled()); JPanel leftPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - leftPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Grid_Line_Color") + ":")); + leftPane.add(new UILabel(i18nText("Fine-Design_Basic_Preference_Grid_Line_Color") + ":")); leftPane.add(gridLineColorTBButton); JPanel rightPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - rightPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Pagination_Line_Color") + ":")); + rightPane.add(new UILabel(i18nText("Fine-Design_Basic_Preference_Pagination_Line_Color") + ":")); rightPane.add(paginationLineColorTBButton); colorSettingPane.add(leftPane); colorSettingPane.add(rightPane); @@ -440,9 +461,9 @@ public class PreferencePane extends BasicPane { //richer:选择导出log文件的目录. JPanel logPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); advancePane.add(logPane); - JPanel logExportPane = FRGUIPaneFactory.createTitledBorderPane("log" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Export_Setting")); + JPanel logExportPane = FRGUIPaneFactory.createTitledBorderPane("log" + i18nText("Fine-Design_Basic_Export_Setting")); logPane.add(logExportPane); - UILabel logLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Select_Export_Log_Directory") + ":"); + UILabel logLabel = new UILabel(i18nText("Fine-Design_Basic_Select_Export_Log_Directory") + ":"); logExportPane.add(logLabel, BorderLayout.WEST); logExportDirectoryField = new UITextField(24); logExportPane.add(logExportDirectoryField, BorderLayout.CENTER); @@ -450,6 +471,7 @@ public class PreferencePane extends BasicPane { logExportPane.add(chooseDirBtn, BorderLayout.EAST); chooseDirBtn.setPreferredSize(new Dimension(25, 25)); chooseDirBtn.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent evt) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -461,11 +483,12 @@ public class PreferencePane extends BasicPane { } }); - JPanel logLevelPane = FRGUIPaneFactory.createTitledBorderPane("log" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Level_Setting")); + JPanel logLevelPane = FRGUIPaneFactory.createTitledBorderPane("log" + i18nText("Fine-Design_Basic_Level_Setting")); logPane.add(logLevelPane); logLevelComboBox = new UIComboBox(LOG); logLevelPane.add(logLevelComboBox); logLevelComboBox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { Configurations.update(new Worker() { @Override @@ -485,13 +508,13 @@ public class PreferencePane extends BasicPane { private void createLanPane(JPanel generalPane) { // ben:选择版本语言; JPanel languageAndDashBoard_pane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); - JPanel LanguagePane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Choose_Language")); + JPanel LanguagePane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Choose_Language")); generalPane.add(languageAndDashBoard_pane); languageAndDashBoard_pane.add(LanguagePane); languageComboBox = createLanguageComboBox(); - ActionLabel languageLabel = new ActionLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Designer_Language")); + ActionLabel languageLabel = new ActionLabel(i18nText("Fine-Design_Basic_Designer_Language")); languageLabel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -505,7 +528,7 @@ public class PreferencePane extends BasicPane { dlg.setVisible(true); } }); - UILabel noticeLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Work_After_Restart_Designer"));//sail:提示重启后生效 + UILabel noticeLabel = new UILabel(i18nText("Fine-Design_Basic_Work_After_Restart_Designer"));//sail:提示重启后生效 double p = TableLayout.PREFERRED; double rowSize[] = {p}; double columnSize[] = {p, p, p}; @@ -551,16 +574,16 @@ public class PreferencePane extends BasicPane { double rowSize[] = {p}; // 长度单位选择 - JPanel lengthPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Setting_Ruler_Units")); + JPanel lengthPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Setting_Ruler_Units")); advancePane.add(lengthPane); - pageLengthComboBox = new UIComboBox(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Page_Setup_MM"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Unit_CM"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Unit_INCH")}); + pageLengthComboBox = new UIComboBox(new String[]{i18nText("Fine-Design_Basic_Page_Setup_MM"), i18nText("Fine-Design_Report_Unit_CM"), i18nText("Fine-Design_Report_Unit_INCH")}); pageLengthComboBox.setPreferredSize(new Dimension(80, 20)); pageLengthComboBox.setMinimumSize(new Dimension(80, 20)); - reportLengthComboBox = new UIComboBox(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Page_Setup_MM"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Unit_CM"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Unit_INCH"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Unit_PT_Duplicate")}); + reportLengthComboBox = new UIComboBox(new String[]{i18nText("Fine-Design_Basic_Page_Setup_MM"), i18nText("Fine-Design_Report_Unit_CM"), i18nText("Fine-Design_Report_Unit_INCH"), i18nText("Fine-Design_Report_Unit_PT_Duplicate")}); reportLengthComboBox.setPreferredSize(new Dimension(80, 20)); reportLengthComboBox.setMinimumSize(new Dimension(80, 20)); - UILabel pagelengthLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Page_Setup_Scale_Units") + ":"); - UILabel reportLengthLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Report_Design_Ruler_Units") + ":"); + UILabel pagelengthLabel = new UILabel(i18nText("Fine-Design_Basic_Page_Setup_Scale_Units") + ":"); + UILabel reportLengthLabel = new UILabel(i18nText("Fine-Design_Basic_Report_Design_Ruler_Units") + ":"); Component[][] lengthComponents = { {pagelengthLabel, pageLengthComboBox, reportLengthLabel, reportLengthComboBox}, }; @@ -573,13 +596,13 @@ public class PreferencePane extends BasicPane { double rowSize[] = {p}; double columnSize[] = {p, p, p}; - JPanel serverPortPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Web_Preview_Port_Setting")); + JPanel serverPortPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Web_Preview_Port_Setting")); advancePane.add(serverPortPane); portEditor = new IntegerEditor(); portEditor.setPreferredSize(new Dimension(80, 20)); portEditor.setMinimumSize(new Dimension(80, 20)); - UILabel notiJlabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Work_After_Restart_Designer")); - UILabel serverPortLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Web_Preview_Port") + ":"); + UILabel notiJlabel = new UILabel(i18nText("Fine-Design_Basic_Work_After_Restart_Designer")); + UILabel serverPortLabel = new UILabel(i18nText("Fine-Design_Basic_Web_Preview_Port") + ":"); Component[][] portComponents = { {serverPortLabel, portEditor, notiJlabel}, }; @@ -588,10 +611,10 @@ public class PreferencePane extends BasicPane { } private JPanel createMemoryPane() { - JPanel memoryPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Caching_Template")); - UILabel memoryLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Max_Caching_Template")); + JPanel memoryPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Caching_Template")); + UILabel memoryLabel = new UILabel(i18nText("Fine-Design_Basic_Preference_Max_Caching_Template")); UILabel memoryTipLabel = FRWidgetFactory.createLineWrapLabel( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Caching_Template_Tip"), MEMORY_TIP_LABEL_MAX_WIDTH); + i18nText("Fine-Design_Basic_Preference_Caching_Template_Tip"), MEMORY_TIP_LABEL_MAX_WIDTH); memoryTipLabel.setBorder(BorderFactory.createEmptyBorder(0, CACHING_GAP, 0, 0)); cachingTemplateSpinner = new UISpinner(0, CACHING_MAX, 1, CACHING_DEFAULT); JPanel memorySpace = new JPanel(FRGUIPaneFactory.createLeftZeroLayout()); @@ -604,7 +627,7 @@ public class PreferencePane extends BasicPane { @Override protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_M_Window_Preference"); + return i18nText("Fine-Design_Basic_M_Window_Preference"); } /** @@ -639,6 +662,11 @@ public class PreferencePane extends BasicPane { defaultStringToFormulaBox.setSelected(false); } VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); + if (FineClusterConfig.getInstance().isCluster()) { + vcsEnableCheckBox.setEnabled(false); + gcEnableCheckBox.setEnabled(false); + } + if (VcsHelper.getInstance().needInit()) { vcsEnableCheckBox.setSelected(vcsConfigManager.isVcsEnable()); } else { @@ -654,7 +682,8 @@ public class PreferencePane extends BasicPane { saveIntervalEditor.setValue(vcsConfigManager.getSaveInterval()); saveCommitCheckBox.setSelected(vcsConfigManager.isSaveCommit()); useIntervalCheckBox.setSelected(vcsConfigManager.isUseInterval()); - + gcEnableCheckBox.setSelected(GcConfig.getInstance().isGcEnable()); + gcButton.setEnabled(gcEnableCheckBox.isSelected()); supportCellEditorDefCheckBox.setSelected(designerEnvManager.isSupportCellEditorDef()); isDragPermitedCheckBox.setSelected(designerEnvManager.isDragPermited()); @@ -673,10 +702,9 @@ public class PreferencePane extends BasicPane { this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort())); -// openDebugComboBox.setSelected(designerEnvManager.isOpenDebug()); -// useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()); -// -// useUniverseDBMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseUniverseDBM()); + useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()); + + useUniverseDBMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseUniverseDBM()); this.oracleSpace.setSelected(designerEnvManager.isOracleSystemSpace()); this.cachingTemplateSpinner.setValue(designerEnvManager.getCachingTemplateLimit()); @@ -685,6 +713,8 @@ public class PreferencePane extends BasicPane { if (this.autoPushUpdateCheckBox != null) { this.autoPushUpdateCheckBox.setSelected(designerEnvManager.isAutoPushUpdateEnabled()); } + + this.embedServerLazyStartupCheckBox.setSelected(designerEnvManager.isEmbedServerLazyStartup()); } private int chooseCase(int sign) { @@ -741,16 +771,27 @@ public class PreferencePane extends BasicPane { designerEnvManager.setJettyServerPort(portEditor.getValue().intValue()); -// designerEnvManager.setOpenDebug(openDebugComboBox.isSelected()); - designerEnvManager.setOracleSystemSpace(this.oracleSpace.isSelected()); designerEnvManager.setCachingTemplateLimit((int) this.cachingTemplateSpinner.getValue()); designerEnvManager.setJoinProductImprove(this.joinProductImproveCheckBox.isSelected()); + designerEnvManager.setEmbedServerLazyStartup(this.embedServerLazyStartupCheckBox.isSelected()); VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue()); vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected()); vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected()); vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected()); + Configurations.update(new Worker() { + @Override + public void run() { + GcConfig.getInstance().setGcEnable(gcEnableCheckBox.isSelected()); + } + + @Override + public Class[] targets() { + return new Class[]{GcConfig.class}; + } + }); + if (this.autoPushUpdateCheckBox != null) { designerEnvManager.setAutoPushUpdateEnabled(this.autoPushUpdateCheckBox.isSelected()); } @@ -772,21 +813,20 @@ public class PreferencePane extends BasicPane { } }); -// Configurations.update(new Worker() { -// @Override -// public void run() { -// ServerPreferenceConfig.getInstance().setUseOptimizedUPM(useOptimizedUPMCheckbox.isSelected()); -// ServerPreferenceConfig.getInstance().setUseUniverseDBM(useUniverseDBMCheckbox.isSelected()); -// } -// -// @Override -// public Class[] targets() { -// return new Class[] {ServerPreferenceConfig.class}; -// } -// }); + Configurations.update(new Worker() { + @Override + public void run() { + ServerPreferenceConfig.getInstance().setUseOptimizedUPM(useOptimizedUPMCheckbox.isSelected()); + ServerPreferenceConfig.getInstance().setUseUniverseDBM(useUniverseDBMCheckbox.isSelected()); + } - } + @Override + public Class[] targets() { + return new Class[]{ServerPreferenceConfig.class}; + } + }); + } // 如果语言设置改变了,则显示重启对话框 public void showRestartDialog() { @@ -795,12 +835,12 @@ public class PreferencePane extends BasicPane { } int rv = JOptionPane.showOptionDialog( null, - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Language_Change_Successful"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), + i18nText("Fine-Design_Basic_Language_Change_Successful"), + i18nText("Fine-Design_Basic_Plugin_Warning"), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, - new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Restart_Designer"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Restart_Designer_Later")}, + new String[]{i18nText("Fine-Design_Basic_Restart_Designer"), i18nText("Fine-Design_Basic_Restart_Designer_Later")}, null ); if (rv == JOptionPane.OK_OPTION) { @@ -822,4 +862,204 @@ public class PreferencePane extends BasicPane { public BasicDialog showWindow(Window window, DialogActionListener l) { return showWindowWithCustomSize(window, l, new Dimension(BasicDialog.DEFAULT.width, this.getPreferredSize().height + OFFSET_HEIGHT)); } + + private void tryGc() { + final SwingWorker worker = new SwingWorker() { + private long size = 0; + + @Override + protected Boolean doInBackground() { + size = WorkContext.getCurrent().get(VcsOperator.class).immediatelyGc(); + return true; + } + + @Override + protected void done() { + try { + get(); + } catch (ExecutionException e) { + updateGcDialogPanelInfo(i18nText("Fine-Design_Vcs_Need_Update_Remote_Server_Jar")); + return; + } catch (InterruptedException e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + updateGcDialogPanelInfo(i18nText("Fine-Design_Vcs_Reduce_File_Size") + fileSizeConvert(size)); + gcDialogDownPane.revalidate(); + gcDialogDownPane.repaint(); + gcDialogDownPane.add(gcOkButton); + } + }; + worker.execute(); + initGcDialog(); + gcOkButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + gcDialog.dispose(); + } + }); + gcDialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + stopGcProgressTimer(); + worker.cancel(true); + } + }); + gcDialog.setVisible(true); + gcDialog.dispose(); + } + + /** + * gc 后更新进度条面板信息 + * + * @param message + */ + private void updateGcDialogPanelInfo(String message) { + stopGcProgressTimer(); + gcMessage.setText(message); + if (null != gcProgressBar) { + gcProgressBarPanel.remove(gcProgressBar); + } + if (null != gcDialog) { + gcDialog.setTitle(i18nText("Fine-Design_Form_Joption_News")); + } + } + + /** + * 初始化 gc 对话框 + */ + private void initGcDialog() { + gcDialog = new JDialog((Dialog) SwingUtilities.getWindowAncestor(PreferencePane.this), i18nText("Fine-Design_Vcs_Clean_Progress") + "...", true); + gcDialog.setSize(new Dimension(340, 140)); + + JPanel jp = new JPanel(); + //中上 + JPanel gcUpPane = new JPanel(); + gcUpPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); + gcUpPane.add(new UILabel(UIManager.getIcon("OptionPane.informationIcon"))); + gcProgressBarPanel = createProgressBarPane(); + gcUpPane.add(gcProgressBarPanel); + + //中下 + gcDialogDownPane = new JPanel(); + gcDialogDownPane.setLayout(new FlowLayout(FlowLayout.CENTER, 6, 0)); + + jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS)); + jp.add(gcUpPane); + jp.add(gcDialogDownPane); + gcDialog.add(jp); + gcDialog.setResizable(false); + gcDialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(PreferencePane.this)); + } + + /** + * gc 进度条面板 + * + * @return + */ + private JPanel createProgressBarPane() { + JPanel jp = new JPanel(); + VerticalFlowLayout layout = new VerticalFlowLayout(); + layout.setAlignLeft(true); + jp.setLayout(layout); + + //提示 + gcMessage = new UILabel(i18nText("Fine-Design_Vcs_Cleaning")); + // 创建一个进度条 + gcProgressBar = createGcProgressBar(0, 30, 240, 15, Color.GREEN); + gcProgressTimer = createGcProgressTimer(500, gcProgressBar); + gcProgressTimer.start(); + jp.add(gcMessage); + jp.add(gcProgressBar); + return jp; + } + + /** + * 创建 gc 进度条 + * + * @param min 最小值 + * @param max 最大值 + * @param width 宽度 + * @param height 高度 + * @param color 填充的图片颜色 + * @return + */ + private JProgressBar createGcProgressBar(int min, int max, int width, int height, Color color) { + // 创建一个进度条 + JProgressBar progressBar = new JProgressBar(min, max); + UIProgressBarUI progressBarUI = new UIProgressBarUI(); + progressBar.setUI(progressBarUI); + + //颜色(进度条里的小方块) + progressBar.setForeground(color); + + progressBar.setOpaque(false); + progressBar.setPreferredSize(new Dimension(width, height)); + return progressBar; + } + + /** + * @param delay 每隔 delay 毫秒更新进度 + * @param progressBar 要更新的进度条 + * @return + */ + private Timer createGcProgressTimer(int delay, final JProgressBar progressBar) { + if (null == progressBar) { + return null; + } + // 模拟延时操作进度, 每隔 delay / 1000 秒更新进度 + Timer timer = new Timer(delay, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int currentProgress = progressBar.getValue() + 1; + if (currentProgress > progressBar.getMaximum()) { + currentProgress = progressBar.getMinimum(); + } + progressBar.setValue(currentProgress); + } + }); + + return timer; + } + + /** + * 停止进度条模拟计时器 + */ + private void stopGcProgressTimer() { + if (null == gcProgressTimer) { + return; + } + gcProgressTimer.stop(); + } + + /** + * 将字节转换成 KB or MB or GB 保留两位小数 + * + * @param size + * @return + */ + private String fileSizeConvert(long size) { + DecimalFormat df = new DecimalFormat("0.00"); + double n = 1024d; + if (size > Math.pow(n, 3)) { + return df.format(size / Math.pow(n, 3)) + "GB"; + } + if (size > Math.pow(n, 2)) { + return df.format(size / Math.pow(n, 2)) + "MB"; + } + return df.format(size / n) + "KB"; + } + + /** + * 立即清理的Button + * + * @return + */ + private UIButton initGcButton() { + UIButton gcButton = new UIButton(i18nText("Fine-Design_Vcs_Clean")); + gcButton.setPreferredSize(new Dimension(100, 15)); + gcButton.setRoundBorder(true, Constants.LEFT); + return gcButton; + } + } + diff --git a/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java b/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java index 2b55da4793..568e713bb9 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java @@ -21,7 +21,7 @@ public class SwitchExistEnv extends MenuDef { initMenuDef(); } - private void initMenuDef() { + private void initMenuDef() { Iterator nameIt = DesignerEnvManager.getEnvManager().getEnvNameIterator(); while (nameIt.hasNext()) { String name = nameIt.next(); 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 c853db1698..0296327097 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,19 +1,29 @@ package com.fr.design.actions.help.alphafine; +import com.fr.general.ComparatorUtils; import com.fr.license.function.VT4FR; import com.fr.stable.OperatingSystem; import com.fr.stable.StringUtils; 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 org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; /** - * Created by XiaXiang on 2017/4/5. + * AlphaFine配置类 + * + * @author XiaXiang + * @date 2017/4/5 */ public class AlphaFineConfigManager implements XMLable { + private static final long serialVersionUID = -8170289826729582122L; private static AlphaFineConfigManager alphaFineConfigManager = new AlphaFineConfigManager(); /** * 是否开启alphafine @@ -56,12 +66,12 @@ public class AlphaFineConfigManager implements XMLable { */ private boolean containPlugin = true; /** - * 分词搜索 - */ + * 分词搜索 + */ private boolean needSegmentationCheckbox = true; /** - * 智能客服 - */ + * 智能客服 + */ private boolean needIntelligentCustomerService = true; /** * 快捷键 @@ -71,24 +81,30 @@ public class AlphaFineConfigManager implements XMLable { * 是否提醒 */ private boolean needRemind = true; + + private Map actionSearchTextCache = new HashMap<>(8); + + private String cacheBuildNO; /** * 直接操作菜单次数 */ private int operateCount; + private AlphaFineConfigManager() { + } + public static AlphaFineConfigManager getInstance() { return alphaFineConfigManager; } public static boolean isALPHALicAvailable() { - + return VT4FR.AlphaFine.isSupport(); } @Override public Object clone() throws CloneNotSupportedException { - AlphaFineConfigManager manager = (AlphaFineConfigManager) super.clone(); - return manager; + return super.clone(); } @Override @@ -107,9 +123,33 @@ public class AlphaFineConfigManager implements XMLable { this.setShortcuts(reader.getAttrAsString("shortcuts", getDefaultShortCuts())); this.setNeedRemind(reader.getAttrAsBoolean("isNeedRemind", true)); this.setOperateCount(reader.getAttrAsInt("operateCount", 0)); - + } else if (reader.isChildNode()) { + if (ComparatorUtils.equals(reader.getTagName(), "ActionSearchTextCache")) { + readActionSearchTextCacheXML(reader); + } } + } + /** + * 读出搜索缓存 + */ + private void readActionSearchTextCacheXML(XMLableReader reader) { + reader.readXMLObject(new XMLReadable() { + @Override + public void readXML(XMLableReader reader) { + if (ComparatorUtils.equals(reader.getTagName(), "ActionSearchTextCache")) { + setCacheBuildNO(reader.getAttrAsString("buildNO", "")); + } else if (ComparatorUtils.equals(reader.getTagName(), "item")) { + String tmpVal = reader.getElementValue(); + if (tmpVal != null) { + actionSearchTextCache.put(reader.getAttrAsString("key", ""), tmpVal); + } else { + actionSearchTextCache.put(reader.getAttrAsString("key", ""), StringUtils.EMPTY); + } + + } + } + }); } @Override @@ -128,6 +168,18 @@ public class AlphaFineConfigManager implements XMLable { .attr("operateCount", this.getOperateCount()) .attr("needSegmentationCheckbox", this.isNeedSegmentationCheckbox()) .attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService()); + writeActionSearchTextCacheXML(writer); + writer.end(); + } + + /** + * 写入搜索缓存 + */ + private void writeActionSearchTextCacheXML(XMLPrintWriter writer) { + writer.startTAG("ActionSearchTextCache").attr("buildNO", cacheBuildNO); + for (Map.Entry item : actionSearchTextCache.entrySet()) { + writer.startTAG("item").attr("key", item.getKey()).textNode(item.getValue()).end(); + } writer.end(); } @@ -262,4 +314,25 @@ public class AlphaFineConfigManager implements XMLable { public void setOperateCount(int operateCount) { this.operateCount = operateCount; } + + @NotNull + public Map getActionSearchTextCache() { + return Collections.unmodifiableMap(actionSearchTextCache); + } + + public void setActionSearchTextCache(@NotNull String key, @NotNull String value) { + this.actionSearchTextCache.put(key, value); + } + + @NotNull + public String getCacheBuildNO() { + if (cacheBuildNO == null) { + return StringUtils.EMPTY; + } + return cacheBuildNO; + } + + public void setCacheBuildNO(@NotNull String cacheBuildNO) { + this.cacheBuildNO = cacheBuildNO; + } } diff --git a/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java b/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java index 76b11b2ff9..15c6cb705c 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java @@ -1,24 +1,17 @@ package com.fr.design.actions.server; - -import com.fr.config.ServerPreferenceConfig; import com.fr.data.impl.Connection; import com.fr.design.actions.UpdateAction; -import com.fr.design.data.datapane.connect.ConnectionManagerPane; import com.fr.design.data.datapane.connect.ConnectionShowPane; import com.fr.design.data.datapane.connect.DatabaseConnectionPane; import com.fr.design.dialog.BasicDialog; -import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.gui.NameInspector; -import com.fr.design.mainframe.DesignerContext; -import com.fr.design.mainframe.DesignerFrame; import com.fr.design.menu.MenuKeySet; -import com.fr.design.dcm.UniversalDatabaseOpener; +import com.fr.stable.os.support.OSBasedAction; +import com.fr.stable.os.support.OSSupportCenter; +import com.fr.design.os.impl.DatabaseDialogAction; import com.fr.file.ConnectionConfig; import com.fr.general.IOUtils; -import com.fr.transaction.CallBackAdaptor; -import com.fr.transaction.Configurations; -import com.fr.transaction.WorkerFacade; import javax.swing.*; import java.awt.event.ActionEvent; @@ -60,14 +53,11 @@ public class ConnectionListAction extends UpdateAction { * @param evt 事件 */ public void actionPerformed(ActionEvent evt) { - if (ServerPreferenceConfig.getInstance().isUseUniverseDBM()) { - UniversalDatabaseOpener.showUniverseDatabaseDialog(); - } else { - openDesignDatabaseManager(); - } + OSBasedAction osBasedAction = OSSupportCenter.getAction(DatabaseDialogAction.class); + osBasedAction.execute(); } - private void openDesignDatabaseManager() { + /* private void openDesignDatabaseManager() { DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); final ConnectionConfig datasourceManager = ConnectionConfig.getInstance(); final ConnectionManagerPane databaseManagerPane = new ConnectionManagerPane() { @@ -108,7 +98,7 @@ public class ConnectionListAction extends UpdateAction { }); databaseListDialog.setVisible(true); } - +*/ /** * 更新datasourceManager diff --git a/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java b/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java index 1b7d7bbc47..7b41f6fd81 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java @@ -1,11 +1,11 @@ package com.fr.design.actions.server; -import com.fr.config.ServerPreferenceConfig; import com.fr.design.actions.UpdateAction; -import com.fr.design.extra.WebViewDlgHelper; import com.fr.design.menu.MenuKeySet; -import com.fr.design.upm.UpmFinder; +import com.fr.design.os.impl.PMDialogAction; import com.fr.general.IOUtils; +import com.fr.stable.os.support.OSBasedAction; +import com.fr.stable.os.support.OSSupportCenter; import javax.swing.*; import java.awt.event.ActionEvent; @@ -16,22 +16,18 @@ import java.awt.event.ActionEvent; * @since 8.0 */ public class PluginManagerAction extends UpdateAction { - + private static String PLUGIN_MANAGER_ROUTE = "#management/plugin"; public PluginManagerAction() { this.setMenuKeySet(PLUGIN_MANAGER); this.setName(getMenuKeySet().getMenuKeySetName()); this.setMnemonic(getMenuKeySet().getMnemonic()); this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/server/plugin.png")); } - @Override public void actionPerformed(ActionEvent e) { // 可以启用新版本的插件商店(使用JxBrowser作为容器) - if (ServerPreferenceConfig.getInstance().isUseOptimizedUPM()) { - UpmFinder.showUPMDialog(); - } else { - WebViewDlgHelper.createPluginDialog(); - } + OSBasedAction osBasedAction = OSSupportCenter.getAction(PMDialogAction.class); + osBasedAction.execute(); } public static final MenuKeySet PLUGIN_MANAGER = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/beans/BasicBeanPane.java b/designer-base/src/main/java/com/fr/design/beans/BasicBeanPane.java index 2fb7737c34..2953def52d 100644 --- a/designer-base/src/main/java/com/fr/design/beans/BasicBeanPane.java +++ b/designer-base/src/main/java/com/fr/design/beans/BasicBeanPane.java @@ -1,41 +1,35 @@ package com.fr.design.beans; +import com.fr.common.annotations.Open; import com.fr.design.dialog.BasicPane; -/** - * Update Pane - */ +@Open public abstract class BasicBeanPane extends BasicPane { - + /** + * 展示数据 + * @param ob 待展示的对象 + */ + public abstract void populateBean(T ob); - /** - * Populate. - */ - public abstract void populateBean(T ob); + /** + * 保存数据 + * @return 待保存的对象 + */ + public abstract T updateBean(); - /** - * Update. - */ - public abstract T updateBean(); + /** + * 保存数据 + * @param ob 待保存的对象 + */ + public void updateBean(T ob) { - public void updateBean(T ob) { + } - } - - /** - * 更新权限工具栏面板 - */ - public void populateAuthority() { - - } - - /** - * 仅用来处理图表设计器的地图面板 - * @param mapType 地图类型 - */ - public void dealWidthMap(String mapType){ - - } + /** + * 更新权限工具栏面板 + */ + public void populateAuthority() { + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/beans/BasicStorePane.java b/designer-base/src/main/java/com/fr/design/beans/BasicStorePane.java new file mode 100644 index 0000000000..09a1378a87 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/beans/BasicStorePane.java @@ -0,0 +1,23 @@ +package com.fr.design.beans; + +import com.fr.common.annotations.Open; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019/9/24 + * 数据存取视图界面 + */ +@Open +public abstract class BasicStorePane extends BasicBeanPane { + + @Override + public T updateBean() { + return null; + } + + public abstract void populateBean(T t); + + @Override + public abstract void updateBean(T t); +} diff --git a/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java b/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java index adec741c2f..8f7d0e4030 100644 --- a/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java +++ b/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java @@ -1,11 +1,9 @@ package com.fr.design.beans; +import com.fr.common.annotations.Open; import com.fr.stable.StringUtils; -/** - * @author zhou - * @since 2012-5-30下午12:12:42 - */ +@Open public abstract class FurtherBasicBeanPane extends BasicBeanPane { /** * 是否是指定类型 diff --git a/designer-base/src/main/java/com/fr/design/border/UIRoundedBorder.java b/designer-base/src/main/java/com/fr/design/border/UIRoundedBorder.java index 65652cbcd5..757bbbbe08 100644 --- a/designer-base/src/main/java/com/fr/design/border/UIRoundedBorder.java +++ b/designer-base/src/main/java/com/fr/design/border/UIRoundedBorder.java @@ -13,23 +13,23 @@ import java.awt.geom.RoundRectangle2D; public class UIRoundedBorder extends LineBorder { private static final long serialVersionUID = 1L; - + private int roundedCorner; private int lineStyle; - + public UIRoundedBorder(Color color) { super(color); } - + public UIRoundedBorder(Color color, int thickness){ super(color, thickness); } - + public UIRoundedBorder(Color color, int thickness, int roundedCorners){ super(color, thickness, true); this.roundedCorner = roundedCorners; } - + public UIRoundedBorder(int lineStyle, Color color, int roundedCorners){ super(color, GraphHelper.getLineStyleSize(lineStyle), true); this.lineStyle = lineStyle; @@ -44,14 +44,15 @@ public class UIRoundedBorder extends LineBorder { return lineStyle; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height){ Color oldColor = g.getColor(); Graphics2D g2d = (Graphics2D)g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(lineColor); - GraphHelper.draw(g2d, new RoundRectangle2D.Double(x, y, width - 1, height-1, roundedCorner, roundedCorner),lineStyle); + GraphHelper.draw(g2d, new RoundRectangle2D.Double(x, y, width - 1.0D, height - 1.0D, roundedCorner, roundedCorner), lineStyle); g2d.setColor(oldColor); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/condition/ConditionAttrSingleConditionPane.java b/designer-base/src/main/java/com/fr/design/condition/ConditionAttrSingleConditionPane.java index a3ce3108a8..751f8b2676 100644 --- a/designer-base/src/main/java/com/fr/design/condition/ConditionAttrSingleConditionPane.java +++ b/designer-base/src/main/java/com/fr/design/condition/ConditionAttrSingleConditionPane.java @@ -1,10 +1,13 @@ package com.fr.design.condition; +import com.fr.common.annotations.Open; + /** * @author richie * @date 2015-03-26 * @since 8.0 */ +@Open public abstract class ConditionAttrSingleConditionPane extends SingleConditionPane { protected HighLightConditionAction hightLighAttrUpdateAction = null; private ConditionAttributesPane conditionAttributesPane; diff --git a/designer-base/src/main/java/com/fr/design/condition/ConditionAttributesPane.java b/designer-base/src/main/java/com/fr/design/condition/ConditionAttributesPane.java index b76e3feed5..781c57b052 100644 --- a/designer-base/src/main/java/com/fr/design/condition/ConditionAttributesPane.java +++ b/designer-base/src/main/java/com/fr/design/condition/ConditionAttributesPane.java @@ -1,6 +1,7 @@ package com.fr.design.condition; +import com.fr.common.annotations.Open; import com.fr.design.actions.UpdateAction; import com.fr.design.beans.BasicBeanPane; import com.fr.design.gui.itoolbar.UIToolbar; @@ -17,6 +18,7 @@ import java.awt.Dimension; import java.util.HashMap; import java.util.Iterator; +@Open public abstract class ConditionAttributesPane extends BasicBeanPane { private static final int MIN_HEIGHT = 60; protected CellHighlightAddMenuDef menuDef; diff --git a/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java b/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java new file mode 100644 index 0000000000..4b532b92d8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java @@ -0,0 +1,44 @@ +package com.fr.design.constants; + +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Null; + +/** + * 设计器启动事件类型 + * + * @author vito + * @date 2019-06-18 + */ +public enum DesignerLaunchStatus implements Event { + /** + * 初始化环境完成 + */ + WORKSPACE_INIT_COMPLETE, + + /** + * 设计器模块启动完成 + */ + DESIGNER_INIT_COMPLETE, + + /** + * 打开模板完成 + */ + OPEN_LAST_FILE_COMPLETE, + + /** + * 启动完成 + */ + STARTUP_COMPLETE; + + private static DesignerLaunchStatus status; + + public static DesignerLaunchStatus getStatus() { + return status; + } + + public static void setStatus(DesignerLaunchStatus state) { + status = state; + EventDispatcher.fire(DesignerLaunchStatus.getStatus()); + } +} 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 a18ae856eb..313ca0e2f7 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 @@ -46,6 +46,7 @@ import java.awt.event.KeyEvent; import java.util.EventObject; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * Coder: zack @@ -70,6 +71,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp * * @return 返回位置 */ + @Override public Location preferredLocation() { return Location.WEST_ABOVE; } @@ -97,6 +99,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp /** * 响应数据集改变 */ + @Override public void fireDSChanged() { fireDSChanged(new HashMap()); } @@ -107,6 +110,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp * * @param map 数据集变化Map */ + @Override public void fireDSChanged(Map map) { DesignTableDataManager.fireDSChanged(map); } @@ -151,6 +155,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp public abstract TableDataTree getDataTree(); + @Override public abstract void refreshDockingView(); protected void checkButtonEnabled(UpdateAction editAction, UpdateAction previewTableDataAction, UpdateAction removeAction, TableDataSourceOP op, TableDataTree dataTree) { @@ -320,6 +325,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp this.setSmallIcon(this.getTDIcon()); } + @Override public void actionPerformed(ActionEvent e) { dgEdit(getTableDataInstance().creatTableDataPane(), createDsName(getNamePrefix()), false); } @@ -400,7 +406,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp data = selectedNO.getObject(); } try { - if (((TableDataWrapper) data).getTableData() instanceof StoreProcedure) { + if (((TableDataWrapper) Objects.requireNonNull(data)).getTableData() instanceof StoreProcedure) { ((StoreProcedure) (((TableDataWrapper) data).getTableData())).resetDataModelList(); if (data instanceof StoreProcedureDataWrapper) { StoreProcedureDataWrapper oldSdw = ((StoreProcedureDataWrapper) data); 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 44de37ea82..0018d5333b 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 @@ -2,6 +2,7 @@ package com.fr.design.data; import com.fr.base.StoreProcedureParameter; import com.fr.base.TableData; +import com.fr.concurrent.NamedThreadFactory; import com.fr.data.TableDataSource; import com.fr.data.TableDataSourceTailor; import com.fr.data.core.DataCoreXmlUtils; @@ -30,12 +31,14 @@ import com.fr.general.ComparatorUtils; import com.fr.general.data.DataModel; import com.fr.general.data.TableDataException; import com.fr.log.FineLoggerFactory; +import com.fr.module.ModuleContext; import com.fr.script.Calculator; import com.fr.stable.ArrayUtils; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; import com.fr.stable.xml.XMLPrintWriter; +import javax.swing.JFrame; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.io.ByteArrayOutputStream; @@ -48,8 +51,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * 设计器管理操作数据集的类: @@ -420,7 +423,7 @@ public abstract class DesignTableDataManager { final Map parameterMap = new HashMap<>(); if (needInputParams(isMustInputParameters, parameters)) { final ParameterInputPane pPane = new ParameterInputPane(parameters); - pPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + pPane.showSmallWindow(new JFrame(), new DialogActionAdapter() { @Override public void doOk() { parameterMap.putAll(pPane.update()); @@ -444,11 +447,18 @@ public abstract class DesignTableDataManager { } catch (Exception e) { throw new TableDataException(e.getMessage(), e); } finally { - new Timer().schedule(new TimerTask() { + ScheduledExecutorService scheduledExecutorService = ModuleContext + .getExecutor() + .newSingleThreadScheduledExecutor(new NamedThreadFactory("")); + scheduledExecutorService.schedule(new Runnable() { + @Override public void run() { - loadingBar.close(); + if (loadingBar != null) { + loadingBar.close(); + } } - }, 100); + }, 100, TimeUnit.MILLISECONDS); + scheduledExecutorService.shutdown(); } } @@ -513,6 +523,7 @@ public abstract class DesignTableDataManager { if (inParameters.length > 0 && !ComparatorUtils.equals(threadLocal.get(), NO_PARAMETER)) {// 检查Parameter. final ParameterInputPane pPane = new ParameterInputPane(inParameters); pPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override public void doOk() { parameterMap.putAll(pPane.update()); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java index 413a0f00d1..028f71363b 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java @@ -438,6 +438,8 @@ public class ChoosePane extends BasicBeanPane implements Refresha } } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); } } @@ -461,7 +463,7 @@ public class ChoosePane extends BasicBeanPane implements Refresha if (!connect) { DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); JOptionPane.showMessageDialog(designerFrame, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.INFORMATION_MESSAGE); + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); failedToFindTable(); return null; } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataSourceOP.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataSourceOP.java index 9c19013901..33e51100ea 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataSourceOP.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataSourceOP.java @@ -56,14 +56,18 @@ public class TableDataSourceOP implements UserObjectOP { return DesignTableDataManager.getEditingDataSet(tc.getBook()); } List> empty = new ArrayList>(); - empty.add(Collections.emptyMap());//数据集 - empty.add(Collections.emptyMap());//服务器数据集 - empty.add(Collections.emptyMap());//存储过程 + //数据集 + empty.add(Collections.emptyMap()); + //服务器数据集 + empty.add(Collections.emptyMap()); + //存储过程 + empty.add(Collections.emptyMap()); return empty; } /** * ButtonEnabled intercept + * * @return interceptbuttonEnabled */ @Override @@ -73,8 +77,10 @@ public class TableDataSourceOP implements UserObjectOP { /** * 移除名字是name的TableData + * * @param name tabledata name */ + @Override public void removeAction(String name) { if (tc != null) { TableDataSource tds = tc.getBook(); @@ -85,7 +91,7 @@ public class TableDataSourceOP implements UserObjectOP { } protected ExpandMutableTreeNode[] getNodeArrayFromMap(Map map) { - List dataList = new ArrayList(); + List dataList = new ArrayList<>(); Iterator> entryIt = map.entrySet().iterator(); while (entryIt.hasNext()) { Entry entry = entryIt.next(); @@ -96,7 +102,7 @@ public class TableDataSourceOP implements UserObjectOP { dataList.add(newChildTreeNode); newChildTreeNode.add(new ExpandMutableTreeNode()); } - return dataList.toArray(new ExpandMutableTreeNode[dataList.size()]); + return dataList.toArray(new ExpandMutableTreeNode[0]); } private ExpandMutableTreeNode initTemplateDataNode(Map templateDataMap) { @@ -124,22 +130,20 @@ public class TableDataSourceOP implements UserObjectOP { */ @Override public ExpandMutableTreeNode[] load() { - Map templateDataMap = null; - Map serverDataMap = null; - Map storeProcedureMap = null; - - if (this != null) { - templateDataMap = this.init().get(0); - serverDataMap = this.init().get(1); - storeProcedureMap = this.init().get(2); - } else { - templateDataMap = Collections.emptyMap(); - serverDataMap = Collections.emptyMap(); - storeProcedureMap = Collections.emptyMap(); - } - List list = new ArrayList(); //所有的数据集 - List templist = new ArrayList(); //模板数据集 - List serverlist = new ArrayList(); //服务器数据集 + Map templateDataMap; + Map serverDataMap; + Map storeProcedureMap; + + templateDataMap = this.init().get(0); + serverDataMap = this.init().get(1); + storeProcedureMap = this.init().get(2); + + //所有的数据集 + List list = new ArrayList<>(); + //模板数据集 + List templist = new ArrayList<>(); + //服务器数据集 + List serverlist = new ArrayList<>(); list.add(initTemplateDataNode(templateDataMap)); addNodeToList(templateDataMap, templist); @@ -160,11 +164,11 @@ public class TableDataSourceOP implements UserObjectOP { } switch (dataMode) { case TEMPLATE_TABLE_DATA: - return templist.toArray(new ExpandMutableTreeNode[templist.size()]); + return templist.toArray(new ExpandMutableTreeNode[0]); case SERVER_TABLE_DATA: - return serverlist.toArray(new ExpandMutableTreeNode[serverlist.size()]); + return serverlist.toArray(new ExpandMutableTreeNode[0]); default: - return list.toArray(new ExpandMutableTreeNode[list.size()]); + return list.toArray(new ExpandMutableTreeNode[0]); } } @@ -182,7 +186,7 @@ public class TableDataSourceOP implements UserObjectOP { } protected void setStoreProcedureTree(TableData tableData, ExpandMutableTreeNode tmpNode) { - ArrayList nodeName = new ArrayList(); + ArrayList nodeName = new ArrayList<>(); StoreProcedure storeProcedure = (StoreProcedure) tableData; String name = ((NameObject) tmpNode.getUserObject()).getName(); StoreProcedureParameter[] parameters = StoreProcedure.getSortPara(storeProcedure.getParameters()); @@ -208,13 +212,13 @@ public class TableDataSourceOP implements UserObjectOP { } if (!resultNames.isEmpty()) { - for (int i = 0; i < resultNames.size(); i++) { - if (!nodeName.contains(resultNames.get(i))) { - nodeName.add(resultNames.get(i)); + for (String resultName : resultNames) { + if (!nodeName.contains(resultName)) { + nodeName.add(resultName); hasChild = true; - String parameterName = name + "_" + resultNames.get(i); + String parameterName = name + "_" + resultName; TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false); - ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(resultNames.get(i), newTwd)); + ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(resultName, newTwd)); newChildNode.add(new ExpandMutableTreeNode()); tmpNode.add(newChildNode); } @@ -230,7 +234,7 @@ public class TableDataSourceOP implements UserObjectOP { public void setDataMode(int i) { - this.dataMode = i; + dataMode = i; } public int getDataMode() { diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java index d6137b986e..7bbcda825f 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java @@ -43,7 +43,8 @@ public class JDBCDefPane extends JPanel { jdbcMap.put(OTHER_DB, new DriverURLName[]{new DriverURLName("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:"), new DriverURLName("org.hsqldb.jdbcDriver", "jdbc:hsqldb:file:[PATH_TO_DB_FILES]"), new DriverURLName("com.inet.tds.TdsDriver", "jdbc:inetdae7:localhost:1433/"), new DriverURLName("COM.cloudscape.JDBCDriver", "jdbc:cloudscape:/cloudscape/"), - new DriverURLName("com.internetcds.jdbc.tds.Driver", "jdbc:freetds:sqlserver://localhost/")}); + new DriverURLName("com.internetcds.jdbc.tds.Driver", "jdbc:freetds:sqlserver://localhost/"), + new DriverURLName("com.fr.swift.jdbc.Driver", "jdbc:swift:emb://default")}); jdbcMap.put("Inceptor",new DriverURLName[]{new DriverURLName("org.apache.hive.jdbc.HiveDriver","jdbc:inceptor2://localhost:10000/default"), new DriverURLName("org.apache.hadoop.hive.jdbc.HiveDriver","jdbc:inceptor://localhost:10000/default")}); jdbcMap.put("Oracle", new DriverURLName[]{new DriverURLName("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@localhost:1521:databaseName")}); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java index 383a1f02aa..01d7c9a6ff 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java @@ -27,15 +27,7 @@ import com.fr.function.TIME; import com.fr.general.FRFont; import com.fr.log.FineLoggerFactory; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingWorker; -import javax.swing.UIManager; +import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableModel; @@ -163,7 +155,7 @@ public class PreviewTablePane extends BasicPane { this.add(new JScrollPane(preveiwTable), BorderLayout.CENTER); if (this.dialog == null) { - this.dialog = this.showWindow(DesignerContext.getDesignerFrame()); + this.dialog = this.showWindow(new JFrame()); } progressBar = new AutoProgressBar(this, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) { public void doMonitorCanceled() { diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java index 0d8b05c401..f55195d3b3 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java @@ -76,6 +76,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class FileTableDataPane extends AbstractTableDataPane { private static final int TEXT = 0; @@ -126,12 +127,12 @@ public class FileTableDataPane extends AbstractTableDataPane { private static final int GAP = 23; - public FileTableDataPane(){ - this(SETPANELWIDTH,WIDTH,HEIGHT,GAP); + public FileTableDataPane() { + this(SETPANELWIDTH, WIDTH, HEIGHT, GAP); } - public FileTableDataPane(int setPanelWidth,int width,int height,int gap) { - this.setLayout(new BorderLayout(gap,0)); + public FileTableDataPane(int setPanelWidth, int width, int height, int gap) { + this.setLayout(new BorderLayout(gap, 0)); JPanel northPanel = new JPanel(new BorderLayout()); JPanel type = new JPanel(); type.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_File_Type") + ":")); @@ -163,16 +164,16 @@ public class FileTableDataPane extends AbstractTableDataPane { southPanel.add(setPanel, BorderLayout.CENTER); setPanel.setPreferredSize(new Dimension(setPanelWidth, 460)); setPanel.setBorder(BorderFactory.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set"))); - JPanel controlPane = textSetPanel(width,height); + JPanel controlPane = textSetPanel(width, height); setPanel.add(controlPane, BorderLayout.NORTH); - fileTypeComboBox.addActionListener(getFileTypeListener(setPanel,width,height)); + fileTypeComboBox.addActionListener(getFileTypeListener(setPanel, width, height)); this.add(northPanel, BorderLayout.NORTH); this.add(centerPanel, BorderLayout.CENTER); this.add(southPanel, BorderLayout.EAST); } - private void addToCenterPanel(JPanel centerPanel){ + private void addToCenterPanel(JPanel centerPanel) { localFileRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Local_File") + ":", true); urlFileRadioButton = new UIRadioButton("URL:", false); ButtonGroup bg = new ButtonGroup(); @@ -217,8 +218,9 @@ public class FileTableDataPane extends AbstractTableDataPane { } private ActionListener testConnectionListener = new ActionListener() { + @Override public void actionPerformed(ActionEvent arg0) { - String uri = ParameterHelper.analyze4Templatee( urlText.getText(), params); + String uri = ParameterHelper.analyze4Templatee(urlText.getText(), params); if (!checkURL(uri)) { JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(FileTableDataPane.this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Add_JS_warning")); return; @@ -245,10 +247,11 @@ public class FileTableDataPane extends AbstractTableDataPane { } }; - private void previewPanel(JPanel jPanel){ + private void previewPanel(JPanel jPanel) { JPanel previewPanel = new JPanel(new BorderLayout()); UIButton preview = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview")); preview.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { preview(); } @@ -257,48 +260,47 @@ public class FileTableDataPane extends AbstractTableDataPane { jPanel.add(previewPanel, BorderLayout.SOUTH); } - private JPanel xmlSetPanel(int width,int height) { + private JPanel xmlSetPanel(int width, int height) { // xml设置pane JPanel controlPane = new JPanel(); - JPanel northPane = new JPanel(new BorderLayout(8,8)); - JPanel northTopPane = new JPanel(new BorderLayout(8,8)); - JPanel southPane = new JPanel(new BorderLayout(8,8)); - JPanel southTopPane = new JPanel(new BorderLayout(8,8)); - JPanel westPane = new JPanel(new BorderLayout()); - controlPane.setLayout(new BorderLayout(8,8)); + JPanel northPane = new JPanel(new BorderLayout(8, 8)); + JPanel northTopPane = new JPanel(new BorderLayout(8, 8)); + JPanel southPane = new JPanel(new BorderLayout(8, 8)); + JPanel southTopPane = new JPanel(new BorderLayout(8, 8)); + controlPane.setLayout(new BorderLayout(8, 8)); controlPane.setPreferredSize(new Dimension(width, height)); - JPanel comboboxPanel = new JPanel(new BorderLayout(8,8)); + JPanel comboboxPanel = new JPanel(new BorderLayout(8, 8)); encodeLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Encoding_Type") + ":"); encodingComboBox = new UIComboBox(EncodeConstants.ALL_ENCODING_ARRAY); encodingComboBox.setSelectedIndex(4); encodingComboBox.setPreferredSize(new Dimension(90, 20)); JPanel treeContainerPane = new JPanel(); - treeContainerPane.setLayout(new BorderLayout(8,8)); + treeContainerPane.setLayout(new BorderLayout(8, 8)); nodeTreePane = new XMLNodeTreePane(); - treeContainerPane.add(nodeTreePane,BorderLayout.CENTER); + treeContainerPane.add(nodeTreePane, BorderLayout.CENTER); comboboxPanel.add(encodeLabel, BorderLayout.WEST); comboboxPanel.add(encodingComboBox, BorderLayout.CENTER); - northPane.add(comboboxPanel,BorderLayout.EAST); - northTopPane.add(northPane,BorderLayout.WEST); - southTopPane.add(southPane,BorderLayout.WEST); - southTopPane.add(treeContainerPane,BorderLayout.CENTER); + northPane.add(comboboxPanel, BorderLayout.EAST); + northTopPane.add(northPane, BorderLayout.WEST); + southTopPane.add(southPane, BorderLayout.WEST); + southTopPane.add(treeContainerPane, BorderLayout.CENTER); controlPane.add(northTopPane, BorderLayout.NORTH); - controlPane.add(southTopPane,BorderLayout.CENTER); + controlPane.add(southTopPane, BorderLayout.CENTER); previewPanel(controlPane); return controlPane; } - private JPanel excelSetPanel(int width,int height) { + private JPanel excelSetPanel(int width, int height) { // excel设置pane int checkBoxWidth = width - EIGHT; JPanel controlPane = new JPanel(); - JPanel northPane = new JPanel(new BorderLayout(8,8)); + JPanel northPane = new JPanel(new BorderLayout(8, 8)); controlPane.setLayout(new BorderLayout()); - controlPane.setPreferredSize(new Dimension(width,height)); + controlPane.setPreferredSize(new Dimension(width, height)); needColumnNameCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FirstRow_IS_Column_Name"), false); needColumnNameCheckBox.setPreferredSize(new Dimension(checkBoxWidth, 20)); northPane.add(needColumnNameCheckBox, BorderLayout.EAST); @@ -321,6 +323,7 @@ public class FileTableDataPane extends AbstractTableDataPane { * * @throws Exception */ + @Override public void checkValid() throws Exception { if (urlFileRadioButton.isSelected()) { String url = urlText.getText().trim(); @@ -331,33 +334,33 @@ public class FileTableDataPane extends AbstractTableDataPane { } - private boolean checkURL(String uri){ + private boolean checkURL(String uri) { try { new URL(uri); return true; } catch (MalformedURLException e) { return false; } - // return (uri.matches("https*://.+|\\$\\{.+\\}.*")); + // return (uri.matches("https*://.+|\\$\\{.+\\}.*")); } - private JPanel textSetPanel(int width,int height) { + private JPanel textSetPanel(int width, int height) { // text设置pane JPanel controlPane = new JPanel(); controlPane.setLayout(new BorderLayout()); - controlPane.setPreferredSize(new Dimension(width,height)); - JPanel northPane = new JPanel(new BorderLayout(8,8)); + controlPane.setPreferredSize(new Dimension(width, height)); + JPanel northPane = new JPanel(new BorderLayout(8, 8)); addToNorthPane(northPane); - controlPane.add(northPane,BorderLayout.WEST); + controlPane.add(northPane, BorderLayout.WEST); previewPanel(controlPane); return controlPane; } - private void addToNorthPane(JPanel northPane){ + private void addToNorthPane(JPanel northPane) { double f = TableLayout.FILL; double p = TableLayout.PREFERRED; - double columnSize[] = {f, p, p}; - double rowSize[] = {B, B, B, B, B, B, B}; + double[] columnSize = {f, p, p}; + double[] rowSize = {B, B, B, B, B, B, B}; needColumnNameCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FirstRow_IS_Column_Name"), true); dismenberLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dismenber") + ":"); tableDismemberRadioButton = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Table_Dismember"), false); @@ -390,18 +393,19 @@ public class FileTableDataPane extends AbstractTableDataPane { encodeLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Encoding_Type") + ":"); charsetComboBox = new UIComboBox(EncodeConstants.ALL_ENCODING_ARRAY); Component[][] comps = { - {encodeLabel,charsetComboBox,null}, - {needColumnNameCheckBox,null,null}, - {dismenberLabel,tableDismemberRadioButton,null}, - {null,spaceDismenberRadioButton,null}, - {null,commaDismenberRadioButton,null}, - {null,otherDismenberRadioButton,otherDismenberTextField}, - {ignoreOneMoreDelimiterCheckBox,null,null} + {encodeLabel, charsetComboBox, null}, + {needColumnNameCheckBox, null, null}, + {dismenberLabel, tableDismemberRadioButton, null}, + {null, spaceDismenberRadioButton, null}, + {null, commaDismenberRadioButton, null}, + {null, otherDismenberRadioButton, otherDismenberTextField}, + {ignoreOneMoreDelimiterCheckBox, null, null} }; - northPane.add(TableLayoutHelper.createTableLayoutPane(comps, rowSize, columnSize),BorderLayout.EAST); + northPane.add(TableLayoutHelper.createTableLayoutPane(comps, rowSize, columnSize), BorderLayout.EAST); } private ActionListener radioActionListener = new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { if (localFileRadioButton.isSelected()) { localRadioSelectAction(); @@ -438,7 +442,7 @@ public class FileTableDataPane extends AbstractTableDataPane { @Override public void actionPerformed(ActionEvent e) { FILEChooserPane fileChooser = FILEChooserPane.getInstance(true, false, new ChooseFileFilter(getFileSuffix())); - if (fileChooser.showOpenDialog(DesignerContext.getDesignerFrame()) == FILEChooserPane.OK_OPTION) { + if (fileChooser.showOpenDialog(FileTableDataPane.this) == FILEChooserPane.OK_OPTION) { final FILE file = fileChooser.getSelectedFILE(); if (file == null) {// 选择的文件不能是 null return; @@ -456,8 +460,8 @@ public class FileTableDataPane extends AbstractTableDataPane { private String[] getFileSuffix() { List suffixList = new ArrayList(); - String suffix = fileTypeComboBox.getSelectedItem().toString().toLowerCase(); - if (suffix.equalsIgnoreCase("excel")) { + String suffix = Objects.requireNonNull(fileTypeComboBox.getSelectedItem()).toString().toLowerCase(); + if ("excel".equalsIgnoreCase(suffix)) { suffixList.add("xls"); suffixList.add("xlsx"); } else { @@ -467,8 +471,8 @@ public class FileTableDataPane extends AbstractTableDataPane { } private String getFileSuffixToString() { - String suffixToString = fileTypeComboBox.getSelectedItem().toString().toLowerCase(); - if (suffixToString.equalsIgnoreCase("excel")) { + String suffixToString = Objects.requireNonNull(fileTypeComboBox.getSelectedItem()).toString().toLowerCase(); + if ("excel".equalsIgnoreCase(suffixToString)) { suffixToString = "xls"; } return suffixToString; @@ -476,16 +480,17 @@ public class FileTableDataPane extends AbstractTableDataPane { private ActionListener getFileTypeListener(final JPanel setPanel, final int width, final int height) { ActionListener fileTypeListener = new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { setPanel.removeAll(); localText.setText(""); urlText.setText(""); if (fileTypeComboBox.getSelectedIndex() == XML) { - setPanel.add(xmlSetPanel(width,height), BorderLayout.NORTH); + setPanel.add(xmlSetPanel(width, height), BorderLayout.NORTH); } else if (fileTypeComboBox.getSelectedIndex() == EXCEL) { - setPanel.add(excelSetPanel(width,height), BorderLayout.NORTH); + setPanel.add(excelSetPanel(width, height), BorderLayout.NORTH); } else { - setPanel.add(textSetPanel(width,height), BorderLayout.NORTH); + setPanel.add(textSetPanel(width, height), BorderLayout.NORTH); } String tipContent = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Type_Parameter") + "reportlets/excel/FineReport${abc}." + getFileSuffixToString() + "
" + "http://192.168.100.120:8080/XXServer/Report/excel${abc}.jsp
" + "  "; @@ -503,6 +508,7 @@ public class FileTableDataPane extends AbstractTableDataPane { this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); } + @Override public void actionPerformed(ActionEvent e) { String[] paramTexts = new String[1]; paramTexts[0] = getFilePathFromUrlOrLocal(); @@ -545,25 +551,25 @@ public class FileTableDataPane extends AbstractTableDataPane { setTextField(xtd); editorPane.populate(xtd.getParams()); encodingComboBox.setSelectedItem(xtd.getCharSet()); - if (!ComparatorUtils.equals(xtd,new XMLTableData())) { + if (!ComparatorUtils.equals(xtd, new XMLTableData())) { xmlNodeTree.initData(); String[] path = xtd.getXPath(); String[] paths; if (path != null && path.length > 0) { - DefaultTreeModel treeModel = (DefaultTreeModel)xmlNodeTree.getModel(); + DefaultTreeModel treeModel = (DefaultTreeModel) xmlNodeTree.getModel(); ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); if (treeModel != null) { - if(!ComparatorUtils.equals(treeModel.getRoot().toString(),"")){ - paths = new String[path.length - 1]; - for(int i = 1;i< path.length;i++){ - paths[i -1] = path[i]; - } - }else{ + if (!ComparatorUtils.equals(treeModel.getRoot().toString(), "")) { + paths = new String[path.length - 1]; + for (int i = 1; i < path.length; i++) { + paths[i - 1] = path[i]; + } + } else { paths = path; root.setUserObject(ROOTTAG); } if (treeModel.getRoot() instanceof ExpandMutableTreeNode) { - selectNode((ExpandMutableTreeNode)treeModel.getRoot(), 0, paths); + selectNode((ExpandMutableTreeNode) treeModel.getRoot(), 0, paths); if (selectedNode != null) { TreePath treepath = new TreePath(treeModel.getPathToRoot(selectedNode)); xmlNodeTree.setSelectionPath(treepath); @@ -571,8 +577,8 @@ public class FileTableDataPane extends AbstractTableDataPane { } } //防止某种操作导致添加的tag作为root出现。 - if(ComparatorUtils.equals(root.toString(),ROOTTAG)){ - root.setUserObject(StringUtils.EMPTY); + if (ComparatorUtils.equals(root.toString(), ROOTTAG)) { + root.setUserObject(StringUtils.EMPTY); } } } @@ -638,7 +644,7 @@ public class FileTableDataPane extends AbstractTableDataPane { ttd.setDelimiter(this.showDelimiter()); ttd.setIgnoreOneMoreDelimiter(ignoreOneMoreDelimiterCheckBox.isSelected()); ttd.setNeedColumnName(needColumnNameCheckBox.isSelected()); - ttd.setCharset((String)charsetComboBox.getSelectedItem()); + ttd.setCharset((String) charsetComboBox.getSelectedItem()); fileTableData = ttd; return ttd; } @@ -667,12 +673,12 @@ public class FileTableDataPane extends AbstractTableDataPane { xmlColumnsList.clear(); ExpandMutableTreeNode treeNode; boolean flag = true; - for(int i = 0;i < selectedNode.getChildCount();i++){ + for (int i = 0; i < selectedNode.getChildCount(); i++) { treeNode = (ExpandMutableTreeNode) selectedNode.getChildAt(i); - if(treeNode.isLeaf()){ + if (treeNode.isLeaf()) { xmlColumnsList.add(treeNode.toString()); - }else{ - if(flag){ + } else { + if (flag) { flag = false; finalSelectedNode = treeNode; leafNode(treeNode); @@ -692,34 +698,34 @@ public class FileTableDataPane extends AbstractTableDataPane { } //wikky:构建树时为了美观把添加的根节点值赋为空显示,现在还得该回去使得预览时能够顺利取到数据。 - private String[] getPaths(){ + private String[] getPaths() { TreePath treePath = GUICoreUtils.getTreePath(finalSelectedNode); String path = StringUtils.EMPTY; if (treePath != null) { Object[] paths = treePath.getPath(); for (int i = 0; i < paths.length; i++) { - path+="/" + paths[i]; + path += "/" + paths[i]; } } if (path.startsWith("/")) { path = path.substring(1); } String[] paths = path.split("/"); - if(ComparatorUtils.equals(paths[0],StringUtils.EMPTY)){ + if (ComparatorUtils.equals(paths[0], StringUtils.EMPTY)) { paths[0] = ROOTTAG; } return paths; } - private void leafNode(ExpandMutableTreeNode treeNode){ + private void leafNode(ExpandMutableTreeNode treeNode) { boolean flag = true; ExpandMutableTreeNode firstNode; - for(int i = 0;i < treeNode.getChildCount();i++){ + for (int i = 0; i < treeNode.getChildCount(); i++) { firstNode = (ExpandMutableTreeNode) treeNode.getChildAt(i); - if(firstNode.isLeaf()){ + if (firstNode.isLeaf()) { xmlColumnsList.add(firstNode.toString()); - }else{ - if(flag){ + } else { + if (flag) { flag = false; finalSelectedNode = treeNode; leafNode(firstNode); @@ -729,16 +735,16 @@ public class FileTableDataPane extends AbstractTableDataPane { } private void selectNode(ExpandMutableTreeNode node, int layer, String[] paths) { - if (selectedNode != null || node == null){ + if (selectedNode != null || node == null) { return; } - if (layer < paths.length && paths[layer] != null && ComparatorUtils.equals(paths[layer],node.getUserObject())) { - if (layer == paths.length -1) { + if (layer < paths.length && paths[layer] != null && ComparatorUtils.equals(paths[layer], node.getUserObject())) { + if (layer == paths.length - 1) { selectedNode = node; return; } for (int i = 0; i < node.getChildCount(); i++) { - selectNode((ExpandMutableTreeNode)node.getChildAt(i), layer + 1, paths); + selectNode((ExpandMutableTreeNode) node.getChildAt(i), layer + 1, paths); } } } @@ -800,8 +806,8 @@ public class FileTableDataPane extends AbstractTableDataPane { toolbarDef.addShortCut(refreshAction); UIToolbar toolBar = ToolBarDef.createJToolBar(); toolbarDef.updateToolBar(toolBar); - toolbarPanel.add(keyPointLaber,BorderLayout.WEST); - toolbarPanel.add(toolBar,BorderLayout.EAST); + toolbarPanel.add(keyPointLaber, BorderLayout.WEST); + toolbarPanel.add(toolBar, BorderLayout.EAST); this.add(toolbarPanel, BorderLayout.NORTH); } @@ -817,6 +823,7 @@ public class FileTableDataPane extends AbstractTableDataPane { this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); } + @Override public void actionPerformed(ActionEvent e) { xmlNodeTree.waitRefresh(); xmlNodeTree.refreshData(); @@ -845,8 +852,9 @@ public class FileTableDataPane extends AbstractTableDataPane { } private MouseListener treeMouseListener = new MouseAdapter() { + @Override public void mousePressed(MouseEvent e) { - if (XMLNodeTree.this.getModel() != treeModel){ + if (XMLNodeTree.this.getModel() != treeModel) { return; } int selRow = XMLNodeTree.this.getRowForLocation(e.getX(), e.getY()); @@ -858,12 +866,12 @@ public class FileTableDataPane extends AbstractTableDataPane { return;//没有选中某个树节点,就直接返回啦 } Object selObject = selPath.getLastPathComponent(); - if (selObject instanceof ExpandMutableTreeNode ) { + if (selObject instanceof ExpandMutableTreeNode) { ExpandMutableTreeNode expandMutableTreeNode = (ExpandMutableTreeNode) selObject; if (!expandMutableTreeNode.isLeaf()) { selectedNode = expandMutableTreeNode; } else { - selectedNode = (ExpandMutableTreeNode)expandMutableTreeNode.getParent(); + selectedNode = (ExpandMutableTreeNode) expandMutableTreeNode.getParent(); } } } @@ -906,7 +914,7 @@ public class FileTableDataPane extends AbstractTableDataPane { DataSource dataSource = null; if (localFileRadioButton.isSelected()) { String localTextString = StringUtils.trimToNull(localText.getText()); - if(StringUtils.isEmpty(localTextString)){ + if (StringUtils.isEmpty(localTextString)) { FineLoggerFactory.getLogger().info("The file path is empty."); loadedTreeModel(); return; @@ -914,7 +922,7 @@ public class FileTableDataPane extends AbstractTableDataPane { dataSource = new FileDataSource(localTextString, params); } else { String urlTextString = StringUtils.trimToNull(urlText.getText()); - if (StringUtils.isEmpty(urlTextString)){ + if (StringUtils.isEmpty(urlTextString)) { FineLoggerFactory.getLogger().info("The url path is empty."); loadedTreeModel(); return; @@ -922,7 +930,7 @@ public class FileTableDataPane extends AbstractTableDataPane { dataSource = new URLDataSource(urlTextString, params); } try { - InputStream in,input; + InputStream in, input; if ((in = dataSource.getSourceStream(params)) != null) { String xmlString = Utils.inputStream2String(in, (String) encodingComboBox.getSelectedItem()); String stringXml = addTag(xmlString); @@ -941,16 +949,20 @@ public class FileTableDataPane extends AbstractTableDataPane { FineLoggerFactory.getLogger().error(e.getMessage(), e); loadedTreeModel(); } - if(treeModel.getChildCount(treeModel.getRoot()) == 1){ - treeModel = new DefaultTreeModel((ExpandMutableTreeNode) treeModel.getChild(treeModel.getRoot(),0)); - }else{ + if (treeModel == null) { + FineLoggerFactory.getLogger().info("The file is wrong or bad, can not create the XMLReader."); + return; + } + if (treeModel.getChildCount(treeModel.getRoot()) == 1) { + treeModel = new DefaultTreeModel((ExpandMutableTreeNode) treeModel.getChild(treeModel.getRoot(), 0)); + } else { ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); root.setUserObject(StringUtils.EMPTY); } this.setModel(treeModel); } - private void loadedTreeModel(){ + private void loadedTreeModel() { ExpandMutableTreeNode rootTreeNode = new ExpandMutableTreeNode(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Loaded_Tree_Model")); rootTreeNode.setExpanded(false); rootTreeNode.setAllowsChildren(false); @@ -958,14 +970,14 @@ public class FileTableDataPane extends AbstractTableDataPane { XMLNodeTree.this.setModel(loadedTreeModel); } - private String addTag(String string){ + private String addTag(String string) { String stringWithTag; int beginIndex = 0; int firstIndex = string.indexOf(">"); int endIndex = string.length(); - String firstPart = string.substring(beginIndex,firstIndex + 1); + String firstPart = string.substring(beginIndex, firstIndex + 1); String secondPart = STARTTAG; - String thirdPart = string.substring(firstIndex + 1,endIndex); + String thirdPart = string.substring(firstIndex + 1, endIndex); String lastPart = ENDTAG; stringWithTag = firstPart + secondPart + thirdPart + lastPart; return stringWithTag; @@ -986,6 +998,7 @@ public class FileTableDataPane extends AbstractTableDataPane { this.layer = layer; } + @Override public void readXML(XMLableReader reader) { String nodeName; if (this.layer < 0) { diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java index 4863a27960..dc37d14bea 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java @@ -40,7 +40,8 @@ public class MaxMemRowCountPanel extends UIToolbar { } } }; - + + @Override public Dimension getPreferredSize() { Dimension dim = super.getPreferredSize(); dim.width = 340; @@ -81,7 +82,7 @@ public class MaxMemRowCountPanel extends UIToolbar { public void setValue(int value) { if (value >= 0) { showMaxPanel(); - numberSpinner.setValue(Integer.valueOf(value)); + numberSpinner.setValue(value); } else { showAllPanel(); } @@ -94,4 +95,4 @@ public class MaxMemRowCountPanel extends UIToolbar { return ((Number) numberSpinner.getValue()).intValue(); } } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/dialog/BasicDialog.java b/designer-base/src/main/java/com/fr/design/dialog/BasicDialog.java index 462a2d311a..3b3b1d620f 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/BasicDialog.java +++ b/designer-base/src/main/java/com/fr/design/dialog/BasicDialog.java @@ -1,10 +1,10 @@ package com.fr.design.dialog; +import com.fr.common.annotations.Open; + import java.awt.*; -/* - * @author _denny - */ +@Open public abstract class BasicDialog extends UIDialog { public static final Dimension SMALL = new Dimension(340, 180); public static final Dimension MEDIUM = new Dimension(600, 400); diff --git a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java index d752f58f07..e684d81f6c 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java +++ b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java @@ -1,24 +1,17 @@ package com.fr.design.dialog; +import com.fr.common.annotations.Open; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.i18n.Toolkit; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.core.PropertyChangeAdapter; -import javax.swing.JPanel; +import javax.swing.*; import javax.swing.event.DocumentEvent; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dialog; -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Window; - -/* - * _denny: 这里的BasicPane通常会有populate & update方法 - * 记得populate 一定要在对应的dialog setVisible之前populate - */ +import java.awt.*; + +@Open public abstract class BasicPane extends JPanel { /** diff --git a/designer-base/src/main/java/com/fr/design/dialog/DialogActionAdapter.java b/designer-base/src/main/java/com/fr/design/dialog/DialogActionAdapter.java index 5f188f0bda..7b44b90b0d 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/DialogActionAdapter.java +++ b/designer-base/src/main/java/com/fr/design/dialog/DialogActionAdapter.java @@ -1,5 +1,8 @@ package com.fr.design.dialog; +import com.fr.common.annotations.Open; + +@Open public abstract class DialogActionAdapter implements DialogActionListener { @Override public void doOk() {} diff --git a/designer-base/src/main/java/com/fr/design/dialog/DialogActionListener.java b/designer-base/src/main/java/com/fr/design/dialog/DialogActionListener.java index 5628918deb..a6cf193453 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/DialogActionListener.java +++ b/designer-base/src/main/java/com/fr/design/dialog/DialogActionListener.java @@ -1,8 +1,11 @@ package com.fr.design.dialog; +import com.fr.common.annotations.Open; + +@Open public interface DialogActionListener { - - public void doOk(); - - public void doCancel(); + + void doOk(); + + void doCancel(); } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/dialog/JWizardPanel.java b/designer-base/src/main/java/com/fr/design/dialog/JWizardPanel.java index 956df9efba..ce3a2f9da6 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/JWizardPanel.java +++ b/designer-base/src/main/java/com/fr/design/dialog/JWizardPanel.java @@ -48,7 +48,7 @@ public class JWizardPanel extends BasicPane { // Set the layout for the content area contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - + contentPane.setBorder(BorderFactory.createEmptyBorder(2, 2, 4, 4)); // Step title @@ -60,16 +60,16 @@ public class JWizardPanel extends BasicPane { add(titlePanel, BorderLayout.NORTH); add(contentPane, BorderLayout.CENTER); } - + @Override protected String title4PopupWindow() { return "wizard"; } - + /** * Set the title to use for this step. Normally this title would be unique * for each wizards step. - * + * * @param stepTitle The title to use for this step. */ public void setStepTitle(String stepTitle) { @@ -82,7 +82,7 @@ public class JWizardPanel extends BasicPane { /** * Get the step title to use for this step. - * + * * @return The step title to use for this step. */ public String getStepTitle() { @@ -93,7 +93,7 @@ public class JWizardPanel extends BasicPane { * Get a JPanel to use for adding your own components to this WizardPanel. * Do not add components directly to the JWizardPanel. The JPanel uses the * layout given in the JWizardPanel constructor. - * + * * @return The JPanel to use for adding components for this wizard step. */ public JPanel getContentPane() { @@ -102,7 +102,7 @@ public class JWizardPanel extends BasicPane { /** * Get the wizard step to go to when the Back button is pressed. - * + * * @return The wizard step to go to when the Back button is pressed. */ @@ -114,7 +114,7 @@ public class JWizardPanel extends BasicPane { * Set the wizard step to go to when the Back button is pressed. This should * be set in the constructor of the JWizardPanel subclass since it * determines whether the Back button is enabled or not. - * + * * @param backStep * The wizard step to go to when the Back button is pressed. */ @@ -129,7 +129,7 @@ public class JWizardPanel extends BasicPane { /** * Get the wizard step to go to when the Next button is pressed. - * + * * @return The wizard step to go to when the Next button is pressed. */ public int getNextStep() { @@ -140,7 +140,7 @@ public class JWizardPanel extends BasicPane { * Set the wizard step to go to when the Next button is pressed. This should * be set in the constructor of the JWizardPanel subclass since it * determines whether the Next and Finish buttons are enabled or not. - * + * * @param nextStep The wizard step to go to when the Next button is pressed. */ public void setNextStep(int nextStep) { @@ -154,7 +154,7 @@ public class JWizardPanel extends BasicPane { /** * Returns the JWizardDialog in which this JWizardPanel resides. This is * valid only after the panel has been added to the dialog. - * + * * @return The JWizardDialog in which this JWizardPanel resides. */ @@ -168,7 +168,7 @@ public class JWizardPanel extends BasicPane { public void addNotify() { if (firstNotify) { Font font = stepTitleLabel.getFont(); - font = font.deriveFont(Font.BOLD, font.getSize() * 14 / 10); + font = font.deriveFont(Font.BOLD, font.getSize() * 14 / 10.0F); stepTitleLabel.setFont(font); firstNotify = false; } @@ -177,7 +177,7 @@ public class JWizardPanel extends BasicPane { /** * Set the JWizardDialog parent for this JWizardPanel. - * + * * @param dialogParent * The JWizardPanel parent for this JWizardPanel. */ @@ -188,7 +188,7 @@ public class JWizardPanel extends BasicPane { /** * Calls back(). This allows the JWizardDialog to call the protected method * back(). - * + * * @see #back() */ @@ -199,7 +199,7 @@ public class JWizardPanel extends BasicPane { /** * Calls next(). This allows the JWizardDialog to call the protected method * next(). - * + * * @see #next() */ void doNext() { @@ -209,7 +209,7 @@ public class JWizardPanel extends BasicPane { /** * Called when the Back button is pressed. By default this displays the * wizard step set by setBackStep(). - * + * * @see #setBackStep(int) */ protected void back() { @@ -219,11 +219,11 @@ public class JWizardPanel extends BasicPane { /** * Called when the Next button is pressed. By default this displays the * wizard step set by setNextStep(). - * + * * @see #setNextStep(int) */ protected void next() { dialogParent.goTo(getNextStep()); } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java b/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java index 7de66602a0..c4e07e9676 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java +++ b/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java @@ -25,13 +25,7 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; -/** - * Created with IntelliJ IDEA. - * User: 小灰灰 - * Date: 13-7-16 - * Time: 下午2:17 - * To change this template use File | Settings | File Templates. - */ + public abstract class UIDialog extends JDialog { public static final String OK_BUTTON = "basic_ok"; public static final String CANCEL_BUTTON = "basic_cancel"; diff --git a/designer-base/src/main/java/com/fr/design/event/DesignerOpenedListener.java b/designer-base/src/main/java/com/fr/design/event/DesignerOpenedListener.java index 77c6bcf8f1..c14fe870fc 100644 --- a/designer-base/src/main/java/com/fr/design/event/DesignerOpenedListener.java +++ b/designer-base/src/main/java/com/fr/design/event/DesignerOpenedListener.java @@ -9,5 +9,5 @@ public interface DesignerOpenedListener extends EventListener { /** * Invoked when the target of the listener has changed the rpt content. */ - public void designerOpened(); + void designerOpened(); } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java b/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java index 43bb8131a4..50add423f4 100644 --- a/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java +++ b/designer-base/src/main/java/com/fr/design/extra/LoginWebBridge.java @@ -1,6 +1,7 @@ package com.fr.design.extra; import com.fr.base.passport.FinePassportManager; +import com.fr.concurrent.NamedThreadFactory; import com.fr.config.MarketConfig; import com.fr.design.dialog.UIDialog; import com.fr.design.extra.exe.PluginLoginExecutor; @@ -8,47 +9,30 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.general.CloudCenter; import com.fr.general.http.HttpClient; import com.fr.log.FineLoggerFactory; -import com.fr.stable.EncodeConstants; import com.fr.stable.StringUtils; import javafx.concurrent.Task; import javafx.scene.web.WebEngine; import netscape.javascript.JSObject; + import javax.swing.JDialog; import javax.swing.SwingUtilities; import java.awt.Color; import java.awt.Desktop; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URLEncoder; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * @author vito */ public class LoginWebBridge { - //默认查询消息时间, 30s - private static final long CHECK_MESSAGE_TIME = 30 * 1000L; - //数据查询正常的标志 ok - private static final String SUCCESS_MESSAGE_STATUS = "ok"; - //数据通讯失败 - private static final String FAILED_MESSAGE_STATUS = "error"; //最低消息的条数 private static final int MIN_MESSAGE_COUNT = 0; - //登录成功 - private static final String LOGININ = "0"; - //用户名不存在 - private static final String USERNAME_NOT_EXSIT = "-1"; - //密码错误 - private static final String PASSWORD_ERROR = "-2"; - //未知错误 - private static final String UNKNOWN_ERROR = "-3"; //网络连接失败 private static final String NET_FAILED = "-4"; //用户名,密码为空 private static final String LOGIN_INFO_EMPTY = "-5"; - private static final int TIME_OUT = 10000; - private static final String LOGIN_SUCCESS = "ok"; - private static final String LOGIN_FAILED = "failed"; private static final Color LOGIN_BACKGROUND = new Color(184, 220, 242); private static LoginWebBridge helper; //消息条数 @@ -131,22 +115,6 @@ public class LoginWebBridge { return client.isServerAlive(); } - private String encode(String str) { - try { - return URLEncoder.encode(str, EncodeConstants.ENCODING_UTF_8); - } catch (UnsupportedEncodingException e) { - return str; - } - } - - private void sleep(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - /** * 注册页面 */ @@ -178,7 +146,9 @@ public class LoginWebBridge { */ public void defaultLogin(String username, String password, final JSObject callback) { Task task = new PluginTask<>(webEngine, callback, new PluginLoginExecutor(username, password)); - new Thread(task).start(); + ExecutorService es = Executors.newSingleThreadExecutor(new NamedThreadFactory("bbsDefaultLogin")); + es.submit(task); + es.shutdown(); } /** @@ -250,10 +220,6 @@ public class LoginWebBridge { } } - public void openUrlAtLocalWebBrowser(WebEngine eng, String url) { - if (url.indexOf("qqLogin.html") > 0) { - return; - } } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginControlPane.java b/designer-base/src/main/java/com/fr/design/extra/PluginControlPane.java index 393626ce01..e5b4feba28 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginControlPane.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginControlPane.java @@ -15,6 +15,7 @@ import com.fr.plugin.manage.control.PluginTaskCallback; import com.fr.plugin.manage.control.PluginTaskResult; import com.fr.plugin.view.PluginView; import com.fr.stable.StringUtils; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -142,6 +143,7 @@ public class PluginControlPane extends BasicPane { } } + @Nullable public PluginView getSelectedPlugin() { return (PluginView) pluginList.getSelectedValue(); } diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginFromStorePane.java b/designer-base/src/main/java/com/fr/design/extra/PluginFromStorePane.java index 0f78a562c5..115cc87dc1 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginFromStorePane.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginFromStorePane.java @@ -28,8 +28,6 @@ import java.util.List; * @since 8.0 */ public class PluginFromStorePane extends PluginAbstractLoadingViewPane, Void> { - private static final int LISTNUM1 = 1; - private static final int LISTNUM100 = 100; private UILabel errorMsgLabel; private UITabbedPane tabbedPane; private PluginControlPane controlPane; @@ -45,6 +43,7 @@ public class PluginFromStorePane extends PluginAbstractLoadingViewPane loadData() throws Exception { - //Thread.sleep(3000); return PluginsReaderFromStore.readPlugins(); } @@ -140,6 +139,7 @@ public class PluginFromStorePane extends PluginAbstractLoadingViewPane plugins) { controlPane.loadPlugins(plugins); tabbedPane.setTitleAt(2, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_All_Plugins") + "(" + plugins.size() + ")"); @@ -150,10 +150,12 @@ public class PluginFromStorePane extends PluginAbstractLoadingViewPane p) throws Exception { - HttpClient httpClient = new HttpClient(getDownloadPath(id)); - if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) { - int totalSize = httpClient.getContentLength(); - InputStream reader = httpClient.getResponseStream(); - String temp = StableUtils.pathJoin(PluginConstants.DOWNLOAD_PATH, PluginConstants.TEMP_FILE); - StableUtils.makesureFileExist(new File(temp)); - FileOutputStream writer = new FileOutputStream(temp); - byte[] buffer = new byte[PluginConstants.BYTES_NUM]; - int bytesRead = 0; - int totalBytesRead = 0; + public static boolean downloadShopScripts(String id, Process p) { + InputStream reader = null; + FileOutputStream writer = null; + try { + HttpClient httpClient = new HttpClient(getDownloadPath(id)); + if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) { + int totalSize = httpClient.getContentLength(); + reader = httpClient.getResponseStream(); + String temp = StableUtils.pathJoin(PluginConstants.DOWNLOAD_PATH, PluginConstants.TEMP_FILE); + StableUtils.makesureFileExist(new File(temp)); + writer = new FileOutputStream(temp); + byte[] buffer = new byte[PluginConstants.BYTES_NUM]; + int bytesRead = 0; + int totalBytesRead = 0; - while ((bytesRead = reader.read(buffer)) > 0) { - writer.write(buffer, 0, bytesRead); - buffer = new byte[PluginConstants.BYTES_NUM]; - totalBytesRead += bytesRead; - p.process(totalBytesRead / (double) totalSize); + while ((bytesRead = reader.read(buffer)) > 0) { + writer.write(buffer, 0, bytesRead); + buffer = new byte[PluginConstants.BYTES_NUM]; + totalBytesRead += bytesRead; + p.process(totalBytesRead / (double) totalSize); + } + } else { + throw new com.fr.plugin.PluginVerifyException(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Connect_Server_Error")); } - reader.close(); - writer.flush(); - writer.close(); - } else { - throw new com.fr.plugin.PluginVerifyException(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Connect_Server_Error")); + } catch (PluginVerifyException e) { + JOptionPane.showMessageDialog(null, e.getMessage(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + return false; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; + } finally { + closeStream(reader, writer); + } + return true; + } + + private static void closeStream(InputStream reader, FileOutputStream writer){ + try { + if (null != reader) { + reader.close(); + } + if (null != writer) { + writer.flush(); + writer.close(); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } } diff --git a/designer-base/src/main/java/com/fr/design/extra/QQLoginWebPane.java b/designer-base/src/main/java/com/fr/design/extra/QQLoginWebPane.java index 43b7b9614d..9928d9ae0e 100644 --- a/designer-base/src/main/java/com/fr/design/extra/QQLoginWebPane.java +++ b/designer-base/src/main/java/com/fr/design/extra/QQLoginWebPane.java @@ -163,7 +163,7 @@ public class QQLoginWebPane extends JFXPanel { final BooleanProperty confirmationResult = new SimpleBooleanProperty(); // initialize the confirmation dialog final Stage dialog = new Stage(StageStyle.UTILITY); - dialog.setX(Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - DEFAULT_CONFIRM_WIDTH / 2 + DEFAULT_OFFEST); + dialog.setX(Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - DEFAULT_CONFIRM_WIDTH / 2.0D + DEFAULT_OFFEST); dialog.setY(Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 + DEFAULT_OFFEST); dialog.setHeight(DEFAULT_CONFIRM_HEIGHT); dialog.setWidth(DEFAULT_CONFIRM_WIDTH); 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 a64158765d..bbb10c6d65 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 @@ -5,18 +5,16 @@ import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.UIDialog; import com.fr.design.gui.frpane.UITabbedPane; import com.fr.design.mainframe.DesignerContext; +import com.fr.general.CloudCenter; import com.fr.general.CommonIOUtils; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; import com.fr.general.IOUtils; - -import com.fr.general.CloudCenter; import com.fr.general.http.HttpClient; import com.fr.general.http.HttpToolbox; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.plugin.PluginStoreConstants; -import com.fr.plugin.PluginVerifyException; import com.fr.stable.CommonUtils; import com.fr.stable.EnvChangedListener; import com.fr.stable.ProductConstants; @@ -260,21 +258,12 @@ public class WebViewDlgHelper { new SwingWorker() { @Override protected Boolean doInBackground() throws Exception { - try { - PluginUtils.downloadShopScripts(scriptsId, new Process() { - @Override - public void process(Double integer) { - // 这个注释毫无意义,就是为了通过SonarQube - } - }); - } catch (PluginVerifyException e) { - JOptionPane.showMessageDialog(null, e.getMessage(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), JOptionPane.ERROR_MESSAGE); - return false; - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - return false; - } - return true; + return PluginUtils.downloadShopScripts(scriptsId, new Process() { + @Override + public void process(Double integer) { + // 这个注释毫无意义,就是为了通过SonarQube + } + }); } @Override @@ -290,7 +279,10 @@ public class WebViewDlgHelper { PluginStoreConstants.refreshProps(); // 下载完刷新一下版本号等 JOptionPane.showMessageDialog(null, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Shop_Installed"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), JOptionPane.INFORMATION_MESSAGE); } - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); + } catch (ExecutionException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java index 59d5d6a085..4cbd063284 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java @@ -53,7 +53,7 @@ public class InstallFromDiskCallback extends AbstractPluginTaskCallback { null, null ); - if (rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { + if (rv == JOptionPane.NO_OPTION || rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { return; } List pluginTasks = result.getPreTasks(); @@ -73,7 +73,7 @@ public class InstallFromDiskCallback extends AbstractPluginTaskCallback { null, null ); - if (rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { + if (rv == JOptionPane.NO_OPTION || rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { return; } PluginOperateUtils.updatePluginFromDisk(zipFile, jsCallback); diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java index 26315fd030..392d8074e9 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java @@ -51,7 +51,7 @@ public class UpdateFromDiskCallback extends AbstractPluginTaskCallback { null, null ); - if (rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { + if (rv == JOptionPane.NO_OPTION || rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { return; } List pluginTasks = result.getPreTasks(); @@ -71,7 +71,7 @@ public class UpdateFromDiskCallback extends AbstractPluginTaskCallback { null, null ); - if (rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { + if (rv == JOptionPane.NO_OPTION || rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { return; } PluginOperateUtils.installPluginFromDisk(zipFile, jsCallback); 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 740f23aa86..8e75fae0bc 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 @@ -41,17 +41,12 @@ public class HistoryTemplateListCache implements CallbackEvent { private List> historyList; private JTemplate editingTemplate; - private static volatile HistoryTemplateListCache instacne; - public static HistoryTemplateListCache getInstance() { - if (instacne == null) { - synchronized (HistoryTemplateListCache.class) { - if (instacne == null) { - instacne = new HistoryTemplateListCache(); - } - } - } - return instacne; + return Holder.INSTANCE; + } + + private static class Holder { + private static final HistoryTemplateListCache INSTANCE = new HistoryTemplateListCache(); } private HistoryTemplateListCache() { diff --git a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java index 170369da71..5a722239c6 100644 --- a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java @@ -325,7 +325,7 @@ public class MutilTempalteTabPane extends JComponent { @Override public void paintComponent(Graphics g) { super.paintComponent(g); - double maxWidth = getWidth() - LIST_BUTTON_WIDTH; //最大宽度 + double maxWidth = getWidth() - LIST_BUTTON_WIDTH * 1.0D; //最大宽度 Graphics2D g2d = (Graphics2D) g; paintBackgroundAndLine(g2d, maxWidth); } @@ -398,8 +398,8 @@ public class MutilTempalteTabPane extends JComponent { //画下面的那条线 if (templateStartX < maxWidth) { GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, 2); - generalPath.moveTo((float) templateStartX, getHeight() - 1); - generalPath.lineTo((float) maxWidth, getHeight() - 1); + generalPath.moveTo((float) templateStartX, getHeight() - 1.0F); + generalPath.lineTo((float) maxWidth, getHeight() - 1.0F); g2d.fill(generalPath); //TODO hzzz delete // g2d.setPaint(UIConstants.LINE_COLOR); @@ -409,7 +409,7 @@ public class MutilTempalteTabPane extends JComponent { private void paintDefaultBackground(Graphics2D g2d) { //画默认背景 - g2d.setPaint(new GradientPaint(1, 1, UIConstants.TEMPLATE_TAB_PANE_BACKGROUND, 1, getHeight() - 1, UIConstants.TEMPLATE_TAB_PANE_BACKGROUND)); + g2d.setPaint(new GradientPaint(1, 1, UIConstants.TEMPLATE_TAB_PANE_BACKGROUND, 1, getHeight() - 1.0F, UIConstants.TEMPLATE_TAB_PANE_BACKGROUND)); g2d.fillRect(0, 0, getWidth(), getHeight()); } @@ -535,7 +535,7 @@ public class MutilTempalteTabPane extends JComponent { double[] x = {templateStartX, templateStartX, templateStartX + realWidth, templateStartX + realWidth, templateStartX}; double[] y = {1, getHeight() + 1, getHeight() + 1, 1, 1}; RoundRectangle2D.Double rect1 = new RoundRectangle2D.Double(templateStartX, 1, this.getWidth(), this.getHeight(), 7, 7); - g2d.setPaint(new GradientPaint(1, 1, UIConstants.SELECT_TAB, 1, getHeight() - 1, UIConstants.SELECT_TAB)); + g2d.setPaint(new GradientPaint(1, 1, UIConstants.SELECT_TAB, 1, getHeight() - 1.0F, UIConstants.SELECT_TAB)); //选了30度和60度的特殊角度的x,y作为经过的两个点的坐标 double specialLocation1 = 2.5; double specialLocation2 = 4.330127; @@ -590,9 +590,9 @@ public class MutilTempalteTabPane extends JComponent { double[] x = {templateStartX, templateStartX, templateStartX + realWidth, templateStartX + realWidth, templateStartX}; double[] y = {-1, getHeight() - 1, getHeight() - 1, -1, -1}; if (selfIndex == mouseOveredIndex) { - g2d.setPaint(new GradientPaint(1, 1, UIConstants.HOVER_BLUE, 1, getHeight() - 1, UIConstants.HOVER_BLUE)); + g2d.setPaint(new GradientPaint(1, 1, UIConstants.HOVER_BLUE, 1, getHeight() - 1.0F, UIConstants.HOVER_BLUE)); } else { - g2d.setPaint(new GradientPaint(1, 1, UIConstants.SHADOW_GREY, 1, getHeight() - 1, UIConstants.SHADOW_GREY)); + g2d.setPaint(new GradientPaint(1, 1, UIConstants.SHADOW_GREY, 1, getHeight() - 1.0F, UIConstants.SHADOW_GREY)); } diff --git a/designer-base/src/main/java/com/fr/design/file/NodeAuthProcessor.java b/designer-base/src/main/java/com/fr/design/file/NodeAuthProcessor.java index 01c4615af3..2a1c0cc94e 100644 --- a/designer-base/src/main/java/com/fr/design/file/NodeAuthProcessor.java +++ b/designer-base/src/main/java/com/fr/design/file/NodeAuthProcessor.java @@ -11,6 +11,7 @@ import com.fr.stable.CoreConstants; import com.fr.stable.project.ProjectConstants; import com.fr.workspace.WorkContext; import com.fr.workspace.server.authority.AuthorityOperator; +import com.fr.workspace.server.authority.decision.DecisionOperator; import java.util.ArrayList; @@ -39,14 +40,15 @@ public class NodeAuthProcessor { authPaths.clear(); if (!WorkContext.getCurrent().isLocal()) { try { - String username = WorkContext.getCurrent().getConnection().getUserName(); - // 远程设计获取全部设计成员的权限列表 - DesignAuthority[] authorities = WorkContext.getCurrent().get(AuthorityOperator.class).getAuthorities(); + String userName = WorkContext.getCurrent().getConnection().getUserName(); + String userId = WorkContext.getCurrent().get(DecisionOperator.class).getUserIdByName(userName); + // 远程设计获取设计成员的权限列表 + DesignAuthority[] authorities = WorkContext.getCurrent().get(AuthorityOperator.class).getAuthorities(userId); DesignAuthority authority = null; if (authorities != null) { for (DesignAuthority designAuthority : authorities) { - if (ComparatorUtils.equals(designAuthority.getUsername(), username)) { + if (ComparatorUtils.equals(designAuthority.getUsername(), userName)) { authority = designAuthority; } } 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 3d0460e868..28bb985552 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 @@ -174,7 +174,7 @@ public final class FunctionConstants { jarPath = StringUtils.perfectStart(jarPath, "/"); } - ZipFile zip; + ZipFile zip = null; try { zip = new ZipFile(jarPath); Enumeration entries = zip.entries(); @@ -193,6 +193,14 @@ public final class FunctionConstants { } } catch (IOException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + if(null != zip){ + try { + zip.close(); + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } } } else { File dir = new File(filePath); diff --git a/designer-base/src/main/java/com/fr/design/formula/JavaEditorPane.java b/designer-base/src/main/java/com/fr/design/formula/JavaEditorPane.java index 597ddbfd66..a3bdbae216 100644 --- a/designer-base/src/main/java/com/fr/design/formula/JavaEditorPane.java +++ b/designer-base/src/main/java/com/fr/design/formula/JavaEditorPane.java @@ -194,6 +194,7 @@ public class JavaEditorPane extends BasicPane { JOptionPane.showMessageDialog(null, message); } catch (InterruptedException e1) { FineLoggerFactory.getLogger().error(e1.getMessage(), e1); + Thread.currentThread().interrupt(); } catch (ExecutionException e1) { FineLoggerFactory.getLogger().error(e1.getMessage(), e1); } diff --git a/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java b/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java index e03fa0e186..5fd384be8e 100644 --- a/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java +++ b/designer-base/src/main/java/com/fr/design/formula/VariableResolverAdapter.java @@ -23,6 +23,7 @@ public abstract class VariableResolverAdapter implements VariableResolver { * * @return 内置参数 */ + @Override public String[] resolveCurReportVariables() { String[] variables = new String[]{ ScriptConstants.SUMMARY_TAG + "page_number", @@ -38,10 +39,10 @@ public abstract class VariableResolverAdapter implements VariableResolver { CalculatorProvider.SERVER_PORT, CalculatorProvider.SERVER_URL, CalculatorProvider.CONTEXT_PATH, CalculatorProvider.SESSION_ID }; Set set = ExtraClassManager.getInstance().getArray(BuiltInParametersProvider.XML_TAG); - for (BuiltInParametersProvider provider : set) { - return (String[]) ArrayUtils.addAll(variables, new String[]{ - ScriptConstants.DETAIL_TAG + provider.getParametersName() - }); + for (BuiltInParametersProvider provider : set) { + ArrayUtils.addAll(variables, new String[]{ + ScriptConstants.DETAIL_TAG + provider.getParametersName() + }); } return variables; } @@ -65,6 +66,8 @@ public abstract class VariableResolverAdapter implements VariableResolver { * * @return 所有参数 */ + @Override + @SuppressWarnings("squid:S2259") public String[] resolveTableDataParameterVariables() { Parameter[] parameters = getCurrentModeParameters(TABLE_DATA_PARA); String[] parameterNames = new String[parameters.length]; @@ -79,6 +82,8 @@ public abstract class VariableResolverAdapter implements VariableResolver { * * @return 所有参数 */ + @Override + @SuppressWarnings("squid:S2259") public String[] resolveReportParameterVariables() { Parameter[] parameters = getCurrentModeParameters(REPORT_DATA_PARA); String[] parameterNames = new String[parameters.length]; @@ -93,6 +98,7 @@ public abstract class VariableResolverAdapter implements VariableResolver { * * @return 所有参数 */ + @Override public String[] resolveGlobalParameterVariables() { // 加上全局的参数 Parameter[] globalParameters = ParameterConfig.getInstance().getGlobalParameters(); diff --git a/designer-base/src/main/java/com/fr/design/fun/ExportAttrTabProvider.java b/designer-base/src/main/java/com/fr/design/fun/ExportAttrTabProvider.java index 811d5e960b..d14726e7b7 100644 --- a/designer-base/src/main/java/com/fr/design/fun/ExportAttrTabProvider.java +++ b/designer-base/src/main/java/com/fr/design/fun/ExportAttrTabProvider.java @@ -1,14 +1,8 @@ package com.fr.design.fun; -import com.fr.design.report.AbstractExportPane; +import com.fr.design.beans.BasicStorePane; import com.fr.stable.fun.mark.Mutable; -import javax.swing.*; - -/** - * Created by vito on 16/5/5. - */ - /** * 导出属性Tab页的接口 */ @@ -18,31 +12,9 @@ public interface ExportAttrTabProvider extends Mutable { int CURRENT_LEVEL = 1; /** - * 转换成SwingComponent - * - * @return JComponent - */ - JComponent toSwingComponent(); - - /** - * 转换成AbstractExportPane - * - * @return AbstractExportPane - */ - AbstractExportPane toExportPane(); - - /** - * tab的标题 - * - * @return - */ - String title(); - - /** - * tag标签 + * 转换成业务视图界面 * - * @return tag名称 - * @deprecated 将来不使用tag作为区分 + * @return 业务视图界面 */ - String tag(); + BasicStorePane toServiceComponent(); } diff --git a/designer-base/src/main/java/com/fr/design/fun/MobileWidgetStyleProvider.java b/designer-base/src/main/java/com/fr/design/fun/MobileWidgetStyleProvider.java new file mode 100644 index 0000000000..bc01837ee7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/MobileWidgetStyleProvider.java @@ -0,0 +1,24 @@ +package com.fr.design.fun; + +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.stable.fun.mark.Mutable; + +/** + * 移动端组件样式扩展接口 + */ +public interface MobileWidgetStyleProvider extends Mutable { + + String XML_TAG = "MobileWidgetStyleProvider"; + + int CURRENT_LEVEL = 1; + + Class classForMobileStyle(); + + Class classForWidgetAppearance(); + + String xTypeForWidget(); + + String displayName(); + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/ParameterWidgetOptionProvider.java b/designer-base/src/main/java/com/fr/design/fun/ParameterWidgetOptionProvider.java index 685c81a921..ffcfef58bc 100644 --- a/designer-base/src/main/java/com/fr/design/fun/ParameterWidgetOptionProvider.java +++ b/designer-base/src/main/java/com/fr/design/fun/ParameterWidgetOptionProvider.java @@ -17,6 +17,7 @@ public interface ParameterWidgetOptionProvider extends Mutable { /** * 自定义参数控件的实际类,该类需要继承自com.fr.form.ui.Widget + * 如果有控件值属性,该类需要实现DataControl接口,否则可能有部分功能无法使用,比如:值编辑器选择控件的时候无法找到插件里的控件 * @return 控件类 */ Class classForWidget(); diff --git a/designer-base/src/main/java/com/fr/design/fun/ReportSupportedFileUIProvider.java b/designer-base/src/main/java/com/fr/design/fun/ReportSupportedFileUIProvider.java new file mode 100644 index 0000000000..4f4ea45c3c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/ReportSupportedFileUIProvider.java @@ -0,0 +1,40 @@ +package com.fr.design.fun; + +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILEChooserPane; +import com.fr.stable.fun.mark.Mutable; + +import javax.swing.Icon; + +/** + * Created by kerry on 2019-10-11 + */ +public interface ReportSupportedFileUIProvider extends Mutable { + + int CURRENT_LEVEL = 1; + + String XML_TAG = "ReportSupportedFileUIProvider"; + + /** + * 向文件选择器中添加指定文件类型过滤器 + * @param fileChooser 文件选择器 + * @param suffix 文件后缀 + */ + void addChooseFileFilter(FILEChooserPane fileChooser, String suffix); + + + /** + * 获取文件关联的icon + * @param path 文件路径 + * @param isShowLock 是否显示被锁住 + * @return 对应的图标 + */ + Icon getFileIcon(String path,boolean isShowLock); + + /** + * 保存为新类型文件 + * @param targetPath 目标路径 + * @param jTemplate 模板对象 + */ + boolean saveToNewFile(String targetPath, JTemplate jTemplate); +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractExportAttrTabProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractExportAttrTabProvider.java index 2e526e6973..0d76c58309 100644 --- a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractExportAttrTabProvider.java +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractExportAttrTabProvider.java @@ -1,19 +1,55 @@ package com.fr.design.fun.impl; +import com.fr.design.beans.BasicStorePane; import com.fr.design.fun.ExportAttrTabProvider; +import com.fr.design.report.AbstractExportPane; +import com.fr.stable.StringUtils; import com.fr.stable.fun.impl.AbstractProvider; import com.fr.stable.fun.mark.API; +import javax.swing.*; + /** * Created by vito on 16/5/5. */ @API(level = ExportAttrTabProvider.CURRENT_LEVEL) -public abstract class AbstractExportAttrTabProvider extends AbstractProvider implements ExportAttrTabProvider { +public abstract class AbstractExportAttrTabProvider extends AbstractProvider implements ExportAttrTabProvider { @Override public int currentAPILevel() { return CURRENT_LEVEL; } + /** + * @see ExportAttrTabProvider#toServiceComponent() + */ + @Deprecated + public AbstractExportPane toExportPane() { + return null; + } + + /** + * @see ExportAttrTabProvider#toServiceComponent() + */ + @Deprecated + public JComponent toSwingComponent() { + return toServiceComponent(); + } + + @Deprecated + public String title() { + return StringUtils.EMPTY; + } + + @Deprecated + public String tag() { + return StringUtils.EMPTY; + } + + @Override + public BasicStorePane toServiceComponent() { + return toExportPane(); + } + @Override public String mark4Provider() { return this.getClass().getName(); diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractMobileWidgetStyleProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractMobileWidgetStyleProvider.java new file mode 100644 index 0000000000..407aa058c7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractMobileWidgetStyleProvider.java @@ -0,0 +1,20 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.MobileWidgetStyleProvider; +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +@API(level = MobileWidgetStyleProvider.CURRENT_LEVEL) +public abstract class AbstractMobileWidgetStyleProvider extends AbstractProvider implements MobileWidgetStyleProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractReportSupportedFileUIProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractReportSupportedFileUIProvider.java new file mode 100644 index 0000000000..e8d1dfcc19 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractReportSupportedFileUIProvider.java @@ -0,0 +1,40 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.ReportSupportedFileUIProvider; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILEChooserPane; +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +import javax.swing.Icon; + +/** + * Created by kerry on 2019-10-14 + */ +@API(level = ReportSupportedFileUIProvider.CURRENT_LEVEL) +public abstract class AbstractReportSupportedFileUIProvider extends AbstractProvider implements ReportSupportedFileUIProvider { + @Override + public void addChooseFileFilter(FILEChooserPane fileChooser, String suffix) { + + } + + @Override + public Icon getFileIcon(String path, boolean isShowLock) { + return null; + } + + @Override + public boolean saveToNewFile(String targetPath, JTemplate jTemplate) { + return false; + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/UIDefaultTheme.java b/designer-base/src/main/java/com/fr/design/gui/UIDefaultTheme.java index 26030c47c9..78750e389a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/UIDefaultTheme.java +++ b/designer-base/src/main/java/com/fr/design/gui/UIDefaultTheme.java @@ -76,7 +76,6 @@ public class UIDefaultTheme extends DefaultMetalTheme { table.put("Table.background", ThemeUtils.TEXT_BG_COLOR); table.put("Table.selectionForeground", ThemeUtils.NORMAL_FOREGROUND); table.put("Table.selectionBackground", new ColorUIResource(200, 221, 233)); - table.put("Table.gridColor", new ColorUIResource(200, 221, 233)); table.put("TableHeader.background", new ColorUIResource(229, 229, 229)); table.put("ProgressBar.foreground", ThemeUtils.PROCESS_COLOR); table.put("ProgressBar.background", ThemeUtils.TEXT_BG_COLOR); @@ -85,7 +84,6 @@ public class UIDefaultTheme extends DefaultMetalTheme { table.put("ProgressBar.selectionForeground", ThemeUtils.NORMAL_FOREGROUND); table.put("ProgressBar.selectionBackground", ThemeUtils.NORMAL_FOREGROUND); table.put("PopupMenu.background", ThemeUtils.NORMAL_BG); - table.put("TabbedPane.background", ThemeUtils.TEXT_BG_COLOR); table.put("TabbedPane.background", ThemeUtils.NORMAL_BG); table.put("TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 0)); table.put("TabbedPane.tabInsets", new InsetsUIResource(1, 6, 4, 6)); @@ -108,7 +106,6 @@ public class UIDefaultTheme extends DefaultMetalTheme { table.put("ComboBox.foreground", ThemeUtils.NORMAL_FOREGROUND); table.put("ComboBox.background", ThemeUtils.TEXT_BG_COLOR); table.put("ComboBox.disabledBackground", ThemeUtils.TEXT_DISABLED_BG_COLOR); - table.put("EditorPane.background", ThemeUtils.TEXT_BG_COLOR); table.put("EditorPane.foreground", ThemeUtils.NORMAL_FOREGROUND); table.put("PasswordField.background", ThemeUtils.TEXT_BG_COLOR); table.put("PasswordField.foreground", ThemeUtils.NORMAL_FOREGROUND); diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java index b9d9afcc08..8bc805f464 100644 --- a/designer-base/src/main/java/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java @@ -195,6 +195,9 @@ public class LanguageAwareCompletionProvider extends CompletionProviderBase // provider. We do not do function/method completions while editing // strings or comments. CompletionProvider provider = getProviderFor(tc); + if (provider == null) { + return null; + } return provider==defaultProvider ? provider.getParameterizedCompletions(tc) : null; } diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java index a9dd305b05..78d5e74a48 100644 --- a/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java @@ -517,6 +517,10 @@ class ParameterizedCompletionContext { } } + if (currentNext == null) { + return; + } + // No params after caret - go to first one if (currentNext.getStartOffset() + 1 <= dot) { int nextIndex = getFirstHighlight(highlights); diff --git a/designer-base/src/main/java/com/fr/design/gui/borders/UIFrameBorder.java b/designer-base/src/main/java/com/fr/design/gui/borders/UIFrameBorder.java index d4ff794e84..8e6bc4781f 100644 --- a/designer-base/src/main/java/com/fr/design/gui/borders/UIFrameBorder.java +++ b/designer-base/src/main/java/com/fr/design/gui/borders/UIFrameBorder.java @@ -141,8 +141,8 @@ public class UIFrameBorder extends AbstractBorder implements UIResource { int spread1 = ThemeUtils.FRAME_SPREAD_DARK_DISABLED; int spread2 = ThemeUtils.FRAME_SPREAD_LIGHT_DISABLED; int y2 = y; - Color borderColor = null; - drawFirstCaption(g, borderColor, spread1, spread2, x, y2, w); + Color borderColor = isActive ? ThemeUtils.FRAME_BORDER_COLOR : ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + drawFirstCaption(g, borderColor, x, y2, w); Color c2 = ColorRoutines.darken(c, 4 * spread1); drawSecondCaption(g, c2, c, spread2, x, y2, w); c2 = ColorRoutines.darken(c, 6 * spread1); @@ -257,14 +257,8 @@ public class UIFrameBorder extends AbstractBorder implements UIResource { g.drawLine(x + w - 4, y2, x + w - 4, y2); } - private void drawFirstCaption(Graphics g, Color borderColor, int spread1, int spread2, int x, int y2, int w) { - if (isActive) { - borderColor = ThemeUtils.FRAME_BORDER_COLOR; - spread1 = ThemeUtils.FRAME_SPREAD_DARK; - spread2 = ThemeUtils.FRAME_SPREAD_LIGHT; - } else { - borderColor = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; - } + + private void drawFirstCaption(Graphics g, Color borderColor, int x, int y2, int w) { // always paint the semi-transparent parts // 1 // blend @@ -580,4 +574,4 @@ public class UIFrameBorder extends AbstractBorder implements UIResource { } } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/chart/MiddleChartComponent.java b/designer-base/src/main/java/com/fr/design/gui/chart/MiddleChartComponent.java index 9d16d6787a..8269b8d05d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/chart/MiddleChartComponent.java +++ b/designer-base/src/main/java/com/fr/design/gui/chart/MiddleChartComponent.java @@ -1,12 +1,10 @@ package com.fr.design.gui.chart; -import javax.swing.JComponent; - -import com.fr.base.chart.BaseChart; import com.fr.base.chart.BaseChartCollection; -import com.fr.stable.core.PropertyChangeAdapter; import com.fr.stable.core.PropertyChangeListener; +import javax.swing.JComponent; + /** * @author kunsnat E-mail:kunsnat@gmail.com * @version 创建时间:2013-7-10 上午09:19:36 @@ -18,8 +16,6 @@ public abstract class MiddleChartComponent extends JComponent { public abstract BaseChartCollection update(); public abstract void reset(); - - public abstract BaseChart getEditingChart(); - - public abstract void addStopEditingListener(PropertyChangeListener list); + + public abstract void addStopEditingListener(PropertyChangeListener list); } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/columnrow/ColumnRowPane.java b/designer-base/src/main/java/com/fr/design/gui/columnrow/ColumnRowPane.java index 615a17bcef..e94b182695 100644 --- a/designer-base/src/main/java/com/fr/design/gui/columnrow/ColumnRowPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/columnrow/ColumnRowPane.java @@ -146,6 +146,8 @@ public class ColumnRowPane extends JPanel implements UIObserver { if (cftf != null) { cftf.setColumns(3); // specify more width than we need cftf.setHorizontalAlignment(UITextField.LEFT); + }else { + throw new IllegalArgumentException("Spinner'Editor can not be null!"); } ((AbstractDocument) cftf.getDocument()).setDocumentFilter(new DocumentFilter() { diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/ObjectUIControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/ObjectUIControlPane.java index c5786b4c64..be169a744a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/ObjectUIControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/ObjectUIControlPane.java @@ -1,8 +1,8 @@ package com.fr.design.gui.controlpane; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import com.fr.design.beans.BasicBeanPane; +import com.fr.stable.AssistUtils; /** * Created by plough on 2017/8/1. @@ -48,7 +48,7 @@ public abstract class ObjectUIControlPane extends UIListControlPane { if (constructor != null) { return constructor; } else { - if (cls.getName() == Object.class.getName()) { + if (AssistUtils.equals(cls.getName(),Object.class.getName())) { return null; } return getConstructor(clazz, cls.getSuperclass()); diff --git a/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java b/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java index fb44f618f8..be3ef20a3a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java @@ -157,7 +157,7 @@ public class UIDatePicker extends UIComboBox implements Serializable { /** * 设置当前选择的日期 */ - public void setSelectedDate(Date date) throws ParseException { + public synchronized void setSelectedDate(Date date) throws ParseException { if (date == null) { this.setSelectedItem(null); } else { @@ -165,6 +165,7 @@ public class UIDatePicker extends UIComboBox implements Serializable { } } + @Override public void setSelectedItem(Object anObject) { model.setSelectedItem(anObject); super.setSelectedItem(anObject); @@ -192,12 +193,14 @@ public class UIDatePicker extends UIComboBox implements Serializable { setBorder(BorderFactory.createEmptyBorder()); } + @Override public void hide() { if (isWillHide) { super.hide(); } } + @Override public void show() { if (isWillHide || UIDatePicker.this.isEnabled() == false) { return; @@ -211,6 +214,7 @@ public class UIDatePicker extends UIComboBox implements Serializable { /** * 显示弹出面板 */ + @Override protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { @@ -250,12 +254,14 @@ public class UIDatePicker extends UIComboBox implements Serializable { } } + @Override protected ComboBoxUI getUIComboBoxUI() { return new UIComboBoxUI() { + @Override protected ComboPopup createPopup() { return new DatePopup(comboBox); } - + @Override public void mousePressed(MouseEvent e) { if (UIDatePicker.this.isPopupVisible()) { isWillHide = true; diff --git a/designer-base/src/main/java/com/fr/design/gui/demo/LoadingPaneDemo.java b/designer-base/src/main/java/com/fr/design/gui/demo/LoadingPaneDemo.java index 2eb93ad3e0..b173237742 100644 --- a/designer-base/src/main/java/com/fr/design/gui/demo/LoadingPaneDemo.java +++ b/designer-base/src/main/java/com/fr/design/gui/demo/LoadingPaneDemo.java @@ -35,6 +35,7 @@ public class LoadingPaneDemo extends JPanel { Thread.sleep(500); } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); } container.add(new UIButton(i + "adfadwdadawdwad")); } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/BaseHyperlinkGroup.java b/designer-base/src/main/java/com/fr/design/gui/frpane/BaseHyperlinkGroup.java index 8981016982..0c02e6c5cd 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/BaseHyperlinkGroup.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/BaseHyperlinkGroup.java @@ -4,6 +4,7 @@ import com.fr.design.gui.controlpane.NameableCreator; import com.fr.design.module.DesignModuleFactory; import com.fr.js.JavaScript; import com.fr.stable.Filter; +import org.jetbrains.annotations.NotNull; /** * 基础的超级链接类型, 不包括图表相关超链. @@ -18,6 +19,8 @@ public class BaseHyperlinkGroup implements HyperlinkGroupType { * * @return NameableCreator[] */ + @NotNull + @Override public NameableCreator[] getHyperlinkCreators() { return DesignModuleFactory.getCreators4Hyperlink(); } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java index 85dbdbe5c4..afbf43c305 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/CommitTabbedPane.java @@ -296,7 +296,7 @@ public class CommitTabbedPane extends JComponent implements MouseListener, Mous double[] x = {startX, startX, startX + tabWidth, startX + tabWidth, startX}; double[] y = {-1, getHeight(), getHeight(), -1, -1}; RoundRectangle2D.Double rect1 = new RoundRectangle2D.Double(startX, 1, this.getWidth(), this.getHeight(), 7, 7); - g2d.setPaint(new GradientPaint(1, 1, new Color(255, 255, 255), 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); + g2d.setPaint(new GradientPaint(1, 1, new Color(255, 255, 255), 1, getHeight() - 1f, UIConstants.NORMAL_BACKGROUND)); GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length); generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); @@ -345,9 +345,9 @@ public class CommitTabbedPane extends JComponent implements MouseListener, Mous double[] x = {startX, startX, startX + tabWidth, startX + tabWidth, startX}; double[] y = {-1, getHeight() - 1, getHeight() - 1, -1, -1}; if (selfIndex == mouseOveredIndex) { - g2d.setPaint(new GradientPaint(1, 1, new Color(255, 255, 255), 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); + g2d.setPaint(new GradientPaint(1, 1, new Color(255, 255, 255), 1, getHeight() - 1f, UIConstants.NORMAL_BACKGROUND)); } else { - g2d.setPaint(new GradientPaint(1, 1, UIConstants.NORMAL_BACKGROUND, 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); + g2d.setPaint(new GradientPaint(1, 1, UIConstants.NORMAL_BACKGROUND, 1, getHeight() - 1f, UIConstants.NORMAL_BACKGROUND)); } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/HyperlinkGroupType.java b/designer-base/src/main/java/com/fr/design/gui/frpane/HyperlinkGroupType.java index 8db0b9b948..4c5aec60ec 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/HyperlinkGroupType.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/HyperlinkGroupType.java @@ -3,6 +3,7 @@ package com.fr.design.gui.frpane; import com.fr.design.gui.controlpane.NameableCreator; import com.fr.js.JavaScript; import com.fr.stable.Filter; +import org.jetbrains.annotations.NotNull; /** * 超级链接 支持的类型 种类. @@ -17,6 +18,7 @@ public interface HyperlinkGroupType { * * @return NameableCreator[] */ + @NotNull NameableCreator[] getHyperlinkCreators(); diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/LoadingBasicPaneTest.java b/designer-base/src/main/java/com/fr/design/gui/frpane/LoadingBasicPaneTest.java index 7c454ad715..e3a1ae7d7d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/LoadingBasicPaneTest.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/LoadingBasicPaneTest.java @@ -24,6 +24,7 @@ public class LoadingBasicPaneTest { Thread.sleep(500); } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); } container.add(new UIButton(i + "adfadwdadawdwad")); } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/RegPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/RegPane.java index 2df45f8923..f84d0f5fdb 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/RegPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/RegPane.java @@ -111,8 +111,8 @@ public class RegPane extends BasicPane { cardPane.setPreferredSize(new Dimension(0,0 )); detailedCardLayout.show(cardPane, "Default"); } - fireRegChangeAction(); } + fireRegChangeAction(); } }); } diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UINumberSlidePane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UINumberSlidePane.java index 7585c09490..5faa21b3ca 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UINumberSlidePane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UINumberSlidePane.java @@ -14,6 +14,7 @@ import javax.swing.event.ChangeListener; import com.fr.design.beans.BasicBeanPane; import com.fr.design.gui.itextfield.UINumberField; import com.fr.design.gui.style.NumberDragBar; +import com.fr.stable.AssistUtils; /** * 拖拽的滑条和对应滑条值的数字 @@ -65,7 +66,7 @@ public class UINumberSlidePane extends BasicBeanPane { public void checkValue(double value) { value = Math.max(value, minValue); value = Math.min(value, maxValue); - if (this.value == value) { + if (AssistUtils.equals(this.value, value)) { return; } double diff = Math.abs(value - this.value); diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java index ca44c8a228..798b79af08 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java @@ -10,6 +10,7 @@ import com.fr.design.gui.ispinner.UIBasicSpinner; import com.fr.design.gui.itextfield.UINumberField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.stable.AssistUtils; import com.fr.stable.StringUtils; import javax.swing.*; @@ -81,7 +82,7 @@ public abstract class UnitInputPane extends BasicPane { floatValue = de.floatValue(); } //选中多列, 并且列宽不完全一致的话, 就不显示值了. - temp.setText(floatValue == 0 ? StringUtils.EMPTY : Utils.convertNumberStringToString(new Float(floatValue))); + temp.setText(AssistUtils.equals(floatValue, 0) ? StringUtils.EMPTY : Utils.convertNumberStringToString(new Float(floatValue))); // denny:默认应该为选中,方便用户修改 temp.selectAll(); diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIBasicButtonUI.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIBasicButtonUI.java index 185e4c18fc..64db1e91da 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIBasicButtonUI.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIBasicButtonUI.java @@ -321,9 +321,9 @@ public class UIBasicButtonUI extends MetalButtonUI { //harry: 画带有高光的按钮。 private void drawHighLightButton(Graphics2D g2, Color color1, Color color2, int w, int h) { - GradientPaint buttonPaint = new GradientPaint(0, 0, color1, 0, h - 1, color2); - GradientPaint buttonHighLightPaint = new GradientPaint(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.6f), 0, h / 2, new Color(1.0f, 1.0f, 1.0f, 0.2f)); - GradientPaint buttonHighLightLinePaint = new GradientPaint(1, 1, new Color(1.0f, 1.0f, 1.0f, 0.8f), 0, h / 2, new Color(1.0f, 1.0f, 1.0f, 0.4f)); + GradientPaint buttonPaint = new GradientPaint(0, 0, color1, 0, h - 1f, color2); + GradientPaint buttonHighLightPaint = new GradientPaint(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.6f), 0, h / 2f, new Color(1.0f, 1.0f, 1.0f, 0.2f)); + GradientPaint buttonHighLightLinePaint = new GradientPaint(1, 1, new Color(1.0f, 1.0f, 1.0f, 0.8f), 0, h / 2f, new Color(1.0f, 1.0f, 1.0f, 0.4f)); g2.setPaint(buttonPaint); g2.fillRoundRect(0, 0, w - 1, h - 1, 3, 3); g2.setPaint(buttonHighLightLinePaint);//按钮内侧高光线(内发光,0%阻塞) diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java index 078bf692b9..32f20ad563 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java @@ -251,7 +251,7 @@ public class UIButton extends JButton implements UIObserver, UITextComponent { protected void paintOtherBorder(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.setStroke(borderStroke); - Shape shape = new RoundRectangle2D.Float(0.5f, 0.5f, getWidth() - 1, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + Shape shape = new RoundRectangle2D.Float(0.5f, 0.5f, getWidth() - 1f, getHeight() - 1f, UIConstants.ARC, UIConstants.ARC); g2d.setColor(borderColor); g2d.draw(shape); } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButton.java index 21c5ee4b98..cc8aa9f63a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButton.java @@ -232,7 +232,7 @@ public class UISliderButton extends JButton implements UIObserver { protected void paintOtherBorder(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.setStroke(borderStroke); - Shape shape = new RoundRectangle2D.Float(0.5f, 0.5f, getWidth() - 1, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + Shape shape = new RoundRectangle2D.Float(0.5f, 0.5f, getWidth() - 1f, getHeight() - 1f, UIConstants.ARC, UIConstants.ARC); g2d.setColor(borderColor); g2d.draw(shape); } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButtonUI.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButtonUI.java index 6da878d8d7..6a92f5057b 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButtonUI.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UISliderButtonUI.java @@ -176,7 +176,7 @@ public class UISliderButtonUI extends BasicButtonUI { private void fillNormal(Graphics2D g2d, int x, int y, int width, int height, boolean isRound, int rectDirection, boolean isAuthorityEdited, boolean isPressedPainted) { GradientPaint gp; if (DesignerMode.isAuthorityEditing() && isAuthorityEdited) { - gp = new GradientPaint(1, 1, UIConstants.AUTHORITY_BLUE, 1, height - 1, UIConstants.AUTHORITY_DARK_BLUE); + gp = new GradientPaint(1, 1, UIConstants.AUTHORITY_BLUE, 1, height - 1f, UIConstants.AUTHORITY_DARK_BLUE); } else if (isPressedPainted) { gp = new GradientPaint(1, 1, UIConstants.SELECT_TAB, 1, height - 1, UIConstants.SELECT_TAB); }else{ diff --git a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java index 7489b4f592..10ea06a8ce 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java @@ -125,60 +125,58 @@ public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObser private class UICheckBoxUI extends MetalCheckBoxUI { @Override - public void paint(Graphics g, JComponent c) { - synchronized (this) { - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Dimension size = c.getSize(); - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f); - - Rectangle viewRect = new Rectangle(size); - Rectangle iconRect = new Rectangle(); - Rectangle textRect = new Rectangle(); - - Insets i = c.getInsets(); - viewRect.x += i.left; - viewRect.y += i.top; - viewRect.width -= (i.right + viewRect.x); - viewRect.height -= (i.bottom + viewRect.y); - - Icon altIcon = b.getIcon(); - - String text = SwingUtilities.layoutCompoundLabel( - c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(), - b.getVerticalAlignment(), b.getHorizontalAlignment(), - b.getVerticalTextPosition(), b.getHorizontalTextPosition(), - viewRect, iconRect, textRect, b.getIconTextGap()); - - // fill background - if (c.isOpaque()) { - g.setColor(b.getBackground()); - g.fillRect(0, 0, size.width, size.height); - } - - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if (model.isSelected()) { - GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height, false, Constants.NULL, - model.isEnabled() ? UIConstants.CHECKBOX_HOVER_SELECTED : UIConstants.DISABLED_ICON_COLOR, 0); - } else if (model.isRollover() && !model.isSelected()) { - g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED); - g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); - } else { - g.setColor(UIConstants.LINE_COLOR); - g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); - } + public synchronized void paint(Graphics g, JComponent c) { + AbstractButton b = (AbstractButton) c; + ButtonModel model = b.getModel(); + Dimension size = c.getSize(); + Font f = c.getFont(); + g.setFont(f); + FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f); + + Rectangle viewRect = new Rectangle(size); + Rectangle iconRect = new Rectangle(); + Rectangle textRect = new Rectangle(); + + Insets i = c.getInsets(); + viewRect.x += i.left; + viewRect.y += i.top; + viewRect.width -= (i.right + viewRect.x); + viewRect.height -= (i.bottom + viewRect.y); + + Icon altIcon = b.getIcon(); + + String text = SwingUtilities.layoutCompoundLabel( + c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(), + b.getVerticalAlignment(), b.getHorizontalAlignment(), + b.getVerticalTextPosition(), b.getHorizontalTextPosition(), + viewRect, iconRect, textRect, b.getIconTextGap()); + + // fill background + if (c.isOpaque()) { + g.setColor(b.getBackground()); + g.fillRect(0, 0, size.width, size.height); + } - if (model.isSelected()) { - UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2); - } - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + if (model.isSelected()) { + GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height, false, Constants.NULL, + model.isEnabled() ? UIConstants.CHECKBOX_HOVER_SELECTED : UIConstants.DISABLED_ICON_COLOR, 0); + } else if (model.isRollover() && !model.isSelected()) { + g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED); + g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); + } else { + g.setColor(UIConstants.LINE_COLOR); + g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); + } - // Draw the Text - drawLine(text, g, b, c, textRect, fm); + if (model.isSelected()) { + UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2); } + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + // Draw the Text + drawLine(text, g, b, c, textRect, fm); } private void drawLine(String text, Graphics g, AbstractButton b, JComponent c, Rectangle textRect, FontMetrics fm) { diff --git a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBoxUI.java b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBoxUI.java index 1a7bbb661f..9076d355d3 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBoxUI.java +++ b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBoxUI.java @@ -64,7 +64,7 @@ public class UICheckBoxUI extends MetalCheckBoxUI { } } - static BasicStroke focusStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{1.0f / 1.0f}, 1.0f); + static BasicStroke focusStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{1.0f}, 1.0f); protected void paintFocus(Graphics g, Rectangle t, Dimension arg2) { if (!ThemeUtils.BUTTON_FOCUS) { diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBox.java index be83cf5b1a..300790457a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBox.java @@ -84,6 +84,7 @@ public abstract class LazyComboBox extends UIComboBox implements PopupMenuListen LazyComboBox.this.loadList(get()); } catch (InterruptedException | ExecutionException exception) { FineLoggerFactory.getLogger().debug(exception.getMessage()); + Thread.currentThread().interrupt(); } LazyComboBox.this.showPopup(); } diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBoxTest.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBoxTest.java index 4016a263ce..37e9db1546 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBoxTest.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBoxTest.java @@ -40,6 +40,7 @@ public class LazyComboBoxTest { Thread.sleep(3000); } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + Thread.currentThread().interrupt(); } return m; } diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/UIComboBoxButton.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/UIComboBoxButton.java index a5ebf7b56b..9f96f655eb 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/UIComboBoxButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/UIComboBoxButton.java @@ -127,10 +127,6 @@ public class UIComboBoxButton extends JButton { boolean savedOpaque = false; paintRender(g, c, mustResetOpaque, savedOpaque, leftToRight, width, insets, iconWidth, left, top, height); - if (mustResetOpaque) { - JComponent jc = (JComponent) c; - jc.setOpaque(savedOpaque); - } } private void paintRender(Graphics g, Component c, boolean mustResetOpaque, boolean savedOpaque, boolean leftToRight, @@ -152,14 +148,6 @@ public class UIComboBoxButton extends JButton { } else { rendererPane.paintComponent(g, c, this, left + iconWidth, top, cWidth, height, shouldValidate); } - if (paintFocus && ThemeUtils.COMBO_FOCUS) { - g.setColor(Color.black); - Graphics2D g2d = (Graphics2D) g; - Rectangle r = new Rectangle(left, top, 2, 2); - TexturePaint tp = new TexturePaint(focusImg, r); - g2d.setPaint(tp); - g2d.draw(new Rectangle(left, top, cWidth, height)); - } } } diff --git a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java index a0f4420743..b0b57f29c3 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UICheckListPopup.java @@ -7,12 +7,25 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.icon.IconPathConstants; import com.fr.design.layout.FRGUIPaneFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; +import com.fr.general.IOUtils; + +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; public class UICheckListPopup extends UIPopupMenu { private List listeners = new ArrayList(); @@ -66,10 +79,10 @@ public class UICheckListPopup extends UIPopupMenu { } addSelectListener(); - jScrollPane.setPreferredSize(new Dimension(200, checkBoxList.size() * CHECKBOX_HEIGHT + 10)); + jScrollPane.setPreferredSize(new Dimension(130, checkBoxList.size() * CHECKBOX_HEIGHT + 10)); //超过1页的数量时显示滚动条 if (checkBoxList.size() > maxDisplayNumber) { - jScrollPane.setPreferredSize(new Dimension(200, maxDisplayNumber * CHECKBOX_HEIGHT)); + jScrollPane.setPreferredSize(new Dimension(130, maxDisplayNumber * CHECKBOX_HEIGHT)); } checkboxPane.repaint(); jScrollPane.repaint(); @@ -77,11 +90,11 @@ public class UICheckListPopup extends UIPopupMenu { private void addOneCheckValue(Object checkValue) { JPanel checkPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - checkPane.setPreferredSize(new Dimension(185, CHECKBOX_HEIGHT)); + checkPane.setPreferredSize(new Dimension(120, CHECKBOX_HEIGHT)); final JCheckBox temp = createCheckbox(); final UILabel label = new UILabel(checkValue.toString()); label.setBackground(Color.WHITE); - label.setPreferredSize(new Dimension(156, 20)); + label.setPreferredSize(new Dimension(80, 20)); checkPane.setBackground(Color.WHITE); checkPane.add(temp); checkPane.add(label); @@ -95,8 +108,8 @@ public class UICheckListPopup extends UIPopupMenu { JCheckBox checkBox = new JCheckBox(); checkBox.setPreferredSize(new Dimension(20, 20)); checkBox.setBackground(Color.WHITE); - checkBox.setIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_NORMAL)); - checkBox.setSelectedIcon(BaseUtils.readIcon(IconPathConstants.CHECKBOX_SELECTED)); + checkBox.setIcon(IOUtils.readIcon(IconPathConstants.CHECKBOX_NORMAL)); + checkBox.setSelectedIcon(IOUtils.readIcon(IconPathConstants.CHECKBOX_SELECTED)); return checkBox; } @@ -109,10 +122,12 @@ public class UICheckListPopup extends UIPopupMenu { */ private void addMouseListener(final JCheckBox checkBox, final UILabel label) { label.addMouseListener(new MouseAdapter() { + @Override public void mouseExited(MouseEvent e) { label.setBackground(Color.WHITE); } + @Override public void mouseEntered(MouseEvent e) { label.setOpaque(true); label.setBackground(mouseEnteredColor); @@ -133,6 +148,7 @@ public class UICheckListPopup extends UIPopupMenu { JCheckBox checkBox = checkBoxList.get(i); if (i == 0) { checkBox.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent e) { //全选checkbox事件 doSelectAll(checkBoxList.get(0).isSelected()); @@ -140,6 +156,7 @@ public class UICheckListPopup extends UIPopupMenu { }); } else { checkBox.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent e) { //do半选判断放在commit事件里 commit(); @@ -157,8 +174,17 @@ public class UICheckListPopup extends UIPopupMenu { private void doSelectAll(boolean isSelected) { for (int i = 1; i < checkBoxList.size(); i++) { //全选和反全选都不考虑全选按钮本身 - if (!SELECT_ALL.equals(checkBoxList.get(i).getText())) + if (!SELECT_ALL.equals(checkBoxList.get(i).getText())) { checkBoxList.get(i).setSelected(isSelected); + } + } + } + + public void setSelectedValue(Map selectedValues) { + List allValue = Arrays.asList(values); + for (Object value : selectedValues.keySet()) { + int index = allValue.indexOf(value); + checkBoxList.get(index + 1).setSelected(selectedValues.get(value)); } } @@ -214,8 +240,9 @@ public class UICheckListPopup extends UIPopupMenu { } public void addActionListener(ActionListener listener) { - if (!listeners.contains(listener)) + if (!listeners.contains(listener)) { listeners.add(listener); + } } public void removeActionListener(ActionListener listener) { diff --git a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java index 11cfeb6fe4..e570ee515d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java @@ -11,14 +11,23 @@ import com.fr.design.icon.IconPathConstants; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.stable.StringUtils; -import javax.swing.*; -import java.awt.*; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.FontMetrics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * 设计器下拉复选框组件 @@ -125,7 +134,7 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam private UITextField createEditor() { UITextField editor = new UITextField(); editor.setEditable(false); - editor.setPreferredSize(new Dimension(180, 20)); + editor.setPreferredSize(new Dimension(110, 20)); addPopupListener(editor); return editor; @@ -138,6 +147,7 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam */ private void addPopupListener(Component component) { component.addMouseListener(new MouseAdapter() { + @Override public void mouseClicked(MouseEvent e) { togglePopup(); } @@ -166,6 +176,7 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam private class PopupAction implements ActionListener { + @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals(UICheckListPopup.COMMIT_EVENT)) { selectedValues = popup.getSelectedValues(); @@ -292,13 +303,15 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam } public void addActionListener(ActionListener listener) { - if (!listeners.contains(listener)) + if (!listeners.contains(listener)) { listeners.add(listener); + } } public void removeActionListener(ActionListener listener) { - if (listeners.contains(listener)) + if (listeners.contains(listener)) { listeners.remove(listener); + } } protected void fireActionPerformed(ActionEvent e) { @@ -307,6 +320,10 @@ public class UIComboCheckBox extends JComponent implements UIObserver, GlobalNam } } + public void setSelectedValues(Map map) { + popup.setSelectedValue(map); + } + /** * 简单的测试demo * @param args diff --git a/designer-base/src/main/java/com/fr/design/gui/icontainer/UIResizableContainer.java b/designer-base/src/main/java/com/fr/design/gui/icontainer/UIResizableContainer.java index 73199d2ab2..0a8529abf3 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icontainer/UIResizableContainer.java +++ b/designer-base/src/main/java/com/fr/design/gui/icontainer/UIResizableContainer.java @@ -438,11 +438,6 @@ public class UIResizableContainer extends JPanel { containerWidth = containerWidth > MAX_WIDTH ? MAX_WIDTH : containerWidth; containerWidth = containerWidth < MIN_WIDTH ? MIN_WIDTH : containerWidth; - if (containerWidth < MIN_WIDTH) { - upPane.setVisible(false); - downPane.setVisible(false); - containerWidth = toolPaneHeight; - } refreshContainer(); if (DesignerMode.isAuthorityEditing()) { DesignerContext.getDesignerFrame().doResize(); diff --git a/designer-base/src/main/java/com/fr/design/gui/ilable/MultilineLabel.java b/designer-base/src/main/java/com/fr/design/gui/ilable/MultilineLabel.java index bb890447fa..8934e862a4 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ilable/MultilineLabel.java +++ b/designer-base/src/main/java/com/fr/design/gui/ilable/MultilineLabel.java @@ -19,15 +19,15 @@ import com.fr.design.gui.itextarea.UITextArea; */ public class MultilineLabel extends UITextArea { public MultilineLabel() { - initComponents(); + initCurrentComponents(); } public MultilineLabel(String s) { super(s); - initComponents(); + initCurrentComponents(); } - private void initComponents() { + private void initCurrentComponents() { adjustUI(); } diff --git a/designer-base/src/main/java/com/fr/design/gui/imenu/UIBasicMenuItemUI.java b/designer-base/src/main/java/com/fr/design/gui/imenu/UIBasicMenuItemUI.java index 61587beef2..844120c51b 100644 --- a/designer-base/src/main/java/com/fr/design/gui/imenu/UIBasicMenuItemUI.java +++ b/designer-base/src/main/java/com/fr/design/gui/imenu/UIBasicMenuItemUI.java @@ -7,6 +7,7 @@ package com.fr.design.gui.imenu; import com.fr.design.utils.ColorRoutines; import com.fr.design.utils.ThemeUtils; import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; import javax.swing.AbstractAction; import javax.swing.ActionMap; @@ -579,7 +580,8 @@ public class UIBasicMenuItemUI extends MenuItemUI { */ private boolean isInternalFrameSystemMenu() { String actionCommand = menuItem.getActionCommand(); - return (actionCommand == "Close") || (actionCommand == "Minimize") || (actionCommand == "Restore") || (actionCommand == "Maximize"); + return (StringUtils.equals(actionCommand,"Close") || StringUtils.equals(actionCommand,"Minimize") + || StringUtils.equals(actionCommand,"Restore") || StringUtils.equals(actionCommand,"Maximize")); } ////////////////////////////////////////////////////////// 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 049b868c43..e416083f73 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 @@ -3,10 +3,12 @@ package com.fr.design.gui.iprogressbar; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.UIDialog; import com.fr.design.gui.ilable.UILabel; +import com.fr.stable.os.support.OSBasedAction; +import com.fr.stable.os.support.OSSupportCenter; +import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.FRFont; - import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; @@ -29,7 +31,12 @@ public class ProgressDialog extends UIDialog { setUndecorated(true); setSize(parent.getSize()); setLocationRelativeTo(null); - setOpacity(0.5f); + OSSupportCenter.buildAction(new OSBasedAction() { + @Override + public void execute(Object... objects) { + setOpacity(0.5f); + } + }, SupportOSImpl.OPACITY); initComponent(); } @@ -47,6 +54,7 @@ public class ProgressDialog extends UIDialog { progressBar.setBorderPainted(false); progressBar.setOpaque(false); progressBar.setBorder(null); + progressBar.setMaximum(1000); panel.add(progressBar, BorderLayout.CENTER); text = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Loading_Project"), JLabel.CENTER); FRFont font = FRFont.getInstance().applySize(14).applyForeground(new ColorUIResource(333334)); @@ -54,7 +62,6 @@ public class ProgressDialog extends UIDialog { panel.add(text, BorderLayout.SOUTH); panel.setVisible(true); centerDialog.getContentPane().add(panel); - } @Override @@ -72,11 +79,20 @@ public class ProgressDialog extends UIDialog { progressBar.setValue(value); } + public void setProgressMaximum(int value) { + progressBar.setMaximum(value); + } + + public int getProgressMaximum() { + return progressBar.getMaximum(); + } + @Override public void dispose() { centerDialog.dispose(); super.dispose(); } + public void updateLoadingText(String text) { this.text.setText(text); } diff --git a/designer-base/src/main/java/com/fr/design/gui/iscrollbar/UIScrollBarUI.java b/designer-base/src/main/java/com/fr/design/gui/iscrollbar/UIScrollBarUI.java index da9aec9817..d3393054ae 100644 --- a/designer-base/src/main/java/com/fr/design/gui/iscrollbar/UIScrollBarUI.java +++ b/designer-base/src/main/java/com/fr/design/gui/iscrollbar/UIScrollBarUI.java @@ -1,5 +1,7 @@ package com.fr.design.gui.iscrollbar; +import com.fr.design.constants.UIConstants; +import com.fr.stable.StringUtils; import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -20,7 +22,6 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; - import javax.swing.BoundedRangeModel; import javax.swing.InputMap; import javax.swing.JComponent; @@ -38,8 +39,6 @@ import javax.swing.event.ChangeListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ScrollBarUI; import javax.swing.plaf.UIResource; - -import com.fr.design.constants.UIConstants; import sun.swing.DefaultLookup; /** @@ -148,6 +147,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo * * @param c */ + @Override public void installUI(JComponent c) { scrollbar = (JScrollBar) c; thumbRect = new Rectangle(0, 0, 0, 0); @@ -163,6 +163,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo * * @param c */ + @Override public void uninstallUI(JComponent c) { scrollbar = (JScrollBar) c; uninstallListeners(); @@ -357,6 +358,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo /** * 只画Thumb */ + @Override public void paint(Graphics g, JComponent c) { Rectangle thumbBounds = getThumbBounds(); if (thumbBounds.intersects(g.getClipBounds())) { @@ -380,6 +382,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo * @see #getMaximumSize * @see #getMinimumSize */ + @Override public Dimension getPreferredSize(JComponent c) { return (scrollbar.getOrientation() == JScrollBar.VERTICAL) ? new Dimension(scrollBarWidth, 48) : new Dimension(48, scrollBarWidth); } @@ -390,6 +393,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo * @see #getMinimumSize * @see #getPreferredSize */ + @Override public Dimension getMaximumSize(JComponent c) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } @@ -937,6 +941,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo private transient int direction = +1; + @Override public void mouseReleased(MouseEvent e) { isPressing = false; if (isDragging) { @@ -968,6 +973,7 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo * one page. If there is no thumb then page up if the mouse is in the * upper half of the track. */ + @Override public void mousePressed(MouseEvent e) { boolean isMiddle = !isSupportsAbsolutePositioning() && SwingUtilities.isMiddleMouseButton(e); if (SwingUtilities.isRightMouseButton(e) || isMiddle) { @@ -1313,20 +1319,20 @@ public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingCo public void propertyChange(PropertyChangeEvent e) { String propertyName = e.getPropertyName(); - if ("model" == propertyName) { + if (StringUtils.equals("model", propertyName)) { BoundedRangeModel oldModel = (BoundedRangeModel) e.getOldValue(); BoundedRangeModel newModel = (BoundedRangeModel) e.getNewValue(); oldModel.removeChangeListener(modelListener); newModel.addChangeListener(modelListener); scrollbar.repaint(); scrollbar.revalidate(); - } else if ("orientation" == propertyName) { + } else if (StringUtils.equals("orientation", propertyName)) { updateButtonDirections(); - } else if ("componentOrientation" == propertyName) { + } else if (StringUtils.equals("componentOrientation", propertyName)) { updateButtonDirections(); InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, inputMap); } } } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java b/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java index ba6913a38a..fb6752ac19 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java +++ b/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java @@ -9,9 +9,11 @@ import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButtonUI; import com.fr.design.gui.itextfield.UINumberField; import com.fr.design.utils.gui.GUIPaintUtils; +import com.fr.stable.CommonUtils; import com.fr.stable.Constants; import com.fr.stable.StringUtils; +import com.fr.stable.collections.utils.MathUtils; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -37,6 +39,7 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver private String spinnerName = StringUtils.EMPTY; private UIObserverListener uiObserverListener; private GlobalNameListener globalNameListener = null; + private boolean lessMinValue = false; public UISpinner(double minValue, double maxValue, double dierta) { @@ -91,6 +94,18 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver return textField; } + public UIButton getNextButton() { + return nextButton; + } + + public boolean isLessMinValue() { + return lessMinValue; + } + + public void resetLessMinValue() { + lessMinValue = false; + } + public void setValue(double value) { setValue(value, true); } @@ -107,9 +122,10 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver if (globalNameListener != null && shouldResponseNameListener()) { globalNameListener.setGlobalName(spinnerName); } - value = value < minValue ? minValue : value; + lessMinValue = value < minValue; + value = lessMinValue ? minValue : value; value = value > maxValue ? maxValue : value; - if (value == this.value) { + if (CommonUtils.equals(value, this.value)) { return; } this.value = value; @@ -129,10 +145,11 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver if (globalNameListener != null && shouldResponseNameListener()) { globalNameListener.setGlobalName(spinnerName); } - value = value < minValue ? minValue : value; + lessMinValue = value < minValue; + value = lessMinValue ? minValue : value; value = value > maxValue ? maxValue : value; - if (value == this.value) { + if (CommonUtils.equals(value, this.value)) { return; } this.value = value; @@ -371,4 +388,4 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver // jf.setSize(400, 400); // jf.setVisible(true); } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ispinner/UnsignedIntUISpinner.java b/designer-base/src/main/java/com/fr/design/gui/ispinner/UnsignedIntUISpinner.java new file mode 100644 index 0000000000..42a40cd79e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ispinner/UnsignedIntUISpinner.java @@ -0,0 +1,46 @@ +package com.fr.design.gui.ispinner; + +import com.fr.design.gui.itextfield.UIIntNumberField; +import com.fr.design.gui.itextfield.UINumberField; + + +/** + * Created by IntelliJ IDEA. + * Author : Hugh.C + * Date: 19-08-28 + * Time: 下午2:19 + */ +public class UnsignedIntUISpinner extends UISpinner { + + private double minValue; + private double maxValue; + + public UnsignedIntUISpinner(double minValue, double maxValue, double dierta) { + super(minValue, maxValue, dierta); + this.minValue = minValue; + this.maxValue = maxValue; + } + + public UnsignedIntUISpinner(double minValue, double maxValue, double dierta, double defaultValue) { + super(minValue, maxValue, dierta, defaultValue); + this.minValue = minValue; + this.maxValue = maxValue; + } + + @Override + protected UINumberField initNumberField() { + return new UIIntNumberField() { + public boolean shouldResponseChangeListener() { + return false; + } + + public NumberDocument createNumberDocument() { + return new NumberDocument() { + public boolean isContinueInsertWhenOverMaxOrMinValue() { + return true; + } + }; + } + }; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/itable/AbstractPropertyTable.java b/designer-base/src/main/java/com/fr/design/gui/itable/AbstractPropertyTable.java index 4367d8f6b5..ccdd8eb647 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itable/AbstractPropertyTable.java +++ b/designer-base/src/main/java/com/fr/design/gui/itable/AbstractPropertyTable.java @@ -3,11 +3,15 @@ */ package com.fr.design.gui.itable; -import java.awt.*; +import com.fr.general.ComparatorUtils; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; - import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.table.AbstractTableModel; @@ -16,9 +20,6 @@ import javax.swing.table.JTableHeader; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; -import com.fr.general.ComparatorUtils; - - /** * @author richer * @since 6.5.3 @@ -109,8 +110,8 @@ public abstract class AbstractPropertyTable extends JTable { @Override public TableCellEditor getCellEditor(int row, int column) { - if (groups != null) { - Point pIndex = getGroupIndex(row); + Point pIndex = getGroupIndex(row); + if (groups != null && pIndex != null) { PropertyGroup group = groups.get(pIndex.x); if (pIndex.y == 0) { return super.getCellEditor(row, column); @@ -162,7 +163,7 @@ public abstract class AbstractPropertyTable extends JTable { int row = AbstractPropertyTable.super.rowAtPoint(e.getPoint()); if (row != -1) { Point pIndex = getGroupIndex(row); - if (pIndex.y == 0 && e.getClickCount() > 1) { + if (pIndex != null && pIndex.y == 0 && e.getClickCount() > 1) { toggleCollapse(pIndex.x); } } @@ -180,7 +181,7 @@ public abstract class AbstractPropertyTable extends JTable { int row = AbstractPropertyTable.super.rowAtPoint(e.getPoint()); if (row != -1) { Point pIndex = getGroupIndex(row); - if (pIndex.y == 0 && e.getClickCount() == 1 && e.getX() < PROPERTY_ICON_WIDTH) { + if (pIndex != null && pIndex.y == 0 && e.getClickCount() == 1 && e.getX() < PROPERTY_ICON_WIDTH) { toggleCollapse(pIndex.x); } } @@ -263,6 +264,9 @@ public abstract class AbstractPropertyTable extends JTable { @Override public void setValueAt(Object aValue, int row, int column) { Point pIndex = getGroupIndex(row); + if (pIndex == null) { + return; + } PropertyGroup group = groups.get(pIndex.x); if (pIndex.y != 0) { Object old_value = getValueAt(row, column); @@ -276,16 +280,11 @@ public abstract class AbstractPropertyTable extends JTable { @Override public boolean isCellEditable(int row, int column) { Point pIndex = getGroupIndex(row); - PropertyGroup group = groups.get(pIndex.x); - if (pIndex.y == 0) { - if (column == 0) { - return false; - } else { - return false; - } - } else { - return column == 1 && group.getModel().isEditable(pIndex.y - 1); + if (pIndex == null) { + return false; } + PropertyGroup group = groups.get(pIndex.x); + return pIndex.y != 0 && (column == 1 && group.getModel().isEditable(pIndex.y - 1)); } } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java index acea8dcc57..0ec8fe90c6 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java +++ b/designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java @@ -244,7 +244,7 @@ public abstract class UITableModelAdapter extends AbstractTabl FineLoggerFactory.getLogger().error(ee.getMessage(), ee); } } - if (getRowCount() < 1 || selectedRow.length < 0) { + if (getRowCount() < 1) { return; } diff --git a/designer-base/src/main/java/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java b/designer-base/src/main/java/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java index 1c3f004f91..45db9b8a6f 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java @@ -153,6 +153,7 @@ public class UITabsHeaderIconPane extends JPanel implements UITabComponent { try { Thread.sleep(3); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); } } if (currentPanel != panel) { @@ -202,7 +203,7 @@ public class UITabsHeaderIconPane extends JPanel implements UITabComponent { } @Override - public int getSelectedIndex() { + public synchronized int getSelectedIndex() { return selectedIndex; } diff --git a/designer-base/src/main/java/com/fr/design/gui/itextfield/UIIntNumberField.java b/designer-base/src/main/java/com/fr/design/gui/itextfield/UIIntNumberField.java index 59e5e8825e..37b1e74e4a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itextfield/UIIntNumberField.java +++ b/designer-base/src/main/java/com/fr/design/gui/itextfield/UIIntNumberField.java @@ -1,11 +1,10 @@ package com.fr.design.gui.itextfield; -import com.fr.design.gui.itextfield.UINumberField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; -import java.awt.*; +import java.awt.Toolkit; /** * Created with IntelliJ IDEA. @@ -15,11 +14,11 @@ import java.awt.*; * To change this template use File | Settings | File Templates. */ public class UIIntNumberField extends UINumberField { - public void setFieldDocument(){ - setDocument(new NumberDocument()); + public void setFieldDocument() { + setDocument(createNumberDocument()); } - class NumberDocument extends PlainDocument { + public class NumberDocument extends PlainDocument { public NumberDocument() { } @@ -33,17 +32,30 @@ public class UIIntNumberField extends UINumberField { String strNew = str.substring(0, offset) + s + str.substring(offset, getLength()); - if (isOverMaxOrMinValue(strNew)) { + if (isOverMaxOrMinValue(strNew) && !isContinueInsertWhenOverMaxOrMinValue()) { Toolkit.getDefaultToolkit().beep(); return; } - setisContentChanged(true); + setisContentChanged(true); super.insertString(offset, s, a); } + /** + * 是否继续插入输入的字符 - 当超出范围时 + * + * @return true : 继续插入输入的字符 + */ + public boolean isContinueInsertWhenOverMaxOrMinValue() { + return false; + } + private boolean isOverMaxOrMinValue( String strNew) { return (Double.parseDouble(strNew)getMaxValue()); } } + + public NumberDocument createNumberDocument() { + return new NumberDocument(); + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java b/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java index 1ffb3c1dde..12b894ddce 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java +++ b/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java @@ -35,6 +35,7 @@ public class UINumberField extends UITextField { private double maxValue = Double.MAX_VALUE; private boolean isContentChanged = false; + private boolean fillNegativeNumber = true; public UINumberField() { this(MAX_INTEGERLENGTH_32, MAX_DECIMALLENGTH); @@ -62,6 +63,10 @@ public class UINumberField extends UITextField { initListener(); } + public void canFillNegativeNumber(boolean fillNegativeNumber) { + this.fillNegativeNumber = fillNegativeNumber; + } + public int getMaxIntegerLength() { return maxIntegerLength; } @@ -185,6 +190,9 @@ public class UINumberField extends UITextField { // kunsnat: 这种限制输入 有个不好的地方, 比如删除时: 10.1 最大值限定100, 那么就删除中间的小数点之后变为101, 超出了100. // 但是直接限制不能删除中间类似小数点, 那么也可能遇到: 最小值10 , 从100变化到其中的19, 就很难.. private boolean notChange(String strNew) { + if (!fillNegativeNumber && strNew.contains("-")) { + return true; + } boolean noChange = false; boolean isMinus = strNew.startsWith("-"); strNew = strNew.replaceFirst("-", StringUtils.EMPTY); // 控制能输入负数 diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileNodeConstants.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileNodeConstants.java index 8c5f0e154a..f5da5302c4 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileNodeConstants.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileNodeConstants.java @@ -1,14 +1,15 @@ package com.fr.design.gui.itree.filetree; import com.fr.base.FRContext; -import com.fr.design.ExtraDesignClassManager; -import com.fr.design.mainframe.App; +import com.fr.base.extension.FileExtension; import com.fr.general.GeneralContext; import com.fr.plugin.context.PluginContext; import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; +import com.fr.report.ExtraReportClassManager; +import com.fr.report.fun.ReportSupportedFileProvider; import java.util.ArrayList; import java.util.Arrays; @@ -44,10 +45,10 @@ public class FileNodeConstants { }); } - private static void addAppExtensions(String[] extensions) { + private static void addAppExtensions(FileExtension[] extensions) { for (int i = 0, size = extensions.length; i < size; i++) { - if (!supportFileType.contains(extensions[i])) { - supportFileType.add(extensions[i]); + if (!supportFileType.contains(extensions[i].getExtension())) { + supportFileType.add(extensions[i].getExtension()); } } } @@ -55,12 +56,14 @@ public class FileNodeConstants { private static void initSupportedTypes() { try { rwl.writeLock().lock(); - supportFileType = new ArrayList<>(Arrays.asList(FRContext.getFileNodes().getSupportedTypes())); + supportFileType = new ArrayList(); //通过插件扩展的 - Set apps = ExtraDesignClassManager.getInstance().getArray(App.MARK_STRING); - for (App app : apps) { - addAppExtensions(app.defaultExtensions()); + Set providers = ExtraReportClassManager.getInstance().getArray(ReportSupportedFileProvider.XML_TAG); + for (ReportSupportedFileProvider provider : providers) { + addAppExtensions(provider.getFileExtensions()); } + supportFileType.addAll(Arrays.asList(FRContext.getFileNodes().getSupportedTypes())); + } finally { rwl.writeLock().unlock(); } diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java index b0e26cc80e..b418c1db4c 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java @@ -1,7 +1,9 @@ package com.fr.design.gui.itree.filetree; import com.fr.base.BaseUtils; +import com.fr.design.ExtraDesignClassManager; import com.fr.design.icon.LockIcon; +import com.fr.design.fun.ReportSupportedFileUIProvider; import com.fr.file.filetree.FileNode; import com.fr.general.ComparatorUtils; import com.fr.stable.StableUtils; @@ -11,6 +13,7 @@ import javax.swing.Icon; import javax.swing.UIManager; import javax.swing.filechooser.FileSystemView; import java.io.File; +import java.util.Set; public class FileTreeIcon { private FileTreeIcon() { @@ -146,16 +149,42 @@ public class FileTreeIcon { if (node.isDirectory()) { return FileTreeIcon.FOLDER_IMAGE_ICON; } - return FileSystemView.getFileSystemView().getSystemIcon(new File(path)); + return getLocalFileIcon(path); } } if (node.isDirectory()) { return FileTreeIcon.FOLDER_IMAGE_ICON; } else { - return FileTreeIcon.getIcon(FileTreeIcon.getFileType(node.getName()), isShowLock); + return getRemoteFileIcon(node, isShowLock); } } + private static Icon getLocalFileIcon(String path) { + Icon icon = getExtraIcon(path, false); + if (icon != null) { + return icon; + } + return FileSystemView.getFileSystemView().getSystemIcon(new File(path)); + } + + private static Icon getRemoteFileIcon(FileNode node, boolean isShowLock) { + Icon icon = getExtraIcon(node.getName(), isShowLock); + if (icon != null) { + return icon; + } + return FileTreeIcon.getIcon(FileTreeIcon.getFileType(node.getName()), isShowLock); + } + + private static Icon getExtraIcon(String path, boolean isShowLock) { + Set providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG); + for (ReportSupportedFileUIProvider provider : providers) { + if (provider.getFileIcon(path, isShowLock) != null) { + return provider.getFileIcon(path, isShowLock); + } + } + return null; + } + private static Icon getIcon(int fileType, boolean isLocked) { if (fileType == JAVA_FILE) { if (isLocked) { @@ -293,4 +322,4 @@ public class FileTreeIcon { return TEXT_FILE; } } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/FormatePaneNumField.java b/designer-base/src/main/java/com/fr/design/gui/style/FormatePaneNumField.java index ee397d7559..dc706416c6 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/FormatePaneNumField.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/FormatePaneNumField.java @@ -1,10 +1,14 @@ package com.fr.design.gui.style; +import com.fr.concurrent.NamedThreadFactory; import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; import com.fr.design.gui.itextfield.UITextField; +import com.fr.module.ModuleContext; +import com.fr.value.ClearableLazyValue; +import org.jetbrains.annotations.NotNull; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * Created with IntelliJ IDEA. @@ -14,31 +18,35 @@ import java.util.TimerTask; * To change this template use File | Settings | File Templates. */ public class FormatePaneNumField extends UITextField { - private Timer timer; + private ClearableLazyValue ses = new ClearableLazyValue() { + @NotNull + @Override + protected ScheduledExecutorService compute() { + return ModuleContext.getExecutor() + .newSingleThreadScheduledExecutor(new NamedThreadFactory("FormatePaneNumFieldRunChange")); + } + }; + public FormatePaneNumField() { super(); } + @Override protected void attributeChange() { if (!AbstractAttrNoScrollPane.isHasChangeListener()) { return; } - if(timer != null){ - timer.cancel(); - } - timer = new Timer(); - timer.schedule(new TimerTask() { + ses.getValue().schedule(new Runnable() { @Override public void run() { runChange(); } - },100); - + }, 100, TimeUnit.MILLISECONDS); } - protected void runChange(){ + protected void runChange() { super.attributeChange(); - timer.cancel(); - + ses.getValue().shutdown(); + ses.drop(); } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/style/NumberDragBar.java b/designer-base/src/main/java/com/fr/design/gui/style/NumberDragBar.java index 5ab5c16985..dce3dc86dd 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/NumberDragBar.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/NumberDragBar.java @@ -127,6 +127,7 @@ public class NumberDragBar extends JComponent { revalidate(); } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.toString()); + Thread.currentThread().interrupt(); } } }); diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/CodeTemplateManager.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/CodeTemplateManager.java index ddefec8b74..61b2018616 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/CodeTemplateManager.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/CodeTemplateManager.java @@ -276,8 +276,9 @@ public class CodeTemplateManager { temp.addAll(templates); for (int i=0; i, */ public boolean getShouldIndentNextLine(int line) { Token t = getTokenListForLine(line); - t = t.getLastNonCommentNonWhitespaceToken(); + if (t != null) { + t = t.getLastNonCommentNonWhitespaceToken(); + } return tokenMaker.getShouldIndentNextLineAfter(t); } diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.java index 3d04602f28..30fc7b8717 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.java @@ -3016,11 +3016,6 @@ private boolean fractionalFontMetricsEnabled; return he; } - private final boolean equal(LinkGeneratorResult e1, - LinkGeneratorResult e2) { - return e1.getSourceOffset()==e2.getSourceOffset(); - } - @Override public void mouseClicked(MouseEvent e) { if (getHyperlinksEnabled() && isScanningForLinks && @@ -3080,8 +3075,7 @@ private boolean fractionalFontMetricsEnabled; isLinkAtOffset(RSyntaxTextArea.this, offs); if (newResult!=null) { // Repaint if we're at a new link now. - if (linkGeneratorResult==null || - !equal(newResult, linkGeneratorResult)) { + if (linkGeneratorResult==null || newResult.getSourceOffset() != linkGeneratorResult.getSourceOffset()) { repaint(); } linkGeneratorResult = newResult; @@ -3120,4 +3114,4 @@ private boolean fractionalFontMetricsEnabled; } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaEditorKit.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaEditorKit.java index c431e329c8..6aa0cd8e4f 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaEditorKit.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaEditorKit.java @@ -2,29 +2,39 @@ * 08/29/2004 * * RSyntaxTextAreaEditorKit.java - The editor kit used by RSyntaxTextArea. - * + * * This library is distributed under a modified BSD license. See the included * RSyntaxTextArea.License.txt file for details. */ package com.fr.design.gui.syntax.ui.rsyntaxtextarea; -import java.awt.*; -import java.awt.event.*; -import java.util.ResourceBundle; -import java.util.Stack; -import javax.swing.*; -import javax.swing.text.*; - import com.fr.design.gui.syntax.ui.rsyntaxtextarea.folding.Fold; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.folding.FoldCollapser; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.folding.FoldManager; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.templates.CodeTemplate; import com.fr.design.gui.syntax.ui.rtextarea.Gutter; import com.fr.design.gui.syntax.ui.rtextarea.IconRowHeader; -import com.fr.design.gui.syntax.ui.rtextarea.RecordableTextAction; import com.fr.design.gui.syntax.ui.rtextarea.RTextArea; import com.fr.design.gui.syntax.ui.rtextarea.RTextAreaEditorKit; +import com.fr.design.gui.syntax.ui.rtextarea.RecordableTextAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JScrollPane; +import javax.swing.KeyStroke; +import javax.swing.UIManager; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Segment; +import javax.swing.text.TextAction; +import java.awt.Component; +import java.awt.Font; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.util.Objects; +import java.util.Stack; /** @@ -32,24 +42,24 @@ import com.fr.design.gui.syntax.ui.rtextarea.RTextAreaEditorKit; * programming-specific stuff. There are currently subclasses to handle: * *
    - *
  • Toggling code folds.
  • - *
  • Aligning "closing" curly braces with their matches, if the current - * programming language uses curly braces to identify code blocks.
  • - *
  • Copying the current selection as RTF.
  • - *
  • Block indentation (increasing the indent of one or multiple lines)
  • - *
  • Block un-indentation (decreasing the indent of one or multiple lines) - *
  • - *
  • Inserting a "code template" when a configurable key (e.g. a space) is - * pressed
  • - *
  • Decreasing the point size of all fonts in the text area
  • - *
  • Increasing the point size of all fonts in the text area
  • - *
  • Moving the caret to the "matching bracket" of the one at the current - * caret position
  • - *
  • Toggling whether the currently selected lines are commented out.
  • - *
  • Better selection of "words" on mouse double-clicks for programming - * languages.
  • - *
  • Better keyboard navigation via Ctrl+arrow keys for programming - * languages.
  • + *
  • Toggling code folds.
  • + *
  • Aligning "closing" curly braces with their matches, if the current + * programming language uses curly braces to identify code blocks.
  • + *
  • Copying the current selection as RTF.
  • + *
  • Block indentation (increasing the indent of one or multiple lines)
  • + *
  • Block un-indentation (decreasing the indent of one or multiple lines) + *
  • + *
  • Inserting a "code template" when a configurable key (e.g. a space) is + * pressed
  • + *
  • Decreasing the point size of all fonts in the text area
  • + *
  • Increasing the point size of all fonts in the text area
  • + *
  • Moving the caret to the "matching bracket" of the one at the current + * caret position
  • + *
  • Toggling whether the currently selected lines are commented out.
  • + *
  • Better selection of "words" on mouse double-clicks for programming + * languages.
  • + *
  • Better keyboard navigation via Ctrl+arrow keys for programming + * languages.
  • *
* * @author Robert Futrell @@ -57,1884 +67,1872 @@ import com.fr.design.gui.syntax.ui.rtextarea.RTextAreaEditorKit; */ public class RSyntaxTextAreaEditorKit extends RTextAreaEditorKit { - private static final long serialVersionUID = 1L; - - public static final String rstaCloseCurlyBraceAction = "RSTA.CloseCurlyBraceAction"; - public static final String rstaCloseMarkupTagAction = "RSTA.CloseMarkupTagAction"; - public static final String rstaCollapseAllFoldsAction = "RSTA.CollapseAllFoldsAction"; - public static final String rstaCollapseAllCommentFoldsAction = "RSTA.CollapseAllCommentFoldsAction"; - public static final String rstaCollapseFoldAction = "RSTA.CollapseFoldAction"; - public static final String rstaCopyAsRtfAction = "RSTA.CopyAsRtfAction"; - public static final String rstaDecreaseIndentAction = "RSTA.DecreaseIndentAction"; - public static final String rstaExpandAllFoldsAction = "RSTA.ExpandAllFoldsAction"; - public static final String rstaExpandFoldAction = "RSTA.ExpandFoldAction"; - public static final String rstaGoToMatchingBracketAction = "RSTA.GoToMatchingBracketAction"; - public static final String rstaPossiblyInsertTemplateAction = "RSTA.TemplateAction"; - public static final String rstaToggleCommentAction = "RSTA.ToggleCommentAction"; - public static final String rstaToggleCurrentFoldAction = "RSTA.ToggleCurrentFoldAction"; - - /** - * The actions that RSyntaxTextAreaEditorKit adds to those of - * RTextAreaEditorKit. - */ - private static final Action[] defaultActions = { - new CloseCurlyBraceAction(), - new CloseMarkupTagAction(), - new BeginWordAction(beginWordAction, false), - new BeginWordAction(selectionBeginWordAction, true), - new ChangeFoldStateAction(rstaCollapseFoldAction, true), - new ChangeFoldStateAction(rstaExpandFoldAction, false), - new CollapseAllFoldsAction(), - new CopyAsRtfAction(), - //new DecreaseFontSizeAction(), - new DecreaseIndentAction(), - new DeletePrevWordAction(), - new EndAction(endAction, false), - new EndAction(selectionEndAction, true), - new EndWordAction(endWordAction, false), - new EndWordAction(endWordAction, true), - new ExpandAllFoldsAction(), - new GoToMatchingBracketAction(), - new InsertBreakAction(), - //new IncreaseFontSizeAction(), - new InsertTabAction(), - new NextWordAction(nextWordAction, false), - new NextWordAction(selectionNextWordAction, true), - new PossiblyInsertTemplateAction(), - new PreviousWordAction(previousWordAction, false), - new PreviousWordAction(selectionPreviousWordAction, true), - new SelectWordAction(), - new ToggleCommentAction(), - }; - - - /** - * Constructor. - */ - public RSyntaxTextAreaEditorKit() { - } - - - /** - * Returns the default document used by RSyntaxTextAreas. - * - * @return The document. - */ - @Override - public Document createDefaultDocument() { - return new RSyntaxDocument(SyntaxConstants.SYNTAX_STYLE_NONE); - } - - - /** - * Overridden to return a row header that is aware of folding. - * - * @param textArea The text area. - * @return The icon row header. - */ - @Override - public IconRowHeader createIconRowHeader(RTextArea textArea) { - return new FoldingAwareIconRowHeader((RSyntaxTextArea)textArea); - } - - - /** - * Fetches the set of commands that can be used - * on a text component that is using a model and - * view produced by this kit. - * - * @return the command list - */ - @Override - public Action[] getActions() { - return TextAction.augmentList(super.getActions(), - RSyntaxTextAreaEditorKit.defaultActions); - } - - - /** - * Returns localized text for an action. There's definitely a better place - * for this functionality. - * - * @param key The key into the action resource bundle. - * @return The localized text. - */ - public static String getString(String key) { - return com.fr.design.i18n.Toolkit.i18nText(key); - } - - - /** - * Positions the caret at the beginning of the word. This class is here - * to better handle finding the "beginning of the word" for programming - * languages. - */ - protected static class BeginWordAction - extends RTextAreaEditorKit.BeginWordAction { - - private Segment seg; - - protected BeginWordAction(String name, boolean select) { - super(name, select); - seg = new Segment(); - } - - @Override - protected int getWordStart(RTextArea textArea, int offs) - throws BadLocationException { - - if (offs==0) { - return offs; - } - - RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument(); - int line = textArea.getLineOfOffset(offs); - int start = textArea.getLineStartOffset(line); - if (offs==start) { - return start; - } - int end = textArea.getLineEndOffset(line); - if (line!=textArea.getLineCount()-1) { - end--; - } - doc.getText(start, end-start, seg); - - // Determine the "type" of char at offs - lower case, upper case, - // whitespace or other. We take special care here as we're starting - // in the middle of the Segment to check whether we're already at - // the "beginning" of a word. - int firstIndex = seg.getBeginIndex() + (offs-start) - 1; - seg.setIndex(firstIndex); - char ch = seg.current(); - char nextCh = offs==end ? 0 : seg.array[seg.getIndex() + 1]; - - // The "word" is a group of letters and/or digits - if (Character.isLetterOrDigit(ch)) { - if (offs!=end && !Character.isLetterOrDigit(nextCh)) { - return offs; - } - do { - ch = seg.previous(); - } while (Character.isLetterOrDigit(ch)); - } - - // The "word" is whitespace - else if (Character.isWhitespace(ch)) { - if (offs!=end && !Character.isWhitespace(nextCh)) { - return offs; - } - do { - ch = seg.previous(); - } while (Character.isWhitespace(ch)); - } - - // Otherwise, the "word" a single "something else" char (operator, - // etc.). - - offs -= firstIndex - seg.getIndex() + 1;//seg.getEndIndex() - seg.getIndex(); - if (ch!=Segment.DONE && nextCh!='\n') { - offs++; - } - - return offs; - - } - - } - - - /** - * Expands or collapses the nearest fold. - */ - public static class ChangeFoldStateAction extends FoldRelatedAction { - - private boolean collapse; - - public ChangeFoldStateAction(String name, boolean collapse) { - super(name); - this.collapse = collapse; - } - - public ChangeFoldStateAction(String name, Icon icon, - String desc, Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - if (rsta.isCodeFoldingEnabled()) { - Fold fold = getClosestFold(rsta); - if (fold!=null) { - fold.setCollapsed(collapse); - } - possiblyRepaintGutter(textArea); - } - else { - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - } - } - - @Override - public final String getMacroID() { - return getName(); - } - - } - - - /** - * Action that (optionally) aligns a closing curly brace with the line - * containing its matching opening curly brace. - */ - public static class CloseCurlyBraceAction extends RecordableTextAction { - - private static final long serialVersionUID = 1L; - - private Point bracketInfo; - private Segment seg; - - public CloseCurlyBraceAction() { - super(rstaCloseCurlyBraceAction); - seg = new Segment(); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - RSyntaxDocument doc = (RSyntaxDocument)rsta.getDocument(); - boolean alignCurlyBraces = rsta.isAutoIndentEnabled() && - doc.getCurlyBracesDenoteCodeBlocks(); - - if (alignCurlyBraces) { - textArea.beginAtomicEdit(); - } - - try { - - textArea.replaceSelection("}"); - - // If the user wants to align curly braces... - if (alignCurlyBraces) { - - Element root = doc.getDefaultRootElement(); - int dot = rsta.getCaretPosition() - 1; // Start before '{' - int line = root.getElementIndex(dot); - Element elem = root.getElement(line); - int start = elem.getStartOffset(); - - // Get the current line's text up to the '}' entered. - try { - doc.getText(start, dot-start, seg); - } catch (BadLocationException ble) { // Never happens - ble.printStackTrace(); - return; - } - - // Only attempt to align if there's only whitespace up to - // the '}' entered. - for (int i=0; i-1) { - try { - String ws = RSyntaxUtilities.getLeadingWhitespace( - doc, bracketInfo.y); - rsta.replaceRange(ws, start, dot); - } catch (BadLocationException ble) { - ble.printStackTrace(); - return; - } - } - - } - - } finally { - if (alignCurlyBraces) { - textArea.endAtomicEdit(); - } - } - - } - - @Override - public final String getMacroID() { - return rstaCloseCurlyBraceAction; - } - - } - - - /** - * (Optionally) completes a closing markup tag. - */ - public static class CloseMarkupTagAction extends RecordableTextAction { - - private static final long serialVersionUID = 1L; - - public CloseMarkupTagAction() { - super(rstaCloseMarkupTagAction); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - if (!textArea.isEditable() || !textArea.isEnabled()) { - UIManager.getLookAndFeel().provideErrorFeedback(textArea); - return; - } - - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - RSyntaxDocument doc = (RSyntaxDocument)rsta.getDocument(); - - Caret c = rsta.getCaret(); - boolean selection = c.getDot()!=c.getMark(); - rsta.replaceSelection("/"); - - // Don't automatically complete a tag if there was a selection - int dot = c.getDot(); - - if (doc.getLanguageIsMarkup() && - doc.getCompleteMarkupCloseTags() && - !selection && rsta.getCloseMarkupTags() && dot>1) { - - try { - - // Check actual char before token type, since it's quicker - char ch = doc.charAt(dot-2); - if (ch=='<' || ch=='[') { - - Token t = doc.getTokenListForLine( - rsta.getCaretLineNumber()); - t = RSyntaxUtilities.getTokenAtOffset(t, dot-1); - if (t!=null && t.getType()==Token.MARKUP_TAG_DELIMITER) { - //System.out.println("Huzzah - closing tag!"); - String tagName = discoverTagName(doc, dot); - if (tagName!=null) { - rsta.replaceSelection(tagName + (char)(ch+2)); - } - } - - } - - } catch (BadLocationException ble) { // Never happens - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - ble.printStackTrace(); - } - - } - - } - - /** - * Discovers the name of the tag being closed. Assumes standard - * SGML-style markup tags. - * - * @param doc The document to parse. - * @param dot The location of the caret. This should be right after - * the start of a closing tag token (e.g. "</" - * or "[" in the case of BBCode). - * @return The name of the tag to close, or null if it - * could not be determined. - */ - private String discoverTagName(RSyntaxDocument doc, int dot) { - - Stack stack = new Stack(); - - Element root = doc.getDefaultRootElement(); - int curLine = root.getElementIndex(dot); - - for (int i=0; i<=curLine; i++) { - - Token t = doc.getTokenListForLine(i); - while (t!=null && t.isPaintable()) { - - if (t.getType()==Token.MARKUP_TAG_DELIMITER) { - if (t.isSingleChar('<') || t.isSingleChar('[')) { - t = t.getNextToken(); - while (t!=null && t.isPaintable()) { - if (t.getType()==Token.MARKUP_TAG_NAME || - // Being lenient here and also checking - // for attributes, in case they - // (incorrectly) have whitespace between - // the '<' char and the element name. - t.getType()==Token.MARKUP_TAG_ATTRIBUTE) { - stack.push(t.getLexeme()); - break; - } - t = t.getNextToken(); - } - } - else if (t.length()==2 && t.charAt(0)=='/' && - (t.charAt(1)=='>' || - t.charAt(1)==']')) { - if (!stack.isEmpty()) { // Always true for valid XML - stack.pop(); - } - } - else if (t.length()==2 && - (t.charAt(0)=='<' || t.charAt(0)=='[') && - t.charAt(1)=='/') { - String tagName = null; - if (!stack.isEmpty()) { // Always true for valid XML - tagName = stack.pop(); - } - if (t.getEndOffset()>=dot) { - return tagName; - } - } - } - - t = t.getNextToken(); - - } - - } - - return null; // Should never happen - - } - - @Override - public String getMacroID() { - return getName(); - } - - } - - - /** - * Collapses all comment folds. - */ - public static class CollapseAllCommentFoldsAction extends FoldRelatedAction{ - - private static final long serialVersionUID = 1L; - - public CollapseAllCommentFoldsAction() { - super(rstaCollapseAllCommentFoldsAction); - setProperties("Action.CollapseCommentFolds"); - } - - public CollapseAllCommentFoldsAction(String name, Icon icon, - String desc, Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - if (rsta.isCodeFoldingEnabled()) { - FoldCollapser collapser = new FoldCollapser(); - collapser.collapseFolds(rsta.getFoldManager()); - possiblyRepaintGutter(textArea); - } - else { - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - } - } - - @Override - public final String getMacroID() { - return rstaCollapseAllCommentFoldsAction; - } - - } - - - /** - * Collapses all folds. - */ - public static class CollapseAllFoldsAction extends FoldRelatedAction { - - private static final long serialVersionUID = 1L; - - public CollapseAllFoldsAction() { - this(false); - } - - public CollapseAllFoldsAction(boolean localizedName) { - super(rstaCollapseAllFoldsAction); - if (localizedName) { - setProperties("Action.CollapseAllFolds"); - } - } - - public CollapseAllFoldsAction(String name, Icon icon, - String desc, Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - if (rsta.isCodeFoldingEnabled()) { - FoldCollapser collapser = new FoldCollapser() { - @Override - public boolean getShouldCollapse(Fold fold) { - return true; - } - }; - collapser.collapseFolds(rsta.getFoldManager()); - possiblyRepaintGutter(textArea); - } - else { - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - } - } - - @Override - public final String getMacroID() { - return rstaCollapseAllFoldsAction; - } - - } - - - /** - * Action for copying text as RTF. - */ - public static class CopyAsRtfAction extends RecordableTextAction { - - private static final long serialVersionUID = 1L; - - public CopyAsRtfAction() { - super(rstaCopyAsRtfAction); - } - - public CopyAsRtfAction(String name, Icon icon, String desc, - Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - ((RSyntaxTextArea)textArea).copyAsRtf(); - textArea.requestFocusInWindow(); - } - - @Override - public final String getMacroID() { - return getName(); - } - - } - - - /** - * Action for decreasing the font size of all fonts in the text area. - */ - public static class DecreaseFontSizeAction - extends RTextAreaEditorKit.DecreaseFontSizeAction { - - private static final long serialVersionUID = 1L; - - public DecreaseFontSizeAction() { - super(); - } - - public DecreaseFontSizeAction(String name, Icon icon, String desc, - Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - SyntaxScheme scheme = rsta.getSyntaxScheme(); - - // All we need to do is update all of the fonts in syntax - // schemes, then call setSyntaxHighlightingColorScheme with the - // same scheme already being used. This relies on the fact that - // that method does not check whether the new scheme is different - // from the old scheme before updating. - - boolean changed = false; - int count = scheme.getStyleCount(); - for (int i=0; i=MINIMUM_SIZE) { - // Shrink by decreaseAmount. - ss.font = font.deriveFont(newSize); - changed = true; - } - else if (oldSize>MINIMUM_SIZE) { - // Can't shrink by full decreaseAmount, but - // can shrink a little bit. - ss.font = font.deriveFont(MINIMUM_SIZE); - changed = true; - } - } - } - } - - // Do the text area's font also. - Font font = rsta.getFont(); - float oldSize = font.getSize2D(); - float newSize = oldSize - decreaseAmount; - if (newSize>=MINIMUM_SIZE) { - // Shrink by decreaseAmount. - rsta.setFont(font.deriveFont(newSize)); - changed = true; - } - else if (oldSize>MINIMUM_SIZE) { - // Can't shrink by full decreaseAmount, but - // can shrink a little bit. - rsta.setFont(font.deriveFont(MINIMUM_SIZE)); - changed = true; - } - - // If we updated at least one font, update the screen. If - // all of the fonts were already the minimum size, beep. - if (changed) { - rsta.setSyntaxScheme(scheme); - // NOTE: This is a hack to get an encompassing - // RTextScrollPane to repaint its line numbers to account - // for a change in line height due to a font change. I'm - // not sure why we need to do this here but not when we - // change the syntax highlighting color scheme via the - // Options dialog... setSyntaxHighlightingColorScheme() - // calls revalidate() which won't repaint the scroll pane - // if scrollbars don't change, which is why we need this. - Component parent = rsta.getParent(); - if (parent instanceof javax.swing.JViewport) { - parent = parent.getParent(); - if (parent instanceof JScrollPane) { - parent.repaint(); - } - } - } - else - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - - } - - } - - - /** - * Action for when un-indenting lines (either the current line if there is - * selection, or all selected lines if there is one). - */ - public static class DecreaseIndentAction extends RecordableTextAction { - - private static final long serialVersionUID = 1L; - - private Segment s; - - public DecreaseIndentAction() { - this(rstaDecreaseIndentAction); - } - - public DecreaseIndentAction(String name) { - super(name); - s = new Segment(); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - if (!textArea.isEditable() || !textArea.isEnabled()) { - UIManager.getLookAndFeel().provideErrorFeedback(textArea); - return; - } - - Document document = textArea.getDocument(); - Element map = document.getDefaultRootElement(); - Caret c = textArea.getCaret(); - int dot = c.getDot(); - int mark = c.getMark(); - int line1 = map.getElementIndex(dot); - int tabSize = textArea.getTabSize(); - - // If there is a selection, indent all lines in the selection. - // Otherwise, indent the line the caret is on. - if (dot!=mark) { - // Note that we cheaply reuse variables here, so don't - // take their names to mean what they are. - int line2 = map.getElementIndex(mark); - dot = Math.min(line1, line2); - mark = Math.max(line1, line2); - Element elem; - try { - for (line1=dot; line1i) { - // If the first character is a tab, remove it. - if (s.array[i]=='\t') { - doc.remove(start, 1); - } - // Otherwise, see if the first character is a space. If it - // is, remove all contiguous whitespaces at the beginning of - // this line, up to the tab size. - else if (s.array[i]==' ') { - i++; - int toRemove = 1; - while (i-1) { - // Go to the position AFTER the bracket so the previous - // bracket (which we were just on) is highlighted. - rsta.setCaretPosition(bracketInfo.y+1); - } - else { - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - } - } - - @Override - public final String getMacroID() { - return rstaGoToMatchingBracketAction; - } - - } - - - /** - * Action for increasing the font size of all fonts in the text area. - */ - public static class IncreaseFontSizeAction - extends RTextAreaEditorKit.IncreaseFontSizeAction { - - private static final long serialVersionUID = 1L; - - public IncreaseFontSizeAction() { - super(); - } - - public IncreaseFontSizeAction(String name, Icon icon, String desc, - Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - SyntaxScheme scheme = rsta.getSyntaxScheme(); - - // All we need to do is update all of the fonts in syntax - // schemes, then call setSyntaxHighlightingColorScheme with the - // same scheme already being used. This relies on the fact that - // that method does not check whether the new scheme is different - // from the old scheme before updating. - - boolean changed = false; - int count = scheme.getStyleCount(); - for (int i=0; ipos that - * is NOT a whitespace char, or -1 if only - * whitespace chars follow pos (or it is the end - * position in the string). - */ - private static final int atEndOfLine(int pos, String s, int sLen) { - for (int i=pos; i0) { - StringBuilder sb = new StringBuilder(); - if (line==textArea.getLineCount()-1) { - sb.append('\n'); - } - if (leadingWS!=null) { - sb.append(leadingWS); - } - sb.append("}\n"); - int dot = textArea.getCaretPosition(); - int end = textArea.getLineEndOffsetOfCurrentLine(); - // Insert at end of line, not at dot: they may have - // pressed Enter in the middle of the line and brought - // some text (though it must be whitespace and/or - // comments) down onto the new line. - textArea.insert(sb.toString(), end); - textArea.setCaretPosition(dot); // Caret may have moved - } - - } - - } - - } - - } - - - /** - * Action for inserting tabs. This is extended to "block indent" a - * group of contiguous lines if they are selected. - */ - public static class InsertTabAction extends RecordableTextAction { - - private static final long serialVersionUID = 1L; - - public InsertTabAction() { - super(insertTabAction); - } - - public InsertTabAction(String name) { - super(name); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - if (!textArea.isEditable() || !textArea.isEnabled()) { - UIManager.getLookAndFeel().provideErrorFeedback(textArea); - return; - } - - Document document = textArea.getDocument(); - Element map = document.getDefaultRootElement(); - Caret c = textArea.getCaret(); - int dot = c.getDot(); - int mark = c.getMark(); - int dotLine = map.getElementIndex(dot); - int markLine = map.getElementIndex(mark); - - // If there is a multi-line selection, indent all lines in - // the selection. - if (dotLine!=markLine) { - int first = Math.min(dotLine, markLine); - int last = Math.max(dotLine, markLine); - Element elem; int start; - - // Since we're using Document.insertString(), we must mimic the - // soft tab behavior provided by RTextArea.replaceSelection(). - String replacement = "\t"; - if (textArea.getTabsEmulated()) { - StringBuilder sb = new StringBuilder(); - int temp = textArea.getTabSize(); - for (int i=0; i0 && - // ((mod&ActionEvent.ALT_MASK)==(mod&ActionEvent.CTRL_MASK))) { - // char ch = str.charAt(0); - // if (ch>=0x20 && ch!=0x7F) - // textArea.replaceSelection(str); - //} - textArea.replaceSelection(" "); - } - - @Override - public final String getMacroID() { - return rstaPossiblyInsertTemplateAction; - } - - } - - - /** - * Action to move the selection and/or caret. Constructor indicates - * direction to use. This class overrides the behavior defined in - * {@link RTextAreaEditorKit} to better skip "words" in source code. - */ - public static class PreviousWordAction - extends RTextAreaEditorKit.PreviousWordAction { - - private Segment seg; - - public PreviousWordAction(String nm, boolean select) { - super(nm, select); - seg = new Segment(); - } - - /** - * Overridden to do better with skipping "words" in code. - */ - @Override - protected int getPreviousWord(RTextArea textArea, int offs) - throws BadLocationException { - - if (offs==0) { - return offs; - } - - RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument(); - Element root = doc.getDefaultRootElement(); - int line = root.getElementIndex(offs); - int start = root.getElement(line).getStartOffset(); - if (offs==start) {// If we're already at the start of the line... - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - if (rsta.isCodeFoldingEnabled()) { // End of next visible line - FoldManager fm = rsta.getFoldManager(); - while (--line>=0 && fm.isLineHidden(line)); - if (line>=0) { // Found an earlier visible line - offs = root.getElement(line).getEndOffset() - 1; - } - // No earlier visible line - we must be at offs==0... - return offs; - } - else { - return start-1; // End of previous line. - } - } - doc.getText(start, offs-start, seg); - - // Determine the "type" of char at offs - lower case, upper case, - // whitespace or other - char ch = seg.last(); - - // Skip any "leading" whitespace - while (Character.isWhitespace(ch)) { - ch = seg.previous(); - } - - // Skip the group of letters and/or digits - if (Character.isLetterOrDigit(ch)) { - do { - ch = seg.previous(); - } while (Character.isLetterOrDigit(ch)); - } - - // Skip groups of "anything else" (operators, etc.). - else if (!Character.isWhitespace(ch)) { - do { - ch = seg.previous(); - } while (ch!=Segment.DONE && - !(Character.isLetterOrDigit(ch) || - Character.isWhitespace(ch))); - } - - offs -= seg.getEndIndex() - seg.getIndex(); - if (ch!=Segment.DONE) { - offs++; - } - - return offs; - - } - - } - - - /** - * Selects the word around the caret. This class is here to better - * handle selecting "words" in programming languages. - */ - public static class SelectWordAction - extends RTextAreaEditorKit.SelectWordAction { - - @Override - protected void createActions() { - start = new BeginWordAction("pigdog", false); - end = new EndWordAction("pigdog", true); - } - - } - - - /** - * Action that toggles whether the currently selected lines are - * commented. - */ - public static class ToggleCommentAction extends RecordableTextAction { - - public ToggleCommentAction() { - super(rstaToggleCommentAction); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - - if (!textArea.isEditable() || !textArea.isEnabled()) { - UIManager.getLookAndFeel().provideErrorFeedback(textArea); - return; - } - - RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument(); - String[] startEnd = doc.getLineCommentStartAndEnd(); - - if (startEnd==null) { - UIManager.getLookAndFeel().provideErrorFeedback(textArea); - return; - } - - Element map = doc.getDefaultRootElement(); - Caret c = textArea.getCaret(); - int dot = c.getDot(); - int mark = c.getMark(); - int line1 = map.getElementIndex(dot); - int line2 = map.getElementIndex(mark); - int start = Math.min(line1, line2); - int end = Math.max(line1, line2); - - // Don't toggle comment on last line if there is no - // text selected on it. - if (start!=end) { - Element elem = map.getElement(end); - if (Math.max(dot, mark)==elem.getStartOffset()) { - end--; - } - } - - textArea.beginAtomicEdit(); - try { - boolean add = getDoAdd(doc,map, start,end, startEnd); - for (line1=start; line1<=end; line1++) { - Element elem = map.getElement(line1); - handleToggleComment(elem, doc, startEnd, add); - } - } catch (BadLocationException ble) { - ble.printStackTrace(); - UIManager.getLookAndFeel().provideErrorFeedback(textArea); - } finally { - textArea.endAtomicEdit(); - } - - } - - private boolean getDoAdd(Document doc, Element map, int startLine, - int endLine, String[] startEnd) - throws BadLocationException { - boolean doAdd = false; - for (int i=startLine; i<=endLine; i++) { - Element elem = map.getElement(i); - int start = elem.getStartOffset(); - String t = doc.getText(start, elem.getEndOffset()-start-1); - if (!t.startsWith(startEnd[0]) || - (startEnd[1]!=null && !t.endsWith(startEnd[1]))) { - doAdd = true; - break; - } - } - return doAdd; - } - - private void handleToggleComment(Element elem, Document doc, - String[] startEnd, boolean add) throws BadLocationException { - int start = elem.getStartOffset(); - int end = elem.getEndOffset() - 1; - if (add) { - doc.insertString(start, startEnd[0], null); - if (startEnd[1]!=null) { - doc.insertString(end+startEnd[0].length(), startEnd[1], - null); - } - } - else { - doc.remove(start, startEnd[0].length()); - if (startEnd[1]!=null) { - int temp = startEnd[1].length(); - doc.remove(end-startEnd[0].length()-temp, temp); - } - } - } - - @Override - public final String getMacroID() { - return rstaToggleCommentAction; - } - - } - - - /** - * Toggles the fold at the current caret position or line. - */ - public static class ToggleCurrentFoldAction extends FoldRelatedAction { - - private static final long serialVersionUID = 1L; - - public ToggleCurrentFoldAction() { - super(rstaToggleCurrentFoldAction); - setProperties("Action.ToggleCurrentFold"); - } - - public ToggleCurrentFoldAction(String name, Icon icon, String desc, - Integer mnemonic, KeyStroke accelerator) { - super(name, icon, desc, mnemonic, accelerator); - } - - @Override - public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { - RSyntaxTextArea rsta = (RSyntaxTextArea)textArea; - if (rsta.isCodeFoldingEnabled()) { - Fold fold = getClosestFold(rsta); - if (fold!=null) { - fold.toggleCollapsedState(); - } - possiblyRepaintGutter(textArea); - } - else { - UIManager.getLookAndFeel().provideErrorFeedback(rsta); - } - } - - @Override - public final String getMacroID() { - return rstaToggleCurrentFoldAction; - } - - } + private static final long serialVersionUID = 1L; + + public static final String rstaCloseCurlyBraceAction = "RSTA.CloseCurlyBraceAction"; + public static final String rstaCloseMarkupTagAction = "RSTA.CloseMarkupTagAction"; + public static final String rstaCollapseAllFoldsAction = "RSTA.CollapseAllFoldsAction"; + public static final String rstaCollapseAllCommentFoldsAction = "RSTA.CollapseAllCommentFoldsAction"; + public static final String rstaCollapseFoldAction = "RSTA.CollapseFoldAction"; + public static final String rstaCopyAsRtfAction = "RSTA.CopyAsRtfAction"; + public static final String rstaDecreaseIndentAction = "RSTA.DecreaseIndentAction"; + public static final String rstaExpandAllFoldsAction = "RSTA.ExpandAllFoldsAction"; + public static final String rstaExpandFoldAction = "RSTA.ExpandFoldAction"; + public static final String rstaGoToMatchingBracketAction = "RSTA.GoToMatchingBracketAction"; + public static final String rstaPossiblyInsertTemplateAction = "RSTA.TemplateAction"; + public static final String rstaToggleCommentAction = "RSTA.ToggleCommentAction"; + public static final String rstaToggleCurrentFoldAction = "RSTA.ToggleCurrentFoldAction"; + + /** + * The actions that RSyntaxTextAreaEditorKit adds to those of + * RTextAreaEditorKit. + */ + private static final Action[] defaultActions = { + new CloseCurlyBraceAction(), + new CloseMarkupTagAction(), + new BeginWordAction(beginWordAction, false), + new BeginWordAction(selectionBeginWordAction, true), + new ChangeFoldStateAction(rstaCollapseFoldAction, true), + new ChangeFoldStateAction(rstaExpandFoldAction, false), + new CollapseAllFoldsAction(), + new CopyAsRtfAction(), + //new DecreaseFontSizeAction(), + new DecreaseIndentAction(), + new DeletePrevWordAction(), + new EndAction(endAction, false), + new EndAction(selectionEndAction, true), + new EndWordAction(endWordAction, false), + new EndWordAction(endWordAction, true), + new ExpandAllFoldsAction(), + new GoToMatchingBracketAction(), + new InsertBreakAction(), + //new IncreaseFontSizeAction(), + new InsertTabAction(), + new NextWordAction(nextWordAction, false), + new NextWordAction(selectionNextWordAction, true), + new PossiblyInsertTemplateAction(), + new PreviousWordAction(previousWordAction, false), + new PreviousWordAction(selectionPreviousWordAction, true), + new SelectWordAction(), + new ToggleCommentAction(), + }; + + + /** + * Constructor. + */ + public RSyntaxTextAreaEditorKit() { + } + + + /** + * Returns the default document used by RSyntaxTextAreas. + * + * @return The document. + */ + @Override + public Document createDefaultDocument() { + return new RSyntaxDocument(SyntaxConstants.SYNTAX_STYLE_NONE); + } + + + /** + * Overridden to return a row header that is aware of folding. + * + * @param textArea The text area. + * @return The icon row header. + */ + @Override + public IconRowHeader createIconRowHeader(RTextArea textArea) { + return new FoldingAwareIconRowHeader((RSyntaxTextArea) textArea); + } + + + /** + * Fetches the set of commands that can be used + * on a text component that is using a model and + * view produced by this kit. + * + * @return the command list + */ + @Override + public Action[] getActions() { + return TextAction.augmentList(super.getActions(), + RSyntaxTextAreaEditorKit.defaultActions); + } + + + /** + * Returns localized text for an action. There's definitely a better place + * for this functionality. + * + * @param key The key into the action resource bundle. + * @return The localized text. + */ + public static String getString(String key) { + return com.fr.design.i18n.Toolkit.i18nText(key); + } + + + /** + * Positions the caret at the beginning of the word. This class is here + * to better handle finding the "beginning of the word" for programming + * languages. + */ + protected static class BeginWordAction + extends RTextAreaEditorKit.BeginWordAction { + + private Segment seg; + + protected BeginWordAction(String name, boolean select) { + super(name, select); + seg = new Segment(); + } + + @Override + protected int getWordStart(RTextArea textArea, int offs) + throws BadLocationException { + + if (offs == 0) { + return offs; + } + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + int line = textArea.getLineOfOffset(offs); + int start = textArea.getLineStartOffset(line); + if (offs == start) { + return start; + } + int end = textArea.getLineEndOffset(line); + if (line != textArea.getLineCount() - 1) { + end--; + } + doc.getText(start, end - start, seg); + + // Determine the "type" of char at offs - lower case, upper case, + // whitespace or other. We take special care here as we're starting + // in the middle of the Segment to check whether we're already at + // the "beginning" of a word. + int firstIndex = seg.getBeginIndex() + (offs - start) - 1; + seg.setIndex(firstIndex); + char ch = seg.current(); + char nextCh = offs == end ? 0 : seg.array[seg.getIndex() + 1]; + + // The "word" is a group of letters and/or digits + if (Character.isLetterOrDigit(ch)) { + if (offs != end && !Character.isLetterOrDigit(nextCh)) { + return offs; + } + do { + ch = seg.previous(); + } while (Character.isLetterOrDigit(ch)); + } + + // The "word" is whitespace + else if (Character.isWhitespace(ch)) { + if (offs != end && !Character.isWhitespace(nextCh)) { + return offs; + } + do { + ch = seg.previous(); + } while (Character.isWhitespace(ch)); + } + + // Otherwise, the "word" a single "something else" char (operator, + // etc.). + + offs -= firstIndex - seg.getIndex() + 1;//seg.getEndIndex() - seg.getIndex(); + if (ch != Segment.DONE && nextCh != '\n') { + offs++; + } + + return offs; + + } + + } + + + /** + * Expands or collapses the nearest fold. + */ + public static class ChangeFoldStateAction extends FoldRelatedAction { + + private boolean collapse; + + public ChangeFoldStateAction(String name, boolean collapse) { + super(name); + this.collapse = collapse; + } + + public ChangeFoldStateAction(String name, Icon icon, + String desc, Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { + Fold fold = getClosestFold(rsta); + if (fold != null) { + fold.setCollapsed(collapse); + } + possiblyRepaintGutter(textArea); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + } + + @Override + public final String getMacroID() { + return getName(); + } + + } + + + /** + * Action that (optionally) aligns a closing curly brace with the line + * containing its matching opening curly brace. + */ + public static class CloseCurlyBraceAction extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + private Point bracketInfo; + private Segment seg; + + public CloseCurlyBraceAction() { + super(rstaCloseCurlyBraceAction); + seg = new Segment(); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + RSyntaxDocument doc = (RSyntaxDocument) rsta.getDocument(); + boolean alignCurlyBraces = rsta.isAutoIndentEnabled() && + doc.getCurlyBracesDenoteCodeBlocks(); + + if (alignCurlyBraces) { + textArea.beginAtomicEdit(); + } + + try { + + textArea.replaceSelection("}"); + + // If the user wants to align curly braces... + if (alignCurlyBraces) { + + Element root = doc.getDefaultRootElement(); + int dot = rsta.getCaretPosition() - 1; // Start before '{' + int line = root.getElementIndex(dot); + Element elem = root.getElement(line); + int start = elem.getStartOffset(); + + // Get the current line's text up to the '}' entered. + try { + doc.getText(start, dot - start, seg); + } catch (BadLocationException ble) { // Never happens + ble.printStackTrace(); + return; + } + + // Only attempt to align if there's only whitespace up to + // the '}' entered. + for (int i = 0; i < seg.count; i++) { + char ch = seg.array[seg.offset + i]; + if (!Character.isWhitespace(ch)) { + return; + } + } + + // Locate the matching '{' bracket, and replace the leading + // whitespace for the '}' to match that of the '{' char's line. + bracketInfo = RSyntaxUtilities.getMatchingBracketPosition( + rsta, bracketInfo); + if (bracketInfo.y > -1) { + try { + String ws = RSyntaxUtilities.getLeadingWhitespace( + doc, bracketInfo.y); + rsta.replaceRange(ws, start, dot); + } catch (BadLocationException ble) { + ble.printStackTrace(); + return; + } + } + + } + + } finally { + if (alignCurlyBraces) { + textArea.endAtomicEdit(); + } + } + + } + + @Override + public final String getMacroID() { + return rstaCloseCurlyBraceAction; + } + + } + + + /** + * (Optionally) completes a closing markup tag. + */ + public static class CloseMarkupTagAction extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + public CloseMarkupTagAction() { + super(rstaCloseMarkupTagAction); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + if (!textArea.isEditable() || !textArea.isEnabled()) { + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + return; + } + + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + RSyntaxDocument doc = (RSyntaxDocument) rsta.getDocument(); + + Caret c = rsta.getCaret(); + boolean selection = c.getDot() != c.getMark(); + rsta.replaceSelection("/"); + + // Don't automatically complete a tag if there was a selection + int dot = c.getDot(); + + if (doc.getLanguageIsMarkup() && + doc.getCompleteMarkupCloseTags() && + !selection && rsta.getCloseMarkupTags() && dot > 1) { + + try { + + // Check actual char before token type, since it's quicker + char ch = doc.charAt(dot - 2); + if (ch == '<' || ch == '[') { + + Token t = doc.getTokenListForLine( + rsta.getCaretLineNumber()); + t = RSyntaxUtilities.getTokenAtOffset(t, dot - 1); + if (t != null && t.getType() == Token.MARKUP_TAG_DELIMITER) { + //System.out.println("Huzzah - closing tag!"); + String tagName = discoverTagName(doc, dot); + if (tagName != null) { + rsta.replaceSelection(tagName + (char) (ch + 2)); + } + } + + } + + } catch (BadLocationException ble) { // Never happens + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + ble.printStackTrace(); + } + + } + + } + + /** + * Discovers the name of the tag being closed. Assumes standard + * SGML-style markup tags. + * + * @param doc The document to parse. + * @param dot The location of the caret. This should be right after + * the start of a closing tag token (e.g. "</" + * or "[" in the case of BBCode). + * @return The name of the tag to close, or null if it + * could not be determined. + */ + private String discoverTagName(RSyntaxDocument doc, int dot) { + + Stack stack = new Stack(); + + Element root = doc.getDefaultRootElement(); + int curLine = root.getElementIndex(dot); + + for (int i = 0; i <= curLine; i++) { + + Token t = doc.getTokenListForLine(i); + while (t != null && t.isPaintable()) { + + if (t.getType() == Token.MARKUP_TAG_DELIMITER) { + if (t.isSingleChar('<') || t.isSingleChar('[')) { + t = t.getNextToken(); + while (t != null && t.isPaintable()) { + if (t.getType() == Token.MARKUP_TAG_NAME || + // Being lenient here and also checking + // for attributes, in case they + // (incorrectly) have whitespace between + // the '<' char and the element name. + t.getType() == Token.MARKUP_TAG_ATTRIBUTE) { + stack.push(t.getLexeme()); + break; + } + t = t.getNextToken(); + } + } else if (t.length() == 2 && t.charAt(0) == '/' && + (t.charAt(1) == '>' || + t.charAt(1) == ']')) { + if (!stack.isEmpty()) { // Always true for valid XML + stack.pop(); + } + } else if (t.length() == 2 && + (t.charAt(0) == '<' || t.charAt(0) == '[') && + t.charAt(1) == '/') { + String tagName = null; + if (!stack.isEmpty()) { // Always true for valid XML + tagName = stack.pop(); + } + if (t.getEndOffset() >= dot) { + return tagName; + } + } + } + + t = Objects.requireNonNull(t).getNextToken(); + + } + + } + + return null; // Should never happen + + } + + @Override + public String getMacroID() { + return getName(); + } + + } + + + /** + * Collapses all comment folds. + */ + public static class CollapseAllCommentFoldsAction extends FoldRelatedAction { + + private static final long serialVersionUID = 1L; + + public CollapseAllCommentFoldsAction() { + super(rstaCollapseAllCommentFoldsAction); + setProperties("Action.CollapseCommentFolds"); + } + + public CollapseAllCommentFoldsAction(String name, Icon icon, + String desc, Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { + FoldCollapser collapser = new FoldCollapser(); + collapser.collapseFolds(rsta.getFoldManager()); + possiblyRepaintGutter(textArea); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + } + + @Override + public final String getMacroID() { + return rstaCollapseAllCommentFoldsAction; + } + + } + + + /** + * Collapses all folds. + */ + public static class CollapseAllFoldsAction extends FoldRelatedAction { + + private static final long serialVersionUID = 1L; + + public CollapseAllFoldsAction() { + this(false); + } + + public CollapseAllFoldsAction(boolean localizedName) { + super(rstaCollapseAllFoldsAction); + if (localizedName) { + setProperties("Action.CollapseAllFolds"); + } + } + + public CollapseAllFoldsAction(String name, Icon icon, + String desc, Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { + FoldCollapser collapser = new FoldCollapser() { + @Override + public boolean getShouldCollapse(Fold fold) { + return true; + } + }; + collapser.collapseFolds(rsta.getFoldManager()); + possiblyRepaintGutter(textArea); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + } + + @Override + public final String getMacroID() { + return rstaCollapseAllFoldsAction; + } + + } + + + /** + * Action for copying text as RTF. + */ + public static class CopyAsRtfAction extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + public CopyAsRtfAction() { + super(rstaCopyAsRtfAction); + } + + public CopyAsRtfAction(String name, Icon icon, String desc, + Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + ((RSyntaxTextArea) textArea).copyAsRtf(); + textArea.requestFocusInWindow(); + } + + @Override + public final String getMacroID() { + return getName(); + } + + } + + + /** + * Action for decreasing the font size of all fonts in the text area. + */ + public static class DecreaseFontSizeAction + extends RTextAreaEditorKit.DecreaseFontSizeAction { + + private static final long serialVersionUID = 1L; + + public DecreaseFontSizeAction() { + super(); + } + + public DecreaseFontSizeAction(String name, Icon icon, String desc, + Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + SyntaxScheme scheme = rsta.getSyntaxScheme(); + + // All we need to do is update all of the fonts in syntax + // schemes, then call setSyntaxHighlightingColorScheme with the + // same scheme already being used. This relies on the fact that + // that method does not check whether the new scheme is different + // from the old scheme before updating. + + boolean changed = false; + int count = scheme.getStyleCount(); + for (int i = 0; i < count; i++) { + Style ss = scheme.getStyle(i); + if (ss != null) { + Font font = ss.font; + if (font != null) { + float oldSize = font.getSize2D(); + float newSize = oldSize - decreaseAmount; + if (newSize >= MINIMUM_SIZE) { + // Shrink by decreaseAmount. + ss.font = font.deriveFont(newSize); + changed = true; + } else if (oldSize > MINIMUM_SIZE) { + // Can't shrink by full decreaseAmount, but + // can shrink a little bit. + ss.font = font.deriveFont(MINIMUM_SIZE); + changed = true; + } + } + } + } + + // Do the text area's font also. + Font font = rsta.getFont(); + float oldSize = font.getSize2D(); + float newSize = oldSize - decreaseAmount; + if (newSize >= MINIMUM_SIZE) { + // Shrink by decreaseAmount. + rsta.setFont(font.deriveFont(newSize)); + changed = true; + } else if (oldSize > MINIMUM_SIZE) { + // Can't shrink by full decreaseAmount, but + // can shrink a little bit. + rsta.setFont(font.deriveFont(MINIMUM_SIZE)); + changed = true; + } + + // If we updated at least one font, update the screen. If + // all of the fonts were already the minimum size, beep. + if (changed) { + rsta.setSyntaxScheme(scheme); + // NOTE: This is a hack to get an encompassing + // RTextScrollPane to repaint its line numbers to account + // for a change in line height due to a font change. I'm + // not sure why we need to do this here but not when we + // change the syntax highlighting color scheme via the + // Options dialog... setSyntaxHighlightingColorScheme() + // calls revalidate() which won't repaint the scroll pane + // if scrollbars don't change, which is why we need this. + Component parent = rsta.getParent(); + if (parent instanceof javax.swing.JViewport) { + parent = parent.getParent(); + if (parent instanceof JScrollPane) { + parent.repaint(); + } + } + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + + } + + } + + + /** + * Action for when un-indenting lines (either the current line if there is + * selection, or all selected lines if there is one). + */ + public static class DecreaseIndentAction extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + private Segment s; + + public DecreaseIndentAction() { + this(rstaDecreaseIndentAction); + } + + public DecreaseIndentAction(String name) { + super(name); + s = new Segment(); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + if (!textArea.isEditable() || !textArea.isEnabled()) { + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + return; + } + + Document document = textArea.getDocument(); + Element map = document.getDefaultRootElement(); + Caret c = textArea.getCaret(); + int dot = c.getDot(); + int mark = c.getMark(); + int line1 = map.getElementIndex(dot); + int tabSize = textArea.getTabSize(); + + // If there is a selection, indent all lines in the selection. + // Otherwise, indent the line the caret is on. + if (dot != mark) { + // Note that we cheaply reuse variables here, so don't + // take their names to mean what they are. + int line2 = map.getElementIndex(mark); + dot = Math.min(line1, line2); + mark = Math.max(line1, line2); + Element elem; + try { + for (line1 = dot; line1 < mark; line1++) { + elem = map.getElement(line1); + handleDecreaseIndent(elem, document, tabSize); + } + // Don't do the last line if the caret is at its + // beginning. We must call getDot() again and not just + // use 'dot' as the caret's position may have changed + // due to the insertion of the tabs above. + elem = map.getElement(mark); + int start = elem.getStartOffset(); + if (Math.max(c.getDot(), c.getMark()) != start) { + handleDecreaseIndent(elem, document, tabSize); + } + } catch (BadLocationException ble) { + ble.printStackTrace(); + UIManager.getLookAndFeel(). + provideErrorFeedback(textArea); + } + } else { + Element elem = map.getElement(line1); + try { + handleDecreaseIndent(elem, document, tabSize); + } catch (BadLocationException ble) { + ble.printStackTrace(); + UIManager.getLookAndFeel(). + provideErrorFeedback(textArea); + } + } + + } + + @Override + public final String getMacroID() { + return rstaDecreaseIndentAction; + } + + /** + * Actually does the "de-indentation." This method finds where the + * given element's leading whitespace ends, then, if there is indeed + * leading whitespace, removes either the last char in it (if it is a + * tab), or removes up to the number of spaces equal to a tab in the + * specified document (i.e., if the tab size was 5 and there were 3 + * spaces at the end of the leading whitespace, the three will be + * removed; if there were 8 spaces, only the first 5 would be + * removed). + * + * @param elem The element to "de-indent." + * @param doc The document containing the specified element. + * @param tabSize The size of a tab, in spaces. + */ + private final void handleDecreaseIndent(Element elem, Document doc, + int tabSize) + throws BadLocationException { + int start = elem.getStartOffset(); + int end = elem.getEndOffset() - 1; // Why always true?? + doc.getText(start, end - start, s); + int i = s.offset; + end = i + s.count; + if (end > i) { + // If the first character is a tab, remove it. + if (s.array[i] == '\t') { + doc.remove(start, 1); + } + // Otherwise, see if the first character is a space. If it + // is, remove all contiguous whitespaces at the beginning of + // this line, up to the tab size. + else if (s.array[i] == ' ') { + i++; + int toRemove = 1; + while (i < end && s.array[i] == ' ' && toRemove < tabSize) { + i++; + toRemove++; + } + doc.remove(start, toRemove); + } + } + } + + } + + + /** + * Deletes the previous word, but differentiates symbols from "words" to + * match the behavior of code editors. + */ + public static class DeletePrevWordAction + extends RTextAreaEditorKit.DeletePrevWordAction { + + private Segment seg = new Segment(); + + @Override + protected int getPreviousWordStart(RTextArea textArea, int offs) + throws BadLocationException { + + if (offs == 0) { + return offs; + } + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + int line = textArea.getLineOfOffset(offs); + int start = textArea.getLineStartOffset(line); + if (offs == start) { + return start - 1; // Just delete the newline + } + int end = textArea.getLineEndOffset(line); + if (line != textArea.getLineCount() - 1) { + end--; + } + doc.getText(start, end - start, seg); + + // Determine the "type" of char at offs - lower case, upper case, + // whitespace or other. We take special care here as we're starting + // in the middle of the Segment to check whether we're already at + // the "beginning" of a word. + int firstIndex = seg.getBeginIndex() + (offs - start) - 1; + seg.setIndex(firstIndex); + char ch = seg.current(); + + // Always strip off whitespace first + if (Character.isWhitespace(ch)) { + do { + ch = seg.previous(); + } while (Character.isWhitespace(ch)); + } + + // The "word" is a group of letters and/or digits + if (Character.isLetterOrDigit(ch)) { + do { + ch = seg.previous(); + } while (Character.isLetterOrDigit(ch)); + } + + // The "word" is a series of symbols. + else { + while (!Character.isWhitespace(ch) && + !Character.isLetterOrDigit(ch) + && ch != Segment.DONE) { + ch = seg.previous(); + } + } + + if (ch == Segment.DONE) { + return start; // Removed last "token" of the line + } + offs -= firstIndex - seg.getIndex(); + return offs; + + } + + } + + + /** + * Moves the caret to the end of the document, taking into account code + * folding. + */ + public static class EndAction extends RTextAreaEditorKit.EndAction { + + public EndAction(String name, boolean select) { + super(name, select); + } + + @Override + protected int getVisibleEnd(RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + return rsta.getLastVisibleOffset(); + } + + } + + + /** + * Positions the caret at the end of the word. This class is here to + * better handle finding the "end of the word" in programming languages. + */ + protected static class EndWordAction + extends RTextAreaEditorKit.EndWordAction { + + private Segment seg; + + protected EndWordAction(String name, boolean select) { + super(name, select); + seg = new Segment(); + } + + @Override + protected int getWordEnd(RTextArea textArea, int offs) + throws BadLocationException { + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + if (offs == doc.getLength()) { + return offs; + } + + int line = textArea.getLineOfOffset(offs); + int end = textArea.getLineEndOffset(line); + if (line != textArea.getLineCount() - 1) { + end--; // Hide newline + } + if (offs == end) { + return end; + } + doc.getText(offs, end - offs, seg); + + // Determine the "type" of char at offs - letter/digit, + // whitespace or other + char ch = seg.first(); + + // The "word" is a group of letters and/or digits + if (Character.isLetterOrDigit(ch)) { + do { + ch = seg.next(); + } while (Character.isLetterOrDigit(ch)); + } + + // The "word" is whitespace. + else if (Character.isWhitespace(ch)) { + + do { + ch = seg.next(); + } while (Character.isWhitespace(ch)); + } + + // Otherwise, the "word" is a single character of some other type + // (operator, etc.). + + offs += seg.getIndex() - seg.getBeginIndex(); + return offs; + + } + + } + + + /** + * Expands all folds. + */ + public static class ExpandAllFoldsAction extends FoldRelatedAction { + + private static final long serialVersionUID = 1L; + + public ExpandAllFoldsAction() { + this(false); + } + + public ExpandAllFoldsAction(boolean localizedName) { + super(rstaExpandAllFoldsAction); + if (localizedName) { + setProperties("Action.ExpandAllFolds"); + } + } + + public ExpandAllFoldsAction(String name, Icon icon, + String desc, Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { + FoldManager fm = rsta.getFoldManager(); + for (int i = 0; i < fm.getFoldCount(); i++) { + expand(fm.getFold(i)); + } + possiblyRepaintGutter(rsta); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + } + + private void expand(Fold fold) { + fold.setCollapsed(false); + for (int i = 0; i < fold.getChildCount(); i++) { + expand(fold.getChild(i)); + } + } + + @Override + public final String getMacroID() { + return rstaExpandAllFoldsAction; + } + + } + + + /** + * Base class for folding-related actions. + */ + static abstract class FoldRelatedAction extends RecordableTextAction { + + public FoldRelatedAction(String name) { + super(name); + } + + public FoldRelatedAction(String name, Icon icon, + String desc, Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + protected Fold getClosestFold(RSyntaxTextArea textArea) { + int offs = textArea.getCaretPosition(); + int line = textArea.getCaretLineNumber(); + FoldManager fm = textArea.getFoldManager(); + Fold fold = fm.getFoldForLine(line); + if (fold == null) { + fold = fm.getDeepestOpenFoldContaining(offs); + } + return fold; + } + + /** + * Repaints the gutter in a text area's scroll pane, if necessary. + * + * @param textArea The text area. + */ + protected void possiblyRepaintGutter(RTextArea textArea) { + Gutter gutter = RSyntaxUtilities.getGutter(textArea); + if (gutter != null) { + gutter.repaint(); + } + } + + } + + + /** + * Action for moving the caret to the "matching bracket" of the bracket + * at the caret position (either before or after). + */ + public static class GoToMatchingBracketAction + extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + private Point bracketInfo; + + public GoToMatchingBracketAction() { + super(rstaGoToMatchingBracketAction); + } + + public GoToMatchingBracketAction(String name, Icon icon, String desc, + Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + bracketInfo = RSyntaxUtilities.getMatchingBracketPosition(rsta, + bracketInfo); + if (bracketInfo.y > -1) { + // Go to the position AFTER the bracket so the previous + // bracket (which we were just on) is highlighted. + rsta.setCaretPosition(bracketInfo.y + 1); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + } + + @Override + public final String getMacroID() { + return rstaGoToMatchingBracketAction; + } + + } + + + /** + * Action for increasing the font size of all fonts in the text area. + */ + public static class IncreaseFontSizeAction + extends RTextAreaEditorKit.IncreaseFontSizeAction { + + private static final long serialVersionUID = 1L; + + public IncreaseFontSizeAction() { + super(); + } + + public IncreaseFontSizeAction(String name, Icon icon, String desc, + Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + SyntaxScheme scheme = rsta.getSyntaxScheme(); + + // All we need to do is update all of the fonts in syntax + // schemes, then call setSyntaxHighlightingColorScheme with the + // same scheme already being used. This relies on the fact that + // that method does not check whether the new scheme is different + // from the old scheme before updating. + + boolean changed = false; + int count = scheme.getStyleCount(); + for (int i = 0; i < count; i++) { + Style ss = scheme.getStyle(i); + if (ss != null) { + Font font = ss.font; + if (font != null) { + float oldSize = font.getSize2D(); + float newSize = oldSize + increaseAmount; + if (newSize <= MAXIMUM_SIZE) { + // Grow by increaseAmount. + ss.font = font.deriveFont(newSize); + changed = true; + } else if (oldSize < MAXIMUM_SIZE) { + // Can't grow by full increaseAmount, but + // can grow a little bit. + ss.font = font.deriveFont(MAXIMUM_SIZE); + changed = true; + } + } + } + } + + // Do the text area's font also. + Font font = rsta.getFont(); + float oldSize = font.getSize2D(); + float newSize = oldSize + increaseAmount; + if (newSize <= MAXIMUM_SIZE) { + // Grow by increaseAmount. + rsta.setFont(font.deriveFont(newSize)); + changed = true; + } else if (oldSize < MAXIMUM_SIZE) { + // Can't grow by full increaseAmount, but + // can grow a little bit. + rsta.setFont(font.deriveFont(MAXIMUM_SIZE)); + changed = true; + } + + // If we updated at least one font, update the screen. If + // all of the fonts were already the minimum size, beep. + if (changed) { + rsta.setSyntaxScheme(scheme); + // NOTE: This is a hack to get an encompassing + // RTextScrollPane to repaint its line numbers to account + // for a change in line height due to a font change. I'm + // not sure why we need to do this here but not when we + // change the syntax highlighting color scheme via the + // Options dialog... setSyntaxHighlightingColorScheme() + // calls revalidate() which won't repaint the scroll pane + // if scrollbars don't change, which is why we need this. + Component parent = rsta.getParent(); + if (parent instanceof javax.swing.JViewport) { + parent = parent.getParent(); + if (parent instanceof JScrollPane) { + parent.repaint(); + } + } + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + + } + + } + + + /** + * Action for when the user presses the Enter key. This is here so we can + * be smart and "auto-indent" for programming languages. + */ + public static class InsertBreakAction + extends RTextAreaEditorKit.InsertBreakAction { + + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + if (!textArea.isEditable() || !textArea.isEnabled()) { + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + return; + } + + RSyntaxTextArea sta = (RSyntaxTextArea) textArea; + boolean noSelection = sta.getSelectionStart() == sta.getSelectionEnd(); + + // First, see if this language wants to handle inserting newlines + // itself. + boolean handled = false; + if (noSelection) { + RSyntaxDocument doc = (RSyntaxDocument) sta.getDocument(); + handled = doc.insertBreakSpecialHandling(e); + } + + // If not... + if (!handled) { + handleInsertBreak(sta, noSelection); + } + + } + + /** + * @return The first location in the string past pos that + * is NOT a whitespace char, or -1 if only + * whitespace chars follow pos (or it is the end + * position in the string). + */ + private static final int atEndOfLine(int pos, String s, int sLen) { + for (int i = pos; i < sLen; i++) { + if (!RSyntaxUtilities.isWhitespace(s.charAt(i))) { + return i; + } + } + return -1; + } + + private static final int getOpenBraceCount(RSyntaxDocument doc) { + int openCount = 0; + Element root = doc.getDefaultRootElement(); + int lineCount = root.getElementCount(); + for (int i = 0; i < lineCount; i++) { + Token t = doc.getTokenListForLine(i); + while (t != null && t.isPaintable()) { + if (t.getType() == Token.SEPARATOR && t.length() == 1) { + char ch = t.charAt(0); + if (ch == '{') { + openCount++; + } else if (ch == '}') { + openCount--; + } + } + t = t.getNextToken(); + } + } + return openCount; + } + + /** + * Actually inserts the newline into the document, and auto-indents + * if appropriate. This method can be called by token makers who + * implement a custom action for inserting newlines. + * + * @param textArea + * @param noSelection Whether there is no selection. + */ + protected void handleInsertBreak(RSyntaxTextArea textArea, + boolean noSelection) { + // If we're auto-indenting... + if (noSelection && textArea.isAutoIndentEnabled()) { + insertNewlineWithAutoIndent(textArea); + } else { + textArea.replaceSelection("\n"); + if (noSelection) { + possiblyCloseCurlyBrace(textArea, null); + } + } + } + + private void insertNewlineWithAutoIndent(RSyntaxTextArea sta) { + + try { + + int caretPos = sta.getCaretPosition(); + Document doc = sta.getDocument(); + Element map = doc.getDefaultRootElement(); + int lineNum = map.getElementIndex(caretPos); + Element line = map.getElement(lineNum); + int start = line.getStartOffset(); + int end = line.getEndOffset() - 1; // Why always "-1"? + int len = end - start; + String s = doc.getText(start, len); + + // endWS is the end of the leading whitespace of the + // current line. + String leadingWS = RSyntaxUtilities.getLeadingWhitespace(s); + StringBuilder sb = new StringBuilder("\n"); + sb.append(leadingWS); + + // If there is only whitespace between the caret and + // the EOL, pressing Enter auto-indents the new line to + // the same place as the previous line. + int nonWhitespacePos = atEndOfLine(caretPos - start, s, len); + if (nonWhitespacePos == -1) { + if (leadingWS.length() == len && + sta.isClearWhitespaceLinesEnabled()) { + // If the line was nothing but whitespace, select it + // so its contents get removed. + sta.setSelectionStart(start); + sta.setSelectionEnd(end); + } + sta.replaceSelection(sb.toString()); + } + + // If there is non-whitespace between the caret and the + // EOL, pressing Enter takes that text to the next line + // and auto-indents it to the same place as the last + // line. + else { + sb.append(s.substring(nonWhitespacePos)); + sta.replaceRange(sb.toString(), caretPos, end); + sta.setCaretPosition(caretPos + leadingWS.length() + 1); + } + + // Must do it after everything else, as the "smart indent" + // calculation depends on the previous line's state + // AFTER the Enter press (stuff may have been moved down). + if (sta.getShouldIndentNextLine(lineNum)) { + sta.replaceSelection("\t"); + } + + possiblyCloseCurlyBrace(sta, leadingWS); + + } catch (BadLocationException ble) { // Never happens + sta.replaceSelection("\n"); + ble.printStackTrace(); + } + + } + + private void possiblyCloseCurlyBrace(RSyntaxTextArea textArea, + String leadingWS) { + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + + if (textArea.getCloseCurlyBraces() && + doc.getCurlyBracesDenoteCodeBlocks()) { + + int line = textArea.getCaretLineNumber(); + Token t = doc.getTokenListForLine(line - 1); + t = t.getLastNonCommentNonWhitespaceToken(); + + if (t != null && t.isLeftCurly()) { + + if (getOpenBraceCount(doc) > 0) { + StringBuilder sb = new StringBuilder(); + if (line == textArea.getLineCount() - 1) { + sb.append('\n'); + } + if (leadingWS != null) { + sb.append(leadingWS); + } + sb.append("}\n"); + int dot = textArea.getCaretPosition(); + int end = textArea.getLineEndOffsetOfCurrentLine(); + // Insert at end of line, not at dot: they may have + // pressed Enter in the middle of the line and brought + // some text (though it must be whitespace and/or + // comments) down onto the new line. + textArea.insert(sb.toString(), end); + textArea.setCaretPosition(dot); // Caret may have moved + } + + } + + } + + } + + } + + + /** + * Action for inserting tabs. This is extended to "block indent" a + * group of contiguous lines if they are selected. + */ + public static class InsertTabAction extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + public InsertTabAction() { + super(insertTabAction); + } + + public InsertTabAction(String name) { + super(name); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + if (!textArea.isEditable() || !textArea.isEnabled()) { + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + return; + } + + Document document = textArea.getDocument(); + Element map = document.getDefaultRootElement(); + Caret c = textArea.getCaret(); + int dot = c.getDot(); + int mark = c.getMark(); + int dotLine = map.getElementIndex(dot); + int markLine = map.getElementIndex(mark); + + // If there is a multi-line selection, indent all lines in + // the selection. + if (dotLine != markLine) { + int first = Math.min(dotLine, markLine); + int last = Math.max(dotLine, markLine); + Element elem; + int start; + + // Since we're using Document.insertString(), we must mimic the + // soft tab behavior provided by RTextArea.replaceSelection(). + String replacement = "\t"; + if (textArea.getTabsEmulated()) { + StringBuilder sb = new StringBuilder(); + int temp = textArea.getTabSize(); + for (int i = 0; i < temp; i++) { + sb.append(' '); + } + replacement = sb.toString(); + } + + textArea.beginAtomicEdit(); + try { + for (int i = first; i < last; i++) { + elem = map.getElement(i); + start = elem.getStartOffset(); + document.insertString(start, replacement, null); + } + // Don't do the last line if the caret is at its + // beginning. We must call getDot() again and not just + // use 'dot' as the caret's position may have changed + // due to the insertion of the tabs above. + elem = map.getElement(last); + start = elem.getStartOffset(); + if (Math.max(c.getDot(), c.getMark()) != start) { + document.insertString(start, replacement, null); + } + } catch (BadLocationException ble) { // Never happens. + ble.printStackTrace(); + UIManager.getLookAndFeel(). + provideErrorFeedback(textArea); + } finally { + textArea.endAtomicEdit(); + } + } else { + textArea.replaceSelection("\t"); + } + + } + + @Override + public final String getMacroID() { + return insertTabAction; + } + + } + + + /** + * Action to move the selection and/or caret. Constructor indicates + * direction to use. This class overrides the behavior defined in + * {@link RTextAreaEditorKit} to better skip "words" in source code. + */ + public static class NextWordAction + extends RTextAreaEditorKit.NextWordAction { + + private Segment seg; + + public NextWordAction(String nm, boolean select) { + super(nm, select); + seg = new Segment(); + } + + /** + * Overridden to do better with skipping "words" in code. + */ + @Override + protected int getNextWord(RTextArea textArea, int offs) + throws BadLocationException { + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + if (offs == doc.getLength()) { + return offs; + } + + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(offs); + int end = root.getElement(line).getEndOffset() - 1; + if (offs == end) {// If we're already at the end of the line... + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { // Start of next visible line + FoldManager fm = rsta.getFoldManager(); + int lineCount = root.getElementCount(); + while (++line < lineCount && fm.isLineHidden(line)) { + ; + } + if (line < lineCount) { // Found a lower visible line + offs = root.getElement(line).getStartOffset(); + } + // No lower visible line - we're already at last visible offset + return offs; + } else { + return offs + 1; // Start of next line. + } + } + doc.getText(offs, end - offs, seg); + + // Determine the "type" of char at offs - letter/digit, + // whitespace or other + char ch = seg.first(); + + // Skip the group of letters and/or digits + if (Character.isLetterOrDigit(ch)) { + do { + ch = seg.next(); + } while (Character.isLetterOrDigit(ch)); + } + + // Skip groups of "anything else" (operators, etc.). + else if (!Character.isWhitespace(ch)) { + do { + ch = seg.next(); + } while (ch != Segment.DONE && + !(Character.isLetterOrDigit(ch) || + Character.isWhitespace(ch))); + } + + // Skip any trailing whitespace + while (Character.isWhitespace(ch)) { + ch = seg.next(); + } + + offs += seg.getIndex() - seg.getBeginIndex(); + return offs; + + } + + } + + + /** + * Action for when the user tries to insert a template (that is, + * they've typed a template ID and pressed the trigger character + * (a space) in an attempt to do the substitution). + */ + public static class PossiblyInsertTemplateAction extends RecordableTextAction { + + private static final long serialVersionUID = 1L; + + public PossiblyInsertTemplateAction() { + super(rstaPossiblyInsertTemplateAction); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + if (!textArea.isEditable() || !textArea.isEnabled()) { + return; + } + + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + + if (RSyntaxTextArea.getTemplatesEnabled()) { + + Document doc = textArea.getDocument(); + if (doc != null) { + + try { + + CodeTemplateManager manager = RSyntaxTextArea. + getCodeTemplateManager(); + CodeTemplate template = manager == null ? null : + manager.getTemplate(rsta); + + // A non-null template means modify the text to insert! + if (template != null) { + template.invoke(rsta); + } + + // No template - insert default text. This is + // exactly what DefaultKeyTypedAction does. + else { + doDefaultInsert(rsta); + } + + } catch (BadLocationException ble) { + UIManager.getLookAndFeel(). + provideErrorFeedback(textArea); + } + + + } // End of if (doc!=null). + + } // End of if (textArea.getTemplatesEnabled()). + + // If templates aren't enabled, just insert the text as usual. + else { + doDefaultInsert(rsta); + } + + } + + private final void doDefaultInsert(RTextArea textArea) { + // FIXME: We need a way to get the "trigger string" (i.e., + // the text that was just typed); however, the text area's + // template manager might be null (if templates are disabled). + // Also, the manager's trigger string doesn't yet match up with + // that defined in RSyntaxTextAreaEditorKit.java (which is + // hardcoded as a space)... + //String str = manager.getInsertTriggerString(); + //int mod = manager.getInsertTrigger().getModifiers(); + //if (str!=null && str.length()>0 && + // ((mod&ActionEvent.ALT_MASK)==(mod&ActionEvent.CTRL_MASK))) { + // char ch = str.charAt(0); + // if (ch>=0x20 && ch!=0x7F) + // textArea.replaceSelection(str); + //} + textArea.replaceSelection(" "); + } + + @Override + public final String getMacroID() { + return rstaPossiblyInsertTemplateAction; + } + + } + + + /** + * Action to move the selection and/or caret. Constructor indicates + * direction to use. This class overrides the behavior defined in + * {@link RTextAreaEditorKit} to better skip "words" in source code. + */ + public static class PreviousWordAction + extends RTextAreaEditorKit.PreviousWordAction { + + private Segment seg; + + public PreviousWordAction(String nm, boolean select) { + super(nm, select); + seg = new Segment(); + } + + /** + * Overridden to do better with skipping "words" in code. + */ + @Override + protected int getPreviousWord(RTextArea textArea, int offs) + throws BadLocationException { + + if (offs == 0) { + return offs; + } + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(offs); + int start = root.getElement(line).getStartOffset(); + if (offs == start) {// If we're already at the start of the line... + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { // End of next visible line + FoldManager fm = rsta.getFoldManager(); + while (--line >= 0 && fm.isLineHidden(line)) { + ; + } + if (line >= 0) { // Found an earlier visible line + offs = root.getElement(line).getEndOffset() - 1; + } + // No earlier visible line - we must be at offs==0... + return offs; + } else { + return start - 1; // End of previous line. + } + } + doc.getText(start, offs - start, seg); + + // Determine the "type" of char at offs - lower case, upper case, + // whitespace or other + char ch = seg.last(); + + // Skip any "leading" whitespace + while (Character.isWhitespace(ch)) { + ch = seg.previous(); + } + + // Skip the group of letters and/or digits + if (Character.isLetterOrDigit(ch)) { + do { + ch = seg.previous(); + } while (Character.isLetterOrDigit(ch)); + } + + // Skip groups of "anything else" (operators, etc.). + else if (!Character.isWhitespace(ch)) { + do { + ch = seg.previous(); + } while (ch != Segment.DONE && + !(Character.isLetterOrDigit(ch) || + Character.isWhitespace(ch))); + } + + offs -= seg.getEndIndex() - seg.getIndex(); + if (ch != Segment.DONE) { + offs++; + } + + return offs; + + } + + } + + + /** + * Selects the word around the caret. This class is here to better + * handle selecting "words" in programming languages. + */ + public static class SelectWordAction + extends RTextAreaEditorKit.SelectWordAction { + + @Override + protected void createActions() { + start = new BeginWordAction("pigdog", false); + end = new EndWordAction("pigdog", true); + } + + } + + + /** + * Action that toggles whether the currently selected lines are + * commented. + */ + public static class ToggleCommentAction extends RecordableTextAction { + + public ToggleCommentAction() { + super(rstaToggleCommentAction); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + + if (!textArea.isEditable() || !textArea.isEnabled()) { + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + return; + } + + RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); + String[] startEnd = doc.getLineCommentStartAndEnd(); + + if (startEnd == null) { + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + return; + } + + Element map = doc.getDefaultRootElement(); + Caret c = textArea.getCaret(); + int dot = c.getDot(); + int mark = c.getMark(); + int line1 = map.getElementIndex(dot); + int line2 = map.getElementIndex(mark); + int start = Math.min(line1, line2); + int end = Math.max(line1, line2); + + // Don't toggle comment on last line if there is no + // text selected on it. + if (start != end) { + Element elem = map.getElement(end); + if (Math.max(dot, mark) == elem.getStartOffset()) { + end--; + } + } + + textArea.beginAtomicEdit(); + try { + boolean add = getDoAdd(doc, map, start, end, startEnd); + for (line1 = start; line1 <= end; line1++) { + Element elem = map.getElement(line1); + handleToggleComment(elem, doc, startEnd, add); + } + } catch (BadLocationException ble) { + ble.printStackTrace(); + UIManager.getLookAndFeel().provideErrorFeedback(textArea); + } finally { + textArea.endAtomicEdit(); + } + + } + + private boolean getDoAdd(Document doc, Element map, int startLine, + int endLine, String[] startEnd) + throws BadLocationException { + boolean doAdd = false; + for (int i = startLine; i <= endLine; i++) { + Element elem = map.getElement(i); + int start = elem.getStartOffset(); + String t = doc.getText(start, elem.getEndOffset() - start - 1); + if (!t.startsWith(startEnd[0]) || + (startEnd[1] != null && !t.endsWith(startEnd[1]))) { + doAdd = true; + break; + } + } + return doAdd; + } + + private void handleToggleComment(Element elem, Document doc, + String[] startEnd, boolean add) throws BadLocationException { + int start = elem.getStartOffset(); + int end = elem.getEndOffset() - 1; + if (add) { + doc.insertString(start, startEnd[0], null); + if (startEnd[1] != null) { + doc.insertString(end + startEnd[0].length(), startEnd[1], + null); + } + } else { + doc.remove(start, startEnd[0].length()); + if (startEnd[1] != null) { + int temp = startEnd[1].length(); + doc.remove(end - startEnd[0].length() - temp, temp); + } + } + } + + @Override + public final String getMacroID() { + return rstaToggleCommentAction; + } + + } + + + /** + * Toggles the fold at the current caret position or line. + */ + public static class ToggleCurrentFoldAction extends FoldRelatedAction { + + private static final long serialVersionUID = 1L; + + public ToggleCurrentFoldAction() { + super(rstaToggleCurrentFoldAction); + setProperties("Action.ToggleCurrentFold"); + } + + public ToggleCurrentFoldAction(String name, Icon icon, String desc, + Integer mnemonic, KeyStroke accelerator) { + super(name, icon, desc, mnemonic, accelerator); + } + + @Override + public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { + RSyntaxTextArea rsta = (RSyntaxTextArea) textArea; + if (rsta.isCodeFoldingEnabled()) { + Fold fold = getClosestFold(rsta); + if (fold != null) { + fold.toggleCollapsedState(); + } + possiblyRepaintGutter(textArea); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(rsta); + } + } + + @Override + public final String getMacroID() { + return rstaToggleCurrentFoldAction; + } + + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxUtilities.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxUtilities.java index 87be458925..ddb3ddfa3c 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxUtilities.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxUtilities.java @@ -3,12 +3,30 @@ * * RSyntaxUtilities.java - Utility methods used by RSyntaxTextArea and its * views. - * + * * This library is distributed under a modified BSD license. See the included * RSyntaxTextArea.License.txt file for details. */ package com.fr.design.gui.syntax.ui.rsyntaxtextarea; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.TokenUtils.TokenSubList; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.folding.FoldManager; +import com.fr.design.gui.syntax.ui.rtextarea.Gutter; +import com.fr.design.gui.syntax.ui.rtextarea.RTextArea; +import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; + +import javax.swing.JLabel; +import javax.swing.JViewport; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Position; +import javax.swing.text.Segment; +import javax.swing.text.TabExpander; +import javax.swing.text.View; import java.awt.Color; import java.awt.Container; import java.awt.Point; @@ -16,23 +34,9 @@ import java.awt.Rectangle; import java.awt.Shape; import java.awt.Toolkit; import java.util.Map; +import java.util.Objects; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Caret; -import javax.swing.text.Document; -import javax.swing.text.Element; -import javax.swing.text.Position; -import javax.swing.text.Segment; -import javax.swing.text.TabExpander; -import javax.swing.text.View; - -import com.fr.design.gui.syntax.ui.rsyntaxtextarea.TokenUtils.TokenSubList; -import com.fr.design.gui.syntax.ui.rsyntaxtextarea.folding.FoldManager; -import com.fr.design.gui.syntax.ui.rtextarea.Gutter; -import com.fr.design.gui.syntax.ui.rtextarea.RTextArea; -import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; /** @@ -44,1267 +48,1276 @@ import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; */ public class RSyntaxUtilities implements SwingConstants { - /** - * Integer constant representing a Windows-variant OS. - */ - public static final int OS_WINDOWS = 1; - - /** - * Integer constant representing Mac OS X. - */ - public static final int OS_MAC_OSX = 2; - - /** - * Integer constant representing Linux. - */ - public static final int OS_LINUX = 4; - - /** - * Integer constant representing an "unknown" OS. 99.99% of the - * time, this means some UNIX variant (AIX, SunOS, etc.). - */ - public static final int OS_OTHER = 8; - - /** - * Used for the color of hyperlinks when a LookAndFeel uses light text - * against a dark background. - */ - private static final Color LIGHT_HYPERLINK_FG = new Color(0xd8ffff); - - private static final int OS = getOSImpl(); - - //private static final int DIGIT_MASK = 1; - private static final int LETTER_MASK = 2; - //private static final int WHITESPACE_MASK = 4; - //private static final int UPPER_CASE_MASK = 8; - private static final int HEX_CHARACTER_MASK = 16; - private static final int LETTER_OR_DIGIT_MASK = 32; - private static final int BRACKET_MASK = 64; - private static final int JAVA_OPERATOR_MASK = 128; - - /** - * A lookup table used to quickly decide if a 16-bit Java char is a - * US-ASCII letter (A-Z or a-z), a digit, a whitespace char (either space - * (0x0020) or tab (0x0009)), etc. This method should be faster - * than Character.isLetter, Character.isDigit, - * and Character.isWhitespace because we know we are dealing - * with ASCII chars and so don't have to worry about code planes, etc. - */ - private static final int[] dataTable = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 4, 128, 0, 0, 0, 128, 128, 0, 64, 64, 128, 128, 0, 128, 0, 128, // 32-47 - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 128, 0, 128, 128, 128, 128, // 48-63 - 0, 58, 58, 58, 58, 58, 58, 42, 42, 42, 42, 42, 42, 42, 42, 42, // 64-79 - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 64, 0, 64, 128, 0, // 80-95 - 0, 50, 50, 50, 50, 50, 50, 34, 34, 34, 34, 34, 34, 34, 34, 34, // 96-111 - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 64, 128, 64, 128, 0, // 112-127 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144- - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160- - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176- - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192- - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208- - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224- - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240-255. - }; - - /** - * Used in bracket matching methods. - */ - private static Segment charSegment = new Segment(); - - /** - * Used in token list manipulation methods. - */ - private static final TokenImpl tempToken = new TokenImpl(); - - /** - * Used internally. - */ - private static final char[] JS_KEYWORD_RETURN = { 'r', 'e', 't', 'u', 'r', 'n' }; - - /** - * Used internally. - */ - private static final String BRACKETS = "{([})]"; - - - /** - * Returns a string with characters that are special to HTML (such as - * <, > and &) replaced - * by their HTML escape sequences. - * - * @param s The input string. - * @param newlineReplacement What to replace newline characters with. - * If this is null, they are simply removed. - * @param inPreBlock Whether this HTML will be in within pre - * tags. If this is true, spaces will be kept as-is; - * otherwise, they will be converted to " ". - * @return The escaped version of s. - */ - public static final String escapeForHtml(String s, - String newlineReplacement, boolean inPreBlock) { - - if (s==null) { - return null; - } - if (newlineReplacement==null) { - newlineReplacement = ""; - } - final String tabString = " "; - boolean lastWasSpace = false; - - StringBuilder sb = new StringBuilder(); - - for (int i=0; i': - sb.append(">"); - lastWasSpace = false; - break; - default: - sb.append(ch); - lastWasSpace = false; - break; - } - } - - return sb.toString(); - - } - - - /** - * Returns the rendering hints for text that will most accurately reflect - * those of the native windowing system. - * - * @return The rendering hints, or null if they cannot be - * determined. - */ - public static Map getDesktopAntiAliasHints() { - return (Map)Toolkit.getDefaultToolkit(). - getDesktopProperty("awt.font.desktophints"); - } - - - /** - * Returns the color to use for the line underneath a folded region line. - * - * @param textArea The text area. - * @return The color to use. - */ - public static Color getFoldedLineBottomColor(RSyntaxTextArea textArea) { - Color color = Color.gray; - Gutter gutter = RSyntaxUtilities.getGutter(textArea); - if (gutter!=null) { - color = gutter.getFoldIndicatorForeground(); - } - return color; - } - - - /** - * Returns the gutter component of the scroll pane containing a text - * area, if any. - * - * @param textArea The text area. - * @return The gutter, or null if the text area is not in - * an {@link RTextScrollPane}. - * @see RTextScrollPane#getGutter() - */ - public static Gutter getGutter(RTextArea textArea) { - Gutter gutter = null; - Container parent = textArea.getParent(); - if (parent instanceof JViewport) { - parent = parent.getParent(); - if (parent instanceof RTextScrollPane) { - RTextScrollPane sp = (RTextScrollPane)parent; - gutter = sp.getGutter(); // Should always be non-null - } - } - return gutter; - } - - - /** - * Returns the color to use for hyperlink-style components. This method - * will return Color.blue unless it appears that the current - * LookAndFeel uses light text on a dark background, in which case a - * brighter alternative is returned. - * - * @return The color to use for hyperlinks. - * @see #isLightForeground(Color) - */ - public static final Color getHyperlinkForeground() { - - // This property is defined by all standard LaFs, even Nimbus (!), - // but you never know what crazy LaFs there are... - Color fg = UIManager.getColor("Label.foreground"); - if (fg==null) { - fg = new JLabel().getForeground(); - } - - return isLightForeground(fg) ? LIGHT_HYPERLINK_FG : Color.blue; - - } - - - /** - * Returns the leading whitespace of a string. - * - * @param text The String to check. - * @return The leading whitespace. - * @see #getLeadingWhitespace(Document, int) - */ - public static String getLeadingWhitespace(String text) { - int count = 0; - int len = text.length(); - while (countoffs is not a valid offset - * in the document. - * @see #getLeadingWhitespace(String) - */ - public static String getLeadingWhitespace(Document doc, int offs) - throws BadLocationException { - Element root = doc.getDefaultRootElement(); - int line = root.getElementIndex(offs); - Element elem = root.getElement(line); - int startOffs = elem.getStartOffset(); - int endOffs = elem.getEndOffset() - 1; - String text = doc.getText(startOffs, endOffs-startOffs); - return getLeadingWhitespace(text); - } - - - private static final Element getLineElem(Document d, int offs) { - Element map = d.getDefaultRootElement(); - int index = map.getElementIndex(offs); - Element elem = map.getElement(index); - if ((offs>=elem.getStartOffset()) && (offsp0, as this is - * the character where the x-pixel value is 0. - * - * @param textArea The text area containing the text. - * @param s A segment in which to load the line. This is passed in so we - * don't have to reallocate a new Segment for each - * call. - * @param p0 The starting position in the physical line in the document. - * @param p1 The position for which to get the bounding box in the view. - * @param e How to expand tabs. - * @param rect The rectangle whose x- and width-values are changed to - * represent the bounding box of p1. This is reused - * to keep from needlessly reallocating Rectangles. - * @param x0 The x-coordinate (pixel) marking the left-hand border of the - * text. This is useful if the text area has a border, for example. - * @return The bounding box in the view of the character p1. - * @throws BadLocationException If p0 or p1 is - * not a valid location in the specified text area's document. - * @throws IllegalArgumentException If p0 and p1 - * are not on the same line. - */ - public static Rectangle getLineWidthUpTo(RSyntaxTextArea textArea, - Segment s, int p0, int p1, - TabExpander e, Rectangle rect, - int x0) - throws BadLocationException { - - RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument(); - - // Ensure p0 and p1 are valid document positions. - if (p0<0) - throw new BadLocationException("Invalid document position", p0); - else if (p1>doc.getLength()) - throw new BadLocationException("Invalid document position", p1); - - // Ensure p0 and p1 are in the same line, and get the start/end - // offsets for that line. - Element map = doc.getDefaultRootElement(); - int lineNum = map.getElementIndex(p0); - // We do ">1" because p1 might be the first position on the next line - // or the last position on the previous one. - // if (lineNum!=map.getElementIndex(p1)) - if (Math.abs(lineNum-map.getElementIndex(p1))>1) - throw new IllegalArgumentException("p0 and p1 are not on the " + - "same line (" + p0 + ", " + p1 + ")."); - - // Get the token list. - Token t = doc.getTokenListForLine(lineNum); - - // Modify the token list 't' to begin at p0 (but still have correct - // token types, etc.), and get the x-location (in pixels) of the - // beginning of this new token list. - TokenSubList subList = TokenUtils.getSubTokenList(t, p0, e, textArea, - 0, tempToken); - t = subList.tokenList; - - rect = t.listOffsetToView(textArea, e, p1, x0, rect); - return rect; - - } - - - /** - * Returns the location of the bracket paired with the one at the current - * caret position. - * - * @param textArea The text area. - * @param input A point to use as the return value. If this is - * null, a new object is created and returned. - * @return A point representing the matched bracket info. The "x" field - * is the offset of the bracket at the caret position (either just - * before or just after the caret), and the "y" field is the offset - * of the matched bracket. Both "x" and "y" will be - * -1 if there isn't a matching bracket (or the caret - * isn't on a bracket). - */ - public static Point getMatchingBracketPosition(RSyntaxTextArea textArea, - Point input) { - - if (input==null) { - input = new Point(); - } - input.setLocation(-1, -1); - - try { - - // Actually position just BEFORE caret. - int caretPosition = textArea.getCaretPosition() - 1; - RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument(); - char bracket = 0; - - // If the caret was at offset 0, we can't check "to its left." - if (caretPosition>=0) { - bracket = doc.charAt(caretPosition); - } - - // Try to match a bracket "to the right" of the caret if one - // was not found on the left. - int index = BRACKETS.indexOf(bracket); - if (index==-1 && caretPosition