* commit '85e914f0c2796528440029b842e83cb9468b6187': (57 commits) CHART-19757 图表块增加名称检测 KERNEL-7634 mac和win使用不同版本的jxbrowser fix 登录名获取方式 KERNEL-7634 mac和win使用不同版本的jxbrowser REPORT-55149【组件背景分离】组件复用-图表块没看到内边距设置项 REPORT-55150 【组件背景分离】组件复用-标题设置下划线,选择下划线样式,目前web预览,不管选的什么下划线样式都显示的是单横线效果 REPORT-55121 【组件背景分离】组件复用-点九图填充设置弹窗的关闭按钮和取消按钮,其实还是确认&保存修改的效果 REPORT-53175 【10.0.18】组件背景分离为标题/背景/边框 REPORT-53175【10.0.18】组件背景分离为标题/背景/边框 REPORT-55070【组件背景分离】 组件复用-tab块点击右侧添加标签按钮,没生效 REPORT-54853 fetchsize为空时,数据连接点击确定无效 CHART-19871 大数据判断 REPORT-55089 组件背景分离】组件复用-标题图案的图片预览图,和交互文档里定的悬浮时出现删除按钮和不透明遮罩预期效果不同 REPORT-53175【10.0.18】组件背景分离为标题/背景/边框 REPORT-55114 【组件背景分离】组件复用-点九图分割线拖动到边缘时,就无法再次选中分割线了 REPORT-55112 【组件背景分离】组件复用-点九图填充设置弹窗,分割线拖拽到靠近边缘时,像素值就被遮挡看不到了 REPORT-55108 【组件背景分离】组件复用-边框选择自定义图片,但还没具体选择某张图片时,此时的点九图填充设置按钮应该先灰化 REPORT-55107 【组件背景分离】组件复用-背景样式 边框选择自定义图片时,下方应出现不透明度设置,目前没有 CHART-19488 日期轴的日期控件构建成字符串公式 REPORT-54122 设计器组件选中状态右侧弹窗改进 去掉无用输出 REPORT-54122 fix 无用import ...bugfix/10.0
@ -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; |
||||
} |
||||
} |
@ -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: 255 B |
After Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 304 B |
After Width: | Height: | Size: 281 B |
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,21 @@
|
||||
package com.fr.van.chart.designer.style; |
||||
|
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* Created by eason on 2016/12/14. |
||||
*/ |
||||
public class VanLegendPaneWidthOutFixedCheck extends VanChartPlotLegendPane{ |
||||
|
||||
public VanLegendPaneWidthOutFixedCheck(){ |
||||
|
||||
} |
||||
|
||||
public VanLegendPaneWidthOutFixedCheck(VanChartStylePane parent){ |
||||
super(parent); |
||||
} |
||||
|
||||
protected JPanel createLegendPane(){ |
||||
return this.createLegendPaneWithoutFixedCheck(); |
||||
} |
||||
} |
@ -1,21 +0,0 @@
|
||||
package com.fr.van.chart.designer.style; |
||||
|
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* Created by eason on 2016/12/14. |
||||
*/ |
||||
public class VanLegendPaneWidthOutHighlight extends VanChartPlotLegendPane{ |
||||
|
||||
public VanLegendPaneWidthOutHighlight(){ |
||||
|
||||
} |
||||
|
||||
public VanLegendPaneWidthOutHighlight(VanChartStylePane parent){ |
||||
super(parent); |
||||
} |
||||
|
||||
protected JPanel createLegendPane(){ |
||||
return this.createLegendPaneWithoutHighlight(); |
||||
} |
||||
} |
@ -0,0 +1,231 @@
|
||||
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.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, true); |
||||
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/edit_unlock.png")); |
||||
initButtonStyle(button); |
||||
button.setSelectedIcon(IOUtils.readIcon("com/fr/design/images/control/edit_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(true); |
||||
|
||||
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(settingButton, creator.isShared()); |
||||
setButtonVisible(toggleButton, AdapterBus.searchLayoutAdapter(designer, creator) instanceof FRAbsoluteLayoutAdapter); |
||||
toggleButton.setSelected(creator.toData().isAspectRatioLocked()); |
||||
|
||||
updateDimension(); |
||||
} |
||||
|
||||
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,41 @@
|
||||
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 void setRelativeBounds(Rectangle rectangle) { |
||||
this.controlPanel.setRelativeBounds(rectangle); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,649 @@
|
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.base.GraphHelper; |
||||
import com.fr.base.Style; |
||||
import com.fr.base.Utils; |
||||
import com.fr.base.background.ImageBackground; |
||||
import com.fr.base.background.ImageFileBackground; |
||||
import com.fr.design.border.UIRoundedBorder; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.designer.IntervalConstants; |
||||
import com.fr.design.dialog.BasicDialog; |
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.dialog.DialogActionAdapter; |
||||
import com.fr.design.event.UIObserver; |
||||
import com.fr.design.event.UIObserverListener; |
||||
import com.fr.design.gui.frpane.ImgChooseWrapper; |
||||
import com.fr.design.gui.frpane.UIPercentDragPane; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ibutton.UIButtonUI; |
||||
import com.fr.design.gui.ibutton.UIColorButton; |
||||
import com.fr.design.gui.icombobox.LineComboBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.backgroundpane.ImagePreviewPane; |
||||
import com.fr.design.style.background.image.ImageFileChooser; |
||||
import com.fr.env.utils.DesignerInteractionHistory; |
||||
import com.fr.form.ui.LayoutBorderStyle; |
||||
import com.fr.general.Background; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.Constants; |
||||
import com.fr.stable.GraphDrawHelper; |
||||
import com.fr.stable.ProjectLibrary; |
||||
import com.fr.stable.StableUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import javax.swing.plaf.basic.BasicButtonUI; |
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseListener; |
||||
import java.awt.event.MouseMotionListener; |
||||
import java.awt.geom.RoundRectangle2D; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 10.0.18 |
||||
* Created by Starryi on 2021/7/2 |
||||
* |
||||
* 可配置图片类型边框的样式设置面板 |
||||
*/ |
||||
public class BorderLineAndImagePane extends JPanel implements UIObserver { |
||||
private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH; |
||||
private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); |
||||
private final String TWEAK_NINE_POINT_HELP_URL = ""; |
||||
|
||||
private UIObserverListener uiObserverListener; |
||||
|
||||
private BorderLineAndImageComboBox borderLineCombo; |
||||
private UIColorButton borderColorPane; |
||||
private ImagePreviewPane imagePreviewPane; |
||||
private UIButton chooseImageButton; |
||||
private UIButton tweakNinePointHelpButton; |
||||
private UIButton tweakNinePointButton; |
||||
private UIPercentDragPane borderImageOpacityPane; |
||||
|
||||
private NinePointImageTweakDialogPane tweakPane; |
||||
private ImageFileChooser imageFileChooser; |
||||
|
||||
private int[] ninePoint = new int[] {-1, -1, -1, -1}; |
||||
|
||||
public BorderLineAndImagePane() { |
||||
this.initComponents(); |
||||
this.initLayout(); |
||||
} |
||||
|
||||
private void initComponents() { |
||||
borderLineCombo = new BorderLineAndImageComboBox(); |
||||
borderColorPane = new UIColorButton(null) {{ |
||||
setUI(createButtonUI(this)); |
||||
set4ToolbarButton(); |
||||
}}; |
||||
imagePreviewPane = new ImagePreviewPane() {{ |
||||
setImageStyle(Style.DEFAULT_STYLE); |
||||
}}; |
||||
chooseImageButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Image_Select_Picture")); |
||||
|
||||
tweakNinePointHelpButton = new UIButton(IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_border_image_help.png")); |
||||
tweakNinePointHelpButton.setUI(new BasicButtonUI()); |
||||
tweakNinePointHelpButton.setBorderPainted(false); |
||||
tweakNinePointHelpButton.setBorder(null); |
||||
tweakNinePointHelpButton.setContentAreaFilled(false); |
||||
tweakNinePointHelpButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
Desktop desktop = Desktop.getDesktop(); |
||||
try { |
||||
desktop.browse(new URI(TWEAK_NINE_POINT_HELP_URL)); |
||||
} catch (IOException | URISyntaxException ioException) { |
||||
ioException.printStackTrace(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
tweakNinePointButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill")); |
||||
borderImageOpacityPane = new UIPercentDragPane(); |
||||
} |
||||
|
||||
private JPanel createBorderLineComposedPane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
return TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Line")), this.borderLineCombo}}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, 0); |
||||
} |
||||
|
||||
private JPanel createBorderColorComposedPane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
return TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Color")), this.borderColorPane}}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, 0); |
||||
} |
||||
|
||||
private JPanel createBorderImageComposePane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p, p, p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel borderedImagePreviewPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
borderedImagePreviewPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 5)); |
||||
borderedImagePreviewPane.setPreferredSize(new Dimension(145, 145)); |
||||
borderedImagePreviewPane.add(imagePreviewPane, BorderLayout.CENTER); |
||||
|
||||
JPanel tweakNinePointComposedPane = new JPanel(); |
||||
tweakNinePointComposedPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0)); |
||||
tweakNinePointButton.setPreferredSize(new Dimension(145, 16)); |
||||
tweakNinePointComposedPane.add(tweakNinePointHelpButton); |
||||
tweakNinePointComposedPane.add(tweakNinePointButton); |
||||
|
||||
return TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{null, borderedImagePreviewPane}, |
||||
{null, chooseImageButton}, |
||||
{tweakNinePointComposedPane, null}, |
||||
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, |
||||
{null, this.borderImageOpacityPane} |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
} |
||||
|
||||
private void initImageFileChooserIfNotExist() { |
||||
if (imageFileChooser == null) { |
||||
imageFileChooser = new ImageFileChooser(); |
||||
imageFileChooser.setMultiSelectionEnabled(false); |
||||
} |
||||
} |
||||
|
||||
private void initImageFileChooserDirectory() { |
||||
DesignerInteractionHistory history = DesignerInteractionHistory.getInstance(); |
||||
String lastUsedBorderImageDirPath = history.getLastSelectedBorderImageDir(); |
||||
File lastUsedBorderImageDir = StringUtils.isNotEmpty(lastUsedBorderImageDirPath) ? new File(lastUsedBorderImageDirPath) : null; |
||||
|
||||
File inbuiltBorderImagesDir = new File(StableUtils.pathJoin(ProjectLibrary.getInstance().getLibHome(), ProjectConstants.ASSETS_NAME, "border_images")); |
||||
|
||||
if (lastUsedBorderImageDir!= null && lastUsedBorderImageDir.exists()) { |
||||
imageFileChooser.setCurrentDirectory(lastUsedBorderImageDir); |
||||
} else if (inbuiltBorderImagesDir.exists()) { |
||||
imageFileChooser.setCurrentDirectory(inbuiltBorderImagesDir); |
||||
} |
||||
} |
||||
|
||||
protected void initNinePointTweakPaneIfNotExist() { |
||||
if (tweakPane == null) { |
||||
tweakPane = new NinePointImageTweakDialogPane(); |
||||
} |
||||
} |
||||
|
||||
private void initLayout() { |
||||
this.setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); |
||||
|
||||
this.add(this.createBorderLineComposedPane(), BorderLayout.NORTH, 0); |
||||
this.add(this.createBorderColorComposedPane(), BorderLayout.CENTER, 1); |
||||
this.add(this.createBorderImageComposePane(), BorderLayout.SOUTH, 2); |
||||
|
||||
getComponent(1).setVisible(false); |
||||
getComponent(2).setVisible(false); |
||||
|
||||
this.borderLineCombo.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
getComponent(1).setVisible(borderLineCombo.isSelectedBorderLine()); |
||||
getComponent(2).setVisible(borderLineCombo.isSelectedBorderImage()); |
||||
|
||||
if (!borderLineCombo.isSelectedBorderLine()) { |
||||
borderColorPane.setColor(Color.BLACK); |
||||
} |
||||
if (!borderLineCombo.isSelectedBorderImage()) { |
||||
imagePreviewPane.setImageWithSuffix(null); |
||||
tweakNinePointButton.setEnabled(false); |
||||
} |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}); |
||||
this.chooseImageButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
initImageFileChooserIfNotExist(); |
||||
initImageFileChooserDirectory(); |
||||
int returnVal = imageFileChooser.showOpenDialog(DesignerContext.getDesignerFrame()); |
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) { |
||||
DesignerInteractionHistory history = DesignerInteractionHistory.getInstance(); |
||||
File selectedDirectory = imageFileChooser.getSelectedFile().getParentFile(); |
||||
history.setLastSelectedBorderImageDir(selectedDirectory.getPath()); |
||||
} |
||||
|
||||
ImgChooseWrapper.getInstance(imagePreviewPane, imageFileChooser, DEFAULT_IMAGE_LAYOUT_STYLE, new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
Image image = imagePreviewPane.getImage(); |
||||
ninePoint = new int[4]; |
||||
ninePoint[0] = ninePoint[2] = (image != null ? image.getWidth(null) / 3 : -1); |
||||
ninePoint[1] = ninePoint[3] = (image != null ? image.getHeight(null) / 3 : -1); |
||||
borderImageOpacityPane.populateBean(1.0); |
||||
if (image != null) { |
||||
tweakNinePointButton.setEnabled(true); |
||||
} |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}).dealWithImageFile(returnVal); |
||||
} |
||||
}); |
||||
this.tweakNinePointButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
initNinePointTweakPaneIfNotExist(); |
||||
|
||||
if (imagePreviewPane.getImage() != null) { |
||||
tweakPane.previewPane.setNinePoint(ninePoint); |
||||
BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(BorderLineAndImagePane.this)); |
||||
dialog.addDialogActionListener(new DialogActionAdapter() { |
||||
@Override |
||||
public void doOk() { |
||||
ninePoint = Arrays.copyOf(tweakPane.previewPane.getNinePoint(), 4); |
||||
fireStateChanged(); |
||||
} |
||||
}); |
||||
dialog.setVisible(true); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void populateBean(LayoutBorderStyle style) { |
||||
int borderLine = style.getBorder(); |
||||
Color borderColor = style.getColor(); |
||||
|
||||
this.borderLineCombo.setSelectedLineStyle(borderLine); |
||||
this.borderColorPane.setColor(borderColor); |
||||
|
||||
Background borderImage = style.getBorderImage(); |
||||
if (borderImage instanceof ImageBackground) { |
||||
// 图片类型边框
|
||||
Image image = ((ImageBackground) borderImage).getImage(); |
||||
int[] ninePoint = ((ImageBackground) borderImage).getNinePoint(); |
||||
|
||||
if (image != null) { |
||||
this.borderLineCombo.selectBorderImage(); |
||||
this.imagePreviewPane.setImageWithSuffix(((ImageBackground) borderImage).getImageWithSuffix()); |
||||
this.tweakNinePointButton.setEnabled(true); |
||||
this.borderImageOpacityPane.populateBean(style.getBorderImageOpacity()); |
||||
if (ninePoint != null && ninePoint.length == 4 && ninePoint[0] > 0 && ninePoint[1] > 0 && ninePoint[2] > 0 && ninePoint[3] > 0) { |
||||
this.ninePoint = Arrays.copyOf(ninePoint, 4); |
||||
} else { |
||||
this.ninePoint = new int[4]; |
||||
this.ninePoint[0] = this.ninePoint[2] = image.getWidth(null) / 3; |
||||
this.ninePoint[1] = this.ninePoint[3] = image.getHeight(null) / 3; |
||||
} |
||||
|
||||
getComponent(1).setVisible(false); |
||||
getComponent(2).setVisible(true); |
||||
|
||||
return; |
||||
} |
||||
} |
||||
|
||||
if (borderLine == Constants.LINE_NONE) { |
||||
getComponent(1).setVisible(false); |
||||
getComponent(2).setVisible(false); |
||||
return; |
||||
} else { |
||||
getComponent(1).setVisible(true); |
||||
getComponent(2).setVisible(false); |
||||
} |
||||
|
||||
this.borderLineCombo.setSelectedLineStyle(style.getBorder()); |
||||
this.borderColorPane.setColor(style.getColor()); |
||||
} |
||||
|
||||
public void updateBean(LayoutBorderStyle style) { |
||||
|
||||
style.setBorder(this.borderLineCombo.getSelectedLineStyle()); |
||||
style.setColor(this.borderColorPane.getColor()); |
||||
style.setBorderImage(null); |
||||
|
||||
if (this.borderLineCombo.isSelectedBorderImage()) { |
||||
Image image = this.imagePreviewPane.getImage(); |
||||
if (image != null) { |
||||
ImageBackground newImageBackground = new ImageFileBackground(this.imagePreviewPane.getImageWithSuffix(), Constants.IMAGE_EXTEND); |
||||
newImageBackground.setNinePoint(Arrays.copyOf(ninePoint, 4)); |
||||
style.setBorderImage(newImageBackground); |
||||
style.setBorderImageOpacity((float)borderImageOpacityPane.updateBean()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void fireStateChanged() { |
||||
if (uiObserverListener != null) { |
||||
uiObserverListener.doChange(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerChangeListener(UIObserverListener listener) { |
||||
this.uiObserverListener = listener; |
||||
} |
||||
|
||||
@Override |
||||
public boolean shouldResponseChangeListener() { |
||||
return true; |
||||
} |
||||
|
||||
protected UIButtonUI createButtonUI(final UIColorButton uiColorButton) { |
||||
return new UIButtonUI() { |
||||
|
||||
public void paint(Graphics g, JComponent c) { |
||||
UIButton b = (UIButton) c; |
||||
g.setColor(Color.black); |
||||
GraphHelper.draw(g, new RoundRectangle2D.Double(1, 1, b.getWidth() - 2, b.getHeight() - 2, 0, 0), 1); |
||||
|
||||
if (b.getModel().isEnabled()) { |
||||
g.setColor(uiColorButton.getColor()); |
||||
} else { |
||||
g.setColor(new Color(Utils.filterRGB(uiColorButton.getColor().getRGB(), 50))); |
||||
} |
||||
g.fillRect(2, 2, b.getWidth() - 3, b.getHeight() - 3); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
protected static class BorderLineAndImageComboBox extends LineComboBox { |
||||
public static final int LINE_PICTURE = -1; |
||||
public final static int[] BORDER_LINE_STYLE_ARRAY = new int[] { |
||||
Constants.LINE_NONE, |
||||
LINE_PICTURE, |
||||
Constants.LINE_THIN, //1px
|
||||
Constants.LINE_MEDIUM, //2px
|
||||
Constants.LINE_THICK, //3px
|
||||
}; |
||||
|
||||
public BorderLineAndImageComboBox() { |
||||
super(BORDER_LINE_STYLE_ARRAY); |
||||
} |
||||
|
||||
@Override |
||||
protected String toStringFromStyle(int style) { |
||||
if (style == LINE_PICTURE) { |
||||
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image"); |
||||
} |
||||
return super.toStringFromStyle(style); |
||||
} |
||||
|
||||
public boolean isSelectedBorderLine() { |
||||
return getSelectedIndex() > 1; |
||||
} |
||||
|
||||
public boolean isSelectedBorderImage() { |
||||
return getSelectedIndex() == 1; |
||||
} |
||||
|
||||
public void selectBorderImage() { |
||||
this.setSelectedIndex(1); |
||||
} |
||||
} |
||||
|
||||
private class NinePointImageTweakDialogPane extends BasicPane { |
||||
public final NinePointLinePreviewPane previewPane = new NinePointLinePreviewPane(); |
||||
|
||||
public NinePointImageTweakDialogPane() { |
||||
this.initComponents(); |
||||
} |
||||
|
||||
private void initComponents() { |
||||
setLayout(new BorderLayout()); |
||||
setBorder(BorderFactory.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill_Preview"))); |
||||
|
||||
JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
content.setBorder(BorderFactory.createEmptyBorder( |
||||
IntervalConstants.INTERVAL_W1, |
||||
IntervalConstants.INTERVAL_W1, |
||||
IntervalConstants.INTERVAL_W1, |
||||
IntervalConstants.INTERVAL_W1)); |
||||
content.add(previewPane); |
||||
previewPane.setPreferredSize(new Dimension(611, 457)); |
||||
|
||||
add(content, BorderLayout.CENTER); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill"); |
||||
} |
||||
} |
||||
|
||||
private class NinePointLinePreviewPane extends JPanel implements MouseMotionListener, MouseListener { |
||||
private final BufferedImage transparentImage = IOUtils.readImage("/com/fr/design/images/transparent_background.jpg"); |
||||
|
||||
public final Color PATCH_COLOR = new Color(0, 0, 0, 38); |
||||
public final Color DIVIDER_COLOR = new Color(250, 250, 250); |
||||
public final Color TEXT_COLOR = Color.WHITE; |
||||
public final int PADDING = 15; |
||||
|
||||
private int ninePointLeft = -1; |
||||
private int ninePointTop = -1; |
||||
private int ninePointRight = -1; |
||||
private int ninePointBottom = -1; |
||||
|
||||
private int imgWidth; |
||||
private int imgHeight; |
||||
private int scaleImgWidth; |
||||
private int scaleImgHeight; |
||||
private int scaleImgX; |
||||
private int scaleImgY; |
||||
private double scale = 1.0; |
||||
|
||||
public NinePointLinePreviewPane() { |
||||
this.addMouseMotionListener(this); |
||||
this.addMouseListener(this); |
||||
} |
||||
|
||||
@Override |
||||
protected void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
|
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.drawImage(transparentImage, 0, 0, getWidth(), getHeight(), null); |
||||
|
||||
Image image = imagePreviewPane.getImage(); |
||||
|
||||
imgWidth = image.getWidth(null); |
||||
imgHeight = image.getHeight(null); |
||||
int autoFixAreaWidth = getWidth() - 2 * PADDING; |
||||
int autoFixAreaHeight = getHeight() - 2 * PADDING; |
||||
int autoFixAreaX = PADDING; |
||||
int autoFixAreaY = PADDING; |
||||
|
||||
if ((imgWidth * 1.0F / imgHeight) > (autoFixAreaWidth * 1.0F / autoFixAreaHeight)) { |
||||
scaleImgWidth = autoFixAreaWidth; |
||||
scaleImgHeight = (int) (1.0F * scaleImgWidth * imgHeight / imgWidth); |
||||
scaleImgX = autoFixAreaX; |
||||
scaleImgY = (autoFixAreaHeight - scaleImgHeight) / 2 + autoFixAreaY; // 垂直居中
|
||||
scale = 1.0 * scaleImgWidth / imgWidth; |
||||
} else { |
||||
scaleImgHeight = autoFixAreaHeight; |
||||
scaleImgWidth = (int) (1.0F * scaleImgHeight * imgWidth / imgHeight); |
||||
scaleImgX = (autoFixAreaWidth - scaleImgWidth) / 2 + autoFixAreaX; // 水平居中
|
||||
scaleImgY = autoFixAreaY; |
||||
scale = 1.0 * scaleImgHeight / imgHeight; |
||||
} |
||||
|
||||
g2d.drawImage(image, scaleImgX, scaleImgY, scaleImgWidth, scaleImgHeight, null); |
||||
|
||||
int scaleLeft = (int) (ninePointLeft * scale); |
||||
int scaleTop = (int) (ninePointTop * scale); |
||||
int scaleRight = (int) (ninePointRight * scale); |
||||
int scaleBottom = (int) (ninePointBottom * scale); |
||||
|
||||
double topYInPane = scaleImgY + scaleTop; |
||||
double bottomYInPane = scaleImgY + scaleImgHeight - scaleBottom; |
||||
double leftXInPane = scaleImgX + scaleLeft; |
||||
double rightXInPane = scaleImgX + scaleImgWidth - scaleRight; |
||||
|
||||
g2d.setColor(PATCH_COLOR); |
||||
// draw horizontal patch
|
||||
GraphDrawHelper.fillRect(g2d, 0, topYInPane, getWidth(), scaleImgHeight - scaleTop - scaleBottom); |
||||
// draw vertical patch
|
||||
GraphDrawHelper.fillRect(g2d, scaleImgX + scaleLeft, 0,scaleImgWidth - scaleLeft - scaleRight, getHeight()); |
||||
|
||||
g2d.setColor(DIVIDER_COLOR); |
||||
// draw top divider
|
||||
GraphDrawHelper.drawLine(g2d, 0, topYInPane, getWidth(), topYInPane); |
||||
// draw bottom divider
|
||||
GraphDrawHelper.drawLine(g2d, 0, bottomYInPane, getWidth(), bottomYInPane); |
||||
// draw left divider
|
||||
GraphDrawHelper.drawLine(g2d, leftXInPane, 0, leftXInPane, getHeight()); |
||||
// draw right divider
|
||||
GraphDrawHelper.drawLine(g2d, rightXInPane, 0, rightXInPane, getHeight()); |
||||
|
||||
g2d.setColor(TEXT_COLOR); |
||||
// draw nine point info
|
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointTop), (leftXInPane + rightXInPane) / 2.0F, topYInPane / 2.0); |
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointBottom), (leftXInPane + rightXInPane) / 2.0F, (bottomYInPane + getHeight()) / 2.0); |
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointLeft), leftXInPane / 2.0, (topYInPane + bottomYInPane) / 2.0); |
||||
GraphDrawHelper.drawString(g2d, Integer.toString(ninePointRight), (rightXInPane + getWidth()) / 2.0, (topYInPane + bottomYInPane) / 2.0); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseDragged(MouseEvent e) { |
||||
int x = e.getX(); |
||||
int y = e.getY(); |
||||
|
||||
int cursorType = getCursor().getType(); |
||||
|
||||
switch (cursorType) { |
||||
case Cursor.W_RESIZE_CURSOR: { |
||||
int nextLeft = (int) ((x - scaleImgX) / scale); |
||||
if (1 <= nextLeft && nextLeft < imgWidth - ninePointRight) { |
||||
ninePointLeft = nextLeft; |
||||
repaint(); |
||||
} |
||||
return; |
||||
} |
||||
case Cursor.E_RESIZE_CURSOR: { |
||||
int nextRight = (int) ((scaleImgX + scaleImgWidth - x) / scale); |
||||
if (1 <= nextRight && nextRight < imgWidth - ninePointLeft) { |
||||
ninePointRight = nextRight; |
||||
repaint(); |
||||
} |
||||
return; |
||||
} |
||||
case Cursor.N_RESIZE_CURSOR: { |
||||
int nextTop = (int) ((y - scaleImgY) / scale); |
||||
if (1 <= nextTop && nextTop < imgHeight - ninePointBottom) { |
||||
ninePointTop = nextTop; |
||||
repaint(); |
||||
} |
||||
return; |
||||
} |
||||
case Cursor.S_RESIZE_CURSOR: { |
||||
int nextBottom = (int) ((scaleImgY + scaleImgHeight - y) / scale); |
||||
if (1 <= nextBottom && nextBottom < imgHeight - ninePointTop) { |
||||
ninePointBottom = nextBottom; |
||||
repaint(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseMoved(MouseEvent e) { |
||||
boolean needRepaint; |
||||
|
||||
int x = e.getX(); |
||||
int y = e.getY(); |
||||
|
||||
double scaleLeft = ninePointLeft * scale; |
||||
double scaleTop = ninePointTop * scale; |
||||
double scaleRight = ninePointRight * scale; |
||||
double scaleBottom = ninePointBottom * scale; |
||||
|
||||
// determine cursor
|
||||
int cursorType = Cursor.DEFAULT_CURSOR; |
||||
|
||||
boolean hoveringLeftDivider = Math.abs(x - (scaleImgX + scaleLeft)) < 2; |
||||
boolean hoveringRightDivider = Math.abs(x - (scaleImgX + scaleImgWidth - scaleRight)) < 2; |
||||
boolean hoveringTopDivider = Math.abs(y - (scaleImgY + scaleTop)) < 2; |
||||
boolean hoveringBottomDivider = Math.abs(y - (scaleImgY + scaleImgHeight - scaleBottom)) < 2; |
||||
|
||||
if (hoveringLeftDivider) { |
||||
cursorType = Cursor.W_RESIZE_CURSOR; |
||||
} else if (hoveringRightDivider) { |
||||
cursorType = Cursor.E_RESIZE_CURSOR; |
||||
} else if (hoveringTopDivider) { |
||||
cursorType = Cursor.N_RESIZE_CURSOR; |
||||
} else if (hoveringBottomDivider) { |
||||
cursorType = Cursor.S_RESIZE_CURSOR; |
||||
} |
||||
|
||||
needRepaint = getCursor().getType() != cursorType; |
||||
this.setCursor(Cursor.getPredefinedCursor(cursorType)); |
||||
|
||||
if (needRepaint) { |
||||
repaint(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void mouseReleased(MouseEvent e) { |
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
||||
|
||||
repaint(); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
|
||||
} |
||||
|
||||
|
||||
public void setNinePoint(int[] ninePoint) { |
||||
ninePointLeft = ninePoint[0]; |
||||
ninePointTop = ninePoint[1]; |
||||
ninePointRight = ninePoint[2]; |
||||
ninePointBottom = ninePoint[3]; |
||||
} |
||||
|
||||
public int[] getNinePoint() { |
||||
return new int[] { ninePointLeft, ninePointTop, ninePointRight, ninePointBottom }; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. |
||||
*/ |
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.form.ui.LayoutBorderStyle; |
||||
|
||||
import javax.swing.*; |
||||
|
||||
/** |
||||
* CardTagLayoutBorderPane Pane. |
||||
*/ |
||||
public class CardTagLayoutStylePane extends LayoutStylePane { |
||||
|
||||
@Override |
||||
protected JPanel createTitleStylePane(){ |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void updateTitle(LayoutBorderStyle style) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
protected void populateTitle() { } |
||||
} |
@ -0,0 +1,511 @@
|
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.base.GraphHelper; |
||||
import com.fr.base.Utils; |
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.design.beans.BasicBeanPane; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.designer.IntervalConstants; |
||||
import com.fr.design.file.HistoryTemplateListCache; |
||||
import com.fr.design.formula.TinyFormulaPane; |
||||
import com.fr.design.gui.frpane.UIPercentDragPane; |
||||
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||
import com.fr.design.gui.ibutton.UIColorButton; |
||||
import com.fr.design.gui.ibutton.UIToggleButton; |
||||
import com.fr.design.gui.icheckbox.UICheckBox; |
||||
import com.fr.design.gui.icombobox.LineComboBox; |
||||
import com.fr.design.gui.icombobox.UIComboBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.ispinner.UISpinner; |
||||
import com.fr.design.gui.style.BackgroundSpecialPane; |
||||
import com.fr.design.gui.style.FRFontPane; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.JForm; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; |
||||
import com.fr.form.ui.LayoutBorderStyle; |
||||
import com.fr.form.ui.WidgetTitle; |
||||
import com.fr.general.Background; |
||||
import com.fr.general.FRFont; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.general.act.TitlePacker; |
||||
import com.fr.stable.Constants; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.border.LineBorder; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 10.0.18 |
||||
* Created by Starryi on 2021/6/25 |
||||
* |
||||
* 可配置图片类型边框的样式设置面板 |
||||
*/ |
||||
public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> { |
||||
public static final String[] BORDER_STYLE = new String[]{ |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow") |
||||
}; |
||||
private static final Dimension BUTTON_SIZE = new Dimension(20, 20); |
||||
public static final int SETTING_LABEL_WIDTH = 60; |
||||
|
||||
protected LayoutBorderStyle style = new LayoutBorderStyle(); |
||||
|
||||
//渲染风格:有无阴影
|
||||
protected UIComboBox borderStyleCombo; |
||||
// 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色)
|
||||
protected BorderLineAndImagePane borderLineAndImagePane; |
||||
//边框圆角或圆角裁剪
|
||||
protected UISpinner cornerSpinner; |
||||
//主体背景
|
||||
protected BackgroundSpecialPane backgroundPane; |
||||
//主体背景透明度
|
||||
protected UIPercentDragPane backgroundOpacityPane; |
||||
|
||||
// 标题可见
|
||||
protected UICheckBox titleVisibleCheckbox; |
||||
//标题文字内容
|
||||
protected TinyFormulaPane titleTextPane; |
||||
//标题字体格式
|
||||
protected UIComboBox titleFontFamilyComboBox; |
||||
//标题字体大小
|
||||
protected UIComboBox titleFontSizeComboBox; |
||||
//标题字体颜色
|
||||
protected UIColorButton titleFontColorSelectPane; |
||||
//标题字体特殊效果:粗体、斜体、下划线
|
||||
private UIToggleButton titleFontBoldButton; |
||||
private UIToggleButton titleFontItalicButton; |
||||
private UIToggleButton titleFontUnderlineButton; |
||||
// private LineComboBox titleFontUnderlineCombo; // 目前前端仅支持短横线类型的下划线,因此设计器端暂时就不展示线型选择框了,待后续优化
|
||||
// 标题图文混排
|
||||
protected TitleInsetImagePane titleInsetImagePane; |
||||
//对齐方式
|
||||
protected UIButtonGroup titleAlignPane; |
||||
//标题整体背景
|
||||
protected BackgroundSpecialPane titleBackgroundPane; |
||||
//标题背景透明度
|
||||
protected UIPercentDragPane titleBackgroundOpacityPane; |
||||
|
||||
public LayoutStylePane() { |
||||
this.initLayout(); |
||||
} |
||||
|
||||
protected void initLayout() { |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
|
||||
JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
boolean currentIsRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane(); |
||||
|
||||
JPanel titlePane = createTitleStylePane(); |
||||
if (titlePane != null) { |
||||
container.add(titlePane, BorderLayout.NORTH); |
||||
if (currentIsRootLayout) { |
||||
titlePane.setVisible(false); |
||||
} |
||||
} |
||||
|
||||
//界面上表单主体只有背景和透明度可以设置
|
||||
JPanel mainStylePane = currentIsRootLayout ? createMainStylePane4RootLayout() : createMainStylePane4WidgetLayout(); |
||||
if (mainStylePane != null) { |
||||
container.add(mainStylePane, BorderLayout.CENTER); |
||||
} |
||||
|
||||
this.add(container, BorderLayout.CENTER); |
||||
} |
||||
|
||||
protected void initMainComponents() { |
||||
borderStyleCombo = new UIComboBox(BORDER_STYLE); |
||||
borderLineAndImagePane = new BorderLineAndImagePane(); |
||||
cornerSpinner = new UISpinner(0,1000,1,0); |
||||
backgroundPane = new LayoutBackgroundSpecialPane(); |
||||
backgroundOpacityPane = new UIPercentDragPane(); |
||||
} |
||||
|
||||
protected JPanel createMainStylePane4WidgetLayout() { |
||||
initMainComponents(); |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p, p, p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Frame_Style")), null}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), borderStyleCombo}, |
||||
{this.borderLineAndImagePane, null}, |
||||
{this.createMainBackgroundAndOpacityPane(), null}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(new BottomLineBorder()); |
||||
container.add(contentPane, BorderLayout.NORTH); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected JPanel createMainStylePane4RootLayout() { |
||||
initMainComponents(); |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Frame_Style")), null}, |
||||
{this.createMainBackgroundAndOpacityPane(), null}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(new BottomLineBorder()); |
||||
container.add(contentPane, BorderLayout.NORTH); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected JPanel createMainBackgroundAndOpacityPane() { |
||||
return createBackgroundAndOpacityPane( |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Background"), |
||||
this.backgroundPane, |
||||
this.backgroundOpacityPane); |
||||
} |
||||
|
||||
protected void initTitleComponents() { |
||||
titleVisibleCheckbox = new UICheckBox(); |
||||
|
||||
titleTextPane = new TinyFormulaPane(); |
||||
|
||||
titleFontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); |
||||
titleFontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); |
||||
|
||||
titleFontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); |
||||
titleFontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); |
||||
|
||||
titleFontColorSelectPane = new UIColorButton(); |
||||
titleFontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); |
||||
titleFontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); |
||||
|
||||
titleFontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); |
||||
titleFontBoldButton.setPreferredSize(BUTTON_SIZE); |
||||
titleFontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); |
||||
titleFontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); |
||||
|
||||
titleFontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); |
||||
titleFontItalicButton.setPreferredSize(BUTTON_SIZE); |
||||
titleFontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); |
||||
titleFontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); |
||||
|
||||
titleFontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); |
||||
titleFontUnderlineButton.setPreferredSize(BUTTON_SIZE); |
||||
titleFontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); |
||||
titleFontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); |
||||
|
||||
// titleFontUnderlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY);
|
||||
// titleFontUnderlineCombo.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Line_Style"));
|
||||
|
||||
titleInsetImagePane = new TitleInsetImagePane(); |
||||
|
||||
titleAlignPane = new UIButtonGroup<Integer>( |
||||
new Icon[] { |
||||
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), |
||||
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), |
||||
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png") |
||||
}, |
||||
new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}); |
||||
titleAlignPane.setAllToolTips( |
||||
new String[] { |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right") |
||||
}); |
||||
|
||||
titleBackgroundPane = new LayoutBackgroundSpecialPane(); |
||||
|
||||
titleBackgroundOpacityPane = new UIPercentDragPane(); |
||||
} |
||||
|
||||
protected JPanel createTitleStylePane() { |
||||
initTitleComponents(); |
||||
|
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p,p,p,p,p,p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
final JPanel bottomPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), titleTextPane}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), titleFontFamilyComboBox}, |
||||
{null, createTitleFontButtonPane()}, |
||||
{titleInsetImagePane, null}, |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), titleAlignPane}, |
||||
{this.createTitleBackgroundAndOpacityPane(), null}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||
bottomPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||
bottomPane.setVisible(false); |
||||
|
||||
JPanel visibleComposedPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
|
||||
titleVisibleCheckbox.setSelected(false); |
||||
visibleComposedPane.add(titleVisibleCheckbox, BorderLayout.WEST); |
||||
visibleComposedPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER); |
||||
|
||||
JPanel topPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title")), null}, |
||||
{visibleComposedPane, null} |
||||
}, new double[]{p, p}, new double[]{SETTING_LABEL_WIDTH, p}, IntervalConstants.INTERVAL_L1); |
||||
topPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(new BottomLineBorder()); |
||||
container.add(topPane, BorderLayout.NORTH); |
||||
container.add(bottomPane, BorderLayout.CENTER); |
||||
|
||||
titleVisibleCheckbox.addChangeListener(new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
bottomPane.setVisible(titleVisibleCheckbox.isSelected()); |
||||
} |
||||
}); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected JPanel createTitleFontButtonPane(){ |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p}; |
||||
double[] columnSize = {f, p, p, p, p}; |
||||
|
||||
JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { |
||||
{titleFontSizeComboBox, titleFontColorSelectPane, titleFontItalicButton, titleFontBoldButton, titleFontUnderlineButton}, |
||||
}, rowSize, columnSize, IntervalConstants.INTERVAL_W0); |
||||
|
||||
JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
containerPane.add(buttonPane, BorderLayout.NORTH); |
||||
// containerPane.add(titleFontUnderlineCombo, BorderLayout.CENTER);
|
||||
|
||||
// titleFontUnderlineCombo.setVisible(false);
|
||||
// titleFontUnderlineButton.addChangeListener(new ChangeListener() {
|
||||
// @Override
|
||||
// public void stateChanged(ChangeEvent e) {
|
||||
// titleFontUnderlineCombo.setVisible(titleFontUnderlineButton.isSelected());
|
||||
// }
|
||||
// });
|
||||
|
||||
return containerPane; |
||||
} |
||||
|
||||
protected JPanel createTitleBackgroundAndOpacityPane() { |
||||
return createBackgroundAndOpacityPane( |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background"), |
||||
titleBackgroundPane, |
||||
titleBackgroundOpacityPane); |
||||
} |
||||
|
||||
@Override |
||||
public LayoutBorderStyle updateBean() { |
||||
LayoutBorderStyle style = new LayoutBorderStyle(); |
||||
updateMain(style); |
||||
updateTitle(style); |
||||
return style; |
||||
} |
||||
|
||||
protected void updateMain(LayoutBorderStyle style) { |
||||
if (borderStyleCombo != null) { |
||||
style.setBorderStyle(borderStyleCombo.getSelectedIndex()); |
||||
} |
||||
if (cornerSpinner != null) { |
||||
style.setBorderRadius((int) cornerSpinner.getValue()); |
||||
} |
||||
if (borderLineAndImagePane != null) { |
||||
borderLineAndImagePane.updateBean(style); |
||||
} |
||||
if (backgroundPane != null) { |
||||
style.setBackground(backgroundPane.update()); |
||||
} |
||||
if (backgroundOpacityPane != null) { |
||||
style.setAlpha((float)backgroundOpacityPane.updateBean()); |
||||
} |
||||
} |
||||
|
||||
protected void updateTitle(LayoutBorderStyle style) { |
||||
style.setType(titleVisibleCheckbox != null && titleVisibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD); |
||||
TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); |
||||
title.setTextObject(titleTextPane.updateBean()); |
||||
FRFont frFont = title.getFrFont(); |
||||
frFont = frFont.applySize((Integer) titleFontSizeComboBox.getSelectedItem()); |
||||
frFont = frFont.applyName(titleFontFamilyComboBox.getSelectedItem().toString()); |
||||
frFont = frFont.applyForeground(titleFontColorSelectPane.getColor()); |
||||
frFont = updateTitleFontItalicBold(frFont); |
||||
// int line = titleFontUnderlineButton.isSelected() ? this.titleFontUnderlineCombo.getSelectedLineStyle() : Constants.LINE_NONE;
|
||||
int line = titleFontUnderlineButton.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE; |
||||
frFont = frFont.applyUnderline(line); |
||||
title.setFrFont(frFont); |
||||
title.setPosition((Integer) titleAlignPane.getSelectedItem()); |
||||
titleInsetImagePane.updateBean(title); |
||||
title.setBackground(titleBackgroundPane.update()); |
||||
title.setBackgroundOpacity((float)titleBackgroundOpacityPane.updateBean()); |
||||
style.setTitle(title); |
||||
} |
||||
|
||||
private FRFont updateTitleFontItalicBold(FRFont frFont) { |
||||
int italic_bold = frFont.getStyle(); |
||||
boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC); |
||||
boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC); |
||||
if (titleFontItalicButton.isSelected() && !isItalic) { |
||||
italic_bold += Font.ITALIC; |
||||
} else if (!titleFontItalicButton.isSelected() && isItalic) { |
||||
italic_bold -= Font.ITALIC; |
||||
} |
||||
frFont = frFont.applyStyle(italic_bold); |
||||
if (titleFontBoldButton.isSelected() && !isBold) { |
||||
italic_bold += Font.BOLD; |
||||
} else if (!titleFontBoldButton.isSelected() && isBold) { |
||||
italic_bold -= Font.BOLD; |
||||
} |
||||
frFont = frFont.applyStyle(italic_bold); |
||||
return frFont; |
||||
} |
||||
|
||||
@Override |
||||
public void populateBean(LayoutBorderStyle style) { |
||||
if(this.style == null) { |
||||
this.style = new LayoutBorderStyle(); |
||||
} |
||||
this.style.setStyle(style); |
||||
|
||||
populateMain(); |
||||
populateTitle(); |
||||
} |
||||
|
||||
protected void populateMain() { |
||||
if (this.borderStyleCombo != null) { |
||||
this.borderStyleCombo.setSelectedIndex(style.getBorderStyle()); |
||||
} |
||||
if (this.borderLineAndImagePane != null) { |
||||
this.borderLineAndImagePane.populateBean(style); |
||||
} |
||||
if (this.backgroundPane != null) { |
||||
this.backgroundPane.populateBean(style.getBackground()); |
||||
if (this.backgroundOpacityPane != null) { |
||||
this.backgroundOpacityPane.populateBean(style.getAlpha()); |
||||
} |
||||
} |
||||
if (this.cornerSpinner != null) { |
||||
this.cornerSpinner.setValue(style.getBorderRadius()); |
||||
} |
||||
} |
||||
|
||||
protected void populateTitle() { |
||||
TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle(); |
||||
widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; |
||||
titleVisibleCheckbox.setSelected(style.getType() != LayoutBorderStyle.STANDARD); |
||||
|
||||
this.titleTextPane.populateBean(widgetTitle.getTextObject().toString()); |
||||
|
||||
FRFont frFont = widgetTitle.getFrFont(); |
||||
this.titleFontSizeComboBox.setSelectedItem(frFont.getSize()); |
||||
this.titleFontFamilyComboBox.setSelectedItem(frFont.getFamily()); |
||||
this.titleFontColorSelectPane.setColor(frFont.getForeground()); |
||||
this.titleFontColorSelectPane.repaint(); |
||||
titleFontBoldButton.setSelected(frFont.isBold()); |
||||
titleFontItalicButton.setSelected(frFont.isItalic()); |
||||
|
||||
int line = frFont.getUnderline(); |
||||
if (line == Constants.LINE_NONE) { |
||||
titleFontUnderlineButton.setSelected(false); |
||||
// titleFontUnderlineCombo.setVisible(false);
|
||||
} else { |
||||
titleFontUnderlineButton.setSelected(true); |
||||
// titleFontUnderlineCombo.setVisible(true);
|
||||
// this.titleFontUnderlineCombo.setSelectedLineStyle(line);
|
||||
} |
||||
|
||||
titleAlignPane.setSelectedItem(widgetTitle.getPosition()); |
||||
titleInsetImagePane.populateBean(widgetTitle); |
||||
titleBackgroundPane.populateBean(widgetTitle.getBackground()); |
||||
titleBackgroundOpacityPane.populateBean(widgetTitle.getBackgroundOpacity()); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style"); |
||||
} |
||||
|
||||
private static JPanel createBackgroundAndOpacityPane(String name, BackgroundSpecialPane backgroundPane, UIPercentDragPane opacityPane) { |
||||
JPanel container = new JPanel(); |
||||
container.setLayout(new BorderLayout(0, 6)); |
||||
|
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
// 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐
|
||||
JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); |
||||
backgroundLabelPane.add(new UILabel(name), BorderLayout.NORTH); |
||||
|
||||
JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{backgroundLabelPane, backgroundPane} |
||||
}, |
||||
new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
|
||||
JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{new UILabel(""), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, |
||||
{new UILabel(""), opacityPane} |
||||
}, |
||||
new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||
|
||||
container.add(backgroundComposedPane, BorderLayout.NORTH, 0); |
||||
container.add(opacityComposedPane, BorderLayout.CENTER, 1); |
||||
|
||||
opacityComposedPane.setVisible(false); |
||||
|
||||
backgroundPane.addChangeListener(new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
Background background = backgroundPane.update(); |
||||
opacityComposedPane.setVisible(background != null); |
||||
} |
||||
}); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
protected static class BottomLineBorder extends LineBorder { |
||||
|
||||
public BottomLineBorder() { |
||||
super(Color.lightGray, 1); |
||||
} |
||||
|
||||
@Override |
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
Color oldColor = g2d.getColor(); |
||||
g2d.setColor(this.lineColor); |
||||
GraphHelper.drawLine(g, 0, height, width, height, 1); |
||||
g2d.setColor(oldColor); |
||||
} |
||||
} |
||||
|
||||
protected static class LayoutBackgroundSpecialPane extends BackgroundSpecialPane { |
||||
@Override |
||||
protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { |
||||
return new GradientBackgroundQuickPane(140); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,320 @@
|
||||
package com.fr.design.gui.xpane; |
||||
|
||||
import com.fr.base.Style; |
||||
import com.fr.base.background.ImageBackground; |
||||
import com.fr.base.background.ImageFileBackground; |
||||
import com.fr.design.border.UIRoundedBorder; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.designer.IntervalConstants; |
||||
import com.fr.design.event.UIObserver; |
||||
import com.fr.design.event.UIObserverListener; |
||||
import com.fr.design.gui.frpane.ImgChooseWrapper; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.ispinner.UISpinner; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.backgroundpane.ImagePreviewPane; |
||||
import com.fr.design.style.background.image.ImageFileChooser; |
||||
import com.fr.design.widget.ui.designer.component.UIBoundSpinner; |
||||
import com.fr.form.ui.WidgetTitle; |
||||
import com.fr.general.Background; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.general.ImageWithSuffix; |
||||
import com.fr.general.act.TitlePacker; |
||||
import com.fr.stable.Constants; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import javax.swing.plaf.basic.BasicButtonUI; |
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseListener; |
||||
import java.awt.geom.RoundRectangle2D; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 10.0.18 |
||||
* Created by Starryi on 2021/7/3 |
||||
*/ |
||||
public class TitleInsetImagePane extends JPanel implements UIObserver { |
||||
private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH; |
||||
private final int DELETE_BUTTON_SIZE = 24; |
||||
private final int IMAGE_PREVIEW_SIZE = 145; |
||||
private final Color IMAGE_PREVIEW_OVERLAY_COLOR = new Color(255, 255, 255, 51); |
||||
private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); |
||||
private final int DEFAULT_INSET_LOCATION_INDEX = 0; |
||||
private final int DEFAULT_INSET_PADDING = 10; |
||||
|
||||
private UIObserverListener uiObserverListener; |
||||
|
||||
private UIButton imageChooseButton; |
||||
private UIButton imageDeleteButton; |
||||
private ImagePreviewPane imagePreviewPane; |
||||
private UIButtonGroup<Integer> imageLocationPane; |
||||
private UISpinner imagePaddingPane; |
||||
|
||||
private ImageFileChooser imageFileChooser; |
||||
|
||||
public TitleInsetImagePane() { |
||||
this.initComponents(); |
||||
this.initLayout(); |
||||
} |
||||
|
||||
private JPanel createImageChooseComposedPane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
return TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{ |
||||
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset")), this.imageChooseButton}, |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||
} |
||||
|
||||
private JPanel createImageContentComposedPane() { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] rowSize = {p, p, p, p, p}; |
||||
double[] columnSize = {SETTING_LABEL_WIDTH, f}; |
||||
|
||||
JPanel deletableImagePreviewPane = new JPanel(); |
||||
deletableImagePreviewPane.setLayout(null); |
||||
deletableImagePreviewPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 5)); |
||||
deletableImagePreviewPane.setPreferredSize(new Dimension(IMAGE_PREVIEW_SIZE, IMAGE_PREVIEW_SIZE)); |
||||
JPanel overlayPane = new JPanel(); |
||||
overlayPane.setPreferredSize(new Dimension(IMAGE_PREVIEW_SIZE - 2, IMAGE_PREVIEW_SIZE - 2)); |
||||
overlayPane.setBackground(IMAGE_PREVIEW_OVERLAY_COLOR); |
||||
imagePreviewPane.setBounds(0, 0, IMAGE_PREVIEW_SIZE, IMAGE_PREVIEW_SIZE); |
||||
overlayPane.setBounds(1, 1, IMAGE_PREVIEW_SIZE - 2, IMAGE_PREVIEW_SIZE - 2); |
||||
imageDeleteButton.setBounds(IMAGE_PREVIEW_SIZE - DELETE_BUTTON_SIZE, 0, DELETE_BUTTON_SIZE, DELETE_BUTTON_SIZE); |
||||
deletableImagePreviewPane.add(imageDeleteButton, 0); |
||||
deletableImagePreviewPane.add(overlayPane, 1); |
||||
deletableImagePreviewPane.add(imagePreviewPane, 2); |
||||
|
||||
overlayPane.setVisible(false); |
||||
imageDeleteButton.setVisible(false); |
||||
imageDeleteButton.setEnabled(false); |
||||
deletableImagePreviewPane.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
super.mouseEntered(e); |
||||
overlayPane.setVisible(true); |
||||
imageDeleteButton.setVisible(true); |
||||
imageDeleteButton.setEnabled(true); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
super.mouseExited(e); |
||||
int x = e.getX(); |
||||
int y = e.getY(); |
||||
if (x <= 0 || getWidth() <= x || y <= 0 || y >= getHeight()) { |
||||
overlayPane.setVisible(false); |
||||
imageDeleteButton.setVisible(false); |
||||
imageDeleteButton.setEnabled(false); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
return TableLayoutHelper.createCommonTableLayoutPane( |
||||
new JComponent[][]{ |
||||
{null, deletableImagePreviewPane}, |
||||
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Location"))}, |
||||
{null, this.imageLocationPane}, |
||||
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Padding"))}, |
||||
{null, this.imagePaddingPane} |
||||
}, |
||||
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||
} |
||||
|
||||
private void initImageFileChooserIfNotExist() { |
||||
if (imageFileChooser == null) { |
||||
imageFileChooser = new ImageFileChooser(); |
||||
imageFileChooser.setMultiSelectionEnabled(false); |
||||
} |
||||
} |
||||
|
||||
private void initComponents() { |
||||
imageChooseButton = new UIButton(IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_choose_inset.png")); |
||||
|
||||
imageDeleteButton = new OpaqueColorButton( |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_delete_inset.png"), |
||||
new Color(51, 51, 52, 178), |
||||
2); |
||||
imageDeleteButton.setPreferredSize(new Dimension(DELETE_BUTTON_SIZE, DELETE_BUTTON_SIZE)); |
||||
|
||||
imagePreviewPane = new ImagePreviewPane(); |
||||
imagePreviewPane.setImageStyle(DEFAULT_IMAGE_LAYOUT_STYLE); |
||||
imagePreviewPane.setPreferredSize(new Dimension(IMAGE_PREVIEW_SIZE, IMAGE_PREVIEW_SIZE)); |
||||
|
||||
imageLocationPane = new UIButtonGroup<Integer>(new Icon[][]{ |
||||
{ |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_left_selected.png"), |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_left_unselected.png") |
||||
}, |
||||
{ |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_both_selected.png"), |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_both_unselected.png") |
||||
}, |
||||
{ |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_right_selected.png"), |
||||
IOUtils.readIcon("/com/fr/design/images/buttonicon/icon_inset_right_unselected.png") |
||||
}, |
||||
}); |
||||
imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
imageLocationPane.setAllToolTips(new String[]{ |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Left_Tooltip"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Both_Tooltip"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Right_Tooltip"), |
||||
}); |
||||
|
||||
imagePaddingPane = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, WidgetTitle.DEFAULT_INSET_PADDING); |
||||
imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
} |
||||
|
||||
private void initLayout() { |
||||
|
||||
|
||||
this.setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); |
||||
|
||||
add(createImageChooseComposedPane(), BorderLayout.NORTH, 0); |
||||
add(createImageContentComposedPane(), BorderLayout.CENTER, 1); |
||||
|
||||
getComponent(1).setVisible(false); |
||||
|
||||
this.imageChooseButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
initImageFileChooserIfNotExist(); |
||||
|
||||
int returnVal = imageFileChooser.showOpenDialog(DesignerContext.getDesignerFrame()); |
||||
ImgChooseWrapper.getInstance(imagePreviewPane, imageFileChooser, DEFAULT_IMAGE_LAYOUT_STYLE, new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
if (!getComponent(1).isVisible()) { |
||||
imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
getComponent(1).setVisible(true); |
||||
} |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}).dealWithImageFile(returnVal); |
||||
} |
||||
}); |
||||
this.imageDeleteButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
imagePreviewPane.setImageWithSuffix(null); |
||||
imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
getComponent(1).setVisible(false); |
||||
|
||||
fireStateChanged(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void populateBean(TitlePacker packer) { |
||||
Background insetImage = packer.getInsetImage(); |
||||
if (insetImage instanceof ImageBackground) { |
||||
ImageWithSuffix image = ((ImageBackground) insetImage).getImageWithSuffix(); |
||||
if (image != null) { |
||||
this.imagePreviewPane.setImageWithSuffix(image); |
||||
|
||||
if (!packer.isInsetRelativeTextLeft()) { |
||||
this.imageLocationPane.setSelectedIndex(2); |
||||
} else if (!packer.isInsetRelativeTextRight()) { |
||||
this.imageLocationPane.setSelectedIndex(0); |
||||
} else { |
||||
this.imageLocationPane.setSelectedIndex(1); |
||||
} |
||||
|
||||
this.imagePaddingPane.setValue(packer.getInsetImagePadding()); |
||||
|
||||
getComponent(1).setVisible(true); |
||||
|
||||
return; |
||||
} |
||||
} |
||||
|
||||
this.imagePreviewPane.setImageWithSuffix(null); |
||||
this.imageLocationPane.setSelectedIndex(DEFAULT_INSET_LOCATION_INDEX); |
||||
this.imagePaddingPane.setValue(DEFAULT_INSET_PADDING); |
||||
|
||||
getComponent(1).setVisible(false); |
||||
} |
||||
|
||||
public void updateBean(TitlePacker packer) { |
||||
Image image = imagePreviewPane.getImageWithSuffix(); |
||||
if (image != null) { |
||||
packer.setInsetImage(new ImageFileBackground(image, Constants.IMAGE_DEFAULT)); |
||||
|
||||
int imageLocationIndex = this.imageLocationPane.getSelectedIndex(); |
||||
packer.setInsetRelativeTextLeft(imageLocationIndex == 0 || imageLocationIndex == 1); |
||||
packer.setInsetRelativeTextRight(imageLocationIndex == 2 || imageLocationIndex == 1); |
||||
|
||||
packer.setInsetImagePadding((int) this.imagePaddingPane.getValue()); |
||||
} else { |
||||
packer.setInsetImage(null); |
||||
packer.setInsetImagePadding(WidgetTitle.DEFAULT_INSET_PADDING); |
||||
packer.setInsetRelativeTextLeft(WidgetTitle.DEFAULT_INSET_LEFT); |
||||
packer.setInsetRelativeTextRight(WidgetTitle.DEFAULT_INSET_RIGHT); |
||||
} |
||||
} |
||||
|
||||
private void fireStateChanged() { |
||||
if (uiObserverListener != null) { |
||||
uiObserverListener.doChange(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerChangeListener(UIObserverListener listener) { |
||||
this.uiObserverListener = listener; |
||||
} |
||||
|
||||
@Override |
||||
public boolean shouldResponseChangeListener() { |
||||
return true; |
||||
} |
||||
|
||||
private static class OpaqueColorButton extends UIButton { |
||||
private final Color color; |
||||
private final int radius; |
||||
|
||||
public OpaqueColorButton(Icon icon, Color color, int radius) { |
||||
super(icon); |
||||
setUI(new BasicButtonUI()); |
||||
setOpaque(true); |
||||
setBorderPainted(false); |
||||
setBorder(null); |
||||
setFocusPainted(false); |
||||
setContentAreaFilled(false); |
||||
this.color = color; |
||||
this.radius = radius; |
||||
} |
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
Color oldColor = g2d.getColor(); |
||||
|
||||
Shape shape = new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), radius, radius); |
||||
g2d.clip(shape); |
||||
g2d.setColor(color); |
||||
g2d.fillRect(0, 0, getWidth(), getHeight()); |
||||
|
||||
g2d.setColor(oldColor); |
||||
super.paint(g); |
||||
} |
||||
} |
||||
} |