@ -0,0 +1,47 @@ |
|||||||
|
package com.fr.design.data.datapane.connect; |
||||||
|
|
||||||
|
import com.fr.data.impl.JDBCDatabaseConnection; |
||||||
|
|
||||||
|
/** |
||||||
|
* JDBCDefPane和DBCPAttrPane沟通的桥梁 |
||||||
|
* |
||||||
|
*/ |
||||||
|
public class JDBCConnectionDef { |
||||||
|
|
||||||
|
private static volatile JDBCConnectionDef instance; |
||||||
|
|
||||||
|
private String databaseName; |
||||||
|
private JDBCDatabaseConnection connection; |
||||||
|
|
||||||
|
public static JDBCConnectionDef getInstance() { |
||||||
|
if (instance == null) { |
||||||
|
synchronized (JDBCConnectionDef.class) { |
||||||
|
if (instance == null) { |
||||||
|
instance = new JDBCConnectionDef(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return instance; |
||||||
|
} |
||||||
|
|
||||||
|
private JDBCConnectionDef() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public String getDatabaseName() { |
||||||
|
return databaseName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDatabaseName(String databaseName) { |
||||||
|
this.databaseName = databaseName; |
||||||
|
} |
||||||
|
|
||||||
|
public JDBCDatabaseConnection getConnection() { |
||||||
|
return connection; |
||||||
|
} |
||||||
|
|
||||||
|
public void setConnection(String databaseName, JDBCDatabaseConnection connection) { |
||||||
|
this.databaseName = databaseName; |
||||||
|
this.connection = connection; |
||||||
|
} |
||||||
|
} |
@ -1,5 +0,0 @@ |
|||||||
package com.fr.design.file; |
|
||||||
|
|
||||||
public interface Releasable { |
|
||||||
void releaseResources(); |
|
||||||
} |
|
@ -0,0 +1,30 @@ |
|||||||
|
package com.fr.design.gui.frpane; |
||||||
|
|
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 10.0.18 |
||||||
|
* Created by Starryi on 2021/7/3 |
||||||
|
*/ |
||||||
|
public class UIPercentDragPane extends JPanel { |
||||||
|
|
||||||
|
private final UINumberDragPane dragPane = new UINumberDragPane(0, 100, 1); |
||||||
|
|
||||||
|
public UIPercentDragPane() { |
||||||
|
setLayout(new BorderLayout()); |
||||||
|
add(dragPane, BorderLayout.CENTER); |
||||||
|
add(new UILabel(" %"), BorderLayout.EAST); |
||||||
|
} |
||||||
|
|
||||||
|
public void populateBean(double value) { |
||||||
|
dragPane.populateBean(value * 100); |
||||||
|
} |
||||||
|
|
||||||
|
public double updateBean() { |
||||||
|
return dragPane.updateBean() / 100.0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.fr.design.ui.compatible; |
||||||
|
|
||||||
|
import com.fr.design.ui.ModernUIPane; |
||||||
|
import com.teamdev.jxbrowser.browser.callback.InjectJsCallback; |
||||||
|
import com.teamdev.jxbrowser.chromium.events.LoadListener; |
||||||
|
import com.teamdev.jxbrowser.chromium.events.ScriptContextListener; |
||||||
|
|
||||||
|
/** |
||||||
|
* 封装jxbrwoser v6/v7的构建方式的差异 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/6/13 |
||||||
|
*/ |
||||||
|
public interface BuilderDiff<T> { |
||||||
|
|
||||||
|
ModernUIPane.Builder<T> prepareForV6(ScriptContextListener contextListener); |
||||||
|
|
||||||
|
ModernUIPane.Builder<T> prepareForV6(LoadListener loadListener); |
||||||
|
|
||||||
|
ModernUIPane.Builder<T> prepareForV7(InjectJsCallback callback); |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.fr.design.ui.compatible; |
||||||
|
|
||||||
|
import com.fr.design.ui.ModernUIPane; |
||||||
|
import com.fr.stable.os.OperatingSystem; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/6/13 |
||||||
|
*/ |
||||||
|
public class ModernUIPaneFactory { |
||||||
|
|
||||||
|
public static <T> ModernUIPane.Builder<T> modernUIPaneBuilder() { |
||||||
|
if (OperatingSystem.isWindows()) { |
||||||
|
return new NewModernUIPane.Builder<>(); |
||||||
|
} else { |
||||||
|
return new ModernUIPane.Builder<>(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,301 @@ |
|||||||
|
package com.fr.design.ui.compatible; |
||||||
|
|
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.itoolbar.UIToolbar; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.ui.ModernUIConstants; |
||||||
|
import com.fr.design.ui.ModernUIPane; |
||||||
|
import com.fr.design.utils.gui.GUICoreUtils; |
||||||
|
import com.fr.web.struct.AssembleComponent; |
||||||
|
import com.teamdev.jxbrowser.browser.Browser; |
||||||
|
import com.teamdev.jxbrowser.browser.callback.InjectJsCallback; |
||||||
|
import com.teamdev.jxbrowser.chromium.events.LoadListener; |
||||||
|
import com.teamdev.jxbrowser.chromium.events.ScriptContextListener; |
||||||
|
import com.teamdev.jxbrowser.engine.Engine; |
||||||
|
import com.teamdev.jxbrowser.engine.EngineOptions; |
||||||
|
import com.teamdev.jxbrowser.engine.RenderingMode; |
||||||
|
import com.teamdev.jxbrowser.js.JsObject; |
||||||
|
import com.teamdev.jxbrowser.net.Network; |
||||||
|
import com.teamdev.jxbrowser.net.callback.InterceptRequestCallback; |
||||||
|
import com.teamdev.jxbrowser.view.swing.BrowserView; |
||||||
|
|
||||||
|
|
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
import javax.swing.JDialog; |
||||||
|
import javax.swing.SwingUtilities; |
||||||
|
import javax.swing.WindowConstants; |
||||||
|
|
||||||
|
/** |
||||||
|
* 基于v7 jxbrowser实现 |
||||||
|
* |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-04 |
||||||
|
* 用于加载html5的Swing容器,可以在设计选项设置中打开调试窗口,示例可查看:com.fr.design.ui.ModernUIPaneTest |
||||||
|
*/ |
||||||
|
public class NewModernUIPane<T> extends ModernUIPane<T> { |
||||||
|
|
||||||
|
private Browser browser; |
||||||
|
private String namespace = "Pool"; |
||||||
|
private String variable = "data"; |
||||||
|
private String expression = "update()"; |
||||||
|
|
||||||
|
private NewModernUIPane() { |
||||||
|
super(); |
||||||
|
initialize(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initialize() { |
||||||
|
setLayout(new BorderLayout()); |
||||||
|
if (browser == null) { |
||||||
|
if (DesignerEnvManager.getEnvManager().isOpenDebug()) { |
||||||
|
UIToolbar toolbar = new UIToolbar(); |
||||||
|
add(toolbar, BorderLayout.NORTH); |
||||||
|
UIButton openDebugButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Open_Debug_Window")); |
||||||
|
toolbar.add(openDebugButton); |
||||||
|
UIButton reloadButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Reload")); |
||||||
|
toolbar.add(reloadButton); |
||||||
|
UIButton closeButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Close_Window")); |
||||||
|
toolbar.add(closeButton); |
||||||
|
|
||||||
|
openDebugButton.addActionListener(e -> showDebuggerDialog()); |
||||||
|
|
||||||
|
reloadButton.addActionListener(e -> browser.navigation().reloadIgnoringCache()); |
||||||
|
|
||||||
|
closeButton.addActionListener(e -> SwingUtilities.getWindowAncestor( |
||||||
|
NewModernUIPane.this).setVisible(false)); |
||||||
|
initializeBrowser(); |
||||||
|
add(BrowserView.newInstance(browser), BorderLayout.CENTER); |
||||||
|
} else { |
||||||
|
initializeBrowser(); |
||||||
|
add(BrowserView.newInstance(browser), BorderLayout.CENTER); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void showDebuggerDialog() { |
||||||
|
JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(this)); |
||||||
|
Engine engine = Engine.newInstance( |
||||||
|
EngineOptions.newBuilder(RenderingMode.HARDWARE_ACCELERATED) |
||||||
|
.addSwitch("--disable-google-traffic") |
||||||
|
.remoteDebuggingPort(9222).build()); |
||||||
|
Browser debugger = engine.newBrowser(); |
||||||
|
BrowserView debuggerView = BrowserView.newInstance(debugger); |
||||||
|
dialog.add(debuggerView, BorderLayout.CENTER); |
||||||
|
dialog.setSize(new Dimension(800, 400)); |
||||||
|
GUICoreUtils.centerWindow(dialog); |
||||||
|
dialog.setVisible(true); |
||||||
|
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); |
||||||
|
browser.devTools().remoteDebuggingUrl().ifPresent(url -> { |
||||||
|
debugger.navigation().loadUrl(url); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void initializeBrowser() { |
||||||
|
Engine engine = Engine.newInstance(EngineOptions.newBuilder(RenderingMode.HARDWARE_ACCELERATED).addSwitch("--disable-google-traffic").build()); |
||||||
|
browser = engine.newBrowser(); |
||||||
|
|
||||||
|
// 初始化的时候,就把命名空间对象初始化好,确保window.a.b.c("a.b.c"为命名空间)对象都是初始化过的
|
||||||
|
browser.set(InjectJsCallback.class, params -> { |
||||||
|
params.frame().executeJavaScript(String.format(ModernUIConstants.SCRIPT_INIT_NAME_SPACE, namespace)); |
||||||
|
return InjectJsCallback.Response.proceed(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 转向一个新的地址,相当于重新加载 |
||||||
|
* |
||||||
|
* @param url 新的地址 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void redirect(String url) { |
||||||
|
browser.navigation().loadUrl(url); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 转向一个新的地址,相当于重新加载 |
||||||
|
* |
||||||
|
* @param url 新的地址 |
||||||
|
* @param map 初始化参数 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void redirect(String url, Map<String, String> map) { |
||||||
|
Network network = browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxInterceptRequestCallback(network, map)); |
||||||
|
browser.navigation().loadUrl(url); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return "Modern"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populate(final T t) { |
||||||
|
browser.set(InjectJsCallback.class, params -> { |
||||||
|
JsObject ns = params.frame().executeJavaScript("window." + namespace); |
||||||
|
if (ns != null) { |
||||||
|
ns.putProperty(variable, t); |
||||||
|
} |
||||||
|
return InjectJsCallback.Response.proceed(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public T update() { |
||||||
|
if (browser.mainFrame().isPresent()) { |
||||||
|
return browser.mainFrame().get().executeJavaScript("window." + namespace + "." + expression); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public static class Builder<T> extends ModernUIPane.Builder<T> { |
||||||
|
|
||||||
|
private NewModernUIPane<T> pane = new NewModernUIPane<>(); |
||||||
|
|
||||||
|
public NewModernUIPane.Builder<T> prepare(InjectJsCallback callback) { |
||||||
|
pane.browser.set(InjectJsCallback.class, callback); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加载jar包中的资源 |
||||||
|
* |
||||||
|
* @param path 资源路径 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> withEMB(final String path) { |
||||||
|
Network network = pane.browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxComplexInterceptRequestCallback(network, null)); |
||||||
|
pane.browser.navigation().loadUrl("emb:" + path); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加载url指向的资源 |
||||||
|
* |
||||||
|
* @param url 文件的地址 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> withURL(final String url) { |
||||||
|
Network network = pane.browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxInterceptRequestCallback(network)); |
||||||
|
pane.browser.navigation().loadUrl(url); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加载url指向的资源 |
||||||
|
* |
||||||
|
* @param url 文件的地址 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> withURL(final String url, Map<String, String> map) { |
||||||
|
Network network = pane.browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxInterceptRequestCallback(network, map)); |
||||||
|
pane.browser.navigation().loadUrl(url); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加载Atom组件 |
||||||
|
* |
||||||
|
* @param component Atom组件 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> withComponent(AssembleComponent component) { |
||||||
|
Network network = pane.browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxComplexInterceptRequestCallback(network, component)); |
||||||
|
pane.browser.navigation().loadUrl("emb:dynamic"); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加载Atom组件 |
||||||
|
* |
||||||
|
* @param component Atom组件 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> withComponent(AssembleComponent component, Map<String, String> map) { |
||||||
|
Network network = pane.browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxComplexInterceptRequestCallback(network, component, map)); |
||||||
|
pane.browser.navigation().loadUrl("emb:dynamic"); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 加载html文本内容 |
||||||
|
* |
||||||
|
* @param html 要加载html文本内容 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> withHTML(String html) { |
||||||
|
Network network = pane.browser.engine().network(); |
||||||
|
network.set(InterceptRequestCallback.class, new NxInterceptRequestCallback(network)); |
||||||
|
pane.browser.mainFrame().ifPresent(frame -> { |
||||||
|
frame.loadHtml(html); |
||||||
|
}); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置该前端页面做数据交换所使用的对象 |
||||||
|
* |
||||||
|
* @param namespace 对象名 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> namespace(String namespace) { |
||||||
|
pane.namespace = namespace; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* java端往js端传数据时使用的变量名字 |
||||||
|
* |
||||||
|
* @param name 变量的名字 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> variable(String name) { |
||||||
|
pane.variable = name; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js端往java端传数据时执行的函数表达式 |
||||||
|
* |
||||||
|
* @param expression 函数表达式 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> expression(String expression) { |
||||||
|
pane.expression = expression; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> prepareForV6(ScriptContextListener contextListener) { |
||||||
|
// do nothing
|
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> prepareForV6(LoadListener loadListener) { |
||||||
|
// do nothing
|
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public NewModernUIPane.Builder<T> prepareForV7(InjectJsCallback callback) { |
||||||
|
return prepare(callback); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public NewModernUIPane<T> build() { |
||||||
|
return pane; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,502 @@ |
|||||||
|
package com.fr.design.upm; |
||||||
|
|
||||||
|
import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader; |
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.design.bridge.exec.JSBridge; |
||||||
|
import com.fr.design.bridge.exec.JSCallback; |
||||||
|
import com.fr.design.extra.PluginOperateUtils; |
||||||
|
import com.fr.design.extra.PluginUtils; |
||||||
|
import com.fr.design.extra.exe.GetInstalledPluginsExecutor; |
||||||
|
import com.fr.design.extra.exe.GetPluginCategoriesExecutor; |
||||||
|
import com.fr.design.extra.exe.GetPluginFromStoreExecutor; |
||||||
|
import com.fr.design.extra.exe.GetPluginPrefixExecutor; |
||||||
|
import com.fr.design.extra.exe.PluginLoginExecutor; |
||||||
|
import com.fr.design.extra.exe.ReadUpdateOnlineExecutor; |
||||||
|
import com.fr.design.extra.exe.SearchOnlineExecutor; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.upm.event.CertificateEvent; |
||||||
|
import com.fr.design.upm.event.DownloadEvent; |
||||||
|
import com.fr.design.upm.exec.NewUpmBrowserExecutor; |
||||||
|
import com.fr.design.upm.task.UpmTaskWorker; |
||||||
|
import com.fr.event.EventDispatcher; |
||||||
|
import com.fr.general.GeneralUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.context.PluginMarker; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.teamdev.jxbrowser.js.JsAccessible; |
||||||
|
import com.teamdev.jxbrowser.js.JsFunction; |
||||||
|
import com.teamdev.jxbrowser.js.JsObject; |
||||||
|
|
||||||
|
import javax.swing.JFileChooser; |
||||||
|
import javax.swing.SwingUtilities; |
||||||
|
import javax.swing.SwingWorker; |
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter; |
||||||
|
import java.io.File; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.concurrent.FutureTask; |
||||||
|
import java.util.concurrent.RunnableFuture; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-04-12 |
||||||
|
* 桥接Java和JavaScript的类 |
||||||
|
*/ |
||||||
|
public class NewUpmBridge extends UpmBridge { |
||||||
|
|
||||||
|
public static NewUpmBridge getBridge(JsObject jsObject) { |
||||||
|
return new NewUpmBridge(jsObject); |
||||||
|
} |
||||||
|
|
||||||
|
private JsObject jsObject; |
||||||
|
|
||||||
|
private NewUpmBridge(JsObject jsObject) { |
||||||
|
this.jsObject = jsObject; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新插件管理中心资源文件,这个方法仅仅是为了语义上的作用(更新) |
||||||
|
* |
||||||
|
* @param callback 安装完成后的回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void update(final JsFunction callback) { |
||||||
|
callback.invoke(jsObject, "start", Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Start")); |
||||||
|
try { |
||||||
|
UpmResourceLoader.INSTANCE.download(); |
||||||
|
UpmResourceLoader.INSTANCE.install(); |
||||||
|
callback.invoke(jsObject, "success", Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Success")); |
||||||
|
EventDispatcher.fire(DownloadEvent.UPDATE, "success"); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
callback.invoke(jsObject, "error", Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Error")); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 下载并安装插件管理中心的资源文件 |
||||||
|
* |
||||||
|
* @param callback 安装完成后的回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void startDownload(final JsFunction callback) { |
||||||
|
callback.invoke(jsObject, "start", Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Start")); |
||||||
|
new SwingWorker<Void, Void>() { |
||||||
|
@Override |
||||||
|
protected Void doInBackground() throws Exception { |
||||||
|
UpmResourceLoader.INSTANCE.download(); |
||||||
|
UpmResourceLoader.INSTANCE.install(); |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void done() { |
||||||
|
try { |
||||||
|
get(); |
||||||
|
callback.invoke(jsObject, "success", Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Success")); |
||||||
|
EventDispatcher.fire(DownloadEvent.SUCCESS, "success"); |
||||||
|
} catch (Exception e) { |
||||||
|
callback.invoke(jsObject, "error", Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Error")); |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
EventDispatcher.fire(DownloadEvent.ERROR, "error"); |
||||||
|
} |
||||||
|
} |
||||||
|
}.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取upm的版本信息 |
||||||
|
* |
||||||
|
* @return 版本信息 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public String getVersion() { |
||||||
|
return super.getVersion(); |
||||||
|
} |
||||||
|
|
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public String i18nText(String key) { |
||||||
|
return super.i18nText(key); |
||||||
|
} |
||||||
|
|
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public void closeWindow() { |
||||||
|
super.closeWindow(); |
||||||
|
} |
||||||
|
|
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public boolean isDesigner() { |
||||||
|
return super.isDesigner(); |
||||||
|
} |
||||||
|
|
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void getPackInfo(final JsFunction callback) { |
||||||
|
callback.invoke(jsObject, StringUtils.EMPTY); |
||||||
|
} |
||||||
|
|
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void getPluginPrefix(final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> task = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new GetPluginPrefixExecutor()); |
||||||
|
task.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 在线获取插件分类 |
||||||
|
* |
||||||
|
* @param callback 回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void getPluginCategories(final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> task = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new GetPluginCategoriesExecutor()); |
||||||
|
task.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据条件获取在线插件 |
||||||
|
* |
||||||
|
* @param info 插件信息 |
||||||
|
* @param callback 回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void getPluginFromStoreNew(String info, final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> task = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new GetPluginFromStoreExecutor(new JSONObject(info))); |
||||||
|
task.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 已安装插件检查更新 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void readUpdateOnline(final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> task = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new ReadUpdateOnlineExecutor()); |
||||||
|
task.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取已经安装的插件的数组 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void getInstalledPlugins(final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> task = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new GetInstalledPluginsExecutor()); |
||||||
|
task.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从插件服务器上更新选中的插件 |
||||||
|
* |
||||||
|
* @param pluginIDs 插件集合 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void updatePluginOnline(JsObject pluginIDs, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
List<PluginMarker> pluginMarkerList = new ArrayList<>(); |
||||||
|
for (String key : pluginIDs.propertyNames()) { |
||||||
|
pluginIDs.property(key).ifPresent(v -> { |
||||||
|
pluginMarkerList.add(PluginUtils.createPluginMarker(GeneralUtils.objectToString(v))); |
||||||
|
}); |
||||||
|
} |
||||||
|
PluginOperateUtils.updatePluginOnline(pluginMarkerList, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void updatePluginOnline(String pluginID, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
List<PluginMarker> pluginMarkerList = new ArrayList<>(); |
||||||
|
pluginMarkerList.add(PluginUtils.createPluginMarker(pluginID)); |
||||||
|
PluginOperateUtils.updatePluginOnline(pluginMarkerList, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 搜索在线插件 |
||||||
|
* |
||||||
|
* @param keyword 关键字 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void searchPlugin(String keyword, final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> worker = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new SearchOnlineExecutor(keyword)); |
||||||
|
worker.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从磁盘上选择插件安装包进行安装 |
||||||
|
* |
||||||
|
* @param filePath 插件包的路径 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void installPluginFromDisk(final String filePath, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
File file = new File(filePath); |
||||||
|
PluginOperateUtils.installPluginFromDisk(file, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 卸载当前选中的插件 |
||||||
|
* |
||||||
|
* @param pluginInfo 插件信息 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void uninstallPlugin(final String pluginInfo, final boolean isForce, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
PluginOperateUtils.uninstallPlugin(pluginInfo, isForce, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从插件服务器上安装插件 |
||||||
|
* |
||||||
|
* @param pluginInfo 插件的ID |
||||||
|
* @param callback 回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void installPluginOnline(final String pluginInfo, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); |
||||||
|
PluginOperateUtils.installPluginOnline(pluginMarker, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从磁盘上选择插件安装包进行插件升级 |
||||||
|
* |
||||||
|
* @param filePath 插件包的路径 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void updatePluginFromDisk(String filePath, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
File file = new File(filePath); |
||||||
|
PluginOperateUtils.updatePluginFromDisk(file, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 修改选中的插件的活跃状态 |
||||||
|
* |
||||||
|
* @param pluginID 插件ID |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void setPluginActive(String pluginID, final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
PluginOperateUtils.setPluginActive(pluginID, jsCallback); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择文件对话框 |
||||||
|
* |
||||||
|
* @return 选择的文件的路径 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public String showFileChooser() { |
||||||
|
return super.showFileChooser(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择文件对话框 |
||||||
|
* |
||||||
|
* @param des 过滤文件描述 |
||||||
|
* @param filter 文件的后缀 |
||||||
|
* @return 选择的文件的路径 |
||||||
|
* 这里换用JFileChooser会卡死,不知道为什么 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public String showFileChooserWithFilter(final String des, final String filter) { |
||||||
|
return super.showFileChooserWithFilter(des, filter); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择文件对话框 |
||||||
|
* |
||||||
|
* @param des 过滤文件描述 |
||||||
|
* @param args 文件的后缀 |
||||||
|
* @return 选择的文件的路径 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public String showFileChooserWithFilters(final String des, final String args) { |
||||||
|
RunnableFuture<String> future = new FutureTask<>(() -> { |
||||||
|
JFileChooser fileChooser = new JFileChooser(); |
||||||
|
List<String> filterList = new ArrayList<>(); |
||||||
|
filterList.add(args); |
||||||
|
String[] filters = filterList.toArray(new String[0]); |
||||||
|
if (ArrayUtils.isNotEmpty(filters)) { |
||||||
|
FileNameExtensionFilter filter = new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(filters)); |
||||||
|
fileChooser.setFileFilter(filter); |
||||||
|
} |
||||||
|
int result = fileChooser.showOpenDialog(UpmFinder.getDialog()); |
||||||
|
if (result == JFileChooser.APPROVE_OPTION) { |
||||||
|
return fileChooser.getSelectedFile().getAbsolutePath(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
}); |
||||||
|
SwingUtilities.invokeLater(future); |
||||||
|
try { |
||||||
|
return future.get(); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择文件对话框 |
||||||
|
* |
||||||
|
* @param des 过滤文件描述 |
||||||
|
* @param args 文件的后缀 |
||||||
|
* @return 选择的文件的路径 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public String showFileChooserWithFilters(final String des, final JsObject args) { |
||||||
|
RunnableFuture<String> future = new FutureTask<>(() -> { |
||||||
|
JFileChooser fileChooser = new JFileChooser(); |
||||||
|
List<String> filterList = new ArrayList<>(); |
||||||
|
for (String key : args.propertyNames()) { |
||||||
|
args.property(key).ifPresent(v -> { |
||||||
|
filterList.add(GeneralUtils.objectToString(v)); |
||||||
|
}); |
||||||
|
} |
||||||
|
String[] filters = filterList.toArray(new String[0]); |
||||||
|
if (ArrayUtils.isNotEmpty(filters)) { |
||||||
|
FileNameExtensionFilter filter = new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(filters)); |
||||||
|
fileChooser.setFileFilter(filter); |
||||||
|
} |
||||||
|
int result = fileChooser.showOpenDialog(UpmFinder.getDialog()); |
||||||
|
if (result == JFileChooser.APPROVE_OPTION) { |
||||||
|
return fileChooser.getSelectedFile().getAbsolutePath(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
}); |
||||||
|
SwingUtilities.invokeLater(future); |
||||||
|
try { |
||||||
|
return future.get(); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
////////登录相关///////
|
||||||
|
|
||||||
|
/** |
||||||
|
* 获取系统登录的用户名 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public String getLoginInfo(final JsFunction callback) { |
||||||
|
registerLoginInfo(callback); |
||||||
|
return DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 系统登录注册 |
||||||
|
* |
||||||
|
* @param callback 回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void registerLoginInfo(final JsFunction callback) { |
||||||
|
JSCallback jsCallback = new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)); |
||||||
|
String username = DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); |
||||||
|
if (StringUtils.isEmpty(username)) { |
||||||
|
jsCallback.execute(StringUtils.EMPTY); |
||||||
|
EventDispatcher.fire(CertificateEvent.LOGOUT, StringUtils.EMPTY); |
||||||
|
} else { |
||||||
|
jsCallback.execute(username); |
||||||
|
EventDispatcher.fire(CertificateEvent.LOGIN, username); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 设计器端的用户登录 |
||||||
|
* |
||||||
|
* @param username 用户名 |
||||||
|
* @param password 密码 |
||||||
|
* @param callback 回调函数 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
public void defaultLogin(String username, String password, final JsFunction callback) { |
||||||
|
UpmTaskWorker<Void> worker = new UpmTaskWorker<>(new JSCallback(NewUpmBrowserExecutor.create(jsObject, callback)), new PluginLoginExecutor(username, password)); |
||||||
|
worker.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清除用户信息 |
||||||
|
*/ |
||||||
|
@JsAccessible |
||||||
|
@JSBridge |
||||||
|
@Override |
||||||
|
public void clearUserInfo() { |
||||||
|
super.clearUserInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 打开论坛消息界面 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public void getPriviteMessage() { |
||||||
|
super.getPriviteMessage(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 忘记密码 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public void forgetHref() { |
||||||
|
super.forgetHref(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 立即注册 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public void registerHref() { |
||||||
|
super.registerHref(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 使用系统浏览器打开网页 |
||||||
|
* |
||||||
|
* @param url 要打开的网页 |
||||||
|
*/ |
||||||
|
@JSBridge |
||||||
|
@JsAccessible |
||||||
|
@Override |
||||||
|
public void openShopUrlAtWebBrowser(String url) { |
||||||
|
super.openShopUrlAtWebBrowser(url); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package com.fr.design.upm.exec; |
||||||
|
|
||||||
|
import com.fr.design.bridge.exec.JSExecutor; |
||||||
|
import com.teamdev.jxbrowser.js.JsFunction; |
||||||
|
import com.teamdev.jxbrowser.js.JsObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-04-18 |
||||||
|
*/ |
||||||
|
public class NewUpmBrowserExecutor implements JSExecutor { |
||||||
|
|
||||||
|
public static NewUpmBrowserExecutor create(JsObject window, JsFunction callback) { |
||||||
|
return new NewUpmBrowserExecutor(window, callback); |
||||||
|
} |
||||||
|
|
||||||
|
private final JsFunction callback; |
||||||
|
private final JsObject window; |
||||||
|
|
||||||
|
private NewUpmBrowserExecutor(JsObject window, JsFunction callback) { |
||||||
|
this.window = window; |
||||||
|
this.callback = callback; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void executor(String newValue) { |
||||||
|
callback.invoke(window, newValue); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,148 @@ |
|||||||
|
package com.fr.env.utils; |
||||||
|
|
||||||
|
import com.fr.common.annotations.Compatible; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.EncodeConstants; |
||||||
|
import com.fr.stable.ProductConstants; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLReadable; |
||||||
|
import com.fr.stable.xml.XMLTools; |
||||||
|
import com.fr.stable.xml.XMLWriter; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
import com.fr.third.javax.xml.stream.XMLStreamException; |
||||||
|
|
||||||
|
import java.io.BufferedWriter; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.FileOutputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.OutputStreamWriter; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 10.0.18 |
||||||
|
* Created by Starryi on 2021/7/7 |
||||||
|
* 设计器访问和获取关键历史交互信息的持久化工具,该关键历史交互信息, |
||||||
|
* 如用户是否点击过某按钮,是否查看过某弹窗信息,上次选择过的文件所在目录等 |
||||||
|
*/ |
||||||
|
@Compatible |
||||||
|
public class DesignerInteractionHistory implements XMLReadable, XMLWriter { |
||||||
|
|
||||||
|
private static final String FILE_NAME = "designer.ix.history.info"; |
||||||
|
private static final String ROOT_TAG = "History"; |
||||||
|
|
||||||
|
private static DesignerInteractionHistory history; |
||||||
|
public static DesignerInteractionHistory getInstance() { |
||||||
|
if (history == null) { |
||||||
|
history = new DesignerInteractionHistory(); |
||||||
|
|
||||||
|
readXMLFile(history, history.getHistoryFile()); |
||||||
|
} |
||||||
|
|
||||||
|
return history; |
||||||
|
} |
||||||
|
|
||||||
|
private File getHistoryFile() { |
||||||
|
return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME)); |
||||||
|
} |
||||||
|
|
||||||
|
private static void readXMLFile(XMLReadable xmlReadable, File xmlFile) { |
||||||
|
if (xmlFile == null || !xmlFile.exists()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
String charset = EncodeConstants.ENCODING_UTF_8; |
||||||
|
try { |
||||||
|
String decodeContent = getFileContent(xmlFile); |
||||||
|
InputStream xmlInputStream = new ByteArrayInputStream(decodeContent.getBytes(charset)); |
||||||
|
InputStreamReader inputStreamReader = new InputStreamReader(xmlInputStream, charset); |
||||||
|
|
||||||
|
XMLableReader xmlReader = XMLableReader.createXMLableReader(inputStreamReader); |
||||||
|
|
||||||
|
if (xmlReader != null) { |
||||||
|
xmlReader.readXMLObject(xmlReadable); |
||||||
|
} |
||||||
|
xmlInputStream.close(); |
||||||
|
} catch (IOException | XMLStreamException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static String getFileContent(File xmlFile) throws FileNotFoundException, UnsupportedEncodingException { |
||||||
|
InputStream encodeInputStream = new FileInputStream(xmlFile); |
||||||
|
return IOUtils.inputStream2String(encodeInputStream); |
||||||
|
} |
||||||
|
|
||||||
|
private static void writeContentToFile(String fileContent, File file) { |
||||||
|
try (FileOutputStream fos = new FileOutputStream(file); |
||||||
|
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); |
||||||
|
BufferedWriter bw = new BufferedWriter(osw)) { |
||||||
|
bw.write(fileContent); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void saveXMLFile() { |
||||||
|
File xmlFile = this.getHistoryFile(); |
||||||
|
try { |
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||||
|
XMLTools.writeOutputStreamXML(this, out); |
||||||
|
out.flush(); |
||||||
|
out.close(); |
||||||
|
String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); |
||||||
|
writeContentToFile(fileContent, xmlFile); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static final String HAS_SHOWN_SHIFT_DRAG_RESIZING_TOOLTIP = "hasShownShiftDragResizingTooltip"; |
||||||
|
private static final String LAST_SELECTED_BORDER_IMAGE_DIR = "lastSelectedBorderImageDir"; |
||||||
|
|
||||||
|
// 是否已展示过按下Shift键可锁定比例拖拽尺寸的Tooltip
|
||||||
|
private boolean hasShownShiftDragResizingTooltip = false; |
||||||
|
// 用户上次通过文件选择器选择的边框图片所在目录
|
||||||
|
private String lastSelectedBorderImageDir = StringUtils.EMPTY; |
||||||
|
|
||||||
|
public boolean isHasShownShiftDragResizingTooltip() { |
||||||
|
return hasShownShiftDragResizingTooltip; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHasShownShiftDragResizingTooltip(boolean shown) { |
||||||
|
this.hasShownShiftDragResizingTooltip = shown; |
||||||
|
} |
||||||
|
|
||||||
|
public String getLastSelectedBorderImageDir() { |
||||||
|
return lastSelectedBorderImageDir; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLastSelectedBorderImageDir(String dirPath) { |
||||||
|
this.lastSelectedBorderImageDir = dirPath; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeXML(XMLPrintWriter writer) { |
||||||
|
writer.startTAG(ROOT_TAG) |
||||||
|
.attr(HAS_SHOWN_SHIFT_DRAG_RESIZING_TOOLTIP, isHasShownShiftDragResizingTooltip()) |
||||||
|
.attr(LAST_SELECTED_BORDER_IMAGE_DIR, getLastSelectedBorderImageDir()) |
||||||
|
.end(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void readXML(XMLableReader reader) { |
||||||
|
setHasShownShiftDragResizingTooltip(reader.getAttrAsBoolean(HAS_SHOWN_SHIFT_DRAG_RESIZING_TOOLTIP, false)); |
||||||
|
setLastSelectedBorderImageDir(reader.getAttrAsString(LAST_SELECTED_BORDER_IMAGE_DIR, StringUtils.EMPTY)); |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 468 B |
After Width: | Height: | Size: 280 B |
After Width: | Height: | Size: 147 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 155 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 225 B |
After Width: | Height: | Size: 229 B |
After Width: | Height: | Size: 226 B |
After Width: | Height: | Size: 229 B |
After Width: | Height: | Size: 272 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 255 B |
After Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 304 B |
After Width: | Height: | Size: 281 B |
@ -0,0 +1,242 @@ |
|||||||
|
package com.fr.design.designer.ui; |
||||||
|
|
||||||
|
import com.fr.design.designer.beans.AdapterBus; |
||||||
|
import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter; |
||||||
|
import com.fr.design.designer.beans.events.DesignerEvent; |
||||||
|
import com.fr.design.designer.creator.XCreator; |
||||||
|
import com.fr.design.designer.creator.XWTitleLayout; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.VerticalFlowLayout; |
||||||
|
import com.fr.design.mainframe.CoverReportPane; |
||||||
|
import com.fr.design.mainframe.EditingMouseListener; |
||||||
|
import com.fr.design.mainframe.FormDesigner; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.awt.event.MouseListener; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/7/8 |
||||||
|
*/ |
||||||
|
public class PopupControlPanel extends JPanel { |
||||||
|
|
||||||
|
private static final int ARC_VALUE = 4; |
||||||
|
private static final Color FILLED_COLOR = new Color(60, 63, 65); |
||||||
|
private static final int BUTTON_SIZE = 16; |
||||||
|
private static final int BUTTON_MARGIN = 4; |
||||||
|
private static final int PANE_WIDTH = BUTTON_SIZE + BUTTON_MARGIN * 2; // 24
|
||||||
|
|
||||||
|
private final Dimension defaultDimension = new Dimension(PANE_WIDTH, 0); |
||||||
|
private Rectangle rectangle; |
||||||
|
|
||||||
|
private final List<JComponent> buttons = new ArrayList<>(); |
||||||
|
private final JButton editButton; |
||||||
|
private final JButton settingButton; |
||||||
|
private final JToggleButton toggleButton; |
||||||
|
private final XCreator creator; |
||||||
|
|
||||||
|
public PopupControlPanel(XCreator creator, FormDesigner designer) { |
||||||
|
setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0)); |
||||||
|
setBorder(BorderFactory.createEmptyBorder()); |
||||||
|
this.creator = creator; |
||||||
|
|
||||||
|
editButton = createEditButton(designer); |
||||||
|
toggleButton = createAspectRatioLockedButton(designer); |
||||||
|
settingButton = createSettingButton(); |
||||||
|
|
||||||
|
addButton(editButton, 0); |
||||||
|
addButton(toggleButton, 1); |
||||||
|
addButton(settingButton, 2); |
||||||
|
|
||||||
|
setButtonVisible(editButton, false); |
||||||
|
setButtonVisible(toggleButton, false); |
||||||
|
setButtonVisible(settingButton, false); |
||||||
|
} |
||||||
|
|
||||||
|
private JButton createEditButton(FormDesigner designer) { |
||||||
|
JButton editButton = createNormalButton(IOUtils.readIcon("/com/fr/design/images/control/show_edit.png"), Toolkit.i18nText("Fine-Design_Form_Edit_Widget")); |
||||||
|
editButton.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
int x = rectangle.x + rectangle.width / 2; |
||||||
|
int y = rectangle.y + rectangle.height / 2; |
||||||
|
XCreator childCreator = PopupControlPanel.this.creator.getEditingChildCreator(); |
||||||
|
MouseListener[] listeners = designer.getMouseListeners(); |
||||||
|
if (ArrayUtils.isNotEmpty(listeners) && listeners[0] instanceof EditingMouseListener) { |
||||||
|
childCreator.respondClick(((EditingMouseListener) listeners[0]), new MouseEvent(childCreator, MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), x, y, 2, false)); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
return editButton; |
||||||
|
} |
||||||
|
|
||||||
|
private JToggleButton createAspectRatioLockedButton(FormDesigner designer) { |
||||||
|
JToggleButton button = new JToggleButton(IOUtils.readIcon("/com/fr/design/images/control/aspect_ratio_unlock.png")); |
||||||
|
initButtonStyle(button); |
||||||
|
button.setSelectedIcon(IOUtils.readIcon("com/fr/design/images/control/aspect_ratio_lock.png")); |
||||||
|
button.setToolTipText(Toolkit.i18nText("Fine-Design_Form_UnLock_Widget_Ratio")); |
||||||
|
button.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
JToggleButton toggleBtn = (JToggleButton) e.getSource(); |
||||||
|
String toolTipText = toggleBtn.isSelected() ? Toolkit.i18nText("Fine-Design_Form_Lock_Widget_Ratio") : Toolkit.i18nText("Fine-Design_Form_UnLock_Widget_Ratio"); |
||||||
|
toggleBtn.setToolTipText(toolTipText); |
||||||
|
creator.toData().setAspectRatioLocked(toggleBtn.isSelected()); |
||||||
|
designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_RESIZED); |
||||||
|
} |
||||||
|
}); |
||||||
|
return button; |
||||||
|
} |
||||||
|
|
||||||
|
private JButton createSettingButton() { |
||||||
|
JButton settingButton = createNormalButton(IOUtils.readIcon("/com/fr/design/images/control/show_setting.png"), Toolkit.i18nText("Fine-Design_Share_Help_Settings")); |
||||||
|
|
||||||
|
settingButton.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
CoverReportPane.showShareConfig(creator.toData()); |
||||||
|
} |
||||||
|
}); |
||||||
|
return settingButton; |
||||||
|
} |
||||||
|
|
||||||
|
private void addButton(JComponent component, int index) { |
||||||
|
buttons.add(index, component); |
||||||
|
if (index > 0) { |
||||||
|
this.add(new SeparatorLabel(), index * 2 - 1); |
||||||
|
} |
||||||
|
this.add(component, index * 2); |
||||||
|
} |
||||||
|
|
||||||
|
private void setButtonVisible(JComponent component, boolean visible) { |
||||||
|
int index = buttons.indexOf(component); |
||||||
|
|
||||||
|
boolean hasVisibleButtonBeforeCurrent = false; |
||||||
|
for (int i = 0; i < index; i++) { |
||||||
|
if (buttons.get(i).isVisible()) { |
||||||
|
hasVisibleButtonBeforeCurrent = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (hasVisibleButtonBeforeCurrent) { |
||||||
|
buttons.get(index).setVisible(visible); |
||||||
|
getComponent(2 * index - 1).setVisible(visible); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// 在当前按钮之前没有可见的按钮了
|
||||||
|
if (index > 0) { |
||||||
|
getComponent(2 * index - 1).setVisible(false); |
||||||
|
} |
||||||
|
buttons.get(index).setVisible(visible); |
||||||
|
|
||||||
|
if (!visible) { |
||||||
|
// 如果当前按钮设置为不可见,且在当前按钮之前的其他按钮也不可见,则下一个可见按钮前无分割线
|
||||||
|
for (int i = index + 1; i < buttons.size(); i++) { |
||||||
|
if (buttons.get(i).isVisible()) { |
||||||
|
if (i > 0) { |
||||||
|
getComponent(2 * i - 1).setVisible(false); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private JButton createNormalButton(Icon icon, String toolTipText) { |
||||||
|
JButton button = new JButton(icon); |
||||||
|
button.setPreferredSize(new Dimension(BUTTON_SIZE + 2 * BUTTON_MARGIN, BUTTON_SIZE + 2 * BUTTON_MARGIN)); |
||||||
|
button.setBorder(BorderFactory.createEmptyBorder(BUTTON_MARGIN, BUTTON_MARGIN, BUTTON_MARGIN, BUTTON_MARGIN)); |
||||||
|
initButtonStyle(button); |
||||||
|
button.setToolTipText(toolTipText); |
||||||
|
return button; |
||||||
|
} |
||||||
|
|
||||||
|
private void initButtonStyle(AbstractButton button) { |
||||||
|
button.setPreferredSize(new Dimension(BUTTON_SIZE + 2 * BUTTON_MARGIN, BUTTON_SIZE + 2 * BUTTON_MARGIN)); |
||||||
|
button.setBorder(BorderFactory.createEmptyBorder(BUTTON_MARGIN, BUTTON_MARGIN, BUTTON_MARGIN, BUTTON_MARGIN)); |
||||||
|
button.setBorderPainted(false); |
||||||
|
button.setContentAreaFilled(false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void paintComponent(Graphics g) { |
||||||
|
super.paintComponent(g); |
||||||
|
int w = this.getWidth(); |
||||||
|
int h = this.getHeight(); |
||||||
|
Graphics2D g2d = (Graphics2D) g; |
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||||
|
g2d.setColor(FILLED_COLOR); |
||||||
|
g2d.fillRoundRect(0, 0, w - 1, h - 1, ARC_VALUE, ARC_VALUE); |
||||||
|
g2d.setColor(Color.WHITE); |
||||||
|
g2d.drawRoundRect(0, 0, w - 1, h - 1, ARC_VALUE, ARC_VALUE); |
||||||
|
} |
||||||
|
|
||||||
|
public Dimension getDefaultDimension() { |
||||||
|
return defaultDimension; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRelativeBounds(Rectangle rectangle) { |
||||||
|
this.rectangle = rectangle; |
||||||
|
} |
||||||
|
|
||||||
|
public void updatePane(FormDesigner designer) { |
||||||
|
setButtonVisible(editButton, creator.acceptType(XWTitleLayout.class)); |
||||||
|
setButtonVisible(settingButton, creator.isShared()); |
||||||
|
setButtonVisible(toggleButton, AdapterBus.searchLayoutAdapter(designer, creator) instanceof FRAbsoluteLayoutAdapter); |
||||||
|
toggleButton.setSelected(creator.toData().isAspectRatioLocked()); |
||||||
|
|
||||||
|
updateDimension(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean hasVisibleButtons() { |
||||||
|
for (int i = 0; i < buttons.size(); i++) { |
||||||
|
if (buttons.get(i).isVisible()) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private void updateDimension() { |
||||||
|
int height = 0; |
||||||
|
for (int i = 0; i < buttons.size(); i++) { |
||||||
|
JComponent component = buttons.get(i); |
||||||
|
if (component.isVisible()) { |
||||||
|
if (i > 0) { |
||||||
|
height += 1; |
||||||
|
} |
||||||
|
height += component.getHeight(); |
||||||
|
} |
||||||
|
} |
||||||
|
height += 2; |
||||||
|
|
||||||
|
defaultDimension.height = height; |
||||||
|
} |
||||||
|
|
||||||
|
private static class SeparatorLabel extends UILabel { |
||||||
|
public SeparatorLabel() { |
||||||
|
setPreferredSize(new Dimension(PANE_WIDTH, 1)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
super.paint(g); |
||||||
|
Graphics2D g2d = (Graphics2D) g; |
||||||
|
g2d.setColor(Color.WHITE); |
||||||
|
g2d.drawLine(BUTTON_MARGIN, 0, getWidth() - BUTTON_MARGIN, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
package com.fr.design.designer.ui; |
||||||
|
|
||||||
|
import com.fr.design.designer.creator.XCreator; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.FormDesigner; |
||||||
|
import java.awt.Rectangle; |
||||||
|
import javax.swing.JDialog; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/7/09 |
||||||
|
*/ |
||||||
|
public class SelectedPopupDialog extends JDialog { |
||||||
|
|
||||||
|
/** |
||||||
|
* 弹窗的相对组件的偏移 |
||||||
|
*/ |
||||||
|
public static final int OFFSET_X = 5; |
||||||
|
|
||||||
|
private final PopupControlPanel controlPanel; |
||||||
|
|
||||||
|
public SelectedPopupDialog(XCreator creator, FormDesigner designer) { |
||||||
|
super(DesignerContext.getDesignerFrame()); |
||||||
|
this.setUndecorated(true); |
||||||
|
this.setModal(false); |
||||||
|
controlPanel = new PopupControlPanel(creator, designer); |
||||||
|
this.getContentPane().add(controlPanel); |
||||||
|
this.setSize(controlPanel.getDefaultDimension()); |
||||||
|
} |
||||||
|
|
||||||
|
public void updatePane(FormDesigner designer) { |
||||||
|
controlPanel.updatePane(designer); |
||||||
|
this.setSize(controlPanel.getDefaultDimension()); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean hasVisibleButtons() { |
||||||
|
return controlPanel.hasVisibleButtons(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRelativeBounds(Rectangle rectangle) { |
||||||
|
this.controlPanel.setRelativeBounds(rectangle); |
||||||
|
} |
||||||
|
|
||||||
|
} |