diff --git a/designer-base/src/main/java/com/fr/base/svg/IconUtils.java b/designer-base/src/main/java/com/fr/base/svg/IconUtils.java index 4b5f1b881..79d3cef76 100644 --- a/designer-base/src/main/java/com/fr/base/svg/IconUtils.java +++ b/designer-base/src/main/java/com/fr/base/svg/IconUtils.java @@ -2,9 +2,15 @@ package com.fr.base.svg; import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; +import com.fr.stable.bridge.StableFactory; +import com.fr.stable.fun.ResourcePathTransformer; +import com.fr.stable.plugin.ExtraClassManagerProvider; import javax.swing.Icon; import javax.swing.ImageIcon; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; /** * 主要是用来读取svgIcon的工具类 @@ -36,7 +42,7 @@ public class IconUtils { // 判断是否以.svg结尾 if (resource.endsWith(ICON_SUFFIX_SVG)) { if (IOUtils.readResource(resource) != null) { - return SVGIcon.readSVGIcon(resource); + return SVGIcon.readSVGIcon(transformPath(resource)); } // 适配插件 return adjustPluginsPng(resource); @@ -68,15 +74,15 @@ public class IconUtils { private static Icon readNoSuffixResource(String resource, String svgIconType) { String svgPath = resource + svgIconType; if (IOUtils.readResource(svgPath) != null) { - return SVGIcon.readSVGIcon(svgPath); + return SVGIcon.readSVGIcon(transformPath(svgPath)); } String pngPath = resource + ICON_SUFFIX_PNG; if (IOUtils.readResource(pngPath) != null) { - return IOUtils.readIcon(pngPath); + return IOUtils.readIcon(transformPath(pngPath)); } String gifPath = resource + ICON_SUFFIX_GIF; if (IOUtils.readResource(gifPath) != null) { - return IOUtils.readIcon(gifPath); + return IOUtils.readIcon(transformPath(gifPath)); } FineLoggerFactory.getLogger().error("File not exists:{}", resource); return new ImageIcon(); @@ -113,8 +119,30 @@ public class IconUtils { private static Icon readSpecifiedTypeIcon(String resource, String oldSuffix, String newSuffix) { String iconPath = resource.replace(oldSuffix, newSuffix); if (IOUtils.readResource(iconPath) != null) { - return SVGIcon.readSVGIcon(iconPath); + return SVGIcon.readSVGIcon(transformPath(iconPath)); } return readIcon(resource); } + + private static String transformPath(String path) { + Set set = getResourcePathTransformers(); + for (ResourcePathTransformer transformer : set) { + if (transformer.accept(path)) { + return transformer.transform(path); + } + } + return path; + } + + private static Set getResourcePathTransformers() { + Set set = new HashSet(); + ExtraClassManagerProvider provider = StableFactory.getExtraClassManager(); + if (provider != null) { + Set pluginProvided = provider.getArray(ResourcePathTransformer.MARK_STRING); + set.addAll(pluginProvided); + } + ResourcePathTransformer[] oemSet = StableFactory.getMarkedObjectsFromCollection(ResourcePathTransformer.MARK_STRING, ResourcePathTransformer.class); + set.addAll(Arrays.asList(oemSet)); + return set; + } } diff --git a/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java b/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java new file mode 100644 index 000000000..d556548c1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java @@ -0,0 +1,26 @@ +package com.fr.design.actions.community; + + +import com.fr.design.i18n.Toolkit; +import com.fr.design.utils.BrowseUtils; +import com.fr.general.CloudCenter; + +import java.awt.event.ActionEvent; + +/** + * @Description 工单中心 + * @Author Henry.Wang + * @Date 2021/3/8 14:02 + **/ +public class WorkOrderCenterAction extends UpAction { + public WorkOrderCenterAction() { + this.setSmallIcon("/com/fr/design/images/bbs/workOrderCenter"); + this.setName(Toolkit.i18nText("Fine-Design_Basic_Commuinity_Work_Order_Center")); + } + + @Override + public void actionPerformed(ActionEvent arg0) { + String url = CloudCenter.getInstance().acquireUrlByKind("bbs.work.order.center"); + BrowseUtils.browser(url); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/actions/core/ActionFactory.java b/designer-base/src/main/java/com/fr/design/actions/core/ActionFactory.java index 574195470..f19c962f8 100644 --- a/designer-base/src/main/java/com/fr/design/actions/core/ActionFactory.java +++ b/designer-base/src/main/java/com/fr/design/actions/core/ActionFactory.java @@ -13,12 +13,14 @@ import javax.swing.KeyStroke; import java.awt.event.KeyEvent; import java.lang.reflect.Constructor; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; /** * 插入单元格元素和插入悬浮元素的一些集合方法 @@ -27,8 +29,8 @@ import java.util.concurrent.ConcurrentMap; * @version 2017年11月17日14点39分 */ public class ActionFactory { - private static LinkedHashSet> actionClasses = new LinkedHashSet<>(); - private static LinkedHashSet> floatActionClasses = new LinkedHashSet<>(); + private static Set> actionClasses = new CopyOnWriteArraySet<>(); + private static Set> floatActionClasses = new CopyOnWriteArraySet<>(); private static Class chartCollectionClass = null; /** * 无需每次实例化的悬浮元素编辑器 @@ -256,14 +258,14 @@ public class ActionFactory { */ public static void registerCellInsertActionClass(Class[] cls) { if (cls != null) { - Collections.addAll(actionClasses, cls); + actionClasses.addAll(Arrays.asList(cls)); } } public static void referCellInsertActionClass(Class[] cls) { if (cls != null) { actionClasses.clear(); - Collections.addAll(actionClasses, cls); + actionClasses.addAll(Arrays.asList(cls)); } } @@ -321,14 +323,14 @@ public class ActionFactory { */ public static void registerFloatInsertActionClass(Class[] cls) { if (cls != null) { - Collections.addAll(floatActionClasses, cls); + floatActionClasses.addAll(Arrays.asList(cls)); } } public static void referFloatInsertActionClass(Class[] cls) { if (cls != null) { floatActionClasses.clear(); - Collections.addAll(floatActionClasses, cls); + floatActionClasses.addAll(Arrays.asList(cls)); } } diff --git a/designer-base/src/main/java/com/fr/design/actions/file/WebPreviewUtils.java b/designer-base/src/main/java/com/fr/design/actions/file/WebPreviewUtils.java index 8d1e5828d..9f87943e1 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/WebPreviewUtils.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/WebPreviewUtils.java @@ -86,6 +86,8 @@ public final class WebPreviewUtils { if (!jt.saveAsTemplate()) { return; } + } else { + return; } currentTemplate = jt.getEditingFILE(); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java index 4b4d66866..a979a20cd 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java @@ -1,27 +1,32 @@ package com.fr.design.data.datapane.connect; import com.fr.base.BaseUtils; +import com.fr.data.core.db.TableProcedure; import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.Connection; -import com.fr.design.constants.UIConstants; -import com.fr.data.core.db.TableProcedure; import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.dialog.BasicPane; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.ilist.TableViewList; +import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.dialog.BasicPane; import com.fr.general.GeneralContext; - import com.fr.stable.ArrayUtils; -import javax.swing.*; +import javax.swing.JPanel; +import javax.swing.ToolTipManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.*; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.List; /** @@ -48,10 +53,11 @@ public class ConnectionTableProcedurePane extends BasicPane { filter(connection, conName, nameList); } + @Override protected void refreshItems() { super.refreshItems(); if (tableViewList != null) { - search(); + search(true); } } }; @@ -148,17 +154,17 @@ public class ConnectionTableProcedurePane extends BasicPane { @Override public void removeUpdate(DocumentEvent e) { - search(); + search(false); } @Override public void insertUpdate(DocumentEvent e) { - search(); + search(false); } @Override public void changedUpdate(DocumentEvent e) { - search(); + search(false); } }; @@ -166,14 +172,14 @@ public class ConnectionTableProcedurePane extends BasicPane { @Override public void actionPerformed(ActionEvent e) { - search(); + search(false); } }; /** * 选项改变,需要重新刷新下拉列表里面的项 */ - protected void search() { + protected void search(boolean refresh) { String selectedObj = connectionComboBox.getSelectedItem(); String[] types = ArrayUtils.EMPTY_STRING_ARRAY; @@ -187,7 +193,7 @@ public class ConnectionTableProcedurePane extends BasicPane { } else { types = (String[]) ArrayUtils.add(types, TableProcedure.PROCEDURE); } - tableViewList.populate(selectedObj, searchField.getText().trim(), types); + tableViewList.populate(selectedObj, searchField.getText().trim(), refresh, types); } @Override @@ -196,7 +202,6 @@ public class ConnectionTableProcedurePane extends BasicPane { } /** - * * @param l */ public void addDoubleClickListener(DoubleClickSelectedNodeOnTreeListener l) { 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 da87c10f6..e95a5999a 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 @@ -169,7 +169,6 @@ public class PreviewTablePane extends BasicPane { this.add(new JScrollPane(preveiwTable), BorderLayout.CENTER); if (this.dialog == null) { this.dialog = this.showWindow(new JFrame()); - GUICoreUtils.centerWindow(DesignerContext.getDesignerFrame(), this.dialog); } progressBar = new AutoProgressBar(this, Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) { public void doMonitorCanceled() { 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 e684d81f6..930dde76c 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 @@ -3,6 +3,7 @@ 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.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.core.PropertyChangeAdapter; @@ -33,7 +34,7 @@ public abstract class BasicPane extends JPanel { * @return 对话框 */ public BasicDialog showWindow(Window window, DialogActionListener l) { - return showWindowWithCustomSize(window, l, BasicDialog.DEFAULT); + return showWindowWithCustomSize(window, l, DesignSizeI18nManager.getInstance().i18nDimension(this.i18nText4PopupWindow())); } /** @@ -236,6 +237,14 @@ public abstract class BasicPane extends JPanel { return title4PopupWindow(); } + /** + * 国际化标识 + * @return 默认是取当前类的全限定名 + */ + protected String i18nText4PopupWindow() { + return this.getClass().getName(); + } + /** * 作为名字面板 * @@ -403,4 +412,4 @@ public abstract class BasicPane extends JPanel { } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java b/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java index d70901350..ba7c0092d 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java @@ -16,6 +16,7 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.locale.impl.BbsRegisterMark; import com.fr.design.locale.impl.BbsResetMark; import com.fr.design.locale.impl.BbsSpaceMark; +import com.fr.design.plugin.DesignerPluginContext; import com.fr.design.utils.concurrent.ThreadFactoryBuilder; import com.fr.general.CloudCenter; import com.fr.general.locale.LocaleCenter; @@ -401,6 +402,7 @@ public class PluginWebBridge { if (uiDialog != null) { uiDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); uiDialog.setVisible(false); + DesignerPluginContext.setPluginDialog(null); } } diff --git a/designer-base/src/main/java/com/fr/design/extra/ShopDialog.java b/designer-base/src/main/java/com/fr/design/extra/ShopDialog.java index e0170cef8..fed317989 100644 --- a/designer-base/src/main/java/com/fr/design/extra/ShopDialog.java +++ b/designer-base/src/main/java/com/fr/design/extra/ShopDialog.java @@ -3,6 +3,7 @@ package com.fr.design.extra; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.UIDialog; import com.fr.design.jdk.JdkVersion; +import com.fr.design.plugin.DesignerPluginContext; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.StableUtils; @@ -25,6 +26,7 @@ public class ShopDialog extends UIDialog { setSize(createDefaultDimension()); GUICoreUtils.centerWindow(this); setResizable(false); + DesignerPluginContext.setPluginDialog(this); } private Dimension createDefaultDimension() { diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java index 8015e00fb..78e338f8c 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java @@ -5,6 +5,7 @@ import com.fr.design.dialog.FineJOptionPane; import com.fr.design.extra.PluginOperateUtils; import com.fr.design.i18n.Toolkit; +import com.fr.design.plugin.DesignerPluginContext; import com.fr.log.FineLoggerFactory; import com.fr.plugin.manage.control.PluginTaskCallback; import com.fr.plugin.manage.control.PluginTaskResult; @@ -31,9 +32,9 @@ public class ModifyStatusCallback implements PluginTaskCallback{ pluginInfo + Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Disabled_Duplicate") : pluginInfo + Toolkit.i18nText("Fine-Design_Plugin_Has_Been_Actived_Duplicate"); FineLoggerFactory.getLogger().info(modifyMessage); - FineJOptionPane.showMessageDialog(null, modifyMessage); + FineJOptionPane.showMessageDialog(DesignerPluginContext.getPluginDialog(), modifyMessage); } else { - FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + FineJOptionPane.showMessageDialog(DesignerPluginContext.getPluginDialog(), pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), JOptionPane.ERROR_MESSAGE); } } diff --git a/designer-base/src/main/java/com/fr/design/fun/PluginManagerProvider.java b/designer-base/src/main/java/com/fr/design/fun/PluginManagerProvider.java new file mode 100644 index 000000000..11fcecc2c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/PluginManagerProvider.java @@ -0,0 +1,20 @@ +package com.fr.design.fun; + +import com.fr.design.actions.UpdateAction; +import com.fr.stable.fun.mark.Selectable; + +/** + * 替换插件管理入口 + * @author Lucian.Chen + * @version 10.0 + * Created by Lucian.Chen on 2021/2/20 + */ +public interface PluginManagerProvider extends Selectable { + + String MARK_STRING = "PluginManagerProvider"; + + int CURRENT_LEVEL = 1; + + // 插件管理 + UpdateAction pluginManagerAction(); +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPluginManagerProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPluginManagerProvider.java new file mode 100644 index 000000000..cfffd66f4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPluginManagerProvider.java @@ -0,0 +1,30 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.PluginManagerProvider; +import com.fr.stable.fun.assist.Selector; +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Lucian.Chen + * @version 10.0 + * Created by Lucian.Chen on 2021/2/20 + */ +@API(level = PluginManagerProvider.CURRENT_LEVEL) +public abstract class AbstractPluginManagerProvider extends AbstractProvider implements PluginManagerProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } + + @Override + public Selector selector() { + return Selector.ALWAYS; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java b/designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java index 4a002cf01..df36add40 100644 --- a/designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java +++ b/designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java @@ -2,7 +2,7 @@ * 12/21/2008 * * DefaultCompletionProvider.java - A basic completion provider implementation. - * + * * This library is distributed under a modified BSD license. See the included * RSyntaxTextArea.License.txt file for details. */ @@ -24,7 +24,11 @@ import javax.swing.text.Segment; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; + +import com.fr.log.FineLoggerFactory; import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; /** @@ -38,337 +42,345 @@ import org.xml.sax.SAXException; */ public class DefaultCompletionProvider extends AbstractCompletionProvider { - protected Segment seg; - - /** - * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}. - */ - private String lastCompletionsAtText; - - /** - * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}, - * since this may be called multiple times in succession (this is usually - * called by JTextComponent.getToolTipText(), and if the user - * wiggles the mouse while a tool tip is displayed, this method gets - * repeatedly called. It can be costly so we try to speed it up a tad). - */ - private List lastParameterizedCompletionsAt; - - /** - * Constructor. The returned provider will not be aware of any completions. - * - * @see #addCompletion(Completion) - */ - public DefaultCompletionProvider() { - init(); - } - - - /** - * Creates a completion provider that provides completion for a simple - * list of words. - * - * @param words The words to offer as completion suggestions. If this is - * null, no completions will be known. - * @see BasicCompletion - */ - public DefaultCompletionProvider(String[] words) { - init(); - addWordCompletions(words); - } - - - /** - * Returns the text just before the current caret position that could be - * the start of something auto-completable.

- * - * This method returns all characters before the caret that are matched - * by {@link #isValidChar(char)}. - * - * {@inheritDoc} - */ - public String getAlreadyEnteredText(JTextComponent comp) { - - Document doc = comp.getDocument(); - - int dot = comp.getCaretPosition(); - Element root = doc.getDefaultRootElement(); - int index = root.getElementIndex(dot); - Element elem = root.getElement(index); - int start = elem.getStartOffset(); - int len = dot-start; - try { - doc.getText(start, len, seg); - } catch (BadLocationException ble) { - - return EMPTY_STRING; - } - - int segEnd = seg.offset + len; - start = segEnd - 1; - while (start>=seg.offset && isValidChar(seg.array[start])) { - start--; - } - start++; - - len = segEnd - start; - return len==0 ? EMPTY_STRING : new String(seg.array, start, len); - - } - - - /** - * {@inheritDoc} - */ - public List getCompletionsAt(JTextComponent tc, Point p) { - - int offset = tc.viewToModel(p); - if (offset<0 || offset>=tc.getDocument().getLength()) { - lastCompletionsAtText = null; - return lastParameterizedCompletionsAt = null; - } - - Segment s = new Segment(); - Document doc = tc.getDocument(); - Element root = doc.getDefaultRootElement(); - int line = root.getElementIndex(offset); - Element elem = root.getElement(line); - int start = elem.getStartOffset(); - int end = elem.getEndOffset() - 1; - - try { - - doc.getText(start, end-start, s); - - // Get the valid chars before the specified offset. - int startOffs = s.offset + (offset-start) - 1; - while (startOffs>=s.offset && isValidChar(s.array[startOffs])) { - startOffs--; - } - - // Get the valid chars at and after the specified offset. - int endOffs = s.offset + (offset-start); - while (endOffs list = getCompletionByInputText(text); - lastCompletionsAtText = text; - return lastParameterizedCompletionsAt = list; - - } catch (BadLocationException ble) { - // Never happens - } - - lastCompletionsAtText = null; - return lastParameterizedCompletionsAt = null; - - } - - - /** - * {@inheritDoc} - */ - public List getParameterizedCompletions( - JTextComponent tc) { - - List list = null; - - // If this provider doesn't support parameterized completions, - // bail out now. - char paramListStart = getParameterListStart(); - if (paramListStart==0) { - return list; // null - } - - int dot = tc.getCaretPosition(); - Segment s = new Segment(); - Document doc = tc.getDocument(); - Element root = doc.getDefaultRootElement(); - int line = root.getElementIndex(dot); - Element elem = root.getElement(line); - int offs = elem.getStartOffset(); - int len = dot - offs - 1/*paramListStart.length()*/; - if (len<=0) { // Not enough chars on line for a method. - return list; // null - } - - try { - - doc.getText(offs, len, s); - - // Get the identifier preceding the '(', ignoring any whitespace - // between them. - offs = s.offset + len - 1; - while (offs>=s.offset && Character.isWhitespace(s.array[offs])) { - offs--; - } - int end = offs; - while (offs>=s.offset && isValidChar(s.array[offs])) { - offs--; - } - - String text = new String(s.array, offs+1, end-offs); - - // Get a list of all Completions matching the text, but then - // narrow it down to just the ParameterizedCompletions. - List l = getCompletionByInputText(text); - if (l!=null && !l.isEmpty()) { - for (int i=0; i(1); - } - list.add((ParameterizedCompletion)o); - } - } - } - - } catch (BadLocationException ble) { - // Never happens - } - - return list; - - } - - - /** - * Initializes this completion provider. - */ - protected void init() { - completions = new ArrayList(); - seg = new Segment(); - } - - - /** - * Returns whether the specified character is valid in an auto-completion. - * The default implementation is equivalent to - * "Character.isLetterOrDigit(ch) || ch=='_'". Subclasses - * can override this method to change what characters are matched. - * - * @param ch The character. - * @return Whether the character is valid. - */ - protected boolean isValidChar(char ch) { - return Character.isLetterOrDigit(ch) || ch=='_'; - } - - - /** - * Loads completions from an XML file. The XML should validate against - * CompletionXml.dtd. - * - * @param file An XML file to load from. - * @throws IOException If an IO error occurs. - */ - public void loadFromXML(File file) throws IOException { - BufferedInputStream bin = new BufferedInputStream( - new FileInputStream(file)); - try { - loadFromXML(bin); - } finally { - bin.close(); - } - } - - - /** - * Loads completions from an XML input stream. The XML should validate - * against CompletionXml.dtd. - * - * @param in The input stream to read from. - * @throws IOException If an IO error occurs. - */ - public void loadFromXML(InputStream in) throws IOException { - loadFromXML(in, null); - } - - - /** - * Loads completions from an XML input stream. The XML should validate - * against CompletionXml.dtd. - * - * @param in The input stream to read from. - * @param cl The class loader to use when loading any extra classes defined - * in the XML, such as custom {@link FunctionCompletion}s. This - * may be null if the default is to be used, or if no - * custom completions are defined in the XML. - * @throws IOException If an IO error occurs. - */ - public void loadFromXML(InputStream in, ClassLoader cl) throws IOException { - - //long start = System.currentTimeMillis(); - - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setValidating(true); - CompletionXMLParser handler = new CompletionXMLParser(this, cl); - BufferedInputStream bin = new BufferedInputStream(in); - try { - SAXParser saxParser = factory.newSAXParser(); - saxParser.parse(bin, handler); - List completions = handler.getCompletions(); - addCompletions(completions); - char startChar = handler.getParamStartChar(); - if (startChar!=0) { - char endChar = handler.getParamEndChar(); - String sep = handler.getParamSeparator(); - if (endChar!=0 && sep!=null && sep.length()>0) { // Sanity - setParameterizedCompletionParams(startChar, sep, endChar); - } - } - } catch (SAXException se) { - throw new IOException(se.toString()); - } catch (ParserConfigurationException pce) { - throw new IOException(pce.toString()); - } finally { - //long time = System.currentTimeMillis() - start; - //System.out.println("XML loaded in: " + time + "ms"); - bin.close(); - } - - } - - - /** - * Loads completions from an XML file. The XML should validate against - * CompletionXml.dtd. - * - * @param resource A resource the current ClassLoader can get to. - * @throws IOException If an IO error occurs. - */ - public void loadFromXML(String resource) throws IOException { - ClassLoader cl = getClass().getClassLoader(); - InputStream in = cl.getResourceAsStream(resource); - if (in==null) { - File file = new File(resource); - if (file.isFile()) { - in = new FileInputStream(file); - } - else { - throw new IOException("No such resource: " + resource); - } - } - BufferedInputStream bin = new BufferedInputStream(in); - try { - loadFromXML(bin); - } finally { - bin.close(); - } - } + protected Segment seg; + + /** + * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}. + */ + private String lastCompletionsAtText; + + /** + * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}, + * since this may be called multiple times in succession (this is usually + * called by JTextComponent.getToolTipText(), and if the user + * wiggles the mouse while a tool tip is displayed, this method gets + * repeatedly called. It can be costly so we try to speed it up a tad). + */ + private List lastParameterizedCompletionsAt; + + /** + * Constructor. The returned provider will not be aware of any completions. + * + * @see #addCompletion(Completion) + */ + public DefaultCompletionProvider() { + init(); + } + + + /** + * Creates a completion provider that provides completion for a simple + * list of words. + * + * @param words The words to offer as completion suggestions. If this is + * null, no completions will be known. + * @see BasicCompletion + */ + public DefaultCompletionProvider(String[] words) { + init(); + addWordCompletions(words); + } + + + /** + * Returns the text just before the current caret position that could be + * the start of something auto-completable.

+ *

+ * This method returns all characters before the caret that are matched + * by {@link #isValidChar(char)}. + *

+ * {@inheritDoc} + */ + public String getAlreadyEnteredText(JTextComponent comp) { + + Document doc = comp.getDocument(); + + int dot = comp.getCaretPosition(); + Element root = doc.getDefaultRootElement(); + int index = root.getElementIndex(dot); + Element elem = root.getElement(index); + int start = elem.getStartOffset(); + int len = dot - start; + try { + doc.getText(start, len, seg); + } catch (BadLocationException ble) { + + return EMPTY_STRING; + } + + int segEnd = seg.offset + len; + start = segEnd - 1; + while (start >= seg.offset && isValidChar(seg.array[start])) { + start--; + } + start++; + + len = segEnd - start; + return len == 0 ? EMPTY_STRING : new String(seg.array, start, len); + + } + + + /** + * {@inheritDoc} + */ + public List getCompletionsAt(JTextComponent tc, Point p) { + + int offset = tc.viewToModel(p); + if (offset < 0 || offset >= tc.getDocument().getLength()) { + lastCompletionsAtText = null; + return lastParameterizedCompletionsAt = null; + } + + Segment s = new Segment(); + Document doc = tc.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(offset); + Element elem = root.getElement(line); + int start = elem.getStartOffset(); + int end = elem.getEndOffset() - 1; + + try { + + doc.getText(start, end - start, s); + + // Get the valid chars before the specified offset. + int startOffs = s.offset + (offset - start) - 1; + while (startOffs >= s.offset && isValidChar(s.array[startOffs])) { + startOffs--; + } + + // Get the valid chars at and after the specified offset. + int endOffs = s.offset + (offset - start); + while (endOffs < s.offset + s.count && isValidChar(s.array[endOffs])) { + endOffs++; + } + + int len = endOffs - startOffs - 1; + if (len <= 0) { + return lastParameterizedCompletionsAt = null; + } + String text = new String(s.array, startOffs + 1, len); + + if (text.equals(lastCompletionsAtText)) { + return lastParameterizedCompletionsAt; + } + + // Get a list of all Completions matching the text. + List list = getCompletionByInputText(text); + lastCompletionsAtText = text; + return lastParameterizedCompletionsAt = list; + + } catch (BadLocationException ble) { + // Never happens + } + + lastCompletionsAtText = null; + return lastParameterizedCompletionsAt = null; + + } + + + /** + * {@inheritDoc} + */ + public List getParameterizedCompletions( + JTextComponent tc) { + + List list = null; + + // If this provider doesn't support parameterized completions, + // bail out now. + char paramListStart = getParameterListStart(); + if (paramListStart == 0) { + return list; // null + } + + int dot = tc.getCaretPosition(); + Segment s = new Segment(); + Document doc = tc.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(dot); + Element elem = root.getElement(line); + int offs = elem.getStartOffset(); + int len = dot - offs - 1/*paramListStart.length()*/; + if (len <= 0) { // Not enough chars on line for a method. + return list; // null + } + + try { + + doc.getText(offs, len, s); + + // Get the identifier preceding the '(', ignoring any whitespace + // between them. + offs = s.offset + len - 1; + while (offs >= s.offset && Character.isWhitespace(s.array[offs])) { + offs--; + } + int end = offs; + while (offs >= s.offset && isValidChar(s.array[offs])) { + offs--; + } + + String text = new String(s.array, offs + 1, end - offs); + + // Get a list of all Completions matching the text, but then + // narrow it down to just the ParameterizedCompletions. + List l = getCompletionByInputText(text); + if (l != null && !l.isEmpty()) { + for (int i = 0; i < l.size(); i++) { + Object o = l.get(i); + if (o instanceof ParameterizedCompletion) { + if (list == null) { + list = new ArrayList(1); + } + list.add((ParameterizedCompletion) o); + } + } + } + + } catch (BadLocationException ble) { + // Never happens + } + + return list; + + } + + + /** + * Initializes this completion provider. + */ + protected void init() { + completions = new ArrayList(); + seg = new Segment(); + } + + + /** + * Returns whether the specified character is valid in an auto-completion. + * The default implementation is equivalent to + * "Character.isLetterOrDigit(ch) || ch=='_'". Subclasses + * can override this method to change what characters are matched. + * + * @param ch The character. + * @return Whether the character is valid. + */ + protected boolean isValidChar(char ch) { + return Character.isLetterOrDigit(ch) || ch == '_'; + } + + + /** + * Loads completions from an XML file. The XML should validate against + * CompletionXml.dtd. + * + * @param file An XML file to load from. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(File file) throws IOException { + BufferedInputStream bin = new BufferedInputStream( + new FileInputStream(file)); + try { + loadFromXML(bin); + } finally { + bin.close(); + } + } + + + /** + * Loads completions from an XML input stream. The XML should validate + * against CompletionXml.dtd. + * + * @param in The input stream to read from. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(InputStream in) throws IOException { + loadFromXML(in, null); + } + + + /** + * Loads completions from an XML input stream. The XML should validate + * against CompletionXml.dtd. + * + * @param in The input stream to read from. + * @param cl The class loader to use when loading any extra classes defined + * in the XML, such as custom {@link FunctionCompletion}s. This + * may be null if the default is to be used, or if no + * custom completions are defined in the XML. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(InputStream in, ClassLoader cl) throws IOException { + + //long start = System.currentTimeMillis(); + + SAXParserFactory factory = SAXParserFactory.newInstance(); + try { + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + } catch (ParserConfigurationException | SAXNotSupportedException | SAXNotRecognizedException e) { + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + } + + factory.setValidating(true); + CompletionXMLParser handler = new CompletionXMLParser(this, cl); + BufferedInputStream bin = new BufferedInputStream(in); + try { + SAXParser saxParser = factory.newSAXParser(); + saxParser.parse(bin, handler); + List completions = handler.getCompletions(); + addCompletions(completions); + char startChar = handler.getParamStartChar(); + if (startChar != 0) { + char endChar = handler.getParamEndChar(); + String sep = handler.getParamSeparator(); + if (endChar != 0 && sep != null && sep.length() > 0) { // Sanity + setParameterizedCompletionParams(startChar, sep, endChar); + } + } + } catch (SAXException se) { + throw new IOException(se.toString()); + } catch (ParserConfigurationException pce) { + throw new IOException(pce.toString()); + } finally { + //long time = System.currentTimeMillis() - start; + //System.out.println("XML loaded in: " + time + "ms"); + bin.close(); + } + + } + + + /** + * Loads completions from an XML file. The XML should validate against + * CompletionXml.dtd. + * + * @param resource A resource the current ClassLoader can get to. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(String resource) throws IOException { + ClassLoader cl = getClass().getClassLoader(); + InputStream in = cl.getResourceAsStream(resource); + if (in == null) { + File file = new File(resource); + if (file.isFile()) { + in = new FileInputStream(file); + } else { + throw new IOException("No such resource: " + resource); + } + } + BufferedInputStream bin = new BufferedInputStream(in); + try { + loadFromXML(bin); + } finally { + bin.close(); + } + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/ilist/TableViewList.java b/designer-base/src/main/java/com/fr/design/gui/ilist/TableViewList.java index ec05732c6..ba29288fc 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ilist/TableViewList.java +++ b/designer-base/src/main/java/com/fr/design/gui/ilist/TableViewList.java @@ -82,7 +82,7 @@ public class TableViewList extends UIList { * @param searchFilter * @param typesFilter */ - public void populate(final String databaseName, final String searchFilter, final String... typesFilter) { + public void populate(final String databaseName, final String searchFilter, boolean refresh, final String... typesFilter) { DefaultListModel defaultListModel = new DefaultListModel(); defaultListModel.addElement(UIConstants.PENDING); final DefaultListModel failed = new DefaultListModel(); @@ -106,12 +106,9 @@ public class TableViewList extends UIList { if (!status) { throw new Exception(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed")); } - String[] schemas = DataCoreUtils.getDatabaseSchema(datasource); - schemas = (schemas == null || schemas.length == 0) ? new String[]{null} : schemas; - for (String schema : schemas) { - clearCache(datasource, schema); + if (refresh) { + clearCache(datasource); } - clearCache(datasource, null); return processDataInAnotherThread(databaseName, searchFilter, typesFilter); } @@ -132,7 +129,16 @@ public class TableViewList extends UIList { } } - private void clearCache(Connection datasource, String schema) { + private void clearCache(Connection datasource) { + String[] schemas = DataCoreUtils.getDatabaseSchema(datasource); + schemas = (schemas == null || schemas.length == 0) ? new String[]{null} : schemas; + for (String schema : schemas) { + doClearCache(datasource, schema); + } + doClearCache(datasource, null); + } + + private void doClearCache(Connection datasource, String schema) { DataCoreUtils.refreshTables(datasource, TableProcedure.TABLE, schema); DataCoreUtils.refreshTables(datasource, TableProcedure.VIEW, schema); DataCoreUtils.refreshTables(datasource, TableProcedure.PROCEDURE, schema); 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 f4437a9c4..62d24c56a 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 @@ -5,11 +5,15 @@ import com.fr.general.ComparatorUtils; import com.fr.stable.CoreConstants; import com.fr.stable.StringUtils; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; import java.awt.Dimension; import java.awt.Toolkit; +import java.awt.event.InputMethodEvent; +import java.awt.event.InputMethodListener; /** * Number Field. @@ -35,6 +39,11 @@ public class UINumberField extends UITextField { private boolean isContentChanged = false; private boolean fillNegativeNumber = true; + /** + * 输入法输入完成一个字符输入过程的标记。开始输入的时候是true,输入完矫正光标后为false + */ + private boolean isInputMethodOnceInserting = false; + private int insertOffset = 0; public UINumberField() { this(MAX_INTEGERLENGTH_32, MAX_DECIMALLENGTH); @@ -55,6 +64,7 @@ public class UINumberField extends UITextField { this.minValue = minValue; this.maxValue = maxValue; setFieldDocument(); + initFieldListener(); } public void setFieldDocument() { @@ -62,6 +72,31 @@ public class UINumberField extends UITextField { initListener(); } + private void initFieldListener() { + addInputMethodListener(new InputMethodListener() { + @Override + public void inputMethodTextChanged(InputMethodEvent event) { + isInputMethodOnceInserting = true; + } + + @Override + public void caretPositionChanged(InputMethodEvent event) { + } + }); + + addCaretListener(new CaretListener() { + @Override + public void caretUpdate(CaretEvent e) { + if (isInputMethodOnceInserting) { + isInputMethodOnceInserting = false; + setCaretPosition(insertOffset); + } else { + insertOffset = e.getDot(); + } + } + }); + } + public void canFillNegativeNumber(boolean fillNegativeNumber) { this.fillNegativeNumber = fillNegativeNumber; } @@ -186,6 +221,13 @@ public class UINumberField extends UITextField { super.insertString(offset, s, a); } + public void remove(int offs, int len) throws BadLocationException { + if (isInputMethodOnceInserting) { + return; + } + super.remove(offs, len); + } + // kunsnat: 这种限制输入 有个不好的地方, 比如删除时: 10.1 最大值限定100, 那么就删除中间的小数点之后变为101, 超出了100. // 但是直接限制不能删除中间类似小数点, 那么也可能遇到: 最小值10 , 从100变化到其中的19, 就很难.. private boolean notChange(String strNew) { diff --git a/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java b/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java index 0dcfe4c21..9f948e7a1 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java @@ -217,18 +217,36 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse int lineStyle = currentLineCombo.getSelectedLineStyle(); Color lineColor = currentLineColorPane.getSelectObject(); CellBorderStyle cellBorderStyle = new CellBorderStyle(); - cellBorderStyle.setTopColor(lineColor); + if (topToggleButton.isSelected()) { + cellBorderStyle.setTopColor(lineColor); + } cellBorderStyle.setTopStyle(topToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); - cellBorderStyle.setBottomColor(lineColor); + + if (bottomToggleButton.isSelected()) { + cellBorderStyle.setBottomColor(lineColor); + } cellBorderStyle.setBottomStyle(bottomToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); - cellBorderStyle.setLeftColor(lineColor); + + if (leftToggleButton.isSelected()) { + cellBorderStyle.setLeftColor(lineColor); + } cellBorderStyle.setLeftStyle(leftToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); - cellBorderStyle.setRightColor(lineColor); + + if (rightToggleButton.isSelected()) { + cellBorderStyle.setRightColor(lineColor); + } cellBorderStyle.setRightStyle(rightToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); - cellBorderStyle.setVerticalColor(lineColor); + + if (verticalToggleButton.isSelected()) { + cellBorderStyle.setVerticalColor(lineColor); + } cellBorderStyle.setVerticalStyle(verticalToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); - cellBorderStyle.setHorizontalColor(lineColor); + + if (horizontalToggleButton.isSelected()) { + cellBorderStyle.setHorizontalColor(lineColor); + } cellBorderStyle.setHorizontalStyle(horizontalToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE); + if (leftToggleButton.isSelected() && bottomToggleButton.isSelected() && rightToggleButton.isSelected() && topToggleButton.isSelected()) { outerToggleButton.setSelected(true); } else { diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java index dbaaf4c6f..8bbedf0be 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java @@ -624,6 +624,10 @@ public class SyntaxScheme implements Cloneable, TokenTypes { SyntaxSchemeLoader parser = null; try { XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + reader.setFeature("http://xml.org/sax/features/external-general-entities", false); + reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); parser = new SyntaxSchemeLoader(baseFont); parser.baseFont = baseFont; reader.setContentHandler(parser); diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java index 3b422f574..896a5eec4 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java @@ -22,6 +22,7 @@ import java.lang.reflect.Field; import javax.swing.UIManager; import javax.swing.plaf.ColorUIResource; import javax.swing.text.StyleContext; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.SAXParser; @@ -493,6 +494,8 @@ public class Theme { StreamResult result = new StreamResult(new PrintWriter( new UnicodeWriter(bout, "UTF-8"))); TransformerFactory transFac = TransformerFactory.newInstance(); + transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); Transformer transformer = transFac.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); @@ -580,8 +583,12 @@ public class Theme { public static void load(Theme theme, InputStream in) throws IOException { SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setValidating(true); try { + spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + spf.setFeature("http://xml.org/sax/features/external-general-entities", false); + spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + spf.setValidating(true); SAXParser parser = spf.newSAXParser(); XMLReader reader = parser.getXMLReader(); XmlHandler handler = new XmlHandler(); diff --git a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java index 8a0ba741c..2558eafe0 100644 --- a/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java +++ b/designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java @@ -14,6 +14,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import javax.xml.XMLConstants; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; @@ -94,6 +95,11 @@ public class Macro { DocumentBuilder db = null; Document doc = null; try { + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + dbf.setXIncludeAware(false); db = dbf.newDocumentBuilder(); //InputSource is = new InputSource(new FileReader(file)); InputSource is = new InputSource(new UnicodeReader( @@ -374,6 +380,8 @@ public class Macro { StreamResult result = new StreamResult(new File(fileName)); DOMSource source = new DOMSource(doc); TransformerFactory transFac = TransformerFactory.newInstance(); + transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); Transformer transformer = transFac.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.ENCODING, FILE_ENCODING); diff --git a/designer-base/src/main/java/com/fr/design/i18n/DesignSizeI18nManager.java b/designer-base/src/main/java/com/fr/design/i18n/DesignSizeI18nManager.java new file mode 100644 index 000000000..1dd2306b8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/i18n/DesignSizeI18nManager.java @@ -0,0 +1,57 @@ +package com.fr.design.i18n; + +import com.fr.design.dialog.BasicDialog; +import com.fr.general.GeneralContext; +import com.fr.locale.LocaleManager; +import com.fr.locale.impl.FineLocaleManager; + +import java.awt.Dimension; +import java.util.Map; + +/** + * Created by kerry on 2/23/21 + */ +public class DesignSizeI18nManager { + private static final String I18N_DIMENSION_PATH = "com/fr/design/i18n/dimension"; + private static final String DIMENSION_REGEX = "^[1-9]\\d*\\*[1-9]\\d*$"; + private static final String SEPARATOR_REGEX = "\\*"; + private static final int WIDTH_INDEX = 0; + private static final int HEIGHT_INDEX = 1; + private static final int SPLIT_LENGTH = 2; + + private static DesignSizeI18nManager instance = new DesignSizeI18nManager(); + + public static DesignSizeI18nManager getInstance() { + return instance; + } + + private LocaleManager localeManager = FineLocaleManager.create(); + + private DesignSizeI18nManager() { + localeManager.addResource(I18N_DIMENSION_PATH); + } + + public Dimension i18nDimension(String key) { + if (!containKey(key)) { + return BasicDialog.DEFAULT; + } + String dimension = localeManager.getLocalBundle(GeneralContext.getLocale()).getText(localeManager, key); + return parseDimensionFromText(dimension); + } + + private boolean containKey(String key) { + Map localeKV = localeManager.getLocalBundle(GeneralContext.getLocale()).getKV(localeManager); + return localeKV != null && localeKV.containsKey(key); + } + + private Dimension parseDimensionFromText(String dimensionText) { + if (!dimensionText.matches(DIMENSION_REGEX)) { + return BasicDialog.DEFAULT; + } + String[] arr = dimensionText.split(SEPARATOR_REGEX); + if (arr.length < SPLIT_LENGTH) { + return BasicDialog.DEFAULT; + } + return new Dimension(Integer.parseInt(arr[WIDTH_INDEX]), Integer.parseInt(arr[HEIGHT_INDEX])); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java index d2771cd49..fb8f9a2da 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java @@ -598,8 +598,9 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt }); // 重名提示 warnLabel = new UILabel(); - warnLabel.setPreferredSize(new Dimension(300, 30)); + warnLabel.setPreferredSize(new Dimension(300, 50)); warnLabel.setHorizontalAlignment(SwingConstants.LEFT); + warnLabel.setVerticalAlignment(SwingConstants.TOP); warnLabel.setForeground(Color.RED); warnLabel.setVisible(false); @@ -609,7 +610,6 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt // 确认按钮 confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); - confirmButton.setPreferredSize(new Dimension(60, 25)); confirmButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -619,7 +619,6 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt // 取消按钮 UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); - cancelButton.setPreferredSize(new Dimension(60, 25)); cancelButton.addActionListener(new ActionListener() { @@ -629,25 +628,26 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } }); - JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15)); - bottomPanel.add(confirmButton); - bottomPanel.add(cancelButton); + + JPanel buttonsPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0)); + buttonsPane.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 10)); + buttonsPane.add(confirmButton); + buttonsPane.add(cancelButton); this.add( TableLayoutHelper.createTableLayoutPane( new Component[][]{ new Component[]{topPanel}, new Component[]{midPanel}, - new Component[]{bottomPanel} + new Component[]{buttonsPane} }, - new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, + new double[]{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED}, new double[]{TableLayout.FILL} ), BorderLayout.CENTER); - this.setSize(340, 180); + this.setSize(340, 200); this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Rename")); this.setResizable(false); this.setAlwaysOnTop(true); @@ -760,7 +760,6 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt ); newNameLabel.setHorizontalAlignment(SwingConstants.RIGHT); newNameLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); - newNameLabel.setPreferredSize(new Dimension(118, 15)); // 文件名输入框 nameField = new UITextField(); @@ -804,8 +803,9 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt }); // 重名提示 warnLabel = new UILabel(); - warnLabel.setPreferredSize(new Dimension(300, 30)); + warnLabel.setPreferredSize(new Dimension(300, 50)); warnLabel.setHorizontalAlignment(SwingConstants.LEFT); + warnLabel.setVerticalAlignment(SwingConstants.TOP); warnLabel.setForeground(Color.RED); warnLabel.setVisible(false); @@ -836,8 +836,8 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } }); - JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15)); + JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0)); + bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 10)); bottomPanel.add(confirmButton); bottomPanel.add(cancelButton); @@ -848,13 +848,13 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt new Component[]{midPanel}, new Component[]{bottomPanel} }, - new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, + new double[]{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED}, new double[]{TableLayout.FILL} ), BorderLayout.CENTER); - this.setSize(380, 180); + this.setSize(380, 200); this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Mkdir")); this.setResizable(false); this.setAlwaysOnTop(true); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java index d1abb908b..aca9bcc36 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java @@ -9,17 +9,7 @@ import com.fr.design.DesignState; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; -import com.fr.design.actions.community.BBSAction; -import com.fr.design.actions.community.BugAction; -import com.fr.design.actions.community.BugNeedAction; -import com.fr.design.actions.community.CenterAction; -import com.fr.design.actions.community.FacebookFansAction; -import com.fr.design.actions.community.NeedAction; -import com.fr.design.actions.community.QuestionAction; -import com.fr.design.actions.community.SignAction; -import com.fr.design.actions.community.TechSolutionAction; -import com.fr.design.actions.community.TechSupportAction; -import com.fr.design.actions.community.VideoAction; +import com.fr.design.actions.community.*; import com.fr.design.actions.file.CloseCurrentTemplateAction; import com.fr.design.actions.file.ExitDesignerAction; import com.fr.design.actions.file.OpenRecentReportMenuDef; @@ -41,6 +31,7 @@ import com.fr.design.actions.server.PluginManagerAction; import com.fr.design.file.NewTemplatePane; import com.fr.design.fun.MenuHandler; import com.fr.design.fun.OemProcessor; +import com.fr.design.fun.PluginManagerProvider; import com.fr.design.fun.TableDataPaneProcessor; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; @@ -72,6 +63,7 @@ import com.fr.plugin.observer.PluginEventListener; import com.fr.plugin.observer.PluginEventType; import com.fr.stable.ArrayUtils; import com.fr.stable.StringUtils; +import com.fr.stable.bridge.ObjectHolder; import com.fr.stable.os.support.OSBasedAction; import com.fr.stable.os.support.OSSupportCenter; import com.fr.start.OemHandler; @@ -487,11 +479,7 @@ public abstract class ToolBarMenuDock { } if (!DesignerMode.isAuthorityEditing()) { - if (shouldShowPlugin()) { - menuDef.addShortCut( - new PluginManagerAction() - ); - } + addPluginManagerAction(menuDef); menuDef.addShortCut( new FunctionManagerAction(), new GlobalParameterAction() @@ -502,6 +490,23 @@ public abstract class ToolBarMenuDock { return menuDef; } + private void addPluginManagerAction(MenuDef menuDef) { + Set providers = ExtraDesignClassManager.getInstance().getArray(PluginManagerProvider.MARK_STRING); + if (providers != null) { + for (PluginManagerProvider provider : providers) { + if (provider.selector().accept(new ObjectHolder())) { + menuDef.addShortCut(provider.pluginManagerAction()); + return; + } + } + } + if (shouldShowPlugin()) { + menuDef.addShortCut( + new PluginManagerAction() + ); + } + } + private ShortCut createGlobalTDAction() { TableDataPaneProcessor processor = ExtraDesignClassManager.getInstance().getSingle(TableDataPaneProcessor.XML_TAG); return processor == null ? new GlobalTableDataAction() : processor.createServerTDAction(); @@ -610,7 +615,7 @@ public abstract class ToolBarMenuDock { }, SupportLocaleImpl.TECH_SUPPORT_COMMUNITY); shortCuts.add(SeparatorDef.DEFAULT); - + shortCuts.add(new WorkOrderCenterAction()); shortCuts.add(new CenterAction()); shortCuts.add(new SignAction()); LocaleCenter.buildAction(new LocaleAction() { diff --git a/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java b/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java index 7e74e7651..990e73ee9 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java @@ -19,11 +19,11 @@ public class PMDialogAction implements OSBasedAction { private static String PLUGIN_MANAGER_ROUTE = "#management/plugin"; @Override public void execute(Object... objects) { - if(Arch.getArch() == Arch.ARM || OperatingSystem.isLinux()){ + if(Arch.getArch() == Arch.ARM || OperatingSystem.isLinux() || SupportOSImpl.MACOS_WEB_PLUGIN_MANAGEMENT.support()){ DesignUtils.visitEnvServerByParameters( PLUGIN_MANAGER_ROUTE,null,null); return; } - if (ServerPreferenceConfig.getInstance().isUseOptimizedUPM() && JdkVersion.LE_8.support()) { + if (ServerPreferenceConfig.getInstance().isUseOptimizedUPM() || SupportOSImpl.MACOS_NEW_PLUGIN_MANAGEMENT.support()) { UpmFinder.showUPMDialog(); } else { WebViewDlgHelper.createPluginDialog(); diff --git a/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java b/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java index 88fe2a275..a25d2606a 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java @@ -1,6 +1,7 @@ package com.fr.design.os.impl; import com.fr.base.FRContext; +import com.fr.design.jdk.JdkVersion; import com.fr.general.CloudCenter; import com.fr.general.GeneralContext; import com.fr.json.JSON; @@ -124,6 +125,33 @@ public enum SupportOSImpl implements SupportOS { public boolean support() { return OperatingSystem.isWindows(); } + }, + + MACOS_NEW_PLUGIN_MANAGEMENT { + @Override + public boolean support() { + return JdkVersion.GE_9.support() && OperatingSystem.isMacos() && getMacOsVersion() < BIG_SUR_VERSION_NUMBER; + } + }, + + + MACOS_WEB_PLUGIN_MANAGEMENT { + @Override + public boolean support() { + return JdkVersion.GE_9.support() && OperatingSystem.isMacos() && getMacOsVersion() >= BIG_SUR_VERSION_NUMBER; + } + }; + + private static final int BIG_SUR_VERSION_NUMBER = 16; + + protected int getMacOsVersion() { + String version = System.getProperty("os.version"); + String[] versionSlice = version.split("\\."); + try { + return Integer.parseInt(versionSlice[1]); + } catch (Exception ignored) { + return 0; + } } } diff --git a/designer-base/src/main/java/com/fr/design/plugin/DesignerPluginContext.java b/designer-base/src/main/java/com/fr/design/plugin/DesignerPluginContext.java new file mode 100644 index 000000000..404477ff4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/plugin/DesignerPluginContext.java @@ -0,0 +1,21 @@ +package com.fr.design.plugin; + +import com.fr.design.dialog.UIDialog; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/3/8 + */ +public class DesignerPluginContext { + + private static UIDialog DIALOG; + + public static UIDialog getPluginDialog() { + return DIALOG; + } + + public static void setPluginDialog(UIDialog pluginDialog) { + DesignerPluginContext.DIALOG = pluginDialog; + } +} diff --git a/designer-base/src/main/java/com/fr/design/ui/Assistant.java b/designer-base/src/main/java/com/fr/design/ui/Assistant.java index 1c4d7e14a..7bbc17a80 100644 --- a/designer-base/src/main/java/com/fr/design/ui/Assistant.java +++ b/designer-base/src/main/java/com/fr/design/ui/Assistant.java @@ -3,6 +3,7 @@ package com.fr.design.ui; import com.fr.stable.StringUtils; import com.teamdev.jxbrowser.chromium.Browser; import com.teamdev.jxbrowser.chromium.BrowserContext; +import com.teamdev.jxbrowser.chromium.BrowserPreferences; import com.teamdev.jxbrowser.chromium.ProtocolService; import com.teamdev.jxbrowser.chromium.URLResponse; @@ -12,6 +13,8 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; +import java.util.List; /** * @author richie @@ -20,6 +23,14 @@ import java.nio.file.Path; */ public class Assistant { + public static void addChromiumSwitches(String... switches) { + + List list = BrowserPreferences.getChromiumSwitches(); + Collections.addAll(list, switches); + + BrowserPreferences.setChromiumSwitches((list.toArray(new String[0]))); + } + public static URLResponse inputStream2Response(InputStream inputStream, String filePath) throws Exception { URLResponse response = new URLResponse(); DataInputStream stream = new DataInputStream(inputStream); diff --git a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java index 4a92d3715..745c56ea7 100644 --- a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java +++ b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java @@ -8,18 +8,18 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.web.struct.AssembleComponent; import com.teamdev.jxbrowser.chromium.Browser; -import com.teamdev.jxbrowser.chromium.BrowserPreferences; import com.teamdev.jxbrowser.chromium.JSValue; -import com.teamdev.jxbrowser.chromium.events.FinishLoadingEvent; -import com.teamdev.jxbrowser.chromium.events.LoadAdapter; import com.teamdev.jxbrowser.chromium.events.LoadListener; import com.teamdev.jxbrowser.chromium.events.ScriptContextAdapter; import com.teamdev.jxbrowser.chromium.events.ScriptContextEvent; import com.teamdev.jxbrowser.chromium.events.ScriptContextListener; import com.teamdev.jxbrowser.chromium.swing.BrowserView; -import javax.swing.*; -import java.awt.*; +import javax.swing.JDialog; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Map; @@ -44,7 +44,7 @@ public class ModernUIPane extends BasicPane { private void initialize() { if (browser == null) { setLayout(new BorderLayout()); - BrowserPreferences.setChromiumSwitches("--disable-google-traffic"); + Assistant.addChromiumSwitches("--disable-google-traffic"); if (DesignerEnvManager.getEnvManager().isOpenDebug()) { UIToolbar toolbar = new UIToolbar(); add(toolbar, BorderLayout.NORTH); @@ -75,7 +75,7 @@ public class ModernUIPane extends BasicPane { SwingUtilities.getWindowAncestor(ModernUIPane.this).setVisible(false); } }); - BrowserPreferences.setChromiumSwitches("--remote-debugging-port=9222"); + Assistant.addChromiumSwitches("--remote-debugging-port=9222"); initializeBrowser(); add(new BrowserView(browser), BorderLayout.CENTER); } else { diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java b/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java index 4424d9d74..36e558d17 100644 --- a/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java +++ b/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java @@ -6,6 +6,7 @@ import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.UIDialog; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.plugin.DesignerPluginContext; import com.fr.design.update.ui.dialog.UpdateMainDialog; import com.fr.event.Event; import com.fr.event.EventDispatcher; @@ -114,6 +115,7 @@ public class UpmFinder { dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); dialog.setVisible(false); dialog = null; + DesignerPluginContext.setPluginDialog(null); } } } diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java b/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java index d5f132e98..f0c6c6d49 100644 --- a/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java +++ b/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java @@ -2,6 +2,7 @@ package com.fr.design.upm; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.UIDialog; +import com.fr.design.plugin.DesignerPluginContext; import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.*; @@ -25,6 +26,7 @@ public class UpmShowDialog extends UIDialog { setSize(DEFAULT_SHOP); GUICoreUtils.centerWindow(this); setResizable(false); + DesignerPluginContext.setPluginDialog(this); } @Override diff --git a/designer-base/src/main/java/com/fr/design/utils/gui/GUICoreUtils.java b/designer-base/src/main/java/com/fr/design/utils/gui/GUICoreUtils.java index d55382c49..a89e367d6 100644 --- a/designer-base/src/main/java/com/fr/design/utils/gui/GUICoreUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/gui/GUICoreUtils.java @@ -38,6 +38,7 @@ import com.fr.stable.Constants; import com.fr.stable.OperatingSystem; import com.fr.stable.StringUtils; +import java.awt.Container; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; @@ -318,7 +319,14 @@ public final class GUICoreUtils { public static void centerWindow(Window win) { // Toolkit.getDefaultToolkit().getScreenSize()在有多个显示器也只能获取到主屏的大小 // getGraphicsConfiguration().getBounds()能获取多个屏时 设计器主体界面所在屏的大小和对应的坐标 - Rectangle rectangle = win.getGraphicsConfiguration().getBounds(); + Rectangle rectangle; + Container parent = win.getParent(); + boolean displayByDesignerFrame = (DesignerContext.getDesignerFrame() != null && parent == null) || (parent != null && !parent.isVisible() && DesignerContext.getDesignerFrame() != null); + if (displayByDesignerFrame) { + rectangle = DesignerContext.getDesignerFrame().getGraphicsConfiguration().getBounds(); + } else { + rectangle = win.getGraphicsConfiguration().getBounds(); + } centerWindow(win, rectangle); } diff --git a/designer-base/src/main/java/com/fr/design/utils/gui/GUIPaintUtils.java b/designer-base/src/main/java/com/fr/design/utils/gui/GUIPaintUtils.java index 30984197c..c4efc0282 100644 --- a/designer-base/src/main/java/com/fr/design/utils/gui/GUIPaintUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/gui/GUIPaintUtils.java @@ -1,6 +1,5 @@ package com.fr.design.utils.gui; -import com.fr.base.BaseUtils; import com.fr.base.vcs.DesignerMode; import com.fr.design.constants.UIConstants; import com.fr.stable.Constants; @@ -40,7 +39,10 @@ public class GUIPaintUtils { g2d.drawLine(x, y, x, height - 1); g2d.drawLine(x, height - 1, x + 3, height - 1); } else { - g2d.drawRoundRect(x, y, width - 1, height - 1, UIConstants.ARC, UIConstants.ARC); + double offsetX = Math.min(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform().getScaleX() - 1, 0.5d); + double offsetY = Math.min(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform().getScaleY() - 1, 0.5d); + Shape shape = new RoundRectangle2D.Double(x + offsetX, y + offsetY, width - 1d, height - 1d, UIConstants.ARC, UIConstants.ARC); + g2d.draw(shape); } g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } else { diff --git a/designer-base/src/main/java/com/fr/env/PluginErrorRemindDialog.java b/designer-base/src/main/java/com/fr/env/PluginErrorRemindDialog.java index 42dae0fa1..1558d72e9 100644 --- a/designer-base/src/main/java/com/fr/env/PluginErrorRemindDialog.java +++ b/designer-base/src/main/java/com/fr/env/PluginErrorRemindDialog.java @@ -1,12 +1,16 @@ package com.fr.env; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.actions.UpdateAction; import com.fr.design.actions.server.PluginManagerAction; +import com.fr.design.fun.PluginManagerProvider; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.FRFont; import com.fr.general.IOUtils; +import com.fr.stable.bridge.ObjectHolder; import javax.swing.BorderFactory; import javax.swing.Icon; @@ -23,6 +27,7 @@ import java.awt.Frame; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Set; /** * 插件启动失败提示窗 @@ -77,7 +82,7 @@ public class PluginErrorRemindDialog extends JDialog implements ActionListener { UIButton okButton = new UIButton(Toolkit.i18nText("Fine-Design_Plugin_Error_Remind_Deal_With")); cancelButton.addActionListener(this); - okButton.addActionListener(new PluginManagerActionAdapter(this)); + okButton.addActionListener(new PluginManagerHandleAction(this)); // 按钮 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); @@ -102,18 +107,34 @@ public class PluginErrorRemindDialog extends JDialog implements ActionListener { this.dispose(); } - private static class PluginManagerActionAdapter extends PluginManagerAction { + private static class PluginManagerHandleAction extends UpdateAction { private JDialog jDialog; + private UpdateAction pluginManagerAction; - public PluginManagerActionAdapter(JDialog jDialog) { + public PluginManagerHandleAction(JDialog jDialog) { this.jDialog = jDialog; + initPluginManagerAction(); + } + + private void initPluginManagerAction() { + Set providers = ExtraDesignClassManager.getInstance().getArray(PluginManagerProvider.MARK_STRING); + if (providers != null) { + for (PluginManagerProvider provider : providers) { + if (provider.selector().accept(new ObjectHolder())) { + this.pluginManagerAction = provider.pluginManagerAction(); + } + } + } + if (this.pluginManagerAction == null) { + this.pluginManagerAction = new PluginManagerAction(); + } } @Override public void actionPerformed(ActionEvent e) { this.jDialog.dispose(); - super.actionPerformed(e); + this.pluginManagerAction.actionPerformed(e); } } diff --git a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java index 36b86cb89..5fa8173d4 100644 --- a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java +++ b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java @@ -12,6 +12,7 @@ import com.fr.third.springframework.web.context.support.AnnotationConfigWebAppli import com.fr.workspace.WorkContext; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; +import org.apache.catalina.Wrapper; import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.webresources.StandardRoot; @@ -73,6 +74,10 @@ public class FineEmbedServerActivator extends Activator { String contextPath = "/" + ProductConstants.getAppFolderName(); final Context context = tomcat.addContext(contextPath, docBase); context.setResources(new StandardRoot(context)); + Wrapper servlet = Tomcat.addServlet(context, "DruidStatView", "com.fr.third.alibaba.druid.support.http.StatViewServlet"); + context.addServletMappingDecoded("/druid/*", "DruidStatView"); + servlet.setLoadOnStartup(1); + servlet.setOverridable(true); Tomcat.initWebappDefaults(context); //覆盖tomcat的WebAppClassLoader context.setLoader(new FRTomcatLoader()); diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties new file mode 100644 index 000000000..1cafa6d35 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties @@ -0,0 +1 @@ +com.fr.design.report.ReportColumnsPane=800*600 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties new file mode 100644 index 000000000..e69de29bb diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties new file mode 100644 index 000000000..e69de29bb diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties new file mode 100644 index 000000000..69c2fcef4 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties @@ -0,0 +1 @@ +# \u9ED8\u8BA4\u4E3A\u7C7B\u7684\u5168\u9650\u5B9A\u540D\uFF08\u53EF\u81EA\u5B9A\u4E49key\uFF09= width * height diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties new file mode 100644 index 000000000..e69de29bb diff --git a/designer-base/src/main/resources/com/fr/design/images/bbs/workOrderCenter.png b/designer-base/src/main/resources/com/fr/design/images/bbs/workOrderCenter.png new file mode 100644 index 000000000..6374a0e8d Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/bbs/workOrderCenter.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/bbs/workOrderCenter_normal.svg b/designer-base/src/main/resources/com/fr/design/images/bbs/workOrderCenter_normal.svg new file mode 100644 index 000000000..da3a6a3a9 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/bbs/workOrderCenter_normal.svg @@ -0,0 +1,7 @@ + + + icon/社区/工单中心_normal + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/control/edit_disable.svg b/designer-base/src/main/resources/com/fr/design/images/control/edit_disabled.svg similarity index 100% rename from designer-base/src/main/resources/com/fr/design/images/control/edit_disable.svg rename to designer-base/src/main/resources/com/fr/design/images/control/edit_disabled.svg diff --git a/designer-base/src/main/resources/com/fr/design/images/control/remove_disable.svg b/designer-base/src/main/resources/com/fr/design/images/control/remove_disabled.svg similarity index 100% rename from designer-base/src/main/resources/com/fr/design/images/control/remove_disable.svg rename to designer-base/src/main/resources/com/fr/design/images/control/remove_disabled.svg diff --git a/designer-base/src/main/resources/com/fr/design/images/m_file/preview_disable.svg b/designer-base/src/main/resources/com/fr/design/images/m_file/preview_disabled.svg similarity index 100% rename from designer-base/src/main/resources/com/fr/design/images/m_file/preview_disable.svg rename to designer-base/src/main/resources/com/fr/design/images/m_file/preview_disabled.svg diff --git a/designer-base/src/test/java/com/fr/design/i18n/DesignSizeI18nManagerTest.java b/designer-base/src/test/java/com/fr/design/i18n/DesignSizeI18nManagerTest.java new file mode 100644 index 000000000..da9789526 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/i18n/DesignSizeI18nManagerTest.java @@ -0,0 +1,80 @@ +package com.fr.design.i18n; + +import com.fr.general.GeneralContext; +import com.fr.invoke.Reflect; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.awt.Dimension; +import java.util.Locale; + +/** + * Created by kerry on 2/24/21 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(GeneralContext.class) +public class DesignSizeI18nManagerTest { + @Test + public void testI18nDimension() { + Dimension dimension = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.ReportColumnsPane"); + validDimension(dimension, 660, 600); + + PowerMock.mockStatic(GeneralContext.class); + EasyMock.expect(GeneralContext.getLocale()).andReturn(Locale.ENGLISH).times(3); + PowerMock.replayAll(); + + dimension = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.ReportColumnsPane"); + validDimension(dimension, 800, 600); + } + + @Test + public void testContainKey() { + PowerMock.mockStatic(GeneralContext.class); + EasyMock.expect(GeneralContext.getLocale()).andReturn(Locale.ENGLISH).times(3); + PowerMock.replayAll(); + + boolean result = Reflect.on(DesignSizeI18nManager.getInstance()).call("containKey", "testKey").get(); + Assert.assertFalse(result); + + result = Reflect.on(DesignSizeI18nManager.getInstance()).call("containKey", "com.fr.design.report.ReportColumnsPane").get(); + Assert.assertTrue(result); + + } + + @Test + public void testParseDimensionFromText() { + String dimensionText = "800*600"; + Dimension result = Reflect.on(DesignSizeI18nManager.getInstance()).call("parseDimensionFromText", dimensionText).get(); + validDimension(result, 800, 600); + + dimensionText = "800* 600"; + result = Reflect.on(DesignSizeI18nManager.getInstance()).call("parseDimensionFromText", dimensionText).get(); + validDimension(result, 660, 600); + + dimensionText = " 800*600"; + result = Reflect.on(DesignSizeI18nManager.getInstance()).call("parseDimensionFromText", dimensionText).get(); + validDimension(result, 660, 600); + + dimensionText = "800*600s"; + result = Reflect.on(DesignSizeI18nManager.getInstance()).call("parseDimensionFromText", dimensionText).get(); + validDimension(result, 660, 600); + + dimensionText = "800s*600"; + result = Reflect.on(DesignSizeI18nManager.getInstance()).call("parseDimensionFromText", dimensionText).get(); + validDimension(result, 660, 600); + + dimensionText = "800-600"; + result = Reflect.on(DesignSizeI18nManager.getInstance()).call("parseDimensionFromText", dimensionText).get(); + validDimension(result, 660, 600); + } + + private void validDimension(Dimension dimension, int width, int height) { + Assert.assertEquals(width, dimension.width); + Assert.assertEquals(height, dimension.height); + } +} diff --git a/designer-base/src/test/java/com/fr/design/os/impl/SupportOSImplTest.java b/designer-base/src/test/java/com/fr/design/os/impl/SupportOSImplTest.java index 188753797..ee0804d36 100644 --- a/designer-base/src/test/java/com/fr/design/os/impl/SupportOSImplTest.java +++ b/designer-base/src/test/java/com/fr/design/os/impl/SupportOSImplTest.java @@ -6,6 +6,7 @@ import org.junit.Assert; import org.junit.Test; import java.util.Locale; +import org.powermock.reflect.Whitebox; /** * @author hades @@ -21,4 +22,13 @@ public class SupportOSImplTest extends TestCase { Assert.assertFalse(SupportOSImpl.AUTOPUSHUPDATE.support()); } + @Test + public void testGetMacOsVersion() throws Exception { + String backUp = System.getProperty("os.version"); + System.setProperty("os.version", "10.16"); + int number = Whitebox.invokeMethod(SupportOSImpl.MACOS_WEB_PLUGIN_MANAGEMENT, "getMacOsVersion"); + Assert.assertEquals(16, number); + System.setProperty("os.version", backUp); + } + } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java b/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java index 406b89610..e94c79818 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java @@ -221,12 +221,9 @@ public class GisLayerPane extends JPanel implements UIObserver { /* mapPlot.getGisLayer().setGisLayerType(GISLayerType.AUTO); mapPlot.getGisLayer().setLayerName(GISLayerType.getLocString(GISLayerType.AUTO));*/ - GaoDeGisType gaoDeGisType= mapPlot.getDefaultGisLayerType(); - - mapPlot.getGisLayer().setGisLayerType(GISLayerType.GAO_DE_API); - mapPlot.getGisLayer().setLayerName(gaoDeGisType.getTypeName()); - mapPlot.getGisLayer().setGaoDeGisType(gaoDeGisType); - populate(mapPlot.getGisLayer()); + GisLayer defaultGisLayer = mapPlot.getDefaultGisLayer(); + mapPlot.setGisLayer(defaultGisLayer); + populate(defaultGisLayer); } public void populate(GisLayer layer) { diff --git a/designer-chart/src/main/resources/com/fr/design/editor/script/editor.js b/designer-chart/src/main/resources/com/fr/design/editor/script/editor.js index 3786e47ef..ec4de690d 100644 --- a/designer-chart/src/main/resources/com/fr/design/editor/script/editor.js +++ b/designer-chart/src/main/resources/com/fr/design/editor/script/editor.js @@ -74,10 +74,10 @@ }], layouts: [{ type: "bi.left", - rgap: 5 + rgap: 2 }], value: this.model.mode, - width: 125 + width: 170 }, this._getToolBar()], height: 24 }, { diff --git a/designer-chart/src/main/resources/com/fr/design/editor/script/editor.model.js b/designer-chart/src/main/resources/com/fr/design/editor/script/editor.model.js index e1ee49645..06f7bf2bf 100644 --- a/designer-chart/src/main/resources/com/fr/design/editor/script/editor.model.js +++ b/designer-chart/src/main/resources/com/fr/design/editor/script/editor.model.js @@ -18,7 +18,7 @@ return [{ type: "bi.single_select_radio_item", text: BI.i18nText("BI-Basic_Auto"), - width: 50, + width: 70, logic: { dynamic: true }, @@ -27,7 +27,7 @@ }, { type: "bi.single_select_radio_item", text: BI.i18nText("BI-Basic_Custom"), - width: 60, + width: 80, logic: { dynamic: true }, diff --git a/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/drillmap.png b/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/drillmap.png index 6459771db..a9cf86bdb 100644 Binary files a/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/drillmap.png and b/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/drillmap.png differ diff --git a/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/heatmap.png b/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/heatmap.png index 6e6c2146c..538473be1 100644 Binary files a/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/heatmap.png and b/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/heatmap.png differ diff --git a/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/map.png b/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/map.png index 6459771db..649e1054f 100644 Binary files a/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/map.png and b/designer-chart/src/main/resources/com/fr/design/images/form/toolbar/map.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/area-map.png b/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/area-map.png index 35afc7781..f1be7c1e6 100644 Binary files a/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/area-map.png and b/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/area-map.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/point-map.png b/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/point-map.png index f6659740d..30a32e34e 100644 Binary files a/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/point-map.png and b/designer-chart/src/main/resources/com/fr/van/chart/drillmap/images/point-map.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/heatmap/images/heatmap.png b/designer-chart/src/main/resources/com/fr/van/chart/heatmap/images/heatmap.png old mode 100644 new mode 100755 index 6f28e1c25..9748b2e8d Binary files a/designer-chart/src/main/resources/com/fr/van/chart/heatmap/images/heatmap.png and b/designer-chart/src/main/resources/com/fr/van/chart/heatmap/images/heatmap.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/map/images/area-map.png b/designer-chart/src/main/resources/com/fr/van/chart/map/images/area-map.png old mode 100644 new mode 100755 index ebdcf5567..1eb12abaf Binary files a/designer-chart/src/main/resources/com/fr/van/chart/map/images/area-map.png and b/designer-chart/src/main/resources/com/fr/van/chart/map/images/area-map.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/map/images/custom-map.png b/designer-chart/src/main/resources/com/fr/van/chart/map/images/custom-map.png old mode 100644 new mode 100755 index 557b7966d..640b6c80e Binary files a/designer-chart/src/main/resources/com/fr/van/chart/map/images/custom-map.png and b/designer-chart/src/main/resources/com/fr/van/chart/map/images/custom-map.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/map/images/line-map.png b/designer-chart/src/main/resources/com/fr/van/chart/map/images/line-map.png old mode 100644 new mode 100755 index 1734b8ac5..8fcbd071d Binary files a/designer-chart/src/main/resources/com/fr/van/chart/map/images/line-map.png and b/designer-chart/src/main/resources/com/fr/van/chart/map/images/line-map.png differ diff --git a/designer-chart/src/main/resources/com/fr/van/chart/map/images/point-map.png b/designer-chart/src/main/resources/com/fr/van/chart/map/images/point-map.png old mode 100644 new mode 100755 index 9c77308d2..b3f27a072 Binary files a/designer-chart/src/main/resources/com/fr/van/chart/map/images/point-map.png and b/designer-chart/src/main/resources/com/fr/van/chart/map/images/point-map.png differ diff --git a/designer-form/src/main/java/com/fr/design/form/parameter/FormParaDesigner.java b/designer-form/src/main/java/com/fr/design/form/parameter/FormParaDesigner.java index 8d13f3ab4..0ac74e5b5 100644 --- a/designer-form/src/main/java/com/fr/design/form/parameter/FormParaDesigner.java +++ b/designer-form/src/main/java/com/fr/design/form/parameter/FormParaDesigner.java @@ -474,7 +474,7 @@ public class FormParaDesigner extends FormDesigner implements ParameterDesignerP */ @Override public void updateUI() { - setUI(new FormDesignerUI(){ + setUI(new FormDesignerUI() { @Override protected Rectangle getFitPaintBounds(Component component, Component parent) { return new Rectangle(0, 0, parent.getSize().width, parent.getSize().height); @@ -694,8 +694,8 @@ public class FormParaDesigner extends FormDesigner implements ParameterDesignerP formSubmitButton.setWidgetName("Search"); formSubmitButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Query")); XCreator xCreator = XCreatorUtils.createXCreator(formSubmitButton); - if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * 3 + H_GAP, FIRST_V_LOCATION - + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { + if (this.autoAddComponent(xCreator, H_COMPONENT_GAP * 3 + H_GAP, FIRST_V_LOCATION + + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE))) { currentIndex = ((int) Math.ceil((currentIndex + 1) / (double) NUM_IN_A_LINE)) * NUM_IN_A_LINE; } } @@ -741,7 +741,7 @@ public class FormParaDesigner extends FormDesigner implements ParameterDesignerP } @Override - public boolean checkIfBeyondValidArea(MouseEvent e){ + public boolean checkIfBeyondValidArea(MouseEvent e) { return false; } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/AbstractFRLayoutDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/AbstractFRLayoutDefinePane.java index 0a718ee60..efa2729c2 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/AbstractFRLayoutDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/AbstractFRLayoutDefinePane.java @@ -31,6 +31,8 @@ public abstract class AbstractFRLayoutDefinePane extends for (int i = 0, len = srcLayout.getListenerSize(); i < len; i++) { destLayout.addListener(srcLayout.getListener(i)); } + srcLayout.clearListeners(); + srcLayout.clearMobileWidgetList(); } } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/FRFitLayoutDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/FRFitLayoutDefinePane.java index 4481307bf..e073b2b15 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/FRFitLayoutDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/FRFitLayoutDefinePane.java @@ -207,7 +207,7 @@ public class FRFitLayoutDefinePane extends AbstractFRLayoutDefinePane { /** * */ - public void updateBorder() { - BorderUtils.update(reportPane, ((BorderPane) paneList.get(ONE_INDEX)).update()); + public void updateBorder(Object[] selectionCellBorderObjects) { + BorderUtils.update(reportPane, selectionCellBorderObjects, ((BorderPane) paneList.get(ONE_INDEX)).update()); } /** diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java index f1f916e05..e2d824757 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java @@ -38,10 +38,9 @@ public class StylePane extends UIComboBoxPane