diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index 43d3edd357..c95f1e5cab 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -308,7 +308,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada private static boolean asyncInitEnvManager() { AtomicBoolean noEx = new AtomicBoolean(false); - OptimizeUtil.open(DesignerEnvManager.class.getSimpleName().toLowerCase(), OptimizeUtil.Module.COMMON, () -> { + OptimizeUtil.initiateOpen(DesignerEnvManager.class.getSimpleName().toLowerCase(), () -> { try { designerEnvManager.initElements(designerEnvManager.getDesignerEnvFile()); noEx.set(true); @@ -899,13 +899,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada } public boolean isCloudAnalyticsDelay() { - return designerPushUpdateConfigManager.isCloudAnalyticsDelay(); + return designerPushUpdateConfigManager.isCloudAnalyticsDelay() || designerPushUpdateConfigManager.isUseCloudAnalyticsDelayFirst(); } public void setCloudAnalyticsDelay(boolean cloudAnalyticsDelay) { designerPushUpdateConfigManager.setCloudAnalyticsDelay(cloudAnalyticsDelay); } + public void setUseCloudAnalyticsDelayFirst(boolean useCloudAnalyticsDelayFirst) { + designerPushUpdateConfigManager.setUseCloudAnalyticsDelayFirst(useCloudAnalyticsDelayFirst); + } + + /** * 设计器登录相关配置 */ diff --git a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java index 1f3055d40a..8eb4a9afb7 100644 --- a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java +++ b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java @@ -1,9 +1,6 @@ package com.fr.design; import com.fr.common.report.ReportState; -import com.fr.design.env.processor.RemoteDesignerWorkspaceInfoProcessor; -import com.fr.design.mainframe.manager.clip.TemplateTreeClipboard; -import com.fr.design.plugin.remind.PluginErrorDesignReminder; import com.fr.design.data.DesignTableDataManager; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; @@ -14,13 +11,16 @@ import com.fr.design.env.DesignerWorkspaceInfoContext; import com.fr.design.env.DesignerWorkspaceType; import com.fr.design.env.RemoteDesignerWorkspaceInfo; import com.fr.design.env.RemoteWorkspace; +import com.fr.design.env.processor.RemoteDesignerWorkspaceInfoProcessor; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.SaveSomeTemplatePane; import com.fr.design.file.TemplateTreePane; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.manager.clip.TemplateTreeClipboard; import com.fr.design.notification.NotificationCenter; +import com.fr.design.plugin.remind.PluginErrorDesignReminder; import com.fr.design.utils.DesignUtils; import com.fr.design.versioncheck.VersionCheckUtils; import com.fr.env.EnvListPane; @@ -31,6 +31,7 @@ import com.fr.invoke.Reflect; import com.fr.json.JSONArray; import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; +import com.fr.performance.profile.PerformancePoint; import com.fr.process.ProcessEventPipe; import com.fr.process.engine.core.CarryMessageEvent; import com.fr.process.engine.core.FineProcessContext; @@ -41,12 +42,14 @@ import com.fr.start.server.ServerTray; import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContextCallback; import com.fr.workspace.Workspace; +import com.fr.workspace.WorkspaceSwitchProcess; import com.fr.workspace.base.WorkspaceAPI; import com.fr.workspace.connect.WorkspaceConnectionInfo; import com.fr.workspace.engine.base.FineObjectPool; import com.fr.workspace.engine.channel.http.FunctionalHttpRequest; import com.fr.workspace.engine.exception.WorkspaceConnectionException; import com.fr.workspace.engine.rpc.WorkspaceProxyPool; +import static javax.swing.JOptionPane.QUESTION_MESSAGE; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -58,12 +61,11 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; -import java.util.HashSet; - -import static javax.swing.JOptionPane.QUESTION_MESSAGE; public class EnvChangeEntrance { private static final String BRANCH_TAG = "#"; @@ -125,48 +127,111 @@ public class EnvChangeEntrance { } } + /** * 切换到新环境 * * @param envName 新工作环境名称 + * @param strategy 提示策略 * @return 是否成功 */ private boolean switch2Env(final String envName, PopTipStrategy strategy) { - DesignerEnvManager envManager = DesignerEnvManager.getEnvManager(); - DesignerWorkspaceInfo selectedEnv = customUserName(envManager.getWorkspaceInfo(envName)); - DesignerWorkspaceInfoContext.setWorkspaceInfo(selectedEnv); - WorkspaceConnectionInfo connectionInfo = selectedEnv.getConnection(); + WorkspaceSwitchProcess lastProcess = WorkContext.getSwitcher().getProcess(); + PerformancePoint performancePoint = PerformancePoint.create(); + + boolean switchStatus = doSwitch2Env(envName, strategy); + + WorkspaceSwitchProcess currentProcess = WorkContext.getSwitcher().getProcess(); + // 如果相同,代表根本没切换 == + if (lastProcess != currentProcess) { + // 记录切换耗时 + recordSwitchInfos(performancePoint, switchStatus); + // 触发切换埋点 + triggerSwitchMetric(); + } + return switchStatus; + } + + /** + * 由云端运维,触发切换埋点 + * 内部空实现 + * 见 实现 + */ + private void triggerSwitchMetric() { + } + + /** + * 切换到新环境 + * 1. 先获取选中的环境 + * 2. 生成工作目录 + * 3. 验证工作目录 + * 4. 触发切换操作 + * 5. 触发可能存在异常的切换后动作 + * 6. 触发切换后动作 + * + * @param envName 新工作环境名称 + * @return 是否成功 + */ + private boolean doSwitch2Env(final String envName, PopTipStrategy strategy) { + + DesignerWorkspaceInfo selectedEnv = getSelectedEnv(envName); try { Workspace workspace = DesignerWorkspaceGenerator.generate(selectedEnv); - boolean checkValid = workspace != null && selectedEnv.checkValid(); - if (!checkValid) { + if (notValid(workspace, selectedEnv)) { return false; } - //如果是相同环境 - if (isSameEnv(workspace)) { - //目前切换到相同环境需要更新一下名字,后续如果有别的操作直接往里面加就行了 - switch2SameEnv(envName); - } else { - //切换到新环境,做下封装 - switch2OtherEnv(workspace, envName); - } - // REPORT-25688如果是war包部署的服务器,给与提示 - if (WorkContext.getCurrent().isWarDeploy()) { - FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_War_Deploy_Tip"), - Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE); - } - //REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录 - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (JTemplate.isValid(template)) { - template.refreshToolArea(); - } - PluginErrorDesignReminder.getInstance().remindStartFailedPlugins(); + doSwitchAction(envName, workspace); + afterSwitchWithEx(); } catch (Exception exception) { // 失败的处理 WorkspaceExceptionHandler.getInstance().handleInSwitch(exception, selectedEnv); return false; } + afterSwitch(); + return true; + } + + private DesignerWorkspaceInfo getSelectedEnv(String envName) { + + DesignerEnvManager envManager = DesignerEnvManager.getEnvManager(); + DesignerWorkspaceInfo selectedEnv = customUserName(envManager.getWorkspaceInfo(envName)); + DesignerWorkspaceInfoContext.setWorkspaceInfo(selectedEnv); + return selectedEnv; + } + + private static boolean notValid(Workspace workspace, DesignerWorkspaceInfo selectedEnv) throws Exception { + boolean checkValid = workspace != null && selectedEnv.checkValid(); + return !checkValid; + } + + private void doSwitchAction(String envName, Workspace workspace) { + + //如果是相同环境 + if (isSameEnv(workspace)) { + //目前切换到相同环境需要更新一下名字,后续如果有别的操作直接往里面加就行了 + switch2SameEnv(envName); + } else { + //切换到新环境,做下封装 + switch2OtherEnv(workspace, envName); + } + } + + private static void afterSwitchWithEx() { + // REPORT-25688如果是war包部署的服务器,给与提示 + if (WorkContext.getCurrent().isWarDeploy()) { + FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_War_Deploy_Tip"), + Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE); + } + //REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录 + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (JTemplate.isValid(template)) { + template.refreshToolArea(); + } + PluginErrorDesignReminder.getInstance().remindStartFailedPlugins(); + } + + private static void afterSwitch() { TemplateTreePane.getInstance().refreshDockingView(); DesignModelAdapter model = DesignModelAdapter.getCurrentModelAdapter(); if (model != null) { @@ -175,7 +240,18 @@ public class EnvChangeEntrance { NotificationCenter.getInstance().clearAllNotifications(); //切换环境后,清空粘贴板里面的内容 TemplateTreeClipboard.getInstance().reset(); - return true; + } + + private static void recordSwitchInfos(PerformancePoint performancePoint, boolean switchSuccess) { + + performancePoint.end(elapsed -> { + WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess(); + Optional.ofNullable(process) + .ifPresent((e) -> { + e.recordSwitchElapsed(elapsed); + e.setSwitchSuccess(switchSuccess); + }); + }); } /** diff --git a/designer-base/src/main/java/com/fr/design/RPCConnectHandlerCenter.java b/designer-base/src/main/java/com/fr/design/RPCConnectHandlerCenter.java new file mode 100644 index 0000000000..eb08789d0d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/RPCConnectHandlerCenter.java @@ -0,0 +1,159 @@ +package com.fr.design; + +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.ui.util.UIUtil; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import com.fr.third.org.apache.http.client.config.RequestConfig; +import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; +import com.fr.third.org.apache.http.client.methods.HttpGet; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; +import com.fr.third.org.apache.http.impl.client.HttpClients; +import com.fr.workspace.WorkContext; +import com.fr.workspace.Workspace; +import com.fr.workspace.WorkspaceEvent; +import com.fr.workspace.base.WorkspaceConstants; +import com.fr.workspace.connect.WorkspaceConnectionInfo; +import com.fr.workspace.engine.channel.WorkspaceChannelFactory; +import com.fr.workspace.engine.exception.WorkspaceConnectionException; + +import javax.swing.JOptionPane; +import javax.swing.UIManager; + +/** + * RPC连接处理中心 + * + * @author Roger + * @since 11.0 + * Created on 2023/12/13 + */ +public class RPCConnectHandlerCenter { + + private static volatile boolean alerting = false; + private static final int TIMEOUT = 5000; + + private static Listener listener = new Listener() { + @Override + public void on(Event event, Workspace workspace) { + //暂时先不做重连处理,3次RPC连接失败后提示切换工作目录 + showRPCDisconnectDialog(); + } + }; + + /** + * 开启事件监听 + */ + public static void startListener() { + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.listen(WorkspaceEvent.LostConnect, listener); + } + } + + /** + * 弹窗提示连接断开 + */ + public static void showRPCDisconnectDialog() { + UIUtil.invokeLaterIfNeeded(RPCConnectHandlerCenter::showDialog); + } + + /** + * RPC连接测试 + * + * @param info 连接信息 + * @return 是否连接成功 + */ + public static boolean checkRPCConnect(WorkspaceConnectionInfo info) { + try { + return WorkspaceChannelFactory.testConnection(info); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + return false; + } + } + + /** + * http连接检测,从DesignerSocketIO中移过来的,先保留着 + * + * @param info 连接信息 + * @return 是否连接成功 + */ + public static boolean checkHttpConnect(WorkspaceConnectionInfo info) { + CloseableHttpClient httpclient = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(StableUtils.pathJoin(info.getUrl(), WorkspaceConstants.CONTROLLER_PREFIX, WorkspaceConstants.VT)); + RequestConfig requestConfig = RequestConfig + .custom() + .setConnectTimeout(TIMEOUT) + .setConnectionRequestTimeout(TIMEOUT) + .build(); + httpGet.setConfig(requestConfig); + try { + CloseableHttpResponse response = httpclient.execute(httpGet); + if (isErrorStatus(response.getStatusLine().getStatusCode())) { + //这边nginx做负载,服务器被kill掉,返回的是502,不会抛错,导致checkRPCConnect通过 + //针对500-600的错误码加个判断,其他类型的状态码暂不考虑,如果有遇到再处理,不然怕影响范围大 + throw new WorkspaceConnectionException("Response " + response.getStatusLine().toString()); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + return false; + } + return true; + } + + /** + * 提示连接已经断开,如果已经在提示中了就直接返回 + */ + private static void showDialog() { + if (alerting) { + return; + } + synchronized (RPCConnectHandlerCenter.class) { + if (alerting) { + return; + } + alerting = true; + try { + FineJOptionPane.showMessageDialog( + DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design_Basic_Remote_Disconnected"), + UIManager.getString("OptionPane.messageDialogTitle"), + JOptionPane.ERROR_MESSAGE, + UIManager.getIcon("OptionPane.errorIcon")); + EnvChangeEntrance.getInstance().chooseEnv(); + } finally { + alerting = false; + } + } + } + + /** + * 错误状态码 + * 5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。代码 说明 + * 500 (服务器内部错误) 服务器遇到错误,无法完成请求。 + * 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 + * 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 + * 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 + * 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 + * 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。 + * + * @param status 错误状态码 + * @return 是否是错误状态码 + */ + private static boolean isErrorStatus(int status) { + return status >= 500 && status <= 600; + } + + /** + * 停止事件监听 + */ + public static void stopListener() { + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.stopListen(listener); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 65ed9fc171..f8703275f8 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java @@ -1122,7 +1122,10 @@ public class PreferencePane extends BasicPane { designerEnvManager.setUseOptimizedUPM4Adapter(optimizedUPMFlag); //只有取消掉使用新插件管理器这个选项才需要把useNewPluginFirst置false(意味着用户手动配置了,如果勾选着的话,这个useNewPluginFirst为true就行了) designerEnvManager.setUseNewPluginFirst(optimizedUPMFlag); - designerEnvManager.setCloudAnalyticsDelay(this.cloudAnalyticsDelayCheckBox.isSelected()); + boolean cloudDelayFlag = this.cloudAnalyticsDelayCheckBox.isSelected(); + designerEnvManager.setCloudAnalyticsDelay(cloudDelayFlag); + // cloudDelayFlag默认为true,如果用户手动配置过才会是false,则后续的云端运维配置都按照用户意愿来 + designerEnvManager.setUseCloudAnalyticsDelayFirst(cloudDelayFlag); VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue()); vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected()); diff --git a/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java b/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java index 4720c8e103..9e50551cfc 100644 --- a/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java +++ b/designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java @@ -11,6 +11,11 @@ import com.fr.event.Null; * @date 2019-06-18 */ public enum DesignerLaunchStatus implements Event { + /** + * 界面前置事件初始化完成 + */ + UI_PRE_INIT_COMPLETE, + /** * 初始化环境完成 */ @@ -46,4 +51,14 @@ public enum DesignerLaunchStatus implements Event { status = state; EventDispatcher.fire(DesignerLaunchStatus.getStatus()); } + + /** + * 设置状态并异步触发事件 + * + * @param state 当前启动状态 + */ + public static void setStatusAndAsyncFire(DesignerLaunchStatus state) { + status = state; + EventDispatcher.asyncFire(DesignerLaunchStatus.getStatus()); + } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java index 86e7633be0..ebfd195d8e 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java @@ -1,6 +1,7 @@ package com.fr.design.data.datapane.connect; import com.fr.base.GraphHelper; +import com.fr.data.core.db.dialect.DialectFactory; import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.pool.DBCPConnectionPoolAttr; import com.fr.design.dialog.BasicDialog; @@ -31,6 +32,7 @@ import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -43,7 +45,7 @@ public class DBCPAttrPane extends BasicPane { private static final int ORACLE_DEFAULT_FETCHSIZE = 128; private static final int DB2_DEFAULT_FETCHSIZE = 50; private static final int POSTGRE_DEFAULT_FETCHSIZE = 10000; - private static final int EMPTY_FETCHSIZE = -2; + private static final int INVALID_FETCHSIZE = -1; // carl:DBCP的一些属性 private IntegerEditor DBCP_INITIAL_SIZE = new IntegerEditor(); private IntegerEditor DBCP_MIN_IDLE = new IntegerEditor(); @@ -114,12 +116,25 @@ public class DBCPAttrPane extends BasicPane { this.DBCP_MINEVICTABLEIDLETIMEMILLIS.setValue(dbcpAttr.getMinEvictableIdleTimeMillis() / TIME_MULTIPLE); this.DBCP_NUMTESTSPEREVICTIONRUN.setValue(dbcpAttr.getNumTestsPerEvictionRun()); this.DBCP_TIMEBETWEENEVICTIONRUNSMILLS.setValue(dbcpAttr.getTimeBetweenEvictionRunsMillis()); - Integer fetchSize = DEFAULT_FETCHSIZE_MAP.get(JDBCConnectionDef.getInstance().getDatabaseName()); - if (fetchSize != null) { - if (jdbcDatabase.getFetchSize() == EMPTY_FETCHSIZE) { - this.FETCHSIZE.setText(StringUtils.EMPTY); + + /* + * 填充FetchSize输入框逻辑: + * + * 1. 如果JDBCDatabaseConnection里的fetchSize是有效值(>0),则显示该有效值 + * 2. 如果JDBCDatabaseConnection里的fetchSize是无效值(<=0): + * 2.1 如果我们对这种数据库有默认值(如oracle、db2、pgsql),就显示对应数据库的默认值,因为要避免性能问题,这几种数据库不支持关闭fetchSize + * 2.2 如果我们对这种数据库无默认值,就显示-1 + */ + + int fetchSize = jdbcDatabase.getFetchSize(); + String databaseName = JDBCConnectionDef.getInstance().getDatabaseName(); + if (DialectFactory.isValidFetchSize(fetchSize)) { + this.FETCHSIZE.setText(String.valueOf(fetchSize)); + } else { + if (DEFAULT_FETCHSIZE_MAP.containsKey(databaseName)) { + this.FETCHSIZE.setText(String.valueOf(DEFAULT_FETCHSIZE_MAP.get(databaseName))); } else { - this.FETCHSIZE.setText(jdbcDatabase.getFetchSize() == -1 ? String.valueOf(fetchSize) : String.valueOf(jdbcDatabase.getFetchSize())); + this.FETCHSIZE.setText(String.valueOf(INVALID_FETCHSIZE)); } } } @@ -137,12 +152,34 @@ public class DBCPAttrPane extends BasicPane { dbcpAttr.setMinEvictableIdleTimeMillis(((Number) this.DBCP_MINEVICTABLEIDLETIMEMILLIS.getValue()).intValue() * TIME_MULTIPLE); dbcpAttr.setNumTestsPerEvictionRun(((Number) this.DBCP_NUMTESTSPEREVICTIONRUN.getValue()).intValue()); dbcpAttr.setTimeBetweenEvictionRunsMillis(((Number) this.DBCP_TIMEBETWEENEVICTIONRUNSMILLS.getValue()).intValue()); - Integer fetchSize = DEFAULT_FETCHSIZE_MAP.get(JDBCConnectionDef.getInstance().getDatabaseName()); - if (fetchSize != null) { - if (StringUtils.isEmpty(this.FETCHSIZE.getText())) { - jdbcDatabase.setFetchSize(EMPTY_FETCHSIZE); + + /* + * FetchSize设置逻辑: + * + * 1. 如果客户界面上的fetchSize框留空: + * 1.1 如果我们对这种数据库有默认值(如oracle、db2、pgsql),就存对应数据库的默认值,否则会有性能问题,这几种数据库我们是不支持关闭fetchSize的 + * 1.2 如果我们对这种数据库没有默认值,就置为-1 + * 2. 如果客户界面上的fetchSize框非空: + * 2.1 如果fetchSize是个有效值(>0),就使用该值 + * 2.2 如果fetchSize是个无效值(<=0),就置为-1 + * + * -1带来的结果,就是我们Dialect不会putExecutor,最终不会执行java.sql.Statement.setFetchSize + */ + String fetchSizeText = this.FETCHSIZE.getText(); + String databaseName = JDBCConnectionDef.getInstance().getDatabaseName(); + + if (StringUtils.isEmpty(fetchSizeText)) { + if (DEFAULT_FETCHSIZE_MAP.containsKey(databaseName)) { + Optional.ofNullable(DEFAULT_FETCHSIZE_MAP.get(databaseName)).ifPresent(jdbcDatabase::setFetchSize); + } else { + jdbcDatabase.setFetchSize(INVALID_FETCHSIZE); + } + } else { + int fetchSizeSet = Integer.parseInt(fetchSizeText); + if (DialectFactory.isValidFetchSize(fetchSizeSet)) { + jdbcDatabase.setFetchSize(fetchSizeSet); } else { - jdbcDatabase.setFetchSize(Integer.parseInt(this.FETCHSIZE.getText())); + jdbcDatabase.setFetchSize(INVALID_FETCHSIZE); } } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java index 3c5c2b82a8..11c3f64d64 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java @@ -462,6 +462,7 @@ public abstract class DatabaseConnectionPane implemen } private void checkParameter() { - String[] paramTexts = new String[2]; - paramTexts[0] = this.sqlTextPane.getText(); - paramTexts[1] = this.pageQuery; - Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); + Parameter[] parameters = getParameters(); if (parameters.length < 1 && this.editorPane.update().size() < 1) { return; @@ -443,6 +441,14 @@ public class DBTableDataPane extends AbstractTableDataPane implemen refreshParameters(); } + @NotNull + private Parameter[] getParameters() { + String[] paramTexts = new String[2]; + paramTexts[0] = SqlUtils.clearSqlComments(this.sqlTextPane.getText()); + paramTexts[1] = SqlUtils.clearSqlComments(this.pageQuery); + return ParameterHelper.analyze4Parameters(paramTexts, false); + } + @Override public void populateBean(DBTableData dbTableData) { this.dbTableData = dbTableData; diff --git a/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java b/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java index c9b80ebf72..d4e7ce34a8 100644 --- a/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java +++ b/designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java @@ -167,6 +167,22 @@ public class DeepLinkCore { markPendingURLConsumed(); } + /** + * 符合条件的url才处理 + * + * @param url 接收到的url + * @return true:处理; false:不处理 + */ + public boolean accept(String url) { + UrlBean urlBean = UrlBean.create(url); + for (DeepLink deepLink: deepLinkList) { + if (deepLink.accept(urlBean.getUrl(), urlBean.getHost(), urlBean.getPath(), urlBean.getParams())) { + return true; + } + } + return false; + } + private void performDeepLinks(String url, String host, String path, Map params) { SwingUtilities.invokeLater(new Runnable() { @Override diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java b/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java index d2f1bcc3c2..aa506e679f 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java @@ -153,9 +153,9 @@ public class PluginOperateUtils { public void run() { PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); PluginContext plugin = PluginManager.getContext(pluginMarker); - boolean isRunning = plugin.isRunning(); - PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(isRunning, jsCallback); - changePluginActive(isRunning, pluginMarker, modifyStatusCallback, plugin); + boolean running = plugin.isRunning() || plugin.isPrepare(); + PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(running, jsCallback); + changePluginActive(running, pluginMarker, modifyStatusCallback, plugin); } }); } diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java b/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java index f12f8f8446..85dc24afde 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginUtils.java @@ -270,8 +270,8 @@ public class PluginUtils { jo.put("vendor", pluginContext.getVendor()); jo.put("price", pluginContext.getPrice()); jo.put("requiredJarTime", pluginContext.getRequiredJarTime()); - // 前端需求的active实际上是插件的运行状态,通过isRunning()获取 - jo.put("active", pluginContext.isRunning()); + // 前端需求的active实际上是插件的运行状态,通过isRunning()或isPrepare()获取 + jo.put("active", pluginContext.isRunning() || pluginContext.isPrepare()); jo.put("hidden", pluginContext.isHidden()); jo.put("free", pluginContext.isFree()); jo.put("licDamaged", pluginContext.isLicDamaged()); diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java index 58cb2af5f5..dcfecd81cf 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java @@ -40,6 +40,7 @@ import com.fr.design.gui.itextarea.UITextArea; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java index 93cdc4e4e2..dfece2e133 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java @@ -17,6 +17,7 @@ import com.fr.stable.Nameable; import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; +import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.Icon; import javax.swing.JLabel; @@ -359,6 +360,8 @@ public abstract class JListControlPane extends JControlPane implements ListContr setLayout(new BorderLayout()); this.textLabel = new JLabel(); this.iconLabel = new JLabel(); + this.textLabel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 1)); + this.iconLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 0)); add(this.textLabel, BorderLayout.CENTER); add(this.iconLabel, BorderLayout.WEST); this.iconLabel.setBackground(Color.WHITE); diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FontSizeComboPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/FontSizeComboPane.java similarity index 60% rename from designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FontSizeComboPane.java rename to designer-base/src/main/java/com/fr/design/gui/frpane/FontSizeComboPane.java index 57df97ee12..a89b41d4a1 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FontSizeComboPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/FontSizeComboPane.java @@ -1,7 +1,9 @@ -package com.fr.design.widget.ui.designer.component; +package com.fr.design.gui.frpane; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.collections.CollectionUtils; + import javax.swing.JPanel; import java.awt.BorderLayout; import java.util.Vector; @@ -13,15 +15,22 @@ public class FontSizeComboPane extends JPanel{ private static final int MAX_FONT_SIZE = 100; private UIComboBox comboBox; public FontSizeComboPane(){ - initComponent(); + this(null); } - public void initComponent(){ - this.setLayout(FRGUIPaneFactory.createBorderLayout()); - Vector integerList = new Vector(); - for (int i = 1; i < MAX_FONT_SIZE; i++) { - integerList.add(i); + + public FontSizeComboPane(Vector fontSizes){ + initComponent(fontSizes); + } + + public void initComponent(Vector fontSizes){ + if(CollectionUtils.isEmpty(fontSizes)) { + fontSizes = new Vector<>(); + for (int i = 1; i < MAX_FONT_SIZE; i++) { + fontSizes.add(i); + } } - comboBox = new UIComboBox(integerList); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + comboBox = new UIComboBox(fontSizes); comboBox.setEditable(true); this.add(comboBox, BorderLayout.CENTER); } diff --git a/designer-base/src/main/java/com/fr/design/lock/LockFileReSaveEnum.java b/designer-base/src/main/java/com/fr/design/lock/LockFileReSaveEnum.java new file mode 100644 index 0000000000..3feeb0a0b5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/lock/LockFileReSaveEnum.java @@ -0,0 +1,64 @@ +package com.fr.design.lock; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.TemplateTreePane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.utils.TemplateUtils; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; + +/** + * 被锁住的文件重新保存副本时的处理枚举类 + * + * @author Roger + * @since 11.0 + * Created on 2023/12/21 + */ +public enum LockFileReSaveEnum { + + /** + * 保存目录树里面的模板副本 + */ + TEMPLATE_TREE() { + @Override + public void action() { + FileNode node = TemplateTreePane.getInstance().getFileNode(); + if (node == null) { + return; + } + final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getFilePath()); + TemplateUtils.createAndReOpenTemplate( + Toolkit.i18nText("Fine_Design_Template_Lock_Copy"), + new FileNodeFILE(new FileNode(selectedFilePath, false)), + false, + true); + } + }, + + /** + * 保存设计器里面已经打开的模板副本 + */ + HISTORY_TEMPLATE_CACHE() { + @Override + public void action() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (JTemplate.isValid(template)) { + TemplateUtils.createAndOpenTemplate( + Toolkit.i18nText("Fine_Design_Template_Backup"), + new FileNodeFILE(new FileNode(template.getPath(), false)), + true, + true, + //另存之后需要关闭的模板 + template); + } + } + }; + + /** + * 如何保存模板副本 + */ + public abstract void action(); +} diff --git a/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java b/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java index 44c95c44c2..c183dac2e9 100644 --- a/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java +++ b/designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java @@ -8,15 +8,14 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrameFileDealerPane; -import com.fr.design.utils.TemplateUtils; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.file.FileNodeFILE; -import com.fr.file.filetree.FileNode; import com.fr.general.IOUtils; -import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; -import com.fr.stable.project.ProjectConstants; import com.fr.workspace.base.UserInfo; + +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; @@ -24,9 +23,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import javax.swing.BorderFactory; -import javax.swing.JDialog; -import javax.swing.JPanel; /** * @author hades @@ -37,8 +33,11 @@ public class LockInfoDialog extends JDialog { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); - public LockInfoDialog(UserInfo userInfo) { + private final LockFileReSaveEnum saveEnum; + + public LockInfoDialog(UserInfo userInfo, LockFileReSaveEnum saveEnum) { super(DesignerContext.getDesignerFrame()); + this.saveEnum = saveEnum; JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); panel.add(createContentPane(userInfo), BorderLayout.CENTER); @@ -94,16 +93,7 @@ public class LockInfoDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { dispose(); - FileNode node = TemplateTreePane.getInstance().getFileNode(); - if (node == null) { - return; - } - final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getFilePath()); - TemplateUtils.createAndReOpenTemplate( - Toolkit.i18nText("Fine_Design_Template_Lock_Copy"), - new FileNodeFILE(new FileNode(selectedFilePath, false)), - false, - true); + saveEnum.action(); } }); cancelButton.addActionListener(new ActionListener() { @@ -118,9 +108,25 @@ public class LockInfoDialog extends JDialog { } + /** + * 显示模板被人锁住了的弹窗信息 + * + * @param userInfo 拥有锁的用户信息 + */ public static void show(UserInfo userInfo) { DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode()); - new LockInfoDialog(userInfo); + new LockInfoDialog(userInfo, LockFileReSaveEnum.TEMPLATE_TREE); + } + + /** + * 显示模板被人锁住了的弹窗信息,并以指定方式保存副本模板 + * + * @param userInfo 拥有锁的用户信息 + * @param saveEnum 指定保存副本模板的处理方式 + */ + public static void show(UserInfo userInfo, LockFileReSaveEnum saveEnum) { + DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode()); + new LockInfoDialog(userInfo, saveEnum); } } diff --git a/designer-base/src/main/java/com/fr/design/lock/TemplateLockInfoReSave.java b/designer-base/src/main/java/com/fr/design/lock/TemplateLockInfoReSave.java new file mode 100644 index 0000000000..f1f927abb1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/lock/TemplateLockInfoReSave.java @@ -0,0 +1,56 @@ +package com.fr.design.lock; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.log.FineLoggerFactory; +import com.fr.report.lock.LockInfoOperator; +import com.fr.stable.collections.CollectionUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.Workspace; +import com.fr.workspace.WorkspaceEvent; + +import java.util.List; + +/** + * 更新模板锁信息 + * + * @author Roger + * @since 11.0 + * Created on 2023/12/11 + */ +public class TemplateLockInfoReSave { + + private static Listener listener = new Listener() { + @Override + public void on(Event event, Workspace workspace) { + List> templates = HistoryTemplateListCache.getInstance().getHistoryList(); + if (CollectionUtils.isEmpty(templates)) { + return; + } + String[] paths = templates.stream().map(JTemplate::getPath).toArray(String[]::new); + String[] lockedPath = WorkContext.getCurrent().get(LockInfoOperator.class).lockTemplates(paths); + FineLoggerFactory.getLogger().warn("template lock failed:{}", String.join(";", lockedPath)); + } + }; + + /** + * 启动监听 + */ + public static void startListener() { + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.listen(WorkspaceEvent.ConnectSuccess, listener); + } + } + + /** + * 停止事件监听 + */ + public static void stopListener() { + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.stopListen(listener); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index 685a31843a..ae24c9ca1a 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -4,6 +4,7 @@ import com.fine.theme.icon.LazyIcon; import com.fr.base.Parameter; import com.fr.base.TRL; import com.fr.base.extension.FileExtension; +import com.fr.base.info.TemplateSaveInfoContext; import com.fr.base.io.BaseBook; import com.fr.base.iofile.attr.DesignBanCopyAttrMark; import com.fr.base.iofile.attr.TemplateIdAttrMark; @@ -92,6 +93,7 @@ import com.fr.plugin.observer.PluginEventListener; import com.fr.plugin.observer.PluginEventType; import com.fr.plugin.observer.PluginListenerRegistration; import com.fr.report.InconsistentLockException; +import com.fr.report.LockedException; import com.fr.report.UnLockedException; import com.fr.report.cell.Elem; import com.fr.report.cell.cellattr.CellImage; @@ -101,7 +103,9 @@ import com.fr.stable.Filter; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; import com.fr.stable.core.UUID; +import com.fr.widgettheme.designer.WidgetThemeDisplayAction; import com.fr.workspace.WorkContext; +import com.fr.workspace.base.UserInfo; import com.fr.workspace.server.lock.TplOperator; import javax.swing.BorderFactory; @@ -878,7 +882,10 @@ public abstract class JTemplate> return saveAsTemplate(isShowLoc); } collectInfo(); - return this.saveFile(); + TemplateSaveInfoContext.getInstance().startCollect(template); + boolean result = this.saveFile(); + TemplateSaveInfoContext.getInstance().stopCollect(result); + return result; } private boolean isCancelOperation(int operation) { @@ -967,7 +974,9 @@ public abstract class JTemplate> generateNewTemplateIdForSaveAs(); this.editingFILE = editingFILE; + TemplateSaveInfoContext.getInstance().startCollect(template); boolean result = this.saveToNewFile(oldName); + TemplateSaveInfoContext.getInstance().stopCollect(result); if (result) { DesignerFrameFileDealerPane.getInstance().refresh(); collectInfoWhenSaveAs(originID); @@ -1053,13 +1062,20 @@ public abstract class JTemplate> protected void checkBeforeSave() throws Exception { // 保存前校验下未解锁 - if (WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(getEditingFILE().getPath())) { + LockInfoOperator lockInfoOperator = WorkContext.getCurrent().get(LockInfoOperator.class); + String path = getEditingFILE().getPath(); + if (lockInfoOperator.isTplUnLocked(path)) { throw new UnLockedException(); } + //睡眠超过90s之后,锁信息会被清掉,之后其他人可能打开模板进行锁定,所以定这里还判断一下模板是否被其他人锁 + UserInfo userInfo = lockInfoOperator.getUserInfo(path); + if (userInfo != null) { + throw new LockedException(userInfo); + } // 过滤掉本地文件 boolean localFile = getEditingFILE() instanceof FileFILE; boolean inconsistent = !localFile && getEditingFILE().exists() - && !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath()); + && !lockInfoOperator.consistentCheckAndLockIfNecessary(path); if (inconsistent) { throw new InconsistentLockException(); } @@ -1121,7 +1137,7 @@ public abstract class JTemplate> //查找替换 tplMenu.addShortCut(new NameSeparator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Replace_Name_Separate"))); tplMenu.addShortCut((ShortCut) DesignModuleFactory.getITReplaceAction()); - + tplMenu.insertShortCut(1, new WidgetThemeDisplayAction<>(this)); return new MenuDef[]{tplMenu}; } @@ -1782,6 +1798,8 @@ public abstract class JTemplate> CallbackSaveWorker worker = new CallbackSaveWorker(new Callable() { @Override public Boolean call() throws Exception { + TemplateSaveInfoContext.getInstance().startRecord(); + TemplateSaveInfoContext.getInstance().collectInfo(template.suffix()); return saveAs(finalEditingFILE, sourceFile, oldName); } }, this); @@ -1885,6 +1903,8 @@ public abstract class JTemplate> CallbackSaveWorker worker = new CallbackSaveWorker(new Callable() { @Override public Boolean call() throws Exception { + TemplateSaveInfoContext.getInstance().startRecord(); + TemplateSaveInfoContext.getInstance().collectInfo(template.suffix()); return saveRealFileByWorker(); } }, this); @@ -1943,6 +1963,13 @@ public abstract class JTemplate> @Override public void saveDirectly() { + if (isSaving()) { + // 处理连按ctrl+s触发多线程保存的问题 + // 这里为什么可以不用加锁而直接判断isSaving: + // 实测actionPerformed有线程安全的特性,同一时间只有一个AWT线程走到这里,setSaving是线程安全的(SaveTemplateAction.actionPerformed) + // 多线程场景是因为我们用了SwingWorker子线程处理保存 + return; + } new SaveTypeWorker(getSaveTypeCallable(), this) { @Override protected void done() { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java index 7c19278c20..e8b726b2d6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/chart/info/ChartInfoCollector.java @@ -7,6 +7,7 @@ import com.fr.chartx.config.info.constant.ConfigType; import com.fr.design.mainframe.burying.point.AbstractPointCollector; import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; @@ -184,33 +185,44 @@ public class ChartInfoCollector extends AbstractPointCollector { */ @Override public void collectInfo(String templateId, String originID, TemplateProcessInfo processInfo, int timeConsume) { - if (!shouldCollectInfo()) { - return; - } - if (StringUtils.isEmpty(originID)) { - originID = templateId; - } - boolean testTemplate = isTestTemplate(processInfo); + // 捕获RuntimeException,不中断保存模板核心逻辑,避免出现保存失败弹窗 + try { + if (!shouldCollectInfo()) { + return; + } + if (StringUtils.isEmpty(originID)) { + originID = templateId; + } + boolean testTemplate = isTestTemplate(processInfo); - for (ChartInfo chartInfo : pointInfoMap.values()) { - if (originID.equals(chartInfo.getTemplateId())) { - chartInfo.setTemplateId(templateId); - chartInfo.setTestTemplate(testTemplate); + for (ChartInfo chartInfo : pointInfoMap.values()) { + if (chartInfo != null && originID.equals(chartInfo.getTemplateId())) { + chartInfo.setTemplateId(templateId); + chartInfo.setTestTemplate(testTemplate); + } } - } - for (ChartInfo chartInfo : chartInfoCacheMap.values()) { - BaseBook book = chartInfo.getBook(); - if ((book != null && templateId.equals(book.getTemplateID())) || - originID.equals(chartInfo.getTemplateId())) { - chartInfo.setTemplateId(templateId); - chartInfo.setTestTemplate(testTemplate); - pointInfoMap.put(chartInfo.getChartId(), chartInfo); + for (ChartInfo chartInfo : chartInfoCacheMap.values()) { + if (chartInfo == null) { + continue; + } + BaseBook book = chartInfo.getBook(); + if (accept(templateId, originID, chartInfo, book)) { + chartInfo.setTemplateId(templateId); + chartInfo.setTestTemplate(testTemplate); + pointInfoMap.put(chartInfo.getChartId(), chartInfo); + } } + // 每次更新之后,都同步到暂存文件中 + saveInfo(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } + } - // 每次更新之后,都同步到暂存文件中 - saveInfo(); + private static boolean accept(String templateId, String originID, ChartInfo chartInfo, BaseBook book) { + return (book != null && templateId.equals(book.getTemplateID())) || + originID.equals(chartInfo.getTemplateId()); } private boolean isTestTemplate(TemplateProcessInfo processInfo) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java b/designer-base/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java index 99950edae7..8cef0d5afa 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java @@ -33,6 +33,10 @@ public class ErrorInfo { private String log; private String stackTrace; + private boolean starting; + + private boolean remote; + public ErrorInfo(String username, String uuid, String activekey) { this.username = username; this.uuid = uuid; @@ -51,6 +55,22 @@ public class ErrorInfo { this.username = username; } + public boolean isStarting() { + return starting; + } + + public void setStarting(boolean starting) { + this.starting = starting; + } + + public boolean isRemote() { + return remote; + } + + public void setRemote(boolean remote) { + this.remote = remote; + } + public String getUuid() { return uuid; } @@ -126,6 +146,8 @@ public class ErrorInfo { jo.put("logid", logid); jo.put("log", log); jo.put("stacktrace", stackTrace); + jo.put("starting", starting); + jo.put("remote", remote); saveFileToCache(jo); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/messagecollect/StartErrorMessageCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/messagecollect/StartErrorMessageCollector.java index ca3fd13ccc..03e3694814 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/messagecollect/StartErrorMessageCollector.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/messagecollect/StartErrorMessageCollector.java @@ -1,9 +1,15 @@ package com.fr.design.mainframe.messagecollect; +import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.mainframe.errorinfo.ErrorInfo; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; +import com.fr.start.common.DesignerStartupContext; +import com.fr.workspace.WorkContext; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * @@ -15,9 +21,11 @@ public class StartErrorMessageCollector { private static final StartErrorMessageCollector INSTANCE = new StartErrorMessageCollector(); + private ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory(StartErrorMessageCollector.this.getClass())); private String uuid; private String activeKey; + private boolean extraJudgeStart = false; public static StartErrorMessageCollector getInstance() { return INSTANCE; @@ -35,10 +43,29 @@ public class StartErrorMessageCollector { errorInfo.setLogid(id); errorInfo.setLog(msg); errorInfo.setStackTrace(detail); + errorInfo.setStarting(DesignerStartupContext.getInstance().isOnStartup() || extraJudgeStart); + errorInfo.setRemote(!WorkContext.getCurrent().isLocal()); errorInfo.saveAsJSON(); } + /** + * 异步记录 + */ + public void asyncRecord(String id, String msg, String detail) { + executorService.submit(() -> { + record(id, msg, detail); + StartErrorMessageCollector.getInstance().setExtraJudgeStart(false); + }); + } + public void record(String id, String msg) { record(id, msg, StringUtils.EMPTY); } + + public void setExtraJudgeStart(boolean extraJudgeStart) { + this.extraJudgeStart = extraJudgeStart; + } + + + } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStylePane.java index aafc5d4e2b..f32205b4cc 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStylePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStylePane.java @@ -5,10 +5,6 @@ import com.fr.design.beans.BasicBeanPane; import com.fr.design.dialog.BasicPane; import com.fr.design.fun.MobileWidgetStyleProvider; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.mobile.processor.MobileStyleDefinePaneCreator; -import com.fr.event.Event; -import com.fr.event.EventDispatcher; -import com.fr.event.Listener; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WScaleLayout; import com.fr.form.ui.mobile.MobileCommonExtraStyle; @@ -16,9 +12,8 @@ import com.fr.form.ui.mobile.MobileStyle; import com.fr.form.ui.mobile.StyleClassMap; import com.fr.form.ui.widget.CRBoundsWidget; import com.fr.log.FineLoggerFactory; -import com.fr.plugin.context.PluginContext; -import com.fr.plugin.observer.PluginEventType; import com.fr.stable.ArrayUtils; +import com.fr.widgettheme.widget.mobile.provider.WidgetThemeMobileStyleDefinePaneCreator; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; @@ -43,8 +38,6 @@ public class MobileStylePane extends BasicPane { private JList styleList; private Map> map = new HashMap<>(); - private boolean checkFlag = true; - public MobileStylePane(Widget widget) { if (widget instanceof WScaleLayout) { this.widget = ((CRBoundsWidget) ((WScaleLayout) widget).getBoundsWidget()).getWidget(); @@ -81,7 +74,6 @@ public class MobileStylePane extends BasicPane { private void init() { initComponent(); - initPluginListener(); } private void initComponent() { @@ -129,11 +121,10 @@ public class MobileStylePane extends BasicPane { listModel.addElement(displayName); try { - MobileStyleDefinePaneCreator processor = ExtraDesignClassManager.getInstance().getSingle(MobileStyleDefinePaneCreator.XML_TAG); BasicBeanPane mobileStyleBasicBeanPane = new MobileStyleDefinePane(widget, appearanceClazz, mobileStyleClazz); - if (checkFlag && processor != null && processor.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz) != null) { - mobileStyleBasicBeanPane = processor.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz); - Class extraStyle = processor.classForCommonExtraStyle(widget); + if (WidgetThemeMobileStyleDefinePaneCreator.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz) != null) { + mobileStyleBasicBeanPane = WidgetThemeMobileStyleDefinePaneCreator.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz); + Class extraStyle = WidgetThemeMobileStyleDefinePaneCreator.classForCommonExtraStyle(widget); if (extraStyle != null) { StyleClassMap.putCommonStyle(extraStyle.getName(), extraStyle.getName()); } @@ -164,32 +155,4 @@ public class MobileStylePane extends BasicPane { return styleProviders; } - private void initPluginListener() { - EventDispatcher.listen(PluginEventType.AfterRun, new Listener() { - @Override - public void on(Event event, PluginContext pluginContext) { - if (pluginContext.getRuntime().contain(MobileStyleDefinePaneCreator.XML_TAG)) { - checkFlag = true; - refreshDockingView(); - } - } - }); - EventDispatcher.listen(PluginEventType.BeforeStop, new Listener() { - @Override - public void on(Event event, PluginContext pluginContext) { - if (pluginContext.getRuntime().contain(MobileStyleDefinePaneCreator.XML_TAG)) { - checkFlag = false; - refreshDockingView(); - } - } - }); - } - - private void refreshDockingView() { - removeAll(); - initComponent(); - populate(widget.getMobileStyle()); - this.updateUI(); - this.repaint(); - } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java index eb15a657f5..922230b158 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java @@ -11,7 +11,11 @@ import com.fr.design.mainframe.theme.edit.ChartStyleFormEditPane; import com.fr.design.mainframe.theme.edit.ComponentStyleEditPane; import com.fr.design.mainframe.theme.edit.FormBodyStyleEditPane; import com.fr.design.mainframe.theme.preview.FormThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ReportThemePreviewPane; import com.fr.design.mainframe.theme.processor.ThemePreviewPaneProcessor; +import com.fr.widgettheme.theme.panel.WidgetDisplayFormThemePreviewPane; +import com.fr.widgettheme.theme.panel.WidgetDisplayReportThemePreviewPane; +import com.fr.widgettheme.util.WidgetThemeDesignerUtils; import javax.swing.JPanel; @@ -38,7 +42,7 @@ public class FormThemeProfilePane extends TemplateThemeProfilePane { if (processor != null) { return processor.createFormThemePreviewPane(); } - return new FormThemePreviewPane(); + return WidgetThemeDesignerUtils.enableWidgetEnhance() ? new WidgetDisplayFormThemePreviewPane() : new FormThemePreviewPane(); } @Override diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java index 57e6ddf5f1..3f654cae5c 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java @@ -7,6 +7,8 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.theme.edit.ReportBodyStyleEditPane; import com.fr.design.mainframe.theme.preview.ReportThemePreviewPane; import com.fr.design.mainframe.theme.processor.ThemePreviewPaneProcessor; +import com.fr.widgettheme.theme.panel.WidgetDisplayReportThemePreviewPane; +import com.fr.widgettheme.util.WidgetThemeDesignerUtils; /** * @author Starryi @@ -26,7 +28,7 @@ public class ReportThemeProfilePane extends TemplateThemeProfilePane extends J protected void refreshExtraAdvancedPane() { extraPaneList.clear(); + if(WidgetThemeDesignerUtils.enableWidgetEnhance()) { + extraPaneList.add(new ParamContainerStyleEditPane<>()); + extraPaneList.add(new WidgetStyleEditContainerPane<>()); + } Set> providers = ExtraDesignClassManager.getInstance().getArray(TemplateThemePaneProvider.XML_TAG); for (TemplateThemePaneProvider provider : providers) { insertShortCut(provider.getInsertPosition(extraPaneList.size()), provider.getTab()); diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java index 950d76d7b9..ea279bb036 100644 --- a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java +++ b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java @@ -15,7 +15,8 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { private static DesignerPushUpdateConfigManager singleton; private boolean autoPushUpdateEnabled = true; // 是否开启自动推送更新 - private boolean cloudAnalyticsDelay = false; // 是否云端运维模块延迟启动 + private boolean cloudAnalyticsDelay = true; // 是否云端运维模块延迟启动 + private boolean useCloudAnalyticsDelayFirst = true; // 默认打开,如果有手动改延迟启动配置则按客户配置的来 private String lastIgnoredVersion = StringUtils.EMPTY; // 最近一次跳过的更新版本 private DesignerPushUpdateConfigManager() { @@ -33,7 +34,8 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { if (reader.isAttr()) { this.setAutoPushUpdateEnabled(reader.getAttrAsBoolean("autoPushUpdateEnabled", true)); this.setLastIgnoredVersion(reader.getAttrAsString("lastIgnoredVersion", StringUtils.EMPTY)); - this.setCloudAnalyticsDelay(reader.getAttrAsBoolean("cloudAnalyticsDelay", false)); + this.setCloudAnalyticsDelay(reader.getAttrAsBoolean("cloudAnalyticsDelay", true)); + this.setUseCloudAnalyticsDelayFirst(reader.getAttrAsBoolean("useCloudAnalyticsDelayFirst", true)); } } @@ -43,6 +45,7 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { writer.attr("autoPushUpdateEnabled", autoPushUpdateEnabled); writer.attr("lastIgnoredVersion", lastIgnoredVersion); writer.attr("cloudAnalyticsDelay", cloudAnalyticsDelay); + writer.attr("useCloudAnalyticsDelayFirst", useCloudAnalyticsDelayFirst); writer.end(); } @@ -69,4 +72,12 @@ public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter { public void setCloudAnalyticsDelay(boolean cloudAnalyticsDelay) { this.cloudAnalyticsDelay = cloudAnalyticsDelay; } + + public boolean isUseCloudAnalyticsDelayFirst() { + return useCloudAnalyticsDelayFirst; + } + + public void setUseCloudAnalyticsDelayFirst(boolean useCloudAnalyticsDelayFirst) { + this.useCloudAnalyticsDelayFirst = useCloudAnalyticsDelayFirst; + } } diff --git a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java index 1b9925be3c..ea06248163 100644 --- a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java @@ -236,7 +236,7 @@ public class DesignUtils { DesignerContext.getDesignerFrame().openTemplate(new FileFILE(f)); } }); - } else { + } else if (DeepLinkCore.getInstance().accept(line)) { String url = line; UIUtil.invokeLaterIfNeeded(new Runnable() { @Override diff --git a/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java b/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java index 9b426b5c87..250846b47c 100644 --- a/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.SwingWorker; import java.io.OutputStream; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -65,14 +66,7 @@ public class TemplateUtils { if (file == null) { return; } - Runnable doAfterCreateTemplate; - //判断一下要保存的文件是否已打开 - int index = HistoryTemplateListCache.getInstance().contains(file); - JTemplate template = null; - if (index != -1) { - template = HistoryTemplateListCache.getInstance().getHistoryList().get(index); - } - createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, template); + createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, null); } /** @@ -181,23 +175,29 @@ public class TemplateUtils { * @param template 需要关闭的模板 */ private static void openNewTemplateAndCloseOldTemplate(FILE file, boolean openNewTemplate, @Nullable JTemplate template) { - new SwingWorker() { + new SwingWorker>, Void>() { @Override - protected Boolean doInBackground() throws Exception { + protected List> doInBackground() throws Exception { + List> needCloseTemplate = new ArrayList<>(); + //判断一下要保存的副本文件是否已打开 + int index = HistoryTemplateListCache.getInstance().contains(file); + if (index != -1) { + WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(file.getPath()); + needCloseTemplate.add(HistoryTemplateListCache.getInstance().getHistoryList().get(index)); + } if (JTemplate.isValid(template)) { //给要关闭的模板解锁 WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(template.getPath()); - return true; + needCloseTemplate.add(template); } - return false; + return needCloseTemplate; } @Override protected void done() { try { - if (get()) { - //模板释放锁成功后关闭该模板 - HistoryTemplateListCache.getInstance().closeSelectedReport(template); - } + //获取需要关闭的模板 + List> jTemplates = get(); + jTemplates.forEach(jTemplate -> HistoryTemplateListCache.getInstance().closeSelectedReport(jTemplate)); if (openNewTemplate) { DesignerContext.getDesignerFrame().openTemplate(file); } diff --git a/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java b/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java index ed2597f1d7..b7a50a3af1 100644 --- a/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java +++ b/designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java @@ -1,5 +1,6 @@ package com.fr.design.worker.save; +import com.fr.base.info.TemplateSaveInfoContext; import com.fr.common.util.Collections; import com.fr.design.mainframe.JTemplate; import java.util.LinkedList; @@ -34,6 +35,8 @@ public class CallbackSaveWorker extends SaveWorker { } successRunnableList = null; failRunnableList = null; + TemplateSaveInfoContext.getInstance().stopRecord(); + TemplateSaveInfoContext.getInstance().setSaveCompleted(success); } private void fireRunnable(List list) { diff --git a/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java b/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java index 9ab897d7e8..bf6209cf6b 100644 --- a/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java +++ b/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java @@ -2,18 +2,17 @@ package com.fr.design.worker.save; import com.fr.common.exception.ThrowableHandler; import com.fr.design.dialog.FineJOptionPane; -import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.i18n.Toolkit; +import com.fr.design.lock.LockFileReSaveEnum; +import com.fr.design.lock.LockInfoDialog; import com.fr.design.mainframe.DesignerContext; -import com.fr.design.mainframe.JTemplate; import com.fr.design.ui.util.UIUtil; -import com.fr.design.utils.TemplateUtils; -import com.fr.file.FileNodeFILE; -import com.fr.file.filetree.FileNode; import com.fr.general.IOUtils; +import com.fr.report.InconsistentLockException; +import com.fr.report.LockedException; import com.fr.report.UnLockedException; +import com.fr.workspace.base.UserInfo; import com.fr.workspace.exception.DiskSpaceFullException; -import com.fr.report.InconsistentLockException; import java.awt.Frame; import javax.swing.JOptionPane; @@ -89,6 +88,25 @@ public class SaveFailureHandler implements ThrowableHandler { } }, + LOCKED { + @Override + public boolean process(Throwable e) { + LockedException exception = null; + if (e.getCause() instanceof LockedException) { + exception = (LockedException) e.getCause(); + } + if (e instanceof LockedException) { + exception = (LockedException) e; + } + if (exception != null) { + UserInfo userInfo = exception.getUserInfo(); + LockInfoDialog.show(userInfo, LockFileReSaveEnum.HISTORY_TEMPLATE_CACHE); + return true; + } + return false; + } + }, + Other { @Override public boolean process(Throwable e) { @@ -112,16 +130,7 @@ public class SaveFailureHandler implements ThrowableHandler { IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"), new Object[] {Toolkit.i18nText("Fine_Design_Template_SaveAs_Backup"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null); if (option == JOptionPane.YES_OPTION) { - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (JTemplate.isValid(template)) { - TemplateUtils.createAndOpenTemplate( - Toolkit.i18nText("Fine_Design_Template_Backup"), - new FileNodeFILE(new FileNode(template.getPath(), false)), - true, - true, - //另存之后需要关闭的模板 - template); - } + LockFileReSaveEnum.HISTORY_TEMPLATE_CACHE.action(); } } @@ -134,16 +143,7 @@ public class SaveFailureHandler implements ThrowableHandler { IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"), new Object[] {Toolkit.i18nText("Fine_Design_Template_SaveAs_Backup"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null); if (option == JOptionPane.YES_OPTION) { - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (JTemplate.isValid(template)) { - TemplateUtils.createAndOpenTemplate( - Toolkit.i18nText("Fine_Design_Template_Backup"), - new FileNodeFILE(new FileNode(template.getPath(), false)), - true, - true, - //另存之后需要关闭的模板 - template); - } + LockFileReSaveEnum.HISTORY_TEMPLATE_CACHE.action(); } } diff --git a/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java b/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java index e70804c4dc..ee91602aa0 100644 --- a/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java +++ b/designer-base/src/main/java/com/fr/start/server/FineEmbedServer.java @@ -2,6 +2,7 @@ package com.fr.start.server; import com.fr.event.EventDispatcher; import com.fr.module.ModuleContext; +import com.fr.plugin.listener.SpecialPluginEvent; /** * Created by juhaoyu on 2018/6/6. @@ -15,6 +16,7 @@ public abstract class FineEmbedServer { public synchronized static void start() { onStarting = true; + EventDispatcher.fire(SpecialPluginEvent.WITH_SERVER_AND_NOT_START_IN_REMOTE); EventDispatcher.fire(EmbedServerEvent.BeforeStart); ModuleContext.getModule(FineEmbedServerActivator.class).start(); onStarting = false; diff --git a/designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java b/designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java index 5ed94d82eb..e6e2ebb793 100644 --- a/designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java +++ b/designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java @@ -39,6 +39,11 @@ public class DesignerStartupModel { * mode:模式,0-有设计器起动页;1-无设计器起始页 */ private int mode; + + /** + * jdkVersion:JDK版本 + */ + private String jdkVersion; public DesignerStartupModel() { } @@ -73,7 +78,15 @@ public class DesignerStartupModel { public void setInfo(MachineInfo info) { this.info = info; } - + + public String getJdkVersion() { + return jdkVersion; + } + + public void setJdkVersion(String jdkVersion) { + this.jdkVersion = jdkVersion; + } + public int getMode() { return mode; } @@ -83,7 +96,7 @@ public class DesignerStartupModel { } private void fillInfo() { - + this.setJdkVersion(System.getProperty("java.version")); MachineInfo info = new MachineInfo(); AbstractOperatingSystem operatingSystem = OperatingSystem.getOperatingSystem(); info.setSystem(operatingSystem.getDisplayString()); diff --git a/designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java b/designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java index 43d2fd9709..a2d9965e50 100644 --- a/designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java +++ b/designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java @@ -1,6 +1,7 @@ package com.fr.startup.ui; import com.fr.base.svg.IconUtils; +import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.dialog.UIExpandDialog; import com.fr.design.gui.icontainer.UIScrollPane; @@ -8,6 +9,8 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector; +import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage; import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.ColorUtils; import com.fr.design.utils.ThemeUtils; @@ -49,6 +52,8 @@ import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * 启动页 @@ -253,6 +258,7 @@ public class StartupPageWindow extends JFrame { try { Void result = get(); setVisible(false); + StartErrorMessageCollector.getInstance().setExtraJudgeStart(false); } catch (Exception e) { // 处理错误 UIUtil.invokeLaterIfNeeded(() -> { @@ -269,6 +275,9 @@ public class StartupPageWindow extends JFrame { setEnabled(true); }); FineLoggerFactory.getLogger().error(e.getMessage(), e); + StartErrorMessageCollector.getInstance().asyncRecord(DesignerErrorMessage.UNEXCEPTED_START_FAILED.getId(), + DesignerErrorMessage.UNEXCEPTED_START_FAILED.getMessage(), + e.getMessage()); } finally { loadingPanel.hide(); } diff --git a/designer-base/src/main/java/com/fr/widgettheme/ParameterBackgroundStyleSettingPane.java b/designer-base/src/main/java/com/fr/widgettheme/ParameterBackgroundStyleSettingPane.java new file mode 100644 index 0000000000..144308c223 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/ParameterBackgroundStyleSettingPane.java @@ -0,0 +1,102 @@ +package com.fr.widgettheme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.widget.accessibles.AccessibleBackgroundEditor; +import com.fr.form.ui.container.WParameterLayout; +import com.fr.general.Background; +import org.jetbrains.annotations.Nullable; + +import javax.swing.JPanel; +import java.awt.BorderLayout; + +/** + * 设计器参数面板的“高级”设置增加背景的主题样式设置 + * + * @author Bruce.Deng + * @since 11.0 + * Created on 2023/2/20 + */ +public class ParameterBackgroundStyleSettingPane extends BasicBeanPane { + + public static final String[] FOLLOWING_THEME_STRING_ARRAYS = new String[]{ + Toolkit.i18nText("Fine-Design_Widget_Follow_Theme"), + Toolkit.i18nText("Fine-Design_Widget_Theme_Custom") + }; + + private UIButtonGroup head; + private JPanel customPane; + private AccessibleBackgroundEditor background; + + public ParameterBackgroundStyleSettingPane() { + this.setLayout(new BorderLayout(0, LayoutConstants.VGAP_SMALL)); + head = new UIButtonGroup(FOLLOWING_THEME_STRING_ARRAYS) { + @Override + public void setSelectedIndex(int newSelectedIndex, boolean fireChanged) { + //表示从跟随主题切换到自定义 + if (selectedIndex != newSelectedIndex && newSelectedIndex == 1) { + background.setValue(getThemeBackground()); + } + super.setSelectedIndex(newSelectedIndex, fireChanged); + } + }; + customPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + background = new AccessibleBackgroundEditor(); + customPane.add(background); + this.add(head, BorderLayout.NORTH); + this.add(customPane, BorderLayout.CENTER); + } + + private void attributeChange() { + customPane.setVisible(head.getSelectedIndex() == 1); + } + + @Override + public void populateBean(WParameterLayout wParameterLayout) { + if (wParameterLayout.isBackgroundFollowTheme()) { + head.setSelectedIndex(0); + } else { + head.setSelectedIndex(1); + background.setValue(wParameterLayout.getBackground()); + } + attributeChange(); + } + + @Override + @Nullable + public WParameterLayout updateBean() { + return null; + } + + @Override + public void updateBean(WParameterLayout wParameterLayout) { + attributeChange(); + if (head.getSelectedIndex() != 1) { + wParameterLayout.setBackgroundFollowTheme(true); + wParameterLayout.setBackground(getThemeBackground()); + } else { + wParameterLayout.setBackgroundFollowTheme(false); + wParameterLayout.setBackground((Background) background.getValue()); + } + } + + private Background getThemeBackground() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (JTemplate.isValid(template)) { + TemplateTheme theme = template.getTemplateTheme(); + return theme.getParamContainerStyle().getBackground(); + } + return (Background) background.getValue(); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Widget_Theme_ParamContainer_Background"); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayAction.java b/designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayAction.java new file mode 100644 index 0000000000..21c7f3ac93 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayAction.java @@ -0,0 +1,50 @@ +package com.fr.widgettheme.designer; + +import com.fr.base.io.BaseBook; +import com.fr.base.svg.IconUtils; +import com.fr.design.actions.JTemplateAction; +import com.fr.widgettheme.util.WidgetThemeDesignerUtils; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr; + +import java.awt.event.ActionEvent; + +/** + * 控件主题显示增强菜单action + * + * @author Bruce.Deng + * @since 11.0 + * Created on 2022/11/28 + */ +public class WidgetThemeDisplayAction> extends JTemplateAction { + + public WidgetThemeDisplayAction(T jwb) { + super(jwb); + setName(Toolkit.i18nText("Fine-Design_Widget_Display_Enhance")); + this.setSmallIcon(IconUtils.readIcon("/com/fr/widgettheme/menu.svg")); + } + + @Override + public void actionPerformed(ActionEvent e) { + final T jTemplate = getEditingComponent(); + if (!JTemplate.isValid(jTemplate)) { + return; + } + BaseBook baseBook = jTemplate.getTarget(); + WidgetDisplayEnhanceMarkAttr attr = WidgetThemeDesignerUtils.getStrongestControlAttrFromTemplate(baseBook); + final WidgetThemeDisplayConfigPane configPane = new WidgetThemeDisplayConfigPane(); + configPane.populate(attr); + configPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + baseBook.addAttrMark(configPane.update()); + jTemplate.fireTargetModified(); + HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().activeOldJTemplate(); + } + }).setVisible(true); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayConfigPane.java b/designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayConfigPane.java new file mode 100644 index 0000000000..ad96c00a9f --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayConfigPane.java @@ -0,0 +1,81 @@ +package com.fr.widgettheme.designer; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr; + +import javax.swing.JPanel; +import java.awt.Color; + +/** + * 控件主题显示增强配置窗口 + * + * @author Bruce.Deng + * @since 11.0 + * Created on 2022/11/28 + */ +public class WidgetThemeDisplayConfigPane extends BasicPane { + + private UICheckBox widgetEnhance; + + public WidgetThemeDisplayConfigPane() { + initComponents(); + } + + private void initComponents() { + VerticalFlowLayout layout = new VerticalFlowLayout(); + layout.setAlignLeft(true); + this.setLayout(layout); + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(northPane); + widgetEnhance = new UICheckBox(Toolkit.i18nText("Fine-Design_Widget_Enable_Display_Enhance")); + widgetEnhance.setSelected(true); + northPane.add(widgetEnhance); + + JPanel southPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(southPane); + UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Widget_Display_Enhance_Tip")); + label.setForeground(Color.GRAY); + southPane.add(label); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Widget_Display_Enhance"); + } + + /** + * 根据属性填充pane选项 + * + * @param widgetDisplayEnhanceMarkAttr 控件显示增强属性 + */ + public void populate(WidgetDisplayEnhanceMarkAttr widgetDisplayEnhanceMarkAttr) { + if (widgetDisplayEnhanceMarkAttr == null) { + widgetDisplayEnhanceMarkAttr = new WidgetDisplayEnhanceMarkAttr(); + } + widgetEnhance.setSelected(widgetDisplayEnhanceMarkAttr.isWidgetEnhance()); + } + + /** + * 更新 + */ + public WidgetDisplayEnhanceMarkAttr update() { + WidgetDisplayEnhanceMarkAttr attr = new WidgetDisplayEnhanceMarkAttr(); + attr.setWidgetEnhance(widgetEnhance.isSelected()); + if (widgetEnhance.isSelected()) { + collectWidgetDisplayEnhanceRecord(); + } + return attr; + } + + /** + * 记录埋点信息,具体实现在云端运维插件,这里只作为切入点 + */ + private void collectWidgetDisplayEnhanceRecord() { + //记录埋点 + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerBackgroundPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerBackgroundPane.java new file mode 100644 index 0000000000..429df171ce --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerBackgroundPane.java @@ -0,0 +1,88 @@ +package com.fr.widgettheme.theme.edit; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.event.UIObserverListener; +import com.fr.design.fun.BackgroundQuickUIProvider; +import com.fr.design.gui.style.BackgroundPane; +import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ImageBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.NullBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.PatternBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.TextureBackgroundQuickPane; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * 参数面板背景编辑窗口 + * + * @author Bruce.Deng + * @since 11.0 + * Created on 2023/1/5 + */ +public class ParamContainerBackgroundPane extends BackgroundPane { + + private NullBackgroundQuickPane nullBackgroundPane; + private ColorBackgroundQuickPane colorBackgroundPane; + private ImageBackgroundQuickPane imageBackgroundPane; + private GradientBackgroundQuickPane gradientBackgroundPane; + private TextureBackgroundQuickPane textureBackgroundPane; + private PatternBackgroundQuickPane patternBackgroundPane; + + public ParamContainerBackgroundPane() { + super(); + } + + + @Override + protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { + nullBackgroundPane = new NullBackgroundQuickPane(); + + colorBackgroundPane = new ColorBackgroundQuickPane(true); + colorBackgroundPane.registerChangeListener(this::fireStateChanged); + + imageBackgroundPane = new ImageBackgroundQuickPane(); + imageBackgroundPane.registerChangeListener(this::fireStateChanged); + + gradientBackgroundPane = createGradientBackgroundQuickPane(); + gradientBackgroundPane.registerChangeListener(this::fireStateChanged); + + textureBackgroundPane = new TextureBackgroundQuickPane(); + textureBackgroundPane.registerChangeListener(this::fireStateChanged); + + patternBackgroundPane = new PatternBackgroundQuickPane(); + patternBackgroundPane.registerChangeListener(this::fireStateChanged); + + + return createBackgroundQuickPanes(); + } + + private BackgroundQuickPane[] createBackgroundQuickPanes() { + List kinds = new ArrayList<>(); + + kinds.add(nullBackgroundPane); + kinds.add(colorBackgroundPane); + kinds.add(imageBackgroundPane); + kinds.add(gradientBackgroundPane); + kinds.add(textureBackgroundPane); + kinds.add(patternBackgroundPane); + + Set providers = ExtraDesignClassManager.getInstance().getArray(BackgroundQuickUIProvider.MARK_STRING); + for (BackgroundQuickUIProvider provider : providers) { + BackgroundQuickPane newTypePane = provider.appearanceForBackground(); + newTypePane.registerChangeListener(this::fireStateChanged); + kinds.add(newTypePane); + } + + return kinds.toArray(new BackgroundQuickPane[kinds.size()]); + } + + + protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { + // 使用默认的150宽度构建渐变条 + return new GradientBackgroundQuickPane(); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerStyleEditPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerStyleEditPane.java new file mode 100644 index 0000000000..5f64b15bcc --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerStyleEditPane.java @@ -0,0 +1,84 @@ +package com.fr.widgettheme.theme.edit; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.AbstractThemedParamContainerStyle; +import com.fr.base.theme.settings.DefaultThemedParamContainerStyle; +import com.fr.widgettheme.theme.widget.style.ThemedParamContainerStyle; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + +/** + * 参数面板样式编辑pane + * + * @author Bruce.Deng + * @since 11.0 + * Created on 2022/12/16 + */ +public class ParamContainerStyleEditPane extends BasicBeanPane { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ParamContainerBackgroundPane backgroundPane; + + public ParamContainerStyleEditPane() { + backgroundPane = new ParamContainerBackgroundPane(); + + double p = TableLayout.PREFERRED; + + JPanel uiLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + uiLabelPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Background")), BorderLayout.NORTH); + uiLabelPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + JPanel backgroundLabeledPane = TableLayoutHelper.createCommonTableLayoutPane( + new Component[][]{ new Component[] { uiLabelPane, backgroundPane } }, + new double[] { p }, new double[] { LABEL_WIDTH, SETTING_WIDTH}, IntervalConstants.INTERVAL_L1 + ); + backgroundLabeledPane.setBorder(BorderFactory.createEmptyBorder( + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1 + )); + this.add(backgroundLabeledPane); + setBorder(BorderFactory.createEmptyBorder()); + } + + @Override + public void populateBean(T t) { + AbstractThemedParamContainerStyle paramContainerStyle = t.getParamContainerStyle(); + if (paramContainerStyle == null || paramContainerStyle instanceof DefaultThemedParamContainerStyle) { + paramContainerStyle = new ThemedParamContainerStyle(); + t.setParamContainerStyle(paramContainerStyle); + } + backgroundPane.populateBean(paramContainerStyle.getBackground()); + } + + @Override + public T updateBean() { + return null; + } + + @Override + public void updateBean(T t) { + ThemedParamContainerStyle style = (ThemedParamContainerStyle) t.getParamContainerStyle(); + if (style == null) { + style = new ThemedParamContainerStyle(); + t.setParamContainerStyle(style); + } + style.setBackground(backgroundPane.update()); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Widget_Theme_ParamContainer"); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java new file mode 100644 index 0000000000..aca4b690de --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java @@ -0,0 +1,121 @@ +package com.fr.widgettheme.theme.edit.widget; + +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.TemplateTheme; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.widgettheme.theme.widget.style.BorderStyle; +import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle; +import com.fr.widgettheme.theme.widget.style.ThemeTextStyle; +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; +import com.fr.widgettheme.util.ThemeTextStylePaneCreator; + +import javax.swing.ButtonGroup; +import javax.swing.JPanel; +import java.awt.Component; + + +/** + * 桌面端主题面板 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/3/28 + */ +public class DesktopWidgetStyleEditPane extends WidgetStyleEditPane { + // 风格1 + protected UIRadioButton style1; + // 风格2 + protected UIRadioButton style2; + + /** + * 下拉面板背景颜色 + */ + private NewColorSelectBox selectBackgroundColorBox; + public DesktopWidgetStyleEditPane() { + super(); + } + + @Override + public Component[][] generateComponent() { + initStyleEditor(); + initSelectBackgroundColorBox(); + // 容纳风格1和风格2的panel + JPanel stylePane = new JPanel(FRGUIPaneFactory.createBoxFlowLayout()); + stylePane.add(style1); + stylePane.add(style2); + + return new Component[][]{ + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Color")), colorSelectBox}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Style")), stylePane}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Line")), lineComboBox}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Radius")), borderRadiusSpinner}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Text_Style")), ThemeTextStylePaneCreator.create(fontSizePane, fontColorButton)}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Background_Select_Box")), selectBackgroundColorBox} + }; + } + + + private void initStyleEditor() { + style1 = new UIRadioButton(Toolkit.i18nText("Fine-Design_Widget_Theme_Style_1")); + style2 = new UIRadioButton(Toolkit.i18nText("Fine-Design_Widget_Theme_Style_2")); + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(style1); + buttonGroup.add(style2); + } + + private void initSelectBackgroundColorBox() { + selectBackgroundColorBox = new NewColorSelectBox(140, true); + selectBackgroundColorBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR); + } + + @Override + public void populateBean(T t) { + ThemedWidgetStyle style = (ThemedWidgetStyle) t.getWidgetStyle(); + if (style == null) { + style = new ThemedWidgetStyle(); + t.setWidgetStyle(style); + } + if (style.getStyleType() == 1) { + style1.setSelected(true); + } else { + style2.setSelected(true); + } + colorSelectBox.setSelectObject(style.getThemeColor()); + lineComboBox.setSelectedLineStyle(style.getBorderStyle().getLineType()); + borderRadiusSpinner.setValue(style.getBorderStyle().getRadius()); + fontSizePane.setValue(style.getTextStyle().getFontSize()); + fontColorButton.setColor(style.getTextStyle().getFontColor()); + selectBackgroundColorBox.setSelectObject(style.getSelectBackgroundColor()); + } + + @Override + public void updateBean(T t) { + ThemedWidgetStyle style = (ThemedWidgetStyle) t.getWidgetStyle(); + if (style == null) { + style = new ThemedWidgetStyle(); + t.setWidgetStyle(style); + } + style.setThemeColor(colorSelectBox.getSelectObject()); + BorderStyle borderStyle = new BorderStyle(); + borderStyle.setLineType(lineComboBox.getSelectedLineStyle()); + borderStyle.setRadius((int) borderRadiusSpinner.getValue()); + style.setBorderStyle(borderStyle); + ThemeTextStyle textStyle = new ThemeTextStyle(); + textStyle.setFontSize(fontSizePane.getValue()); + textStyle.setFontColor(fontColorButton.getColor()); + style.setTextStyle(textStyle); + ButtonBackgroundStyle buttonBackgroundStyle = new ButtonBackgroundStyle(); + ColorBackground buttonBackground = ColorBackground.getInstance(style.getThemeColor()); + buttonBackgroundStyle.setInitialBackground(buttonBackground); + buttonBackgroundStyle.setOverBackground(buttonBackground); + buttonBackgroundStyle.setClickBackground(buttonBackground); + style.setButtonBackgroundStyle(buttonBackgroundStyle); + style.setStyleType(style1.isSelected() ? 1 : 2); + style.setSelectBackgroundColor(selectBackgroundColorBox.getSelectObject()); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/MobileWidgetStyleEditPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/MobileWidgetStyleEditPane.java new file mode 100644 index 0000000000..ec6ef9aebb --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/MobileWidgetStyleEditPane.java @@ -0,0 +1,78 @@ +package com.fr.widgettheme.theme.edit.widget; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.gui.frpane.FontSizeComboPane; +import com.fr.widgettheme.theme.widget.style.BorderStyle; +import com.fr.widgettheme.theme.widget.style.MobileThemedWidgetStyle; +import com.fr.design.gui.icombobox.LineComboBox; +import com.fr.widgettheme.theme.widget.style.ThemeTextStyle; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; + +import java.util.Arrays; +import java.util.Vector; + +/** + * 移动端控件样式编辑面板 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/3/28 + */ +public class MobileWidgetStyleEditPane extends WidgetStyleEditPane { + /** + * 移动端字体列表 12-18 + */ + private static Vector FONT_SIZES = new Vector() { + { + addAll(Arrays.asList(12, 13, 14, 15, 16, 17, 18)); + } + }; + + public MobileWidgetStyleEditPane() { + super(); + } + + @Override + public void initLineBox() { + lineComboBox = new LineComboBox(WidgetThemeDisplayConstants.MOBILE_BORDER_LINE_STYLE_ARRAY); + lineComboBox.setSelectedLineStyle(com.fr.stable.Constants.LINE_THIN); + } + + @Override + protected void initFontSizePane() { + fontSizePane = new FontSizeComboPane(FONT_SIZES); + } + + @Override + public void populateBean(T t) { + MobileThemedWidgetStyle style = (MobileThemedWidgetStyle) t.getMobileWidgetStyle(); + if (style == null) { + style = new MobileThemedWidgetStyle(); + t.setMobileWidgetStyle(style); + } + colorSelectBox.setSelectObject(style.getThemeColor()); + lineComboBox.setSelectedLineStyle(style.getBorderStyle().getLineType()); + borderRadiusSpinner.setValue(style.getBorderStyle().getRadius()); + fontSizePane.setValue(style.getTextStyle().getFontSize()); + fontColorButton.setColor(style.getTextStyle().getFontColor()); + } + + @Override + public void updateBean(T t) { + MobileThemedWidgetStyle style = (MobileThemedWidgetStyle) t.getMobileWidgetStyle(); + if (style == null) { + style = new MobileThemedWidgetStyle(); + t.setMobileWidgetStyle(style); + } + style.setThemeColor(colorSelectBox.getSelectObject()); + BorderStyle borderStyle = new BorderStyle(); + borderStyle.setLineType(lineComboBox.getSelectedLineStyle()); + borderStyle.setRadius((int) borderRadiusSpinner.getValue()); + style.setBorderStyle(borderStyle); + ThemeTextStyle textStyle = new ThemeTextStyle(); + textStyle.setFontSize(fontSizePane.getValue()); + textStyle.setFontColor(fontColorButton.getColor()); + style.setTextStyle(textStyle); + } + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditContainerPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditContainerPane.java new file mode 100644 index 0000000000..789c0f61ac --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditContainerPane.java @@ -0,0 +1,136 @@ +package com.fr.widgettheme.theme.edit.widget; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import org.jetbrains.annotations.Nullable; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * 组件主题编辑容器,包含移动端控制面板和桌面端控制面板 + * 默认展开桌面端 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/3/28 + */ +public class WidgetStyleEditContainerPane extends BasicBeanPane { + private UIButtonGroup terminalStyleGroup; + private WidgetStyleEditPane desktop; + private WidgetStyleEditPane mobile; + + public WidgetStyleEditContainerPane() { + initComponent(); + } + + private void initComponent() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + // 初始化按钮组,桌面端&移动端 + initButtonGroup(); + // 创建按钮组面板 + createButtonGroupPane(); + // 默认选中桌面端 + terminalStyleGroup.setSelectedIndex(0); + // cardLayout用来切换面板 + // 桌面端 + initDesktopPanel(); + // 移动端 + initMobilePanel(); + createCardContainer(); + initListener(); + } + + private void createCardContainer() { + JPanel cardPanel = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardPanel.add(desktop, BorderLayout.CENTER); + cardPanel.add(mobile, BorderLayout.CENTER); + this.add(cardPanel, BorderLayout.CENTER); + } + + private void initMobilePanel() { + mobile = new MobileWidgetStyleEditPane<>(); + mobile.setVisible(false); + } + + private void initDesktopPanel() { + desktop = new DesktopWidgetStyleEditPane<>(); + // 默认可见性 + desktop.setVisible(true); + } + + private void createButtonGroupPane() { + Component[][] components = { + new Component[]{terminalStyleGroup}, + }; + final double p = TableLayout.PREFERRED; + double[] rowSize = {p}; + double[] columnSize = {p, p}; + int[][] rowCount = {{1, 1}}; + JPanel groupPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + this.add(groupPane, BorderLayout.NORTH); + } + + /** + * 初始化按钮组 + */ + private void initButtonGroup() { + terminalStyleGroup = new UIButtonGroup<>(new String[]{ + Toolkit.i18nText("Fine-Design_Widget_Terminal_Desktop"), + Toolkit.i18nText("Fine-Design_Widget_Terminal_Mobile")}); + this.add(terminalStyleGroup, BorderLayout.NORTH); + terminalStyleGroup.setSelectedIndex(0); + } + + /** + * 初始化按钮组的listener + */ + private void initListener() { + terminalStyleGroup.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showTerminalPane(); + } + }); + } + + /** + * 展示具体面板 + */ + private void showTerminalPane() { + desktop.setVisible(terminalStyleGroup.getSelectedIndex() == 0); + mobile.setVisible(terminalStyleGroup.getSelectedIndex() == 1); + } + + @Override + public void populateBean(T ob) { + desktop.populateBean(ob); + mobile.populateBean(ob); + } + + @Nullable + @Override + public T updateBean() { + return null; + } + + @Override + public void updateBean(T ob) { + desktop.updateBean(ob); + mobile.updateBean(ob); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Theme_Widget_Style"); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java new file mode 100644 index 0000000000..1c8ab2ff14 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java @@ -0,0 +1,125 @@ +package com.fr.widgettheme.theme.edit.widget; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.frpane.FontSizeComboPane; +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.gui.ispinner.UISpinner; +import com.fr.design.gui.style.FRFontPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.stable.StringUtils; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; +import com.fr.widgettheme.util.ThemeTextStylePaneCreator; +import org.jetbrains.annotations.Nullable; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + + +/** + * 组件样式编辑基础类 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/5/22 + */ +public class WidgetStyleEditPane extends BasicBeanPane { + + // 主题色 + protected NewColorSelectBox colorSelectBox; + + // 边框线型 + protected LineComboBox lineComboBox; + // 圆角边框 + protected UISpinner borderRadiusSpinner; + /** + * 文本样式面板 + */ + protected FontSizeComboPane fontSizePane; + + protected UIColorButton fontColorButton; + + public WidgetStyleEditPane() { + initComponents(); + } + + private void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initCommonStyleEditor(); + double f = TableLayout.PREFERRED; + final double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p, p, p}; + double[] columnSize = {p, p}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; + Component[][] components = generateComponent(); + JPanel customPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + customPane.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10)); + this.add(customPane, BorderLayout.NORTH); + } + + /** + * 初始化标签 + * + * @return components + */ + public Component[][] generateComponent() { + return new Component[][]{new Component[]{ + new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Color")), colorSelectBox}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Line")), lineComboBox}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Radius")), borderRadiusSpinner}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Text_Style")), ThemeTextStylePaneCreator.create(fontSizePane, fontColorButton)} + }; + } + + private void initCommonStyleEditor() { + colorSelectBox = new NewColorSelectBox(WidgetThemeDisplayConstants.THEME_WIDGET_COMPONENT_WIDTH, true); + colorSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR); + initLineBox(); + borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1); + initFontSizePane(); + fontColorButton = new UIColorButton(); + } + + protected void initFontSizePane() { + fontSizePane = new FontSizeComboPane(FRFontPane.getFontSizes()); + } + + /** + * 初始化边框线型 + */ + public void initLineBox() { + lineComboBox = new LineComboBox(WidgetThemeDisplayConstants.BORDER_LINE_STYLE_ARRAY); + } + + + @Override + public void populateBean(T t) { + + } + + @Nullable + @Override + public T updateBean() { + return null; + } + + @Override + public void updateBean(T t) { + } + + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ButtonStyleDefinedPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ButtonStyleDefinedPane.java new file mode 100644 index 0000000000..c6ec951eb4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ButtonStyleDefinedPane.java @@ -0,0 +1,77 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle; +import com.fr.design.dialog.BasicPane; +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.widgettheme.theme.bean.ButtonBackground; +import com.fr.design.mainframe.widget.accessibles.AccessibleImgBackgroundEditor; +import com.fr.general.Background; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + +/** + * 按钮样式定义窗口 + * + * @author obo + * @since 11.0 + * Created on 2023/11/13 + */ +public class ButtonStyleDefinedPane extends BasicPane { + + protected AccessibleImgBackgroundEditor initBackgroundPane; + protected AccessibleImgBackgroundEditor overBackgroundPane; + protected AccessibleImgBackgroundEditor clickBackgroundPane; + + public ButtonStyleDefinedPane() { + this.initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initBackgroundPane = new AccessibleImgBackgroundEditor(); + overBackgroundPane = new AccessibleImgBackgroundEditor(); + clickBackgroundPane = new AccessibleImgBackgroundEditor(); + double f = TableLayout.FILL; + final double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p}; + double[] columnSize = {p, f}; + int[][] rowCount = {{1, 1},{1, 1},{1, 1}}; + Component[][] components = new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Background_Initial")), initBackgroundPane}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Background_Over")), overBackgroundPane}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Background_Click")), clickBackgroundPane}, + }; + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, 7, 7); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + this.add(panel, BorderLayout.CENTER); + + } + + /** + * 填充 + */ + public void populate(ButtonBackground buttonBackground) { + initBackgroundPane.setValue(buttonBackground.getInitialBackground()); + overBackgroundPane.setValue(buttonBackground.getOverBackground()); + clickBackgroundPane.setValue(buttonBackground.getClickBackground()); + } + + /** + * 更新 + */ + public ButtonBackgroundStyle update() { + return new ButtonBackgroundStyle((Background) initBackgroundPane.getValue(), (Background) overBackgroundPane.getValue(), (Background) clickBackgroundPane.getValue()); + } + + @Override + protected String title4PopupWindow() { + return null; + } + +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCell.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCell.java new file mode 100644 index 0000000000..7dca24b7c1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCell.java @@ -0,0 +1,141 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.BaseUtils; +import com.fr.base.Style; +import com.fr.base.theme.TemplateTheme; +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LayoutManager; +import java.awt.image.BufferedImage; + +/** + * 主题界面预览单元格子 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class ControlPreviewCell extends JPanel { + protected static final LayoutManager DEFAULT = FRGUIPaneFactory.createRightFlowLayout(); + protected static final Color DEFAULT_COLOR = new Color(210, 210, 210); + protected static final Color DEFAULT_THEME_COLOR = new Color(54, 133, 242); + protected static final String DEFAULT_MESSAGE = ""; + protected static final int NO_SCALE_RESOLUTION = 100; + protected static final int DEFAULT_ALPHA = 255; + /** + * 格子文本数据 + */ + protected String value; + protected TemplateTheme reportTheme; + /** + * 字体的颜色 + */ + protected Color textColor = DEFAULT_COLOR; + + public Color getTextColor() { + return textColor; + } + + public void setTextColor(Color textColor) { + this.textColor = textColor; + } + + public ControlPreviewCell() { + this(DEFAULT, DEFAULT_MESSAGE); + } + + public ControlPreviewCell(String value) { + this(DEFAULT, value); + } + + public ControlPreviewCell(LayoutManager layoutManager, String value) { + this.setLayout(layoutManager); + this.setOpaque(false); + this.value = value; + this.setPreferredSize(new Dimension(80, 30)); + } + + /** + * 主题样式变化后监听改变 + */ + public void refresh(TemplateTheme reportTheme) { + this.reportTheme = reportTheme; + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) this.reportTheme.getWidgetStyle(); + //主题色设置为透明或者插件启动前已有的主题启动插件后主题色为null + if (widgetStyle.getThemeColor() == null) { + widgetStyle.setThemeColor(DEFAULT_THEME_COLOR); + } + } + + /** + * 填充圆角矩形背景色 + */ + public void paintBgColor(Graphics g, ThemedWidgetStyle widgetStyle) { + this.paintBgColor(g, widgetStyle, DEFAULT_ALPHA); + } + + public boolean isDefaultStyle() { + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + return widgetStyle.getStyleType() == ThemedWidgetStyle.DEFAULT_STYLE; + } + + public Color getThemeColor() { + + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + return widgetStyle.getThemeColor(); + + } + + protected Icon setStyleTwoIcon(Icon icon, Icon defaultIcon) { + if (this.reportTheme != null && !isDefaultStyle()) { + + if (icon instanceof ImageIcon) { + ImageIcon imageIcon = (ImageIcon) icon; + BufferedImage bufferedImage = ImageUtils.colorImage(ImageUtils.imageIconToBufferedImage(imageIcon), getThemeColor()); + return new ImageIcon(bufferedImage); + } + } + return defaultIcon; + } + + /** + * 填充圆角矩形背景色 + */ + public void paintBgColor(Graphics g, ThemedWidgetStyle widgetStyle, int alpha) { + Color themeColor = widgetStyle.getThemeColor(); + g.setColor(new Color(themeColor.getRed(), themeColor.getGreen(), themeColor.getBlue(), alpha)); + g.fillRoundRect(0, 0, getSize().width - 1, getSize().height - 1, widgetStyle.getBorderStyle().getRadius(), widgetStyle.getBorderStyle().getRadius()); + //需要重新绘制一遍字体,否则会被颜色填充给遮住 + Graphics2D g2d = (Graphics2D) g.create(); + FRFont font = FRFont.getInstance(FRFont.DEFAULT_FONTNAME, Font.PLAIN, widgetStyle.getTextStyle().getFontSize(), textColor); + BaseUtils.drawStringStyleInRotation(g2d, getWidth(), getHeight(), this.value, + Style.getInstance(font).deriveHorizontalAlignment(Constants.LEFT) + .deriveTextStyle(Style.TEXTSTYLE_SINGLELINE), NO_SCALE_RESOLUTION); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + if (this.reportTheme == null) { + return; + } + Graphics2D g2d = (Graphics2D) g.create(); + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + FRFont font = FRFont.getInstance(FRFont.DEFAULT_FONTNAME, Font.PLAIN, widgetStyle.getTextStyle().getFontSize(), textColor); + //每个预览格子通用的字体绘制 + BaseUtils.drawStringStyleInRotation(g2d, getWidth(), getHeight(), this.value, + Style.getInstance(font).deriveHorizontalAlignment(Constants.LEFT) + .deriveTextStyle(Style.TEXTSTYLE_SINGLELINE), NO_SCALE_RESOLUTION); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCellWithIcon.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCellWithIcon.java new file mode 100644 index 0000000000..eb5f1eb9b9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCellWithIcon.java @@ -0,0 +1,77 @@ +package com.fr.widgettheme.theme.panel; + + +import com.fr.base.svg.IconUtils; +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; +import com.fr.design.border.UIRoundedBorder; +import com.fr.stable.StringUtils; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; + +import javax.swing.Icon; +import javax.swing.JLabel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.LayoutManager; + +/** + * 主题界面预览控件单元格子,控件图表直接用icon + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class ControlPreviewCellWithIcon extends ControlPreviewCell { + private static final int CONTROL_ALPHA = 16; + + JLabel jLabel; + Icon icon; + Icon defaultIcon; + + public ControlPreviewCellWithIcon() { + this(DEFAULT, DEFAULT_MESSAGE); + } + + public ControlPreviewCellWithIcon(String value) { + this(DEFAULT, value); + } + + public ControlPreviewCellWithIcon(LayoutManager layoutManager, String value) { + this.setLayout(layoutManager); + this.value = value; + this.setPreferredSize(new Dimension(100, 27)); + } + + /** + * 根据icon地址绘制一个图标,用jlabel进行展示 + * + * @param url icon地址 + */ + public void drawIcon(String url) { + if (StringUtils.isEmpty(url)) { + return; + } + defaultIcon = IconUtils.readIcon(url); + icon = setStyleTwoIcon(icon, defaultIcon); + this.jLabel = new JLabel(icon); + jLabel.setPreferredSize(new Dimension(21, 17)); + + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + //风格一边框不显示主题色 + Color borderColor = isDefaultStyle() ? DEFAULT_COLOR : widgetStyle.getThemeColor(); + this.setBorder(new UIRoundedBorder(widgetStyle.getBorderStyle().getLineType() + , borderColor, widgetStyle.getBorderStyle().getRadius())); + icon = setStyleTwoIcon(icon, defaultIcon); + this.jLabel.setIcon(icon); + this.add(jLabel, BorderLayout.EAST); + if (widgetStyle.getStyleType() != ThemedWidgetStyle.DEFAULT_STYLE) { + paintBgColor(g, widgetStyle, CONTROL_ALPHA); + } + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewPane.java new file mode 100644 index 0000000000..110e6943c4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewPane.java @@ -0,0 +1,133 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.TemplateTheme; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.general.Background; + +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +/** + * 主题界面页面中的参数界面 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class ControlPreviewPane extends JPanel implements ThemePreviewed { + + public static final int PREVIEW_WIDTH = 615; + + public static final int PREVIEW_HEIGHT = 62; + + /** + * 参数界面中放置的所有cell,用于监听主题样式变更 + */ + public final List list = new ArrayList<>(); + + private Background background; + + private static final String DATE_ICON_URL = "/com/fr/web/images/form/resources/date_16.png"; + + private static final String COMBOBOX_ICON_URL = "/com/fr/widgettheme/combobox.png"; + + @Override + public void refresh(TemplateTheme style) { + this.background = style.getParamContainerStyle().getBackground(); + for (ControlPreviewCell controlPreviewCell : list) { + controlPreviewCell.refresh(style); + } + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + paintBackground((Graphics2D) g); + } + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + } + + /** + * 初始化参数界面,往里面添加各种cell + */ + public void initControlPreviewPane() { + initDateControlPane(); + initComboboxControlPane(); + initRadioButtonControlPane(); + initNormalButtonControlPane(); + } + + /** + * 初始化日期控件包括文字跟控件 + */ + private void initDateControlPane() { + TextPreviewCell dateTextCell = new TextPreviewCell(Toolkit.i18nText("Fine-Design_Theme_Control_Date_Text")); + dateTextCell.setPreferredSize(new Dimension(80, 30)); + ControlPreviewCellWithIcon dateEditorCell = new ControlPreviewCellWithIcon(Toolkit.i18nText("Fine-Design_Theme_Control_Date_Editor_Text")); + dateEditorCell.drawIcon(DATE_ICON_URL); + dateEditorCell.setTextColor(ControlPreviewCell.DEFAULT_COLOR); + this.add(dateTextCell); + this.add(dateEditorCell); + this.list.add(dateTextCell); + this.list.add(dateEditorCell); + } + + /** + * 初始化下拉框控件包括文件跟控件 + */ + private void initComboboxControlPane() { + TextPreviewCell comboBoxTextCell = new TextPreviewCell(Toolkit.i18nText("Fine-Design_Theme_Control_ComboBox_Text")); + comboBoxTextCell.setPreferredSize(new Dimension(60, 30)); + ControlPreviewCellWithIcon comboBoxControlPreviewCell = new ControlPreviewCellWithIcon(Toolkit.i18nText("Fine-Design_Theme_Control_ComboBox_Editor_Text")); + comboBoxControlPreviewCell.drawIcon(COMBOBOX_ICON_URL); + comboBoxControlPreviewCell.setTextColor(ControlPreviewCell.DEFAULT_COLOR); + this.add(comboBoxTextCell); + this.add(comboBoxControlPreviewCell); + this.list.add(comboBoxControlPreviewCell); + this.list.add(comboBoxTextCell); + } + + /** + * 初始化单选按钮组控件 + */ + private void initRadioButtonControlPane() { + RingControlPreviewCell ringControlPreviewCell = new RingControlPreviewCell(); + RoundControlPreviewCell roundControlPreviewCell = new RoundControlPreviewCell(); + + TextPreviewCell yearTextFieldCell = new TextPreviewCell(Toolkit.i18nText("Fine-Design_Theme_Control_Radio_Year")); + yearTextFieldCell.setPreferredSize(new Dimension(38, 30)); + TextPreviewCell monthTextFieldCell = new TextPreviewCell(Toolkit.i18nText("Fine-Design_Theme_Control_Radio_Month")); + monthTextFieldCell.setPreferredSize(new Dimension(38, 30)); + this.add(ringControlPreviewCell); + this.add(yearTextFieldCell); + this.add(roundControlPreviewCell); + this.add(monthTextFieldCell); + this.list.add(ringControlPreviewCell); + this.list.add(roundControlPreviewCell); + this.list.add(yearTextFieldCell); + this.list.add(monthTextFieldCell); + } + + /** + * 初始化按钮预览格子 + */ + private void initNormalButtonControlPane() { + NormalButtonPreviewCell normalButton = new NormalButtonPreviewCell(FRGUIPaneFactory.createCenterFlowLayout(), ControlPreviewCell.DEFAULT_MESSAGE); + this.add(normalButton); + this.list.add(normalButton); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ImageUtils.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ImageUtils.java new file mode 100644 index 0000000000..63da90e6f7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/ImageUtils.java @@ -0,0 +1,89 @@ +package com.fr.widgettheme.theme.panel; + +import javax.swing.ImageIcon; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; + +/** + * 控件主题Image处理工具类 + * + * @author obo + * @since 11.0 + * Created on 2023/11/13 + */ +public class ImageUtils { + + /** + * 根据主题色处理image + * + * @param image 图像 + * @param color 主题色 + * @return 处理结果 + */ + public static BufferedImage colorImage(BufferedImage image, Color color) { + int width = image.getWidth(); + int height = image.getHeight(); + WritableRaster raster = image.getRaster(); + + for (int xx = 0; xx < width; xx++) { + for (int yy = 0; yy < height; yy++) { + int[] pixels = raster.getPixel(xx, yy, (int[]) null); + setRedPixels(pixels, color); + setGreenPixels(pixels, color); + setBluePixels(pixels, color); + raster.setPixel(xx, yy, pixels); + } + } + return image; + } + + /** + * 处理红像素 + * + * @param pixels 像素数组 + * @param color 颜色 + */ + private static void setRedPixels(int[] pixels, Color color) { + pixels[0] = pixels[0] > 0 && pixels[0] < 255 ? color.getRed() : 255; + } + + /** + * 处理绿像素 + * + * @param pixels 像素数组 + * @param color 颜色 + */ + private static void setGreenPixels(int[] pixels, Color color) { + pixels[1] = pixels[1] > 0 && pixels[1] < 255 ? color.getGreen() : 255; + } + + /** + * 处理蓝像素 + * + * @param pixels 像素数组 + * @param color 颜色 + */ + private static void setBluePixels(int[] pixels, Color color) { + pixels[2] = pixels[2] > 0 && pixels[2] < 255 ? color.getBlue() : 255; + } + + /** + * ImageIcon转换为BufferImage + * + * @param icon imageIcon + * @return BufferedImage + */ + public static BufferedImage imageIconToBufferedImage(ImageIcon icon) { + BufferedImage bi = new BufferedImage( + icon.getIconWidth(), + icon.getIconHeight(), + BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.createGraphics(); + icon.paintIcon(null, g, 0, 0); + g.dispose(); + return bi; + } + +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/NormalButtonPreviewCell.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/NormalButtonPreviewCell.java new file mode 100644 index 0000000000..7d734b2e16 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/NormalButtonPreviewCell.java @@ -0,0 +1,50 @@ +package com.fr.widgettheme.theme.panel; + + +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.general.FRFont; + +import java.awt.*; + +/** + * 主题参数面板按钮预览格子 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/27 + */ +public class NormalButtonPreviewCell extends ControlPreviewCell { + + /** + * 按钮上的label + */ + private UILabel uiLabel; + + public NormalButtonPreviewCell() { + this(DEFAULT, DEFAULT_MESSAGE); + } + + public NormalButtonPreviewCell(String value) { + this(DEFAULT, value); + } + + public NormalButtonPreviewCell(LayoutManager layoutManager, String value) { + this.setLayout(layoutManager); + this.value = value; + this.uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Theme_Control_Normal_Button")); + this.setPreferredSize(new Dimension(80, 27)); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + paintBgColor(g, widgetStyle); + uiLabel.setForeground(Color.WHITE); + FRFont font = FRFont.getInstance(FRFont.DEFAULT_FONTNAME, Font.PLAIN, widgetStyle.getTextStyle().getFontSize(), Color.WHITE); + uiLabel.setFont(font); + this.add(uiLabel, BorderLayout.CENTER); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/RingControlPreviewCell.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/RingControlPreviewCell.java new file mode 100644 index 0000000000..6d492688d4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/RingControlPreviewCell.java @@ -0,0 +1,51 @@ +package com.fr.widgettheme.theme.panel; + + +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; + +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.Graphics2D; +import java.awt.Graphics; +import java.awt.Color; + +/** + * 主题界面预览控件单元格子,单选按钮组被选中的样子 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class RingControlPreviewCell extends ControlPreviewCell { + /** + * 圆环厚度 + */ + private static final int THICK_NESS = 4; + + public RingControlPreviewCell() { + this(DEFAULT, DEFAULT_MESSAGE); + } + + public RingControlPreviewCell(String value) { + this(DEFAULT, value); + } + + public RingControlPreviewCell(LayoutManager layoutManager, String value) { + this.setLayout(layoutManager); + this.setOpaque(false); + this.value = value; + this.setPreferredSize(new Dimension(20, 30)); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setColor(widgetStyle.getThemeColor()); + g2d.fillOval(5, 9, 15, 15); + g2d.setColor(Color.WHITE); + g2d.fillOval(5 + THICK_NESS, 9 + THICK_NESS, 15 - 2 * THICK_NESS, 15 - 2 * THICK_NESS); + } + +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/RoundControlPreviewCell.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/RoundControlPreviewCell.java new file mode 100644 index 0000000000..dc98146b35 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/RoundControlPreviewCell.java @@ -0,0 +1,45 @@ +package com.fr.widgettheme.theme.panel; + + +import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LayoutManager; + +/** + * 主题界面预览控件单元格子,单选按钮组未被选中的样子 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class RoundControlPreviewCell extends ControlPreviewCell { + public RoundControlPreviewCell() { + this(DEFAULT, DEFAULT_MESSAGE); + } + + public RoundControlPreviewCell(String value) { + this(DEFAULT, value); + } + + public RoundControlPreviewCell(LayoutManager layoutManager, String value) { + this.setLayout(layoutManager); + this.setOpaque(false); + this.value = value; + this.setPreferredSize(new Dimension(23, 30)); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) reportTheme.getWidgetStyle(); + //风格一边框不显示主题色 + Color borderColor = isDefaultStyle() ? DEFAULT_COLOR : widgetStyle.getThemeColor(); + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setColor(borderColor); + g2d.drawOval(5, 9, 15, 15); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/TextPreviewCell.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/TextPreviewCell.java new file mode 100644 index 0000000000..c79be9f69d --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/TextPreviewCell.java @@ -0,0 +1,36 @@ +package com.fr.widgettheme.theme.panel; + + +import com.fr.base.theme.TemplateTheme; + +import java.awt.*; + +/** + * 文字预览格子 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/27 + */ +public class TextPreviewCell extends ControlPreviewCell { + + public TextPreviewCell(String value) { + this(DEFAULT, value); + } + + public TextPreviewCell(LayoutManager layoutManager, String value) { + this.setLayout(layoutManager); + this.value = value; + } + + @Override + public void refresh(TemplateTheme reportTheme) { + super.refresh(reportTheme); + // 文字根据是否深色主题自适应改变 + if (reportTheme.isDark()) { + textColor = Color.WHITE; + } else { + textColor = Color.BLACK; + } + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayFormThemePreviewPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayFormThemePreviewPane.java new file mode 100644 index 0000000000..1ae886f62c --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayFormThemePreviewPane.java @@ -0,0 +1,202 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.FormTheme; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartdata.NormalChartData; +import com.fr.chart.charttypes.ChartTypeManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ChartComponentPreviewPane; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.PiePlot4VanChart; +import com.fr.plugin.chart.attr.VanChartLegend; +import com.fr.plugin.chart.base.VanChartTools; +import com.fr.plugin.chart.column.VanChartColumnPlot; +import com.fr.plugin.chart.type.GradientType; +import com.fr.plugin.chart.type.RadiusType; +import com.fr.plugin.chart.vanchart.VanChart; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.JPanel; +import java.awt.AlphaComposite; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import static com.fr.design.i18n.Toolkit.i18nText; +import static com.fr.widgettheme.util.ThemePreviewPaneInitHelper.initColumnPlot; +import static com.fr.widgettheme.util.ThemePreviewPaneInitHelper.initVanChartYAxis; +import static com.fr.widgettheme.util.ThemePreviewPaneInitHelper.initVanChartsTools; + +/** + * 主题界面预览控frm界面,就是主jar里的那个界面,做了简单的修改 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class WidgetDisplayFormThemePreviewPane extends TemplateThemePreviewPane { + private WidgetThemeECComponentPreviewPane elementCasePane; + private Background background; + private ChartComponentPreviewPane columnChartPreviewPane; + private ChartComponentPreviewPane pieChartPreviewPane; + private ControlPreviewPane controlPreviewPane; + private float alpha = 1.0F; + + public WidgetDisplayFormThemePreviewPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + controlPreviewPane = new ControlPreviewPane(); + controlPreviewPane.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + controlPreviewPane.setPreferredSize(new Dimension(615, 40)); + controlPreviewPane.initControlPreviewPane(); + JPanel content = new UINoOpaquePanel(); + content.setLayout(new BorderLayout()); + add(controlPreviewPane, BorderLayout.NORTH); + JPanel chartContent = createChartContent(); + content.add(chartContent, BorderLayout.CENTER); + content.add(elementCasePane = new WidgetThemeECComponentPreviewPane(), BorderLayout.SOUTH); + add(content, BorderLayout.CENTER); + } + + private JPanel createChartContent() { + JPanel chartContent = new UINoOpaquePanel(); + chartContent.setLayout(new BorderLayout()); + JPanel columnChartPanel = new UINoOpaquePanel() { + public Dimension getPreferredSize() { + return new Dimension(379, 314); + } + }; + columnChartPanel.setLayout(new BorderLayout()); + columnChartPreviewPane = createChartPreviewPane(initColumnChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Comp_Title1")); + columnChartPanel.add(columnChartPreviewPane, BorderLayout.CENTER); + + JPanel pieChartPanel = new UINoOpaquePanel() { + public Dimension getPreferredSize() { + return new Dimension(236, 314); + } + }; + pieChartPanel.setLayout(new BorderLayout()); + pieChartPreviewPane = createChartPreviewPane(initPieChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Comp_Title2")); + pieChartPanel.add(pieChartPreviewPane, BorderLayout.CENTER); + chartContent.add(columnChartPanel, BorderLayout.CENTER); + chartContent.add(pieChartPanel, BorderLayout.EAST); + return chartContent; + } + + private ChartComponentPreviewPane createChartPreviewPane(ChartCollection chartCollection, String title) { + ChartComponentPreviewPane chartComponentPreviewPane = new ChartComponentPreviewPane(title); + chartComponentPreviewPane.getContentPane().populate(chartCollection); + chartComponentPreviewPane.getContentPane().setCallbackEvent(this); + return chartComponentPreviewPane; + } + + @Override + public void refresh(FormTheme theme) { + background = theme.getBodyStyle().getStyle().getBackground(); + alpha = theme.getBodyStyle().getStyle().getAlpha(); + elementCasePane.refresh(theme); + columnChartPreviewPane.refresh(theme); + pieChartPreviewPane.refresh(theme); + controlPreviewPane.refresh(theme); + repaint(); + } + + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + g2d.setComposite(oldComposite); + } + + /** + * 初始化柱形图 + * + * @return 存放图表 + */ + private ChartCollection initColumnChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID)[0].clone(); + initColumnChartDetail(chart); + Object[] category = { + Toolkit.i18nText("Fine-Design_Chart_Category") + "1", + Toolkit.i18nText("Fine-Design_Chart_Category") + "2", + Toolkit.i18nText("Fine-Design_Chart_Category") + "3", + Toolkit.i18nText("Fine-Design_Chart_Category") + "4" + }; + Object[] series = { + Toolkit.i18nText("Fine-Design_Chart_Series") + "1", + Toolkit.i18nText("Fine-Design_Chart_Series") + "2" + }; + Object[][] value = { + {"250", "540", "300", "410"}, + {"180", "190", "170", "100"}, + }; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } + + private void initColumnChartDetail(VanChart chart) { + chart.getTitle().setTitleVisible(false); + initVanChartsTools(chart.getVanChartTools()); + VanChartColumnPlot plot = chart.getPlot(); + //Form中独有的setPosition,和Report中不同,先单独放在这里,不写在initPlot中 + plot.getLegend().setPosition(Constants.TOP); + initColumnPlot(plot); + initVanChartYAxis(plot.getDefaultYAxis()); + } + + /** + * 初始化饼图 + * + * @return chartCollection + */ + private ChartCollection initPieChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(PiePlot4VanChart.VAN_CHART_PIE_PLOT)[0].clone(); + chart.getTitle().setTitleVisible(false); + VanChartTools vanChartTools = chart.getVanChartTools(); + vanChartTools.setSort(false); + vanChartTools.setExport(false); + vanChartTools.setFullScreen(false); + + PiePlot4VanChart plot = chart.getPlot(); + VanChartLegend legend = (VanChartLegend) plot.getLegend(); + legend.setPosition(Constants.BOTTOM); + legend.setCustomSize(true); + legend.setMaxHeight(28); + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setInnerRadiusPercent(75); + plot.getRadius().setRadiusType(RadiusType.FIXED); + plot.getRadius().setRadius(70); + + Object[] category = {StringUtils.EMPTY}; + Object[] series = {"A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"}; + Object[][] value = {{45}, {24}, {12}, {8}, {5}, {3}, {2}, {1},}; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayReportThemePreviewPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayReportThemePreviewPane.java new file mode 100644 index 0000000000..31da4aab81 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayReportThemePreviewPane.java @@ -0,0 +1,119 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.ReportTheme; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartdata.NormalChartData; +import com.fr.chart.charttypes.ChartTypeManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ChartPreviewPane; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.column.VanChartColumnPlot; +import com.fr.plugin.chart.vanchart.VanChart; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import static com.fr.widgettheme.util.ThemePreviewPaneInitHelper.initColumnPlot; +import static com.fr.widgettheme.util.ThemePreviewPaneInitHelper.initVanChartYAxis; +import static com.fr.widgettheme.util.ThemePreviewPaneInitHelper.initVanChartsTools; + +/** + * 主题界面预览控cpt界面,就是主jar里的那个界面,做了简单的修改 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/3/18 + */ +public class WidgetDisplayReportThemePreviewPane extends TemplateThemePreviewPane { + private Background background; + + private final WidgetThemeECReportPreviewPane reportPreviewPane; + + private final ChartPreviewPane chartPreviewPane; + + private final ControlPreviewPane controlPreviewPane; + + public WidgetDisplayReportThemePreviewPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + chartPreviewPane = new ChartPreviewPane(); + chartPreviewPane.setPreferredSize(new Dimension(615, 207)); + chartPreviewPane.populate(initColumnChart()); + chartPreviewPane.setCallbackEvent(this); + reportPreviewPane = new WidgetThemeECReportPreviewPane(); + reportPreviewPane.setPreferredSize(new Dimension(615, 257)); + controlPreviewPane = new ControlPreviewPane(); + controlPreviewPane.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + controlPreviewPane.setPreferredSize(new Dimension(615, 40)); + controlPreviewPane.initControlPreviewPane(); + this.add(reportPreviewPane, BorderLayout.CENTER); + this.add(chartPreviewPane, BorderLayout.SOUTH); + this.add(controlPreviewPane, BorderLayout.NORTH); + } + + @Override + public void refresh(ReportTheme theme) { + background = theme.getBodyStyle().getBackground(); + reportPreviewPane.refresh(theme); + chartPreviewPane.refresh(theme); + controlPreviewPane.refresh(theme); + repaint(); + } + + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + } + + + /** + * 初始化柱形图 + * + * @return chartCollection + */ + private ChartCollection initColumnChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID)[0].clone(); + initColumnChartDetail(chart); + Object[] category = { + Toolkit.i18nText("Fine-Design_Chart_Category") + "1", + Toolkit.i18nText("Fine-Design_Chart_Category") + "2", + Toolkit.i18nText("Fine-Design_Chart_Category") + "3", + Toolkit.i18nText("Fine-Design_Chart_Category") + "4" + }; + Object[] series = { + Toolkit.i18nText("Fine-Design_Chart_Series") + "1", + Toolkit.i18nText("Fine-Design_Chart_Series") + "2", + Toolkit.i18nText("Fine-Design_Chart_Series") + "3" + }; + Object[][] value = { + {"340", "510", "300", "250"}, + {"180", "360", "170", "100"}, + {"210", "205", "405", "190"} + }; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } + + private void initColumnChartDetail(VanChart chart) { + initVanChartsTools(chart.getVanChartTools()); + VanChartColumnPlot plot = chart.getPlot(); + initColumnPlot(plot); + initVanChartYAxis(plot.getDefaultYAxis()); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECComponentPreviewPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECComponentPreviewPane.java new file mode 100644 index 0000000000..a2a873ea38 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECComponentPreviewPane.java @@ -0,0 +1,35 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.theme.FormTheme; +import com.fr.design.mainframe.theme.preview.ComponentPreviewPane; + +import java.awt.Component; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * 决策报表主题界面的那个表格+标题部分 + * + * @author John.Ying + * @since 1.0 + * Created on 2021/3/18 + */ +public class WidgetThemeECComponentPreviewPane extends ComponentPreviewPane { + private WidgetThemeECPreviewPane contentPane; + + public WidgetThemeECComponentPreviewPane() { + super(i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Title")); + } + + @Override + protected Component createContentPane() { + contentPane = new WidgetThemeECPreviewPane(); + return contentPane; + } + + @Override + public void refresh(FormTheme theme) { + super.refresh(theme); + contentPane.refresh(theme); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECPreviewPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECPreviewPane.java new file mode 100644 index 0000000000..774ccf1c1e --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECPreviewPane.java @@ -0,0 +1,112 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.CellBorderSourceFlag; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.AbstractECPreviewPane; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.List; + +/** + * 主题界面frm里的那个表格,做了简单修改,削减了几行重复内容,腾出控件参数面板的空间 + * + * @author John.Ying + * @since 11.0 + * Created on 2021/3/18 + */ +public class WidgetThemeECPreviewPane extends AbstractECPreviewPane { + private final List headerCellList = new ArrayList<>(); + private final List contentCellList = new ArrayList<>(); + private final List highLightCellList = new ArrayList<>(); + private final List assistCellList = new ArrayList<>(); + private static final int COL_COUNT = 5; + private static final int CONTENT_ROW_COUNT = 1; + + public WidgetThemeECPreviewPane() { + this.setPreferredSize(new Dimension(517, 158 - 36)); + this.setBorder(BorderFactory.createEmptyBorder(0, 1, 2, 1)); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel titlePane = new UINoOpaquePanel(new GridLayout()); + JPanel extCenterPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + this.add(extCenterPane, BorderLayout.CENTER); + extCenterPane.add(titlePane, BorderLayout.NORTH); + for (int c = 0; c < COL_COUNT; c++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(103, 36)); + titlePane.add(cell); + headerCellList.add(cell); + } + JPanel contentPane = new UINoOpaquePanel(new GridLayout(1, 5, 0, 0)); + extCenterPane.add(contentPane, BorderLayout.CENTER); + for (int i = 0; i < COL_COUNT * CONTENT_ROW_COUNT; i++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text")); + int c = i % COL_COUNT; + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(103, 30)); + contentPane.add(cell); + contentCellList.add(cell); + } + + JPanel endPane = new UINoOpaquePanel(new GridLayout()); + extCenterPane.add(endPane, BorderLayout.SOUTH); + for (int c = 0; c < COL_COUNT; c++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(103, 30)); + endPane.add(cell); + highLightCellList.add(cell); + } + + JPanel extSouthPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + PreviewCell assistCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Assist_Text")); + assistCell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + assistCell.setPreferredSize(new Dimension(123, 30)); + assistCellList.add(assistCell); + extSouthPane.add(assistCell); + this.add(extSouthPane, BorderLayout.SOUTH); + } + + @Override + public void refresh(TemplateTheme theme) { + ThemedCellStyleList cellStyleConfig = theme.getCellStyleList(); + refresh(headerCellList, cellStyleConfig.getUse4Header()); + refresh(contentCellList, cellStyleConfig.getUse4MainText()); + refresh(highLightCellList, cellStyleConfig.getUse4HighlightText()); + refresh(assistCellList, cellStyleConfig.getUse4SupportInfo()); + } + + +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECReportPreviewPane.java b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECReportPreviewPane.java new file mode 100644 index 0000000000..39cd48a566 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECReportPreviewPane.java @@ -0,0 +1,248 @@ +package com.fr.widgettheme.theme.panel; + +import com.fr.base.CellBorderSourceFlag; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.AbstractECPreviewPane; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.CornerPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +/** + * 主题界面report里的那个表格,做了简单修改,削减了几行重复内容,腾出控件参数面板的空间 + * + * @author John.Ying + * @since 1.0 + * Created on 2021/3/18 + */ +public class WidgetThemeECReportPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + private final List headerTitleCellList = new ArrayList<>(); // 大标题样式单元格 + private final List headerCellList = new ArrayList<>(); // 表头样式单元格 + private final List titleCellList = new ArrayList<>(); // 小标题样式单元格 + private final List contentCellList = new ArrayList<>(); // 正文样式单元格 + private final List highLightCellList = new ArrayList<>(); // 高亮文本样式单元格 + private final List assistCellList = new ArrayList<>(); // 辅助信息样式单元格 + private static final int CONTENT_ROW_COUNT = 3; + private static final int COL_COUNT = 3; + + private final PreviewPane previewPane; + + public WidgetThemeECReportPreviewPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + previewPane = new PreviewPane(); + this.add(previewPane, BorderLayout.CENTER); + } + + @Override + public void refresh(ReportTheme theme) { + previewPane.refresh(theme); + } + + + class PreviewPane extends AbstractECPreviewPane { + + + public PreviewPane() { + this.setPreferredSize(new Dimension(517, 208)); + this.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel northPane = createNorthPane(); + JPanel centerPane = createCenterPane(); + JPanel southPane = createSouthPane(); + this.add(northPane, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.CENTER); + this.add(southPane, BorderLayout.SOUTH); + } + + private JPanel createNorthPane() { + JPanel northPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + AbstractPreviewCell bigTitleCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Cell_Style_Big_Title")); + bigTitleCell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + bigTitleCell.setPreferredSize(new Dimension(615, 46)); + headerTitleCellList.add(bigTitleCell); + northPane.add(bigTitleCell, BorderLayout.NORTH); + CornerPreviewCell cornerCell = createCornerPreviewCell(); + titleCellList.add(cornerCell); + northPane.add(cornerCell, BorderLayout.WEST); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + northPane.add(centerPane, BorderLayout.CENTER); + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Small_Title")); + cell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + titleCellList.add(cell); + cell.setPreferredSize(new Dimension(308, 38)); + centerPane.add(cell, BorderLayout.NORTH); + JPanel eastSouthPane = new UINoOpaquePanel(new GridLayout()); + for (int c = 0; c < CONTENT_ROW_COUNT; c++) { + PreviewCell headerCell = createPreviewCellHeader(c); + headerCellList.add(headerCell); + eastSouthPane.add(headerCell); + } + centerPane.add(eastSouthPane, BorderLayout.CENTER); + return northPane; + } + + /** + * 创建CornerPreviewCell + */ + private CornerPreviewCell createCornerPreviewCell() { + CornerPreviewCell cornerCell = new CornerPreviewCell(new String[]{Toolkit.i18nText("Fine-Design_Basic_Column_Name"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Data"), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Row_Name")}, + new Point2D[]{new Point(159, 71), new Point(225, 49)}); + cornerCell.setBorderSourceFlag(CellBorderSourceFlag.INVALID_BORDER_SOURCE); + cornerCell.setPreferredSize(new Dimension(225, 71)); + return cornerCell; + } + + /** + * 创建预览单元格标题 + * + * @param c 文本行数 + * @return PreviewCell + */ + private PreviewCell createPreviewCellHeader(int c) { + PreviewCell headerCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < CONTENT_ROW_COUNT - 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + headerCell.setBorderSourceFlag(flag); + return headerCell; + } + + private JPanel createCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + JPanel westPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + centerPane.add(westPane, BorderLayout.WEST); + PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Small_Title")); + titleCellList.add(cell1); + cell1.setPreferredSize(new Dimension(112, 93)); + westPane.add(cell1, BorderLayout.WEST); + JPanel gridPane = createGridPane(); + + westPane.add(gridPane, BorderLayout.CENTER); + JPanel innerCenterPane = new UINoOpaquePanel(new GridLayout(3, 3)); + centerPane.add(innerCenterPane, BorderLayout.CENTER); + for (int i = 0; i < COL_COUNT*CONTENT_ROW_COUNT; i++) { + PreviewCell cell ; + int r = i / CONTENT_ROW_COUNT; + int c = i % CONTENT_ROW_COUNT; + if (c == CONTENT_ROW_COUNT - 1) { + cell = createPreviewCellHighlight(r); + highLightCellList.add(cell); + } else { + cell = createPreviewCellMain(r, c); + contentCellList.add(cell); + } + cell.setPreferredSize(new Dimension(123, 31)); + innerCenterPane.add(cell); + } + return centerPane; + } + + /** + * 创建高亮预览单元格 + * + * @param r 计算标志位 + * @return 单元格 + */ + private PreviewCell createPreviewCellHighlight(int r) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r != 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r != COL_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + return cell; + } + + /** + * 创建正文预览单元格 + * + * @param r 计算标志位 + * @param c 计算标志位 + * @return 单元格 + */ + private PreviewCell createPreviewCellMain(int r, int c) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r > 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + if (c > 0) { + flag |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; + } + if (c < 1) { + flag |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + return cell; + } + + private JPanel createGridPane() { + int rowCount = 3; + int columnCount = 1; + JPanel gridPane = new UINoOpaquePanel(new GridLayout(rowCount, columnCount)); + for (int r = 0; r < rowCount; r++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header")); + int flag = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; + if (r > 0) { + flag |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; + } + if (r < COL_COUNT - 1) { + flag |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; + } + cell.setBorderSourceFlag(flag); + cell.setPreferredSize(new Dimension(113, 31)); + headerCellList.add(cell); + gridPane.add(cell); + } + return gridPane; + } + + private JPanel createSouthPane(){ + JPanel southPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + PreviewCell assistCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Assist_Text")); + assistCell.setBorderSourceFlag(CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER); + assistCell.setPreferredSize(new Dimension(123, 30)); + assistCellList.add(assistCell); + southPane.add(assistCell, BorderLayout.CENTER); + return southPane; + } + + @Override + public void refresh(TemplateTheme theme) { + ThemedCellStyleList cellStyleConfig = theme.getCellStyleList(); + refresh(headerTitleCellList, cellStyleConfig.getUse4BigTitle()); + refresh(headerCellList, cellStyleConfig.getUse4Header()); + refresh(contentCellList, cellStyleConfig.getUse4MainText()); + refresh(titleCellList, cellStyleConfig.getUse4SmallTitle()); + refresh(highLightCellList, cellStyleConfig.getUse4HighlightText()); + refresh(assistCellList, cellStyleConfig.getUse4SupportInfo()); + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/util/ThemePreviewPaneInitHelper.java b/designer-base/src/main/java/com/fr/widgettheme/util/ThemePreviewPaneInitHelper.java new file mode 100644 index 0000000000..c7adedbbc7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/util/ThemePreviewPaneInitHelper.java @@ -0,0 +1,70 @@ +package com.fr.widgettheme.util; + +import com.fr.base.BaseFormula; +import com.fr.chart.chartattr.Title; +import com.fr.design.i18n.Toolkit; +import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.base.AttrLabel; +import com.fr.plugin.chart.base.VanChartTools; +import com.fr.plugin.chart.column.VanChartColumnPlot; +import com.fr.plugin.chart.type.GradientType; + +/** + * 辅助report和form的控件显示主题预览窗口做初始化工作 + * 没有其他的用途,不要用在其他的地方,只是抽一些方法出来,降低复杂度 + * + * @author obo + * @since 11.0 + * Created on 2023/11/14 + */ +public class ThemePreviewPaneInitHelper { + private ThemePreviewPaneInitHelper() { + } + + /** + * 初始化图表工具 + * + * @param vanChartTools 图表工具 + */ + public static void initVanChartsTools(VanChartTools vanChartTools) { + vanChartTools.setSort(false); + vanChartTools.setExport(false); + vanChartTools.setFullScreen(false); + } + + /** + * 初始化柱形图绘图区 + * + * @param plot 绘图区 + */ + public static void initColumnPlot(VanChartColumnPlot plot) { + AttrLabel defaultAttrLabel = plot.getDefaultAttrLabel(); + defaultAttrLabel.setEnable(true); + defaultAttrLabel.getAttrLabelDetail().getBorder().setBorderStyle(0); + defaultAttrLabel.getAttrLabelDetail().getBackground().setBackground(null); + plot.getConditionCollection().getDefaultAttr().addDataSeriesCondition(defaultAttrLabel); + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setSeriesOverlapPercent(30); + plot.setCategoryIntervalPercent(30); + } + + /** + * 初始化图表Y轴 + * + * @param yAxis 轴 + */ + public static void initVanChartYAxis(VanChartAxis yAxis) { + Title title = new Title(); + title.setTextObject(Toolkit.i18nText("Fine-Design_Chart_Axis_Title")); + title.getTextAttr().setRotation(-90); + title.getTextAttr().setThemed(true); + yAxis.setTitle(title); + yAxis.setShowAxisTitle(true); + yAxis.setCustomMaxValue(true); + yAxis.setCustomMinValue(true); + yAxis.setCustomMainUnit(true); + yAxis.setMaxValue(BaseFormula.createFormulaBuilder().build("=600")); + yAxis.setMinValue(BaseFormula.createFormulaBuilder().build("=0")); + yAxis.setMainUnit(BaseFormula.createFormulaBuilder().build("=200")); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/util/ThemeTextStylePaneCreator.java b/designer-base/src/main/java/com/fr/widgettheme/util/ThemeTextStylePaneCreator.java new file mode 100644 index 0000000000..133f258646 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/util/ThemeTextStylePaneCreator.java @@ -0,0 +1,40 @@ +package com.fr.widgettheme.util; + +import com.fr.design.gui.frpane.FontSizeComboPane; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; + +import javax.swing.Box; +import javax.swing.JPanel; +import java.awt.Component; + +/** + * 创建主题文本样式的工具类 + * + * @author obo + * @since 11.0 + * Created on 2023/12/21 + */ +public class ThemeTextStylePaneCreator { + private ThemeTextStylePaneCreator() {} + + /** + * 创建主题文本样式配置面板 + * 包含字体大小下拉框和字体颜色按钮 + * 可以自适应布局 + * + * @param fontSizePane 字体大小配置 + * @param fontColorButton 字体颜色配置 + * @return 文本样式面板 + */ + public static JPanel create(FontSizeComboPane fontSizePane, UIColorButton fontColorButton) { + Component[][] components = {{fontSizePane, Box.createHorizontalStrut(5), fontColorButton}}; + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {f}; + double[] columnSize = {f, p, p}; + int[][] rowCount = {{1, 1, 1}}; + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, 0, 0); + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/util/WidgetThemeDesignerUtils.java b/designer-base/src/main/java/com/fr/widgettheme/util/WidgetThemeDesignerUtils.java new file mode 100644 index 0000000000..296b5e2e5b --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/util/WidgetThemeDesignerUtils.java @@ -0,0 +1,46 @@ +package com.fr.widgettheme.util; + +import com.fr.base.io.AttrMark; +import com.fr.base.io.IOFile; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.stable.StringUtils; +import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr; + +/** + * 控件主题设计器部分工具类 + * + * @author obo + * @since 11.0 + * Created on 2023/11/13 + */ +public class WidgetThemeDesignerUtils { + + private WidgetThemeDesignerUtils() { + } + + /** + * 从 WorkBook 中加载 WatermarkAttr 属性对象 + * + * @param template AttrMark 对象,包括 WorkBook + * @return StrongestControlMarkAttr 对象 + */ + public static WidgetDisplayEnhanceMarkAttr getStrongestControlAttrFromTemplate(AttrMark template) { + return template.getAttrMark(WidgetDisplayEnhanceMarkAttr.XML_TAG); + } + + /** + * 判断是否启用了控件显示增强 + * + * @return 开启与否 + */ + public static boolean enableWidgetEnhance() { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (JTemplate.isValid(jTemplate)) { + IOFile ioFile = (IOFile) jTemplate.getTarget(); + WidgetDisplayEnhanceMarkAttr mark = ioFile.getAttrMark(WidgetDisplayEnhanceMarkAttr.XML_TAG); + return mark != null && mark.isWidgetEnhance(); + } + return false; + } +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/DisplayEnhanceMobileStyleDefinePane.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/DisplayEnhanceMobileStyleDefinePane.java new file mode 100644 index 0000000000..a0ed4159c7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/DisplayEnhanceMobileStyleDefinePane.java @@ -0,0 +1,273 @@ +package com.fr.widgettheme.widget.mobile.pane; + +import com.fr.base.background.ColorBackground; +import com.fr.widgettheme.theme.widget.style.MobileThemedWidgetStyle; +import com.fr.widgettheme.theme.widget.mobile.style.WidgetThemeMobileCommonExtraStyle; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.file.HistoryTemplateListCache; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.style.color.ColorSelectBox; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileCommonExtraStyle; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.general.FRFont; +import com.fr.invoke.Reflect; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import javax.swing.border.TitledBorder; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +/** + *

开启控件显示增强后替换原通用属性面板 + *

参考{@link com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane} + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/4/11 + */ +public class DisplayEnhanceMobileStyleDefinePane extends BasicBeanPane { + public static final int NORMAL_COMBO_WIDTH = 152; + protected Widget widget; + protected MobileStyleCustomDefinePane customBeanPane; + protected Class mobileStyleClazz; + protected UIComboBox customCombo; + protected JPanel settingPane; + protected NewColorSelectBox themeColorSelectBox; + protected Color titleColor = new Color(47, 142, 241); + protected JPanel commonPane; + protected LineComboBox borderType; + protected UISpinner borderRadius; + protected MobileStyleFontConfigPane fontConfigPane; + protected ColorSelectBox widgetBackgroundSelectBox; + + protected MobileStyle mobileStyle; + + public DisplayEnhanceMobileStyleDefinePane(Widget widget, Class customBeanPaneClass, + Class mobileStyleClazz) { + this.widget = widget; + this.customBeanPane = Reflect.on(customBeanPaneClass).create(widget).get(); + this.mobileStyleClazz = mobileStyleClazz; + // 一些默认的情况,没有,需要初始化一下。 + initMobileStyle(widget); + init(); + } + + private void initMobileStyle(Widget widget) { + mobileStyle = widget.getMobileStyle() != null ? widget.getMobileStyle() : Reflect.on(mobileStyleClazz).create().get(); + } + + @Override + public void populateBean(MobileStyle ob) { + MobileCommonExtraStyle extraStyle = ob.getMobileCommonExtraStyle(); + if (extraStyle instanceof WidgetThemeMobileCommonExtraStyle) { + WidgetThemeMobileCommonExtraStyle style = (WidgetThemeMobileCommonExtraStyle) extraStyle; + customCombo.setSelectedIndex(style.isCustom() ? 1 : 0); + borderType.setSelectedLineStyle(style.getBorderType()); + borderRadius.setValue(style.getBorderRadius()); + if (style.getThemeColor() != null) { + themeColorSelectBox.setSelectObject(style.getThemeColor()); + } + if (style.getNewFont() != null) { + fontConfigPane.populateBean(style.getNewFont()); + } + if (style.getWidgetBackground() != null) { + widgetBackgroundSelectBox.setSelectObject(((ColorBackground) style.getWidgetBackground()).getColor()); + } + } + this.customBeanPane.populateBean(ob); + } + + @Override + public MobileStyle updateBean() { + mobileStyle = Reflect.on(mobileStyleClazz).create().get(); + WidgetThemeMobileCommonExtraStyle extraStyle = new WidgetThemeMobileCommonExtraStyle(); + extraStyle.setCustom(customCombo.getSelectedIndex() == 1); + extraStyle.setThemeColor(themeColorSelectBox.getSelectObject()); + extraStyle.setBorderType(borderType.getSelectedLineStyle()); + extraStyle.setBorderRadius(borderRadius.getValue()); + extraStyle.setNewFont(fontConfigPane.updateBean()); + extraStyle.setWidgetBackground(ColorBackground.getInstance(widgetBackgroundSelectBox.getSelectObject())); + mobileStyle.setMobileCommonExtraStyle(extraStyle); + this.widget.setMobileStyle(mobileStyle); + this.customBeanPane.updateBean(); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + + private void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + createGeneralPane(); + createCustomPane(); + } + + protected void createFontPane(Color defaultFontColor) { + fontConfigPane = new MobileStyleFontConfigPane(defaultFontColor); + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_Font")), fontConfigPane)); + } + + private void createGeneralPane() { + createPreviewPane(); + createCommonPane(); + } + + private void createPreviewPane() { + JPanel mobileStylePreviewPane = Reflect.on(customBeanPane).call("createPreviewPane").get(); + if (mobileStylePreviewPane != null) { + JPanel previewPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + TitledBorder titledBorder = createTitledBorder(Toolkit.i18nText("Fine-Design_Basic_Widget_Style_Preview")); + previewPane.setBorder(titledBorder); + previewPane.setPreferredSize(new Dimension(500, 83)); + previewPane.add(mobileStylePreviewPane, BorderLayout.CENTER); + this.add(previewPane, BorderLayout.NORTH); + } + } + + private void createCommonPane() { + TitledBorder titledBorder = createTitledBorder(Toolkit.i18nText("Fine-Design_Mobile_Common_Attribute")); + commonPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + commonPane.setBorder(titledBorder); + this.add(commonPane, BorderLayout.NORTH); + + + customCombo = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Mobile_Default"), Toolkit.i18nText("Fine-Design_Mobile_Custom")}); + customCombo.setSelectedIndex(0); + customCombo.setPreferredSize(new Dimension(NORMAL_COMBO_WIDTH + 15, 20)); + customCombo.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean custom = customCombo.getSelectedIndex() == 1; + settingPane.setVisible(custom); + } + }); + commonPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Attribute_Settings")), customCombo)); + + settingPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + settingPane.setBorder(new EmptyBorder(-10, 0, 0, 0)); + settingPane.setVisible(false); + commonPane.add(settingPane); + createUniversalPane(); + } + + protected void createUniversalPane() { + // 主题色 + createThemePane(); + // 组件背景 + createBackgroundPane(); + // 边框线型 + createBorderLinePane(); + // 圆角边框 + createBorderRadiusPane(); + // 字体 + createFontPane(WidgetThemeDisplayConstants.DEFAULT_FONT_COLOR_BLACK); + } + + + protected void createBackgroundPane() { + widgetBackgroundSelectBox = new ColorSelectBox(NORMAL_COMBO_WIDTH); + initBackgroundColor(); + JPanel backgroundPane = createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_Background")), widgetBackgroundSelectBox); + settingPane.add(backgroundPane); + } + + protected void initBackgroundColor() { + widgetBackgroundSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_TRANSPARENT_COLOR); + } + + protected void createThemePane() { + themeColorSelectBox = new NewColorSelectBox(NORMAL_COMBO_WIDTH); + // 默认为当前模板选中的主题色 + themeColorSelectBox.setSelectObject(getCurrentTemplateThemeColor()); + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Basic_Theme_Color")), themeColorSelectBox)); + } + + + protected void createBorderLinePane() { + borderType = new LineComboBox(WidgetThemeDisplayConstants.MOBILE_BORDER_LINE_STYLE_ARRAY); + initDefaultLineType(); + borderType.setPreferredSize(new Dimension(NORMAL_COMBO_WIDTH + 15, 20)); + // 边框线型 + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_BorderType")), borderType)); + } + + protected void initDefaultLineType() { + borderType.setSelectedLineStyle(Constants.LINE_THIN); + } + + protected void createBorderRadiusPane() { + borderRadius = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + borderRadius.setPreferredSize(new Dimension(NORMAL_COMBO_WIDTH + 20, 20)); + // 圆角边框 + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_BorderRadius")), borderRadius)); + } + + protected void createCustomPane() { + JPanel configPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + TitledBorder titledBorder = createTitledBorder(Toolkit.i18nText("Fine-Design_Report_Set")); + configPane.setBorder(titledBorder); + + configPane.add(this.customBeanPane, BorderLayout.CENTER); + + this.add(configPane, BorderLayout.CENTER); + } + + protected TitledBorder createTitledBorder(String title) { + TitledBorder titledBorder = GUICoreUtils.createTitledBorder(title, titleColor); + titledBorder.setTitleFont(FRFont.getInstance("PingFangSC-Regular", Font.PLAIN, 12)); + return titledBorder; + } + + protected UILabel createConfigLabel(String title) { + UILabel label = new UILabel(title, UILabel.LEFT); + label.setPreferredSize(new Dimension(75, 20)); + label.setBorder(new EmptyBorder(0, 15, 0, 0)); + return label; + } + + protected JPanel createLeftRightComponentsPane(Component... components) { + JPanel tableLayoutPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{components}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + return tableLayoutPane; + } + + /** + * 获取当前编辑移动端控件样式主题色 + * + * @return + */ + protected Color getCurrentTemplateThemeColor() { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + Color themeColor = WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR; + if (JTemplate.isValid(jTemplate)) { + MobileThemedWidgetStyle mobileWidgetStyle = (MobileThemedWidgetStyle) jTemplate.getTemplateTheme().getMobileWidgetStyle(); + mobileWidgetStyle = mobileWidgetStyle == null ? new MobileThemedWidgetStyle() : mobileWidgetStyle; + themeColor = mobileWidgetStyle.getThemeColor(); + } + return themeColor; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FileEditorMobileStyleDefinePane.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FileEditorMobileStyleDefinePane.java new file mode 100644 index 0000000000..801585f429 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FileEditorMobileStyleDefinePane.java @@ -0,0 +1,59 @@ +package com.fr.widgettheme.widget.mobile.pane; + +import com.fr.base.background.ColorBackground; +import com.fr.widgettheme.theme.widget.mobile.style.FileEditorStyle; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileCommonExtraStyle; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.invoke.Reflect; + +/** + * 文件属性定义面板 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/5/19 + */ +public class FileEditorMobileStyleDefinePane extends DisplayEnhanceMobileStyleDefinePane { + + public FileEditorMobileStyleDefinePane(Widget widget, Class customBeanPaneClass, Class mobileStyleClazz) { + super(widget, customBeanPaneClass, mobileStyleClazz); + } + + @Override + public void populateBean(MobileStyle ob) { + MobileCommonExtraStyle extraStyle = ob.getMobileCommonExtraStyle(); + if (extraStyle instanceof FileEditorStyle) { + FileEditorStyle style = (FileEditorStyle) extraStyle; + customCombo.setSelectedIndex(style.isCustom() ? 1 : 0); + if (style.getWidgetBackground() != null) { + widgetBackgroundSelectBox.setSelectObject(((ColorBackground) style.getWidgetBackground()).getColor()); + } + borderType.setSelectedLineStyle(style.getBorderType()); + borderRadius.setValue(style.getBorderRadius()); + } + this.customBeanPane.populateBean(ob); + } + + @Override + public MobileStyle updateBean() { + mobileStyle = Reflect.on(mobileStyleClazz).create().get(); + FileEditorStyle extraStyle = new FileEditorStyle(); + extraStyle.setCustom(customCombo.getSelectedIndex() == 1); + extraStyle.setWidgetBackground(ColorBackground.getInstance(widgetBackgroundSelectBox.getSelectObject())); + extraStyle.setBorderType(borderType.getSelectedLineStyle()); + extraStyle.setBorderRadius(borderRadius.getValue()); + mobileStyle.setMobileCommonExtraStyle(extraStyle); + this.widget.setMobileStyle(mobileStyle); + this.customBeanPane.updateBean(); + return mobileStyle; + } + + @Override + protected void createUniversalPane() { + createBackgroundPane(); + createBorderLinePane(); + createBorderRadiusPane(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FreeButtonMobileStyleDefinePane.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FreeButtonMobileStyleDefinePane.java new file mode 100644 index 0000000000..6ab19b8dcf --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FreeButtonMobileStyleDefinePane.java @@ -0,0 +1,93 @@ +package com.fr.widgettheme.widget.mobile.pane; + +import com.fr.base.background.ColorBackground; +import com.fr.widgettheme.theme.widget.mobile.style.FreeButtonStyle; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileCommonExtraStyle; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.invoke.Reflect; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; + +/** + * 按钮控件通用属性面板 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/5/25 + */ +public class FreeButtonMobileStyleDefinePane extends DisplayEnhanceMobileStyleDefinePane { + private NewColorSelectBox borderColorSelectBox; + private NewColorSelectBox iconColorSelectBox; + + + public FreeButtonMobileStyleDefinePane(Widget widget, Class customBeanPaneClass, Class mobileStyleClazz) { + super(widget, customBeanPaneClass, mobileStyleClazz); + } + + @Override + public void populateBean(MobileStyle ob) { + super.populateBean(ob); + MobileCommonExtraStyle extraStyle = ob.getMobileCommonExtraStyle(); + if (extraStyle instanceof FreeButtonStyle) { + FreeButtonStyle style = (FreeButtonStyle) extraStyle; + if (style.getBorderColor() != null) { + borderColorSelectBox.setSelectObject(style.getBorderColor()); + } + if (style.getIconColor() != null) { + iconColorSelectBox.setSelectObject(style.getIconColor()); + } + } + } + + @Override + public MobileStyle updateBean() { + mobileStyle = Reflect.on(mobileStyleClazz).create().get(); + FreeButtonStyle extraStyle = new FreeButtonStyle(); + extraStyle.setCustom(customCombo.getSelectedIndex() == 1); + extraStyle.setWidgetBackground(ColorBackground.getInstance(widgetBackgroundSelectBox.getSelectObject())); + extraStyle.setBorderType(borderType.getSelectedLineStyle()); + extraStyle.setBorderColor(borderColorSelectBox.getSelectObject()); + extraStyle.setBorderRadius(borderRadius.getValue()); + extraStyle.setNewFont(fontConfigPane.updateBean()); + extraStyle.setIconColor(iconColorSelectBox.getSelectObject()); + mobileStyle.setMobileCommonExtraStyle(extraStyle); + this.widget.setMobileStyle(mobileStyle); + this.customBeanPane.updateBean(); + return mobileStyle; + } + + @Override + protected void createUniversalPane() { + createBackgroundPane(); + createBorderLinePane(); + initBorderColor(); + createBorderRadiusPane(); + initIconColor(); + createFontPane(WidgetThemeDisplayConstants.DEFAULT_WHITE_COLOR); + } + + private void initIconColor() { + iconColorSelectBox = new NewColorSelectBox(NORMAL_COMBO_WIDTH); + iconColorSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_WHITE_COLOR); + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_Icon_Color")), iconColorSelectBox)); + } + + @Override + protected void initDefaultLineType() { + borderType.setSelectedLineStyle(com.fr.stable.Constants.LINE_NONE); + } + + private void initBorderColor() { + borderColorSelectBox = new NewColorSelectBox(NORMAL_COMBO_WIDTH); + borderColorSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR); + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_BorderColor")), borderColorSelectBox)); + } + + @Override + protected void initBackgroundColor() { + widgetBackgroundSelectBox.setSelectObject(getCurrentTemplateThemeColor()); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/LabelMobileStyleDefinePane.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/LabelMobileStyleDefinePane.java new file mode 100644 index 0000000000..17388b859d --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/LabelMobileStyleDefinePane.java @@ -0,0 +1,77 @@ +package com.fr.widgettheme.widget.mobile.pane; + +import com.fr.base.background.ColorBackground; +import com.fr.widgettheme.theme.widget.mobile.style.LabelIconSettingStyle; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileCommonExtraStyle; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.invoke.Reflect; +import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants; + +/** + * 标签控件属性定义面板 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/5/15 + */ +public class LabelMobileStyleDefinePane extends DisplayEnhanceMobileStyleDefinePane { + private NewColorSelectBox borderColorSelectBox; + + public LabelMobileStyleDefinePane(Widget widget, Class customBeanPaneClass, + Class mobileStyleClazz) { + super(widget, customBeanPaneClass, mobileStyleClazz); + } + + + @Override + public void populateBean(MobileStyle ob) { + super.populateBean(ob); + MobileCommonExtraStyle extraStyle = ob.getMobileCommonExtraStyle(); + if (extraStyle instanceof LabelIconSettingStyle) { + LabelIconSettingStyle style = (LabelIconSettingStyle) extraStyle; + if (style.getBorderColor() != null) { + borderColorSelectBox.setSelectObject(style.getBorderColor()); + } + } + } + + @Override + public MobileStyle updateBean() { + mobileStyle = Reflect.on(mobileStyleClazz).create().get(); + LabelIconSettingStyle extraStyle = new LabelIconSettingStyle(); + extraStyle.setCustom(customCombo.getSelectedIndex() == 1); + extraStyle.setWidgetBackground(ColorBackground.getInstance(widgetBackgroundSelectBox.getSelectObject())); + extraStyle.setBorderType(borderType.getSelectedLineStyle()); + extraStyle.setBorderColor(borderColorSelectBox.getSelectObject()); + extraStyle.setBorderRadius(borderRadius.getValue()); + extraStyle.setNewFont(fontConfigPane.updateBean()); + mobileStyle.setMobileCommonExtraStyle(extraStyle); + this.widget.setMobileStyle(mobileStyle); + this.customBeanPane.updateBean(); + return mobileStyle; + } + + @Override + protected void createUniversalPane() { + createBackgroundPane(); + createBorderLinePane(); + initBorderColor(); + createBorderRadiusPane(); + createFontPane(WidgetThemeDisplayConstants.DEFAULT_FONT_COLOR_BLACK); + } + + private void initBorderColor() { + borderColorSelectBox = new NewColorSelectBox(NORMAL_COMBO_WIDTH); + borderColorSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_TRANSPARENT_COLOR); + settingPane.add(createLeftRightComponentsPane(createConfigLabel(Toolkit.i18nText("Fine-Design_Mobile_Widget_BorderColor")), borderColorSelectBox)); + } + + @Override + protected void initDefaultLineType() { + borderType.setSelectedLineStyle(com.fr.stable.Constants.LINE_NONE); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/MobileStyleFontConfigPane.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/MobileStyleFontConfigPane.java new file mode 100644 index 0000000000..6b02ec9ff0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/MobileStyleFontConfigPane.java @@ -0,0 +1,151 @@ +package com.fr.widgettheme.widget.mobile.pane; + + +import com.fr.base.BaseUtils; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.i18n.Toolkit; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.FRFont; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.util.Vector; + +/** + * 移动端字体面板 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/5/22 + */ +public class MobileStyleFontConfigPane extends JPanel { + public static final int FONT_NONE = 0; + private static final int MAX_FONT_SIZE = 18; + private static final int MIN_FONT_SIZE = 12; + private static final Dimension BUTTON_SIZE = new Dimension(20, 18); + + /** + * 获取字体大小集合 + * + * @return 字体大小集合 + */ + public static Vector getFontSizes() { + Vector fontSizes = new Vector(); + for (int i = MIN_FONT_SIZE; i <= MAX_FONT_SIZE; i++) { + fontSizes.add(i); + } + return fontSizes; + } + + private UIComboBox fontSizeComboBox; + private UIColorButton color; + private UIToggleButton italic; + private UIToggleButton bold; + + public MobileStyleFontConfigPane() { + this.initComponent(new Color(0, 0, 0)); + } + + public MobileStyleFontConfigPane(Color defaultFontColor) { + this.initComponent(defaultFontColor); + } + + private void initComponent(Color defaultFontColor) { + fontSizeComboBox = new UIComboBox(); + fontSizeComboBox.setModel(new DefaultComboBoxModel(getFontSizes())); + fontSizeComboBox.setSelectedItem(16); + fontSizeComboBox.setPreferredSize(new Dimension(60, 20)); + fontSizeComboBox.setRenderer(new LineCellRenderer()); + color = new UIColorButton(); + color.setColor(defaultFontColor); + italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); + bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); + + this.setButtonsTips(); + this.setButtonsSize(BUTTON_SIZE); + + Component[] componentFont = new Component[]{ + fontSizeComboBox, color, italic, bold + }; + + JPanel buttonPane = new JPanel(new BorderLayout()); + JPanel flowPane = GUICoreUtils.createFlowPane(componentFont, FlowLayout.LEFT, LayoutConstants.HGAP_LARGE); + // 4是flowPane的默认横向gap,但会导致最左边的控件和边上也有4的间隙,调整一下 + flowPane.setBorder(new EmptyBorder(0, -LayoutConstants.HGAP_LARGE, 0, 0)); + buttonPane.add(flowPane); + + this.setLayout(new BorderLayout(0, 0)); + this.add(buttonPane, BorderLayout.CENTER); + } + + private void setButtonsTips() { + color.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Foreground")); + italic.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Italic")); + bold.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Bold")); + } + + private void setButtonsSize(Dimension size) { + color.setPreferredSize(size); + italic.setPreferredSize(size); + bold.setPreferredSize(size); + } + + /** + * 填充字体 + * + * @param frFont 字体 + */ + public void populateBean(FRFont frFont) { + fontSizeComboBox.setSelectedItem(frFont.getSize()); + color.setColor(frFont.getForeground()); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + } + + /** + * 更新字体 + */ + public FRFont updateBean() { + int style = Font.PLAIN; + style += this.bold.isSelected() ? Font.BOLD : Font.PLAIN; + style += this.italic.isSelected() ? Font.ITALIC : Font.PLAIN; + return FRFont.getInstance( + FRFont.DEFAULT_FONTNAME, + style, + Float.parseFloat(fontSizeComboBox.getSelectedItem().toString()), + color.getColor(), + Constants.LINE_NONE + ); + } + + private class LineCellRenderer extends UIComboBoxRenderer { + public LineCellRenderer() { + super(); + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel renderer = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + int currentValue = ((Integer) value).intValue(); + if (currentValue == com.fr.design.mainframe.mobile.ui.MobileStyleFontConfigPane.FONT_NONE) { + renderer.setText(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_None")); + } + return renderer; + } + } + +} diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/DisplayEnhanceMobileStyleFactory.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/DisplayEnhanceMobileStyleFactory.java new file mode 100644 index 0000000000..53650ca5d2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/DisplayEnhanceMobileStyleFactory.java @@ -0,0 +1,65 @@ +package com.fr.widgettheme.widget.mobile.provider; + +import com.fr.widgettheme.widget.mobile.pane.FileEditorMobileStyleDefinePane; +import com.fr.widgettheme.widget.mobile.pane.FreeButtonMobileStyleDefinePane; +import com.fr.widgettheme.widget.mobile.pane.LabelMobileStyleDefinePane; +import com.fr.widgettheme.theme.widget.mobile.style.FileEditorStyle; +import com.fr.widgettheme.theme.widget.mobile.style.FreeButtonStyle; +import com.fr.widgettheme.theme.widget.mobile.style.LabelIconSettingStyle; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.form.ui.FreeButton; +import com.fr.form.ui.Label; +import com.fr.form.ui.MultiFileEditor; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileCommonExtraStyle; +import com.fr.form.ui.mobile.MobileStyle; + +/** + * 样式创建工厂 + * + * @author Coral.Chen + * @since 11.0 + * Created on 2023/5/15 + */ +public class DisplayEnhanceMobileStyleFactory { + + /** + * 先写个简单工厂处理一下特殊的控件 + * + * @param widget + * @return 特殊控件的通用属性面板 + */ + public static BasicBeanPane createWidgetMobileStyleDefinePane(Widget widget, Class customDefinePane, Class mobileStyle) { + if (widget instanceof Label) { + return new LabelMobileStyleDefinePane(widget, customDefinePane, mobileStyle); + } + if (widget instanceof MultiFileEditor) { + return new FileEditorMobileStyleDefinePane(widget, customDefinePane, mobileStyle); + } + if (widget instanceof FreeButton) { + return new FreeButtonMobileStyleDefinePane(widget, customDefinePane, mobileStyle); + } + return null; + } + + /** + * 生成控件移动端通用属性 + * + * @param widget + * @return + */ + public static Class classForWidgetCommonExtraStyle(Widget widget) { + if (widget instanceof Label) { + return LabelIconSettingStyle.class; + } + if (widget instanceof MultiFileEditor) { + return FileEditorStyle.class; + } + if (widget instanceof FreeButton) { + return FreeButtonStyle.class; + } + return null; + } + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/WidgetThemeMobileStyleDefinePaneCreator.java b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/WidgetThemeMobileStyleDefinePaneCreator.java new file mode 100644 index 0000000000..a40199327b --- /dev/null +++ b/designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/WidgetThemeMobileStyleDefinePaneCreator.java @@ -0,0 +1,84 @@ +package com.fr.widgettheme.widget.mobile.provider; + +import com.fr.base.io.IOFile; +import com.fr.widgettheme.widget.mobile.pane.DisplayEnhanceMobileStyleDefinePane; +import com.fr.widgettheme.theme.widget.mobile.style.WidgetThemeMobileCommonExtraStyle; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.form.ui.FreeButton; +import com.fr.form.ui.Label; +import com.fr.form.ui.MultiFileEditor; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileCommonExtraStyle; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.log.FineLoggerFactory; +import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr; +import org.jetbrains.annotations.NotNull; + +/** + * 控件主题移动端样式窗口创建类 + * + * @author obo + * @since 11.0 + * Created on 2023/11/13 + */ +public class WidgetThemeMobileStyleDefinePaneCreator { + + private WidgetThemeMobileStyleDefinePaneCreator() { + } + + /** + * 创建移动端控件样式属性窗口 + * + * @param widget 控件 + * @param customDefinePane 窗口类 + * @param mobileStyle 样式类 + * @return 窗口 + */ + public static BasicBeanPane createBaseBeanPane(Widget widget, Class customDefinePane, Class mobileStyle) { + try { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (JTemplate.isValid(jTemplate)) { + IOFile ioFile = (IOFile) jTemplate.getTarget(); + WidgetDisplayEnhanceMarkAttr mark = ioFile.getAttrMark(WidgetDisplayEnhanceMarkAttr.XML_TAG); + if (mark != null && mark.isWidgetEnhance()) { + if (commonWidget(widget)) { + return new DisplayEnhanceMobileStyleDefinePane(widget, customDefinePane, mobileStyle); + } else { + return DisplayEnhanceMobileStyleFactory.createWidgetMobileStyleDefinePane(widget, customDefinePane, mobileStyle); + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("[Strongest-Control]: create base bean pane failed.", e); + } + return null; + } + + /** + * 根据控件获取通用扩展属性类 + * + * @param widget 控件 + * @return class + */ + public static @NotNull Class classForCommonExtraStyle(Widget widget) { + if (commonWidget(widget)) { + return WidgetThemeMobileCommonExtraStyle.class; + } else { + return DisplayEnhanceMobileStyleFactory.classForWidgetCommonExtraStyle(widget); + } + } + + /** + * 是否为普通控件 + * 按钮控件、标签控件、文件控件需要特殊处理 + * + * @param widget 控件 + * @return 是/否 + */ + private static boolean commonWidget(Widget widget) { + return !((widget instanceof FreeButton) || (widget instanceof Label) || (widget instanceof MultiFileEditor)); + } +} diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties index 5098bc3c97..bf7aba4f40 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties @@ -25,3 +25,5 @@ com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369 com.fr.design.report.WatermarkSettingPane=720*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=350*65 com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRuleChoosePane.ruleEditPane=800*600 +com.fr.design.formula.FormulaPane=900*600 +com.fr.design.formula.FormulaPaneWhenReserveFormula=1200*600 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties index 6c3ac0e58c..d070015063 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties @@ -24,3 +24,5 @@ com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369 com.fr.design.report.WatermarkSettingPane=720*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=240*65 com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRuleChoosePane.ruleEditPane=800*600 +com.fr.design.formula.FormulaPane=900*600 +com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties index eaa75e14a0..3fd1ffcad1 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties @@ -24,3 +24,5 @@ com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369 com.fr.design.report.WatermarkSettingPane=720*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=240*65 com.fr.design.data.datapane.preview.desensitization.view.rule.DesensitizationRuleChoosePane.ruleEditPane=800*600 +com.fr.design.formula.FormulaPane=900*600 +com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties index d1e84b4618..2a10d13c7f 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties @@ -24,3 +24,5 @@ com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500 com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369 com.fr.design.report.WatermarkSettingPane=720*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=170*65 +com.fr.design.formula.FormulaPane=900*600 +com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties index 82f86a3a43..faa620cfc8 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties @@ -23,3 +23,5 @@ com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500 com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369 com.fr.design.report.WatermarkSettingPane=720*600 com.fr.design.file.MultiTemplateTabPane.popUpMenu=170*65 +com.fr.design.formula.FormulaPane=900*600 +com.fr.design.formula.FormulaPaneWhenReserveFormula=900*600 diff --git a/designer-base/src/main/resources/com/fr/widgettheme/combobox.png b/designer-base/src/main/resources/com/fr/widgettheme/combobox.png new file mode 100644 index 0000000000..1044d964e6 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/widgettheme/combobox.png differ diff --git a/designer-base/src/main/resources/com/fr/widgettheme/menu.svg b/designer-base/src/main/resources/com/fr/widgettheme/menu.svg new file mode 100644 index 0000000000..1ab9c63a53 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/widgettheme/menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/test/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPaneTest.java b/designer-base/src/test/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPaneTest.java new file mode 100644 index 0000000000..e549f13461 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPaneTest.java @@ -0,0 +1,41 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.Parameter; +import com.fr.design.data.datapane.sqlpane.SQLEditPane; +import com.fr.invoke.Reflect; +import junit.framework.TestCase; +import org.junit.Assert; + +/** + * @author Yuan.Wang + * @since 11.0 + * Created on 2023/12/22 + */ +public class DBTableDataPaneTest extends TestCase { + + public void testGetParameters() { + DBTableDataPane pane = new DBTableDataPane(); + SQLEditPane editPane = new SQLEditPane(); + String sql = "select distinct 类别ID from S产品\n" + + "where 1=1\n" + + "order by 类别ID\n" + + "--${ if(len(comboBox0) = 0,\"\",\"AND 类别00ID = '\" + comboBox0 + \"'\")}"; + + String sql1 = "select distinct 类别ID from S产品\n" + + "where 1=1\n" + + "order by 类别ID\n" + + "${ if(len(comboBox0) = 0,\"\",\"AND 类别00ID = '\" + comboBox0 + \"'\")}"; + editPane.setText(sql); + Reflect.on(pane).set("sqlTextPane", editPane); + Reflect.on(pane).set("pageQuery", sql); + + Parameter[] parameters = Reflect.on(pane).call("getParameters").get(); + + Assert.assertEquals(0, parameters.length); + editPane.setText(sql1); + + parameters = Reflect.on(pane).call("getParameters").get(); + Assert.assertEquals(1, parameters.length); + Assert.assertEquals(parameters[0].getName(), "comboBox0"); + } +} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java b/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java index 177238519a..57082e37f0 100644 --- a/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java @@ -28,6 +28,7 @@ import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormSelection; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.widget.accessibles.AccessibleBackgroundEditor; +import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder; import com.fr.design.utils.gui.LayoutUtils; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.ui.designer.AbstractDataModify; @@ -203,6 +204,7 @@ public class RootDesignDefinePane extends AbstractDataModify { private void refreshExtraAdvancedPane() { extraPaneList.clear(); backgroundPane.removeAll(); + WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList); Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(creator)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java index 67b8e4d26c..79a71d56e0 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java @@ -8,11 +8,13 @@ import com.fr.design.gui.icombobox.DictionaryComboBox; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.widgettheme.processor.WidgetThemeCreatorPaneAdder; import com.fr.design.widget.btn.ButtonWithHotkeysDetailPane; import com.fr.form.ui.Button; import com.fr.general.GeneralContext; import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; +import com.fr.stable.collections.CollectionUtils; import org.jetbrains.annotations.Nullable; import javax.swing.JPanel; @@ -45,7 +47,8 @@ public abstract class AbstractExtraButtonPane extends ButtonWi */ protected void refreshExtraAdvancedPane(Class cls) { extraPaneList.clear(); - boolean containsExtraPane = false; + WidgetThemeCreatorPaneAdder.add(cls, extraPaneList); + boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList); Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(cls)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java index 6889ef7b49..0863260b3e 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer; +import com.finebi.cbb.utils.CollectionUtils; import com.fr.design.ExtraDesignClassManager; import com.fr.design.beans.BasicBeanPane; import com.fr.design.designer.IntervalConstants; @@ -12,6 +13,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.widget.accessibles.AccessibleIconEditor; +import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder; import com.fr.design.widget.btn.ButtonConstants; import com.fr.form.ui.Button; import com.fr.general.GeneralContext; @@ -64,7 +66,8 @@ public abstract class ButtonDefinePane extends AbstractDataMod private void refreshAdvancedPane() { extraPaneList.clear(); - containsExtraPane = false; + WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList); + containsExtraPane = CollectionUtils.isNotEmpty(extraPaneList); Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(creator)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxDefinePane.java index 7768402914..d73582df7b 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer; +import com.finebi.cbb.utils.CollectionUtils; import com.fr.design.ExtraDesignClassManager; import com.fr.design.beans.BasicBeanPane; import com.fr.design.designer.IntervalConstants; @@ -11,7 +12,8 @@ import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.widget.ui.designer.component.FontSizeComboPane; +import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder; +import com.fr.design.gui.frpane.FontSizeComboPane; import com.fr.design.widget.ui.designer.component.FormWidgetValuePane; import com.fr.form.ui.CheckBox; import com.fr.general.GeneralContext; @@ -76,7 +78,8 @@ public class CheckBoxDefinePane extends AbstractDataModify { protected void refreshExtraAdvancedPane() { extraPaneList.clear(); - boolean containsExtraPane = false; + WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList); + boolean containsExtraPane = CollectionUtils.isNotEmpty(extraPaneList); Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(creator)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java index 7df1e90909..06ccb13870 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer; +import com.finebi.cbb.utils.CollectionUtils; import com.fr.base.FRContext; import com.fr.data.core.FormatField; import com.fr.design.ExtraDesignClassManager; @@ -14,6 +15,7 @@ import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder; import com.fr.design.widget.component.DateValuePane; import com.fr.design.widget.component.UIComboBoxNoArrow; import com.fr.design.widget.ui.designer.component.FormWidgetValuePane; @@ -98,7 +100,8 @@ public class DateEditorDefinePane extends DirectWriteEditorDefinePane> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(creator)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/DirectWriteEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/DirectWriteEditorDefinePane.java index 53c38b6421..1a65f3bba6 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/DirectWriteEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/DirectWriteEditorDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer; +import com.finebi.cbb.utils.CollectionUtils; import com.fr.design.ExtraDesignClassManager; import com.fr.design.beans.BasicBeanPane; import com.fr.design.designer.IntervalConstants; @@ -9,6 +10,7 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.widget.ui.designer.component.FormWidgetValuePane; import com.fr.form.ui.DirectWriteEditor; @@ -66,7 +68,8 @@ public abstract class DirectWriteEditorDefinePane e protected void refreshExtraAdvancedPane() { extraPaneList.clear(); - boolean containsExtraPane = false; + WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList); + boolean containsExtraPane = CollectionUtils.isNotEmpty(extraPaneList); Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(creator)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java index 65aeec3a75..81499facc8 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java @@ -20,7 +20,7 @@ import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.widget.ui.designer.component.FontSizeComboPane; +import com.fr.design.gui.frpane.FontSizeComboPane; import com.fr.form.ui.FieldEditor; import com.fr.general.GeneralContext; import com.fr.log.FineLoggerFactory; diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java index 040137141c..1776e2eb18 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer; +import com.finebi.cbb.utils.CollectionUtils; import com.fr.base.BaseUtils; import com.fr.design.ExtraDesignClassManager; import com.fr.design.beans.BasicBeanPane; @@ -15,6 +16,7 @@ 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.widgettheme.processor.WidgetThemeParaCreatorPaneAdder; import com.fr.design.widget.FRWidgetFactory; import com.fr.design.widget.ui.designer.component.FormWidgetValuePane; import com.fr.form.ui.Label; @@ -35,7 +37,11 @@ import java.util.Set; /** - * Created by ibm on 2017/8/3. + * 标签控件pane + * + * @author obo + * @version 11.0 + * Created on 2023/11/13 */ public class LabelDefinePane extends AbstractDataModify