Browse Source

Merge remote-tracking branch 'origin/release/11.0' into release/11.0

release/11.0
xiqiu 7 months ago
parent
commit
a69a2a0d89
  1. 140
      designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java
  2. 59
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java
  3. 8
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  4. 22
      designer-base/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java
  5. 16
      designer-base/src/main/java/com/fr/design/mainframe/messagecollect/StartErrorMessageCollector.java
  6. 45
      designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileStylePane.java
  7. 6
      designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java
  8. 4
      designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java
  9. 7
      designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeEditorPane.java
  10. 3
      designer-base/src/main/java/com/fr/design/worker/save/CallbackSaveWorker.java
  11. 17
      designer-base/src/main/java/com/fr/startup/metric/DesignerStartupModel.java
  12. 8
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java
  13. 102
      designer-base/src/main/java/com/fr/widgettheme/ParameterBackgroundStyleSettingPane.java
  14. 50
      designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayAction.java
  15. 81
      designer-base/src/main/java/com/fr/widgettheme/designer/WidgetThemeDisplayConfigPane.java
  16. 88
      designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerBackgroundPane.java
  17. 82
      designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerStyleEditPane.java
  18. 105
      designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java
  19. 76
      designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/MobileWidgetStyleEditPane.java
  20. 136
      designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditContainerPane.java
  21. 120
      designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java
  22. 77
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/ButtonStyleDefinedPane.java
  23. 142
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCell.java
  24. 77
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCellWithIcon.java
  25. 133
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewPane.java
  26. 89
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/ImageUtils.java
  27. 50
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/NormalButtonPreviewCell.java
  28. 51
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/RingControlPreviewCell.java
  29. 45
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/RoundControlPreviewCell.java
  30. 36
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/TextPreviewCell.java
  31. 202
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayFormThemePreviewPane.java
  32. 119
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetDisplayReportThemePreviewPane.java
  33. 35
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECComponentPreviewPane.java
  34. 112
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECPreviewPane.java
  35. 248
      designer-base/src/main/java/com/fr/widgettheme/theme/panel/WidgetThemeECReportPreviewPane.java
  36. 70
      designer-base/src/main/java/com/fr/widgettheme/util/ThemePreviewPaneInitHelper.java
  37. 58
      designer-base/src/main/java/com/fr/widgettheme/util/WidgetThemeDesignerUtils.java
  38. 273
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/DisplayEnhanceMobileStyleDefinePane.java
  39. 59
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FileEditorMobileStyleDefinePane.java
  40. 93
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/FreeButtonMobileStyleDefinePane.java
  41. 77
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/LabelMobileStyleDefinePane.java
  42. 151
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/pane/MobileStyleFontConfigPane.java
  43. 65
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/DisplayEnhanceMobileStyleFactory.java
  44. 84
      designer-base/src/main/java/com/fr/widgettheme/widget/mobile/provider/WidgetThemeMobileStyleDefinePaneCreator.java
  45. BIN
      designer-base/src/main/resources/com/fr/widgettheme/combobox.png
  46. 3
      designer-base/src/main/resources/com/fr/widgettheme/menu.svg
  47. 2
      designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java
  48. 5
      designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java
  49. 5
      designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java
  50. 5
      designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxDefinePane.java
  51. 5
      designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java
  52. 5
      designer-form/src/main/java/com/fr/design/widget/ui/designer/DirectWriteEditorDefinePane.java
  53. 11
      designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java
  54. 12
      designer-form/src/main/java/com/fr/design/widget/ui/designer/NumberEditorDefinePane.java
  55. 5
      designer-form/src/main/java/com/fr/design/widget/ui/designer/TextFieldEditorDefinePane.java
  56. 5
      designer-form/src/main/java/com/fr/design/widget/ui/designer/btn/ButtonGroupDefinePane.java
  57. 1
      designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TextEditorMobileDefinePane.java
  58. 287
      designer-form/src/main/java/com/fr/design/widgettheme/BaseStyleSettingPane.java
  59. 78
      designer-form/src/main/java/com/fr/design/widgettheme/LabelSettingPane.java
  60. 46
      designer-form/src/main/java/com/fr/design/widgettheme/ParaButtonSettingPane.java
  61. 48
      designer-form/src/main/java/com/fr/design/widgettheme/ParaEditorSettingPane.java
  62. 68
      designer-form/src/main/java/com/fr/design/widgettheme/ParaNormalButtonSettingPane.java
  63. 45
      designer-form/src/main/java/com/fr/design/widgettheme/ParaTreeEditorSettingPane.java
  64. 41
      designer-form/src/main/java/com/fr/design/widgettheme/StyleSetting.java
  65. 108
      designer-form/src/main/java/com/fr/design/widgettheme/common/ButtonSettingPane.java
  66. 115
      designer-form/src/main/java/com/fr/design/widgettheme/common/EditorSettingPane.java
  67. 136
      designer-form/src/main/java/com/fr/design/widgettheme/common/NormalButtonSettingPane.java
  68. 107
      designer-form/src/main/java/com/fr/design/widgettheme/common/TreeEditorSettingPane.java
  69. 119
      designer-form/src/main/java/com/fr/design/widgettheme/processor/WidgetThemeCreatorPaneAdder.java
  70. 107
      designer-form/src/main/java/com/fr/design/widgettheme/processor/WidgetThemeParaCreatorPaneAdder.java
  71. 20
      designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java
  72. 94
      designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoUploader.java
  73. 18
      designer-realize/src/main/java/com/fr/design/widget/ui/CheckBoxDefinePane.java
  74. 12
      designer-realize/src/main/java/com/fr/design/widget/ui/FieldEditorDefinePane.java
  75. 2
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java
  76. 63
      designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java
  77. 67
      designer-realize/src/main/java/com/fr/strongest/WidgetThemeListenerStarter.java

140
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;
}
/**
* 由云端运维触发切换埋点
* 内部空实现
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=945327503">实现</a>
*/
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);
});
});
}
/**

59
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 如果我们对这种数据库有默认值如oracledb2pgsql就显示对应数据库的默认值因为要避免性能问题这几种数据库不支持关闭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 如果我们对这种数据库有默认值如oracledb2pgsql就存对应数据库的默认值否则会有性能问题这几种数据库我们是不支持关闭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);
}
}
}

8
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -3,6 +3,7 @@ package com.fr.design.mainframe;
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;
@ -24,6 +25,7 @@ import com.fr.design.actions.edit.UndoAction;
import com.fr.design.actions.file.SaveAsTemplateAction;
import com.fr.design.actions.file.SaveTemplateAction;
import com.fr.design.actions.file.WebPreviewUtils;
import com.fr.widgettheme.designer.WidgetThemeDisplayAction;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.designer.DesignerProxy;
@ -1120,7 +1122,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
//查找替换
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};
}
@ -1781,6 +1783,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
CallbackSaveWorker worker = new CallbackSaveWorker(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
TemplateSaveInfoContext.getInstance().startRecord();
TemplateSaveInfoContext.getInstance().collectInfo(template.suffix());
return saveAs(finalEditingFILE, sourceFile, oldName);
}
}, this);
@ -1884,6 +1888,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
CallbackSaveWorker worker = new CallbackSaveWorker(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
TemplateSaveInfoContext.getInstance().startRecord();
TemplateSaveInfoContext.getInstance().collectInfo(template.suffix());
return saveRealFileByWorker();
}
}, this);

22
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);
}

16
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,6 +21,7 @@ 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;
@ -35,9 +42,18 @@ public class StartErrorMessageCollector {
errorInfo.setLogid(id);
errorInfo.setLog(msg);
errorInfo.setStackTrace(detail);
errorInfo.setStarting(DesignerStartupContext.getInstance().isOnStartup());
errorInfo.setRemote(!WorkContext.getCurrent().isLocal());
errorInfo.saveAsJSON();
}
/**
* 异步记录
*/
public void asyncRecord(String id, String msg, String detail) {
executorService.submit(() -> record(id, msg, detail));
}
public void record(String id, String msg) {
record(id, msg, StringUtils.EMPTY);
}

45
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<String, BasicBeanPane<MobileStyle>> 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<MobileStyle> mobileStyleBasicBeanPane = new MobileStyleDefinePane(widget, appearanceClazz, mobileStyleClazz);
if (checkFlag && processor != null && processor.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz) != null) {
mobileStyleBasicBeanPane = processor.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz);
Class<? extends MobileCommonExtraStyle> extraStyle = processor.classForCommonExtraStyle(widget);
if (WidgetThemeMobileStyleDefinePaneCreator.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz) != null) {
mobileStyleBasicBeanPane = WidgetThemeMobileStyleDefinePaneCreator.createBaseBeanPane(widget, appearanceClazz, mobileStyleClazz);
Class<? extends MobileCommonExtraStyle> 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<PluginContext>() {
@Override
public void on(Event event, PluginContext pluginContext) {
if (pluginContext.getRuntime().contain(MobileStyleDefinePaneCreator.XML_TAG)) {
checkFlag = true;
refreshDockingView();
}
}
});
EventDispatcher.listen(PluginEventType.BeforeStop, new Listener<PluginContext>() {
@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();
}
}

6
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<FormTheme> {
if (processor != null) {
return processor.createFormThemePreviewPane();
}
return new FormThemePreviewPane();
return WidgetThemeDesignerUtils.enableWidgetEnhance() ? new WidgetDisplayFormThemePreviewPane() : new FormThemePreviewPane();
}
@Override

4
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<ReportTheme
if (processor != null) {
return processor.createReportThemePreviewPane();
}
return new ReportThemePreviewPane();
return WidgetThemeDesignerUtils.enableWidgetEnhance() ? new WidgetDisplayReportThemePreviewPane() : new ReportThemePreviewPane();
}
@Override

7
designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeEditorPane.java

@ -5,6 +5,7 @@ import com.fr.base.theme.TemplateTheme;
import com.fr.base.theme.TemplateThemeConfig;
import com.fr.base.theme.settings.ThemedCellStyleList;
import com.fr.base.theme.settings.ThemedColorScheme;
import com.fr.widgettheme.util.WidgetThemeDesignerUtils;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.designer.IntervalConstants;
@ -28,6 +29,8 @@ import com.fr.general.GeneralContext;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.StringUtils;
import com.fr.widgettheme.theme.edit.ParamContainerStyleEditPane;
import com.fr.widgettheme.theme.edit.widget.WidgetStyleEditContainerPane;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
@ -202,6 +205,10 @@ public abstract class TemplateThemeEditorPane<T extends TemplateTheme> extends J
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
if(WidgetThemeDesignerUtils.enableWidgetEnhance()) {
extraPaneList.add(new ParamContainerStyleEditPane<>());
extraPaneList.add(new WidgetStyleEditContainerPane<>());
}
Set<TemplateThemePaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(TemplateThemePaneProvider.XML_TAG);
for (TemplateThemePaneProvider<T> provider : providers) {
insertShortCut(provider.getInsertPosition(extraPaneList.size()), provider.getTab());

3
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<Runnable> list) {

17
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.runtime.version"));
MachineInfo info = new MachineInfo();
AbstractOperatingSystem operatingSystem = OperatingSystem.getOperatingSystem();
info.setSystem(operatingSystem.getDisplayString());

8
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;
/**
* 启动页
@ -269,6 +274,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();
}

102
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<WParameterLayout> {
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");
}
}

50
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<T extends JTemplate<?, ?>> extends JTemplateAction<T> {
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 == null) {
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);
}
}

81
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() {
//记录埋点
}
}

88
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<BackgroundQuickPane> kinds = new ArrayList<>();
kinds.add(nullBackgroundPane);
kinds.add(colorBackgroundPane);
kinds.add(imageBackgroundPane);
kinds.add(gradientBackgroundPane);
kinds.add(textureBackgroundPane);
kinds.add(patternBackgroundPane);
Set<BackgroundQuickUIProvider> 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();
}
}

82
designer-base/src/main/java/com/fr/widgettheme/theme/edit/ParamContainerStyleEditPane.java

@ -0,0 +1,82 @@
package com.fr.widgettheme.theme.edit;
import com.fr.base.theme.TemplateTheme;
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<T extends TemplateTheme> extends BasicBeanPane<T> {
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) {
ThemedParamContainerStyle paramContainerStyle = (ThemedParamContainerStyle) t.getParamContainerStyle();
if (paramContainerStyle == null) {
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");
}
}

105
designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/DesktopWidgetStyleEditPane.java

@ -0,0 +1,105 @@
package com.fr.widgettheme.theme.edit.widget;
import com.fr.base.background.ColorBackground;
import com.fr.base.theme.TemplateTheme;
import com.fr.widgettheme.theme.widget.style.BorderStyle;
import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle;
import com.fr.widgettheme.theme.widget.style.FontSizeStyle;
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 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<T extends TemplateTheme> extends WidgetStyleEditPane<T> {
// 风格1
protected UIRadioButton style1;
// 风格2
protected UIRadioButton style2;
public DesktopWidgetStyleEditPane() {
super();
}
@Override
public Component[][] generateComponent() {
initStyleEditor();
// 容纳风格1和风格2的panel
JPanel stylePane = new JPanel(FRGUIPaneFactory.createBoxFlowLayout());
stylePane.add(style1);
stylePane.add(style2);
Component[][] components = 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_Font_Size")), fontSizeComoBox}
};
return components;
}
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);
}
@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());
fontSizeComoBox.setSelectedItem(style.getFontSizeStyle().getFontSize());
}
@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);
FontSizeStyle fontSizeStyle = new FontSizeStyle();
fontSizeStyle.setFontSize((Integer) fontSizeComoBox.getSelectedItem());
style.setFontSizeStyle(fontSizeStyle);
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);
}
}

76
designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/MobileWidgetStyleEditPane.java

@ -0,0 +1,76 @@
package com.fr.widgettheme.theme.edit.widget;
import com.fr.base.theme.TemplateTheme;
import com.fr.widgettheme.theme.widget.style.BorderStyle;
import com.fr.widgettheme.theme.widget.style.FontSizeStyle;
import com.fr.widgettheme.theme.widget.style.MobileThemedWidgetStyle;
import com.fr.design.gui.icombobox.LineComboBox;
import com.fr.design.gui.icombobox.UIComboBox;
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<T extends TemplateTheme> extends WidgetStyleEditPane<T> {
/**
* 移动端字体列表 12-18
*/
private static Vector<Integer> FONT_SIZES = new Vector<Integer>() {
{
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 initFontSizeComoBox() {
fontSizeComoBox = new UIComboBox(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());
fontSizeComoBox.setSelectedItem(style.getFontSizeStyle().getFontSize());
}
@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);
FontSizeStyle fontSizeStyle = new FontSizeStyle();
fontSizeStyle.setFontSize((Integer) fontSizeComoBox.getSelectedItem());
style.setFontSizeStyle(fontSizeStyle);
}
}

136
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<T extends TemplateTheme> extends BasicBeanPane<T> {
private UIButtonGroup<Integer> terminalStyleGroup;
private WidgetStyleEditPane<T> desktop;
private WidgetStyleEditPane<T> 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");
}
}

120
designer-base/src/main/java/com/fr/widgettheme/theme/edit/widget/WidgetStyleEditPane.java

@ -0,0 +1,120 @@
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.icombobox.LineComboBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.gui.style.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 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<T extends TemplateTheme> extends BasicBeanPane<T> {
// 主题色
protected NewColorSelectBox colorSelectBox;
// 边框线型
protected LineComboBox lineComboBox;
// 圆角边框
protected UISpinner borderRadiusSpinner;
// 字体大小
protected UIComboBox fontSizeComoBox;
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};
double[] columnSize = {p, p};
int[][] rowCount = {{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() {
Component[][] components = 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_Font_Size")), fontSizeComoBox}};
return components;
}
private void initCommonStyleEditor() {
colorSelectBox = new NewColorSelectBox(140, true);
colorSelectBox.setSelectObject(WidgetThemeDisplayConstants.DEFAULT_THEME_COLOR);
initLineBox();
borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1);
initFontSizeComoBox();
fontSizeComoBox.setSelectedItem(16);
}
protected void initFontSizeComoBox() {
fontSizeComoBox = new UIComboBox(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;
}
}

77
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;
}
}

142
designer-base/src/main/java/com/fr/widgettheme/theme/panel/ControlPreviewCell.java

@ -0,0 +1,142 @@
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.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants;
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.getFontSizeStyle().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.getFontSizeStyle().getFontSize(), textColor);
//每个预览格子通用的字体绘制
BaseUtils.drawStringStyleInRotation(g2d, getWidth(), getHeight(), this.value,
Style.getInstance(font).deriveHorizontalAlignment(Constants.LEFT)
.deriveTextStyle(Style.TEXTSTYLE_SINGLELINE), NO_SCALE_RESOLUTION);
}
}

77
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);
}
}
}

133
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<TemplateTheme> {
public static final int PREVIEW_WIDTH = 615;
public static final int PREVIEW_HEIGHT = 62;
/**
* 参数界面中放置的所有cell用于监听主题样式变更
*/
public final List<ControlPreviewCell> 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);
}
}

89
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;
}
}

50
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.getFontSizeStyle().getFontSize(), Color.WHITE);
uiLabel.setFont(font);
this.add(uiLabel, BorderLayout.CENTER);
}
}

51
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);
}
}

45
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);
}
}

36
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;
}
}
}

202
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<FormTheme> {
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;
}
}

119
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<ReportTheme> {
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());
}
}

35
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);
}
}

112
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<AbstractPreviewCell> headerCellList = new ArrayList<>();
private final List<AbstractPreviewCell> contentCellList = new ArrayList<>();
private final List<AbstractPreviewCell> highLightCellList = new ArrayList<>();
private final List<AbstractPreviewCell> 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());
}
}

248
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<ReportTheme> {
private final List<AbstractPreviewCell> headerTitleCellList = new ArrayList<>(); // 大标题样式单元格
private final List<AbstractPreviewCell> headerCellList = new ArrayList<>(); // 表头样式单元格
private final List<AbstractPreviewCell> titleCellList = new ArrayList<>(); // 小标题样式单元格
private final List<AbstractPreviewCell> contentCellList = new ArrayList<>(); // 正文样式单元格
private final List<AbstractPreviewCell> highLightCellList = new ArrayList<>(); // 高亮文本样式单元格
private final List<AbstractPreviewCell> 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());
}
}
}

70
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"));
}
}

58
designer-base/src/main/java/com/fr/widgettheme/util/WidgetThemeDesignerUtils.java

@ -0,0 +1,58 @@
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;
}
/**
* 判断当前widget是否为新多选下拉树控件
*/
public static boolean isNewComboBoxTreeEditor(Object widget) {
String className = widget.getClass().getName();
if (widget instanceof Class) {
className = ((Class) widget).getName();
}
return StringUtils.equals(className, "com.fr.plugin.widget.newcomboboxtree.NewComboBoxTreeEditor")
|| StringUtils.equals(className, "com.fr.plugin.widget.newcomboboxtree.XNewComboBoxTreeEditor");
}
}

273
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;
/**
* <p> 开启控件显示增强后替换原通用属性面板
* <p> 参考{@link com.fr.design.mainframe.mobile.ui.MobileStyleDefinePane}
*
* @author Coral.Chen
* @since 11.0
* Created on 2023/4/11
*/
public class DisplayEnhanceMobileStyleDefinePane extends BasicBeanPane<MobileStyle> {
public static final int NORMAL_COMBO_WIDTH = 152;
protected Widget widget;
protected MobileStyleCustomDefinePane customBeanPane;
protected Class<? extends MobileStyle> 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<? extends MobileStyleCustomDefinePane> customBeanPaneClass,
Class<? extends MobileStyle> 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;
}
}

59
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<? extends MobileStyleCustomDefinePane> customBeanPaneClass, Class<? extends MobileStyle> 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();
}
}

93
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<? extends MobileStyleCustomDefinePane> customBeanPaneClass, Class<? extends MobileStyle> 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());
}
}

77
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<? extends MobileStyleCustomDefinePane> customBeanPaneClass,
Class<? extends MobileStyle> 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);
}
}

151
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<Integer> getFontSizes() {
Vector<Integer> fontSizes = new Vector<Integer>();
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;
}
}
}

65
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<MobileStyle> createWidgetMobileStyleDefinePane(Widget widget, Class<? extends MobileStyleCustomDefinePane> customDefinePane, Class<? extends MobileStyle> 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<? extends MobileCommonExtraStyle> 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;
}
}

84
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<MobileStyle> createBaseBeanPane(Widget widget, Class<? extends MobileStyleCustomDefinePane> customDefinePane, Class<? extends MobileStyle> 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<? extends MobileCommonExtraStyle> 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));
}
}

BIN
designer-base/src/main/resources/com/fr/widgettheme/combobox.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

3
designer-base/src/main/resources/com/fr/widgettheme/menu.svg

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 1V14H8.5V13H2V2H14V7H15V1H1ZM11 8H11.7L10.9 9H7V10H10.1L9.3 11H7H6V10V9V8H7H11ZM3 4H5V6H3V4ZM5 8H3V10H5V8ZM12 5V4H11H7H6V5V6V7H7H11H12V6V5ZM11 6H7V5H11V6ZM10.0404 12.239L13.1594 8.08039C13.2747 7.92663 13.5194 8.00819 13.5194 8.20039V11.3194H15.5987C15.7635 11.3194 15.8576 11.5075 15.7587 11.6394L12.6397 15.798C12.5244 15.9518 12.2797 15.8702 12.2797 15.678V12.559H10.2004C10.0356 12.559 9.94148 12.3709 10.0404 12.239Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 595 B

2
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<WParameterLayout> {
private void refreshExtraAdvancedPane() {
extraPaneList.clear();
backgroundPane.removeAll();
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
Set<WidgetAdvancedPaneProvider<WParameterLayout>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<WParameterLayout> provider : providers) {
if (!provider.accept(creator)) {

5
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<T extends Button> extends ButtonWi
*/
protected void refreshExtraAdvancedPane(Class cls) {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeCreatorPaneAdder.add(cls, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(cls)) {

5
designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java

@ -12,12 +12,14 @@ 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;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.StableUtils;
import com.fr.stable.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
@ -64,7 +66,8 @@ public abstract class ButtonDefinePane<T extends Button> extends AbstractDataMod
private void refreshAdvancedPane() {
extraPaneList.clear();
containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(creator)) {

5
designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxDefinePane.java

@ -11,12 +11,14 @@ 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.widgettheme.processor.WidgetThemeParaCreatorPaneAdder;
import com.fr.design.widget.ui.designer.component.FontSizeComboPane;
import com.fr.design.widget.ui.designer.component.FormWidgetValuePane;
import com.fr.form.ui.CheckBox;
import com.fr.general.GeneralContext;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
@ -76,7 +78,8 @@ public class CheckBoxDefinePane extends AbstractDataModify<CheckBox> {
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<CheckBox>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<CheckBox> provider : providers) {
if (!provider.accept(creator)) {

5
designer-form/src/main/java/com/fr/design/widget/ui/designer/DateEditorDefinePane.java

@ -14,6 +14,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;
@ -21,6 +22,7 @@ import com.fr.design.widget.ui.designer.date.DateFormatCheckManager;
import com.fr.design.widget.ui.designer.date.DateFormatCheckResult;
import com.fr.form.ui.DateEditor;
import com.fr.stable.ArrayUtils;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
@ -98,7 +100,8 @@ public class DateEditorDefinePane extends DirectWriteEditorDefinePane<DateEditor
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<DateEditor>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<DateEditor> provider : providers) {
if (!provider.accept(creator)) {

5
designer-form/src/main/java/com/fr/design/widget/ui/designer/DirectWriteEditorDefinePane.java

@ -9,9 +9,11 @@ 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;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
@ -66,7 +68,8 @@ public abstract class DirectWriteEditorDefinePane<T extends DirectWriteEditor> e
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(creator)) {

11
designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java

@ -15,6 +15,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;
@ -22,6 +23,7 @@ import com.fr.general.GeneralContext;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.Constants;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
@ -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<Label> {
private static final int WIDGET_VALUE_PANE_WIDTH = 150;
@ -105,7 +111,8 @@ public class LabelDefinePane extends AbstractDataModify<Label> {
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<Label>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<Label> provider : providers) {
if (!provider.accept(creator)) {

12
designer-form/src/main/java/com/fr/design/widget/ui/designer/NumberEditorDefinePane.java

@ -10,9 +10,11 @@ import com.fr.design.gui.ispinner.UIBasicSpinner;
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.component.NumberEditorValidatePane;
import com.fr.design.widget.ui.designer.component.FormWidgetValuePane;
import com.fr.form.ui.NumberEditor;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
@ -21,6 +23,13 @@ import javax.swing.SwingConstants;
import java.awt.Component;
import java.util.Set;
/**
* 数字编辑控件pane
*
* @author obo
* @version 11.0
* Created on 2023/11/13
*/
public class NumberEditorDefinePane extends FieldEditorDefinePane<NumberEditor> {
public NumberEditorDefinePane(XCreator xCreator){
super(xCreator);
@ -67,7 +76,8 @@ public class NumberEditorDefinePane extends FieldEditorDefinePane<NumberEditor>
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<NumberEditor>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<NumberEditor> provider : providers) {
if (!provider.accept(creator)) {

5
designer-form/src/main/java/com/fr/design/widget/ui/designer/TextFieldEditorDefinePane.java

@ -12,10 +12,12 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder;
import com.fr.design.widget.ui.designer.component.FormWidgetValuePane;
import com.fr.form.ui.TextEditor;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
@ -85,7 +87,8 @@ public class TextFieldEditorDefinePane extends FieldEditorDefinePane<TextEditor>
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<TextEditor>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<TextEditor> provider : providers) {
if (!provider.accept(creator)) {

5
designer-form/src/main/java/com/fr/design/widget/ui/designer/btn/ButtonGroupDefinePane.java

@ -11,10 +11,12 @@ 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.AccessibleDictionaryEditor;
import com.fr.design.widgettheme.processor.WidgetThemeParaCreatorPaneAdder;
import com.fr.design.widget.ui.designer.ButtonGroupDictPane;
import com.fr.design.widget.ui.designer.FieldEditorDefinePane;
import com.fr.design.widget.ui.designer.component.FormWidgetValuePane;
import com.fr.form.ui.ButtonGroup;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
@ -68,7 +70,8 @@ public abstract class ButtonGroupDefinePane<T extends ButtonGroup> extends Field
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeParaCreatorPaneAdder.add(creator, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(creator)) {

1
designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TextEditorMobileDefinePane.java

@ -33,6 +33,7 @@ public class TextEditorMobileDefinePane extends BaseTextEditorMobileDefinePane {
inputSettingPane = new MobileTextFieldInputSettingPane();
textSettingPane = new MobileTextEditSettingPane();
container.add(inputSettingPane);
container.add(textSettingPane);
}

287
designer-form/src/main/java/com/fr/design/widgettheme/BaseStyleSettingPane.java

@ -0,0 +1,287 @@
package com.fr.design.widgettheme;
import com.fr.base.theme.TemplateTheme;
import com.fr.widgettheme.theme.widget.style.BorderStyle;
import com.fr.widgettheme.theme.widget.style.FontSizeStyle;
import com.fr.widgettheme.theme.widget.style.ThemedWidgetStyle;
import com.fr.widgettheme.theme.bean.ButtonBackground;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.icombobox.LineComboBox;
import com.fr.design.gui.ilable.UILabel;
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.mainframe.JTemplate;
import com.fr.design.style.color.NewColorSelectBox;
import com.fr.design.widget.ui.designer.component.FontSizeComboPane;
import com.fr.design.widget.ui.designer.component.UIBoundSpinner;
import com.fr.form.ui.Widget;
import com.fr.general.FRFont;
import com.fr.widgettheme.theme.panel.ButtonStyleDefinedPane;
import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 样式设置pane抽象类
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public abstract class BaseStyleSettingPane<T extends Widget> extends BasicBeanPane<T> {
protected List<StyleSetting> styleSettingList;
//样式切换标题头部
protected UIButtonGroup<String> styleSettingHead;
// 自定义样式
protected JPanel customPane;
// 主题色
protected NewColorSelectBox colorSelectBox;
// 风格1
protected UIRadioButton style1;
// 风格2
protected UIRadioButton style2;
// 边框线型
protected LineComboBox lineComboBox;
// 圆角边框
protected UIBoundSpinner borderRadiusSpinner;
// 字体大小
protected FontSizeComboPane fontSizePane;
// 字体详细设置
protected FRFontPane frFontPane;
// 按钮背景设置
protected ButtonStyleDefinedPane buttonStyleDefinedPane;
private final Map<StyleSetting, UILabel> labelMap = new HashMap<>();
private final Map<StyleSetting, Component> paneMap = new HashMap<>();
public BaseStyleSettingPane(List<StyleSetting> styleSettingList) {
this.styleSettingList = styleSettingList;
initLabelMap();
initStyleEditor();
initPane();
initDefaultValue();
}
protected void initPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.add(createHeadPane(), BorderLayout.NORTH);
this.add(createCustomPane(), BorderLayout.CENTER);
}
protected void initStyleEditor() {
initStyle();
colorSelectBox = new NewColorSelectBox(160, true);
lineComboBox = new LineComboBox(WidgetThemeDisplayConstants.BORDER_LINE_STYLE_ARRAY);
fontSizePane = new FontSizeComboPane();
borderRadiusSpinner = new UIBoundSpinner(0, Integer.MAX_VALUE, 1);
frFontPane = new FRFontPane();
buttonStyleDefinedPane = new ButtonStyleDefinedPane();
paneMap.put(StyleSetting.STYLE_TYPE, createStyleTypePane());
paneMap.put(StyleSetting.THEME_COLOR, colorSelectBox);
paneMap.put(StyleSetting.LINE_TYPE, lineComboBox);
paneMap.put(StyleSetting.FONT_SIZE, fontSizePane);
paneMap.put(StyleSetting.BORDER_RADIUS, borderRadiusSpinner);
paneMap.put(StyleSetting.FONT, frFontPane);
paneMap.put(StyleSetting.BTN_BACKGROUND, buttonStyleDefinedPane);
}
/**
* 初始化style1和style2
*/
private void initStyle() {
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);
}
protected JPanel createHeadPane() {
UILabel headLabel = new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Style_Setting"));
String[] titles = new String[]{Toolkit.i18nText("Fine-Design_Widget_Follow_Theme"), Toolkit.i18nText("Fine-Design_Widget_Theme_Custom")};
styleSettingHead = new UIButtonGroup(titles) {
@Override
public void setSelectedIndex(int newSelectedIndex, boolean fireChanged) {
super.setSelectedIndex(newSelectedIndex, fireChanged);
switchCard();
}
};
JPanel headPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{
new Component[]{headLabel, styleSettingHead}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1);
headPane.setBorder(BorderFactory.createEmptyBorder(0, 0, IntervalConstants.INTERVAL_L1, 0));
return headPane;
}
protected JPanel createStyleTypePane() {
// 容纳风格1和风格2的panel
JPanel stylePane = new JPanel(FRGUIPaneFactory.createBoxFlowLayout());
stylePane.add(style1);
stylePane.add(style2);
return stylePane;
}
protected JPanel createCustomPane() {
int size = styleSettingList.size();
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
int columnCount = 2;
double[] rowSize = new double[size];
for (int i = 0; i < size; i++) {
rowSize[i] = p;
}
double[] columnSize = {p, f};
int[][] rowCount = new int[size][columnCount];
for (int i = 0; i < size; i++) {
for (int j = 0; j < columnCount; j++) {
rowCount[i][j] = 1;
}
}
customPane = TableLayoutHelper.createGapTableLayoutPane(createComponents(size), rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1);
customPane.setBorder(BorderFactory.createEmptyBorder(0, 0, IntervalConstants.INTERVAL_L1, 0));
return customPane;
}
protected Component[][] createComponents(int size) {
Component[][] result = new Component[size][2];
for (int i = 0; i < size; i++) {
result[i] = createComponentByStyleSetting(styleSettingList.get(i));
}
return result;
}
protected Component[] createComponentByStyleSetting(StyleSetting styleSetting) {
Component[] components = new Component[2];
components[0] = labelMap.get(styleSetting);
components[1] = paneMap.get(styleSetting);
return components;
}
protected void switchCard() {
customPane.setVisible(styleSettingHead.getSelectedIndex() == 1);
}
protected void initDefaultValue() {
// 读取当前模板的主题
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (JTemplate.isValid(template)) {
TemplateTheme theme = template.getTemplateTheme();
ThemedWidgetStyle widgetStyle = (ThemedWidgetStyle) theme.getWidgetStyle();
if (widgetStyle != null) {
setThemedStyle(widgetStyle);
return;
}
}
setDefaultStyle();
}
private void setThemedStyle(ThemedWidgetStyle widgetStyle) {
setColorSelectBox(widgetStyle);
setStyle(widgetStyle);
setLineComboBox(widgetStyle);
setBorderRadiusSpinner(widgetStyle);
setFontSizePane(widgetStyle);
setFrFontPane(widgetStyle);
setButtonStyleDefinedPane(widgetStyle);
}
private void setColorSelectBox(ThemedWidgetStyle widgetStyle) {
if (colorSelectBox != null) {
colorSelectBox.setSelectObject(widgetStyle.getThemeColor());
}
}
private void setStyle(ThemedWidgetStyle widgetStyle) {
if (widgetStyle.getStyleType() == ThemedWidgetStyle.DEFAULT_STYLE) {
if (style1 != null) {
style1.setSelected(true);
}
} else {
if (style2 != null) {
style2.setSelected(true);
}
}
}
private void setLineComboBox(ThemedWidgetStyle widgetStyle) {
if (lineComboBox != null) {
lineComboBox.setSelectedLineStyle(widgetStyle.getBorderStyle().getLineType());
}
}
private void setBorderRadiusSpinner(ThemedWidgetStyle widgetStyle) {
if (borderRadiusSpinner != null) {
borderRadiusSpinner.setValue(widgetStyle.getBorderStyle().getRadius());
}
}
private void setFontSizePane(ThemedWidgetStyle widgetStyle) {
if (fontSizePane != null) {
fontSizePane.setValue(widgetStyle.getFontSizeStyle().getFontSize());
}
}
private void setFrFontPane(ThemedWidgetStyle widgetStyle) {
if (frFontPane != null) {
frFontPane.populateBean(widgetStyle.getFontStyle().getFont());
}
}
private void setButtonStyleDefinedPane(ThemedWidgetStyle widgetStyle) {
if (buttonStyleDefinedPane != null) {
buttonStyleDefinedPane.populate(ButtonBackground.create(widgetStyle.getButtonBackgroundStyle()));
}
}
private void setDefaultStyle() {
if (colorSelectBox != null) {
colorSelectBox.setSelectObject(ThemedWidgetStyle.DEFAULT_COLOR);
}
if (style1 != null) {
style1.setSelected(true);
}
if (lineComboBox != null) {
lineComboBox.setSelectedLineStyle(BorderStyle.DEFAULT_LINE_TYPE);
}
if (borderRadiusSpinner != null) {
borderRadiusSpinner.setValue(BorderStyle.DEFAULT_BORDER_RADIUS);
}
if (fontSizePane != null) {
fontSizePane.setValue(FontSizeStyle.DEFAULT_FONT_SIZE);
}
if (frFontPane != null) {
frFontPane.populateBean(FRFont.getInstance());
}
}
/**
* 初始化枚举和UILabel对应的map
*/
private void initLabelMap() {
labelMap.put(StyleSetting.THEME_COLOR, new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Color")));
labelMap.put(StyleSetting.FONT_SIZE, new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Font_Size")));
labelMap.put(StyleSetting.FONT, new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Font")));
labelMap.put(StyleSetting.STYLE_TYPE, new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Style")));
labelMap.put(StyleSetting.LINE_TYPE, new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Line")));
labelMap.put(StyleSetting.BORDER_RADIUS, new UILabel(Toolkit.i18nText("Fine-Design_Widget_Theme_Border_Radius")));
labelMap.put(StyleSetting.BTN_BACKGROUND, new UILabel(Toolkit.i18nText("Fine-Design_Theme_Widget_Background")));
}
}

78
designer-form/src/main/java/com/fr/design/widgettheme/LabelSettingPane.java

@ -0,0 +1,78 @@
package com.fr.design.widgettheme;
import com.fr.widgettheme.theme.widget.style.FontStyle;
import com.fr.form.ui.Label;
import com.fr.form.ui.Widget;
import com.fr.general.FRFont;
import com.fr.widgettheme.theme.widget.theme.LabelTheme;
import java.util.Collections;
/**
* 设计器控件属性的高级设置增加主题样式设置项用于标签控件
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public class LabelSettingPane<T extends Widget> extends BaseStyleSettingPane<T> {
public LabelSettingPane() {
super(Collections.singletonList(StyleSetting.FONT));
}
@Override
public void populateBean(T t) {
LabelTheme widgetTheme = initLabelTheme(t);
if (widgetTheme.isFollowTheme()) {
styleSettingHead.setSelectedIndex(0);
} else {
styleSettingHead.setSelectedIndex(1);
FRFont font = ((Label) t).getFont();
frFontPane.populateBean(font);
}
switchCard();
}
private LabelTheme initLabelTheme(T t) {
LabelTheme widgetTheme = (LabelTheme) t.getWidgetTheme();
if (widgetTheme == null) {
widgetTheme = new LabelTheme();
t.setWidgetTheme(widgetTheme);
}
return widgetTheme;
}
@Override
public void updateBean(T t) {
LabelTheme widgetTheme = initLabelTheme(t);
updateLabelBean(widgetTheme);
((Label) t).setFont(widgetTheme.getFontStyle().getFont());
}
private void updateLabelBean(LabelTheme widgetTheme) {
int selectIndex = styleSettingHead.getSelectedIndex();
widgetTheme.setFollowTheme(selectIndex == 0);
updateLabelStyleBean(widgetTheme);
}
private void updateLabelStyleBean(LabelTheme widgetTheme) {
if (widgetTheme.isFollowTheme()) {
widgetTheme.setFontStyle(new FontStyle());
frFontPane.populateBean(widgetTheme.getFontStyle().getFont());
} else {
widgetTheme.setFontStyle(new FontStyle(frFontPane.update(widgetTheme.getFontStyle().getFont())));
}
switchCard();
}
@Override
public T updateBean() {
return null;
}
@Override
protected String title4PopupWindow() {
return "labelSetting";
}
}

46
designer-form/src/main/java/com/fr/design/widgettheme/ParaButtonSettingPane.java

@ -0,0 +1,46 @@
package com.fr.design.widgettheme;
import com.fr.widgettheme.theme.widget.style.FontSizeStyle;
import com.fr.design.widgettheme.common.ButtonSettingPane;
import com.fr.form.ui.Widget;
import com.fr.widgettheme.theme.widget.theme.ParaButtonTheme;
import com.fr.widgettheme.theme.widget.theme.cell.ButtonTheme;
import java.util.Arrays;
/**
* 参数面板:设计器控件属性的高级设置增加主题样式设置项包括
* 单选按钮组控件/复选按钮组控件/复选按钮控件
*
* @author Bruce.Deng
* @since 11.0
* Created on 2023/2/27
*/
public class ParaButtonSettingPane<T extends Widget> extends ButtonSettingPane<T> {
public ParaButtonSettingPane() {
super(Arrays.asList(
StyleSetting.THEME_COLOR,
StyleSetting.STYLE_TYPE,
StyleSetting.FONT_SIZE
));
}
@Override
protected ButtonTheme getButtonTheme() {
return new ParaButtonTheme();
}
@Override
protected void assignFontSizePane(ButtonTheme buttonTheme) {
ParaButtonTheme paraButtonTheme = (ParaButtonTheme) buttonTheme;
fontSizePane.setValue(paraButtonTheme.getFontSizeStyle().getFontSize());
}
@Override
protected void assignFontSizeStyle(ButtonTheme buttonTheme) {
ParaButtonTheme paraButtonTheme = (ParaButtonTheme) buttonTheme;
paraButtonTheme.setFontSizeStyle(new FontSizeStyle(fontSizePane.getValue()));
}
}

48
designer-form/src/main/java/com/fr/design/widgettheme/ParaEditorSettingPane.java

@ -0,0 +1,48 @@
package com.fr.design.widgettheme;
import com.fr.widgettheme.theme.widget.style.FontSizeStyle;
import com.fr.design.widgettheme.common.EditorSettingPane;
import com.fr.form.ui.Widget;
import com.fr.widgettheme.theme.widget.theme.ParaEditorTheme;
import com.fr.widgettheme.theme.widget.theme.cell.EditorTheme;
import java.util.Arrays;
/**
* 设计器控件属性的高级设置增加主题样式设置项包括
* 文本控件/数字控件/密码控件/文本域控件/下拉框控件/下拉复选框控件/下拉树控件/日期控件
*
* @author Bruce.Deng
* @since 11.0
* Created on 2023/2/2
*/
public class ParaEditorSettingPane<T extends Widget> extends EditorSettingPane<T> {
public ParaEditorSettingPane() {
super(Arrays.asList(
StyleSetting.THEME_COLOR,
StyleSetting.STYLE_TYPE,
StyleSetting.LINE_TYPE,
StyleSetting.BORDER_RADIUS,
StyleSetting.FONT_SIZE
));
}
@Override
protected void assignFontSizePane(EditorTheme widgetTheme) {
ParaEditorTheme paraEditorTheme= (ParaEditorTheme) widgetTheme;
fontSizePane.setValue(paraEditorTheme.getFontSizeStyle().getFontSize());
}
@Override
protected void assignFontSizeStyle(EditorTheme widgetTheme) {
ParaEditorTheme paraEditorTheme= (ParaEditorTheme) widgetTheme;
paraEditorTheme.setFontSizeStyle(new FontSizeStyle(fontSizePane.getValue()));
}
@Override
protected EditorTheme getEditorTheme() {
return new ParaEditorTheme();
}
}

68
designer-form/src/main/java/com/fr/design/widgettheme/ParaNormalButtonSettingPane.java

@ -0,0 +1,68 @@
package com.fr.design.widgettheme;
import com.fr.widgettheme.theme.widget.style.FontStyle;
import com.fr.design.widgettheme.common.NormalButtonSettingPane;
import com.fr.form.ui.FreeButton;
import com.fr.form.ui.Widget;
import com.fr.general.FRFont;
import com.fr.widgettheme.theme.widget.theme.ParaNormalButtonTheme;
import com.fr.widgettheme.theme.widget.theme.cell.NormalButtonTheme;
import java.util.Arrays;
/**
* 参数面板常规按钮设置窗口
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public class ParaNormalButtonSettingPane<T extends Widget> extends NormalButtonSettingPane<T> {
public ParaNormalButtonSettingPane() {
super(Arrays.asList(
StyleSetting.BTN_BACKGROUND,
StyleSetting.LINE_TYPE,
StyleSetting.BORDER_RADIUS,
StyleSetting.FONT
));
}
@Override
protected void assignFontPane(NormalButtonTheme normalButtonTheme) {
ParaNormalButtonTheme paraNormalButtonTheme = (ParaNormalButtonTheme) normalButtonTheme;
frFontPane.populateBean(paraNormalButtonTheme.getFontStyle().getFont());
}
@Override
protected void initCustomStyle(FreeButton freeButton, NormalButtonTheme widgetTheme) {
super.initCustomStyle(freeButton, widgetTheme);
FRFont font = freeButton.getFont();
((ParaNormalButtonTheme) widgetTheme).setFontStyle(new FontStyle(font));
}
@Override
protected void updateCustomStyle(FreeButton freeButton, NormalButtonTheme widgetTheme) {
super.updateCustomStyle(freeButton, widgetTheme);
FontStyle fontStyle = ((ParaNormalButtonTheme) widgetTheme).getFontStyle();
freeButton.setFont(fontStyle.getFont());
}
@Override
protected void assignFontStyle(NormalButtonTheme normalButtonTheme) {
ParaNormalButtonTheme paraNormalButtonTheme = (ParaNormalButtonTheme) normalButtonTheme;
if (paraNormalButtonTheme.isFollowTheme()) {
paraNormalButtonTheme.setFontStyle(new FontStyle());
assignFontPane(normalButtonTheme);
} else {
paraNormalButtonTheme.setFontStyle(new FontStyle(frFontPane.update(paraNormalButtonTheme.getFontStyle().getFont())));
}
}
@Override
protected NormalButtonTheme getDefaultNormalButtonTheme() {
return new ParaNormalButtonTheme();
}
}

45
designer-form/src/main/java/com/fr/design/widgettheme/ParaTreeEditorSettingPane.java

@ -0,0 +1,45 @@
package com.fr.design.widgettheme;
import com.fr.widgettheme.theme.widget.style.FontSizeStyle;
import com.fr.design.widgettheme.common.TreeEditorSettingPane;
import com.fr.form.ui.TreeEditor;
import com.fr.widgettheme.theme.widget.theme.ParaTreeTheme;
import com.fr.widgettheme.theme.widget.theme.cell.TreeTheme;
import java.util.Arrays;
/**
* 参数面板设计器控件属性的高级设置增加主题样式设置项包括
* 视图树
*
* @author Bruce.Deng
* @since 11.0
* Created on 2023/2/28
*/
public class ParaTreeEditorSettingPane<T extends TreeEditor> extends TreeEditorSettingPane<T> {
public ParaTreeEditorSettingPane() {
super(Arrays.asList(
StyleSetting.THEME_COLOR,
StyleSetting.STYLE_TYPE,
StyleSetting.FONT_SIZE
));
}
@Override
protected TreeTheme getTreeTheme() {
return new ParaTreeTheme();
}
@Override
protected void assignFontSizePane(TreeTheme widgetTheme) {
ParaTreeTheme paraTreeTheme= (ParaTreeTheme) widgetTheme;
fontSizePane.setValue(paraTreeTheme.getFontSizeStyle().getFontSize());
}
@Override
protected void assignFontSizeStyle(TreeTheme widgetTheme) {
ParaTreeTheme paraTreeTheme= (ParaTreeTheme) widgetTheme;
paraTreeTheme.setFontSizeStyle(new FontSizeStyle(fontSizePane.getValue()));
}
}

41
designer-form/src/main/java/com/fr/design/widgettheme/StyleSetting.java

@ -0,0 +1,41 @@
package com.fr.design.widgettheme;
/**
* 控件样式附加选项类型
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public enum StyleSetting {
/**
* 主题颜色
*/
THEME_COLOR,
/**
* 风格
*/
STYLE_TYPE,
/**
* 线型
*/
LINE_TYPE,
/**
* 边框圆角
*/
BORDER_RADIUS,
/**
* 字体大小
*/
FONT_SIZE,
/**
* 字体
*/
FONT,
/**
* 按钮背景
*/
BTN_BACKGROUND
}

108
designer-form/src/main/java/com/fr/design/widgettheme/common/ButtonSettingPane.java

@ -0,0 +1,108 @@
package com.fr.design.widgettheme.common;
import com.fr.design.widgettheme.StyleSetting;
import com.fr.design.widgettheme.BaseStyleSettingPane;
import com.fr.form.ui.Widget;
import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants;
import com.fr.widgettheme.theme.widget.theme.cell.ButtonTheme;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
/**
* 设计器控件属性的高级设置增加主题样式设置项包括
* 单选按钮组控件/复选按钮组控件/复选按钮控件
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/18
*/
public class ButtonSettingPane<T extends Widget> extends BaseStyleSettingPane<T> {
public ButtonSettingPane() {
super(Arrays.asList(
StyleSetting.THEME_COLOR,
StyleSetting.STYLE_TYPE
));
}
public ButtonSettingPane(List<StyleSetting> styleSettingList) {
super(styleSettingList);
}
@Override
public void populateBean(T t) {
ButtonTheme widgetTheme = initButtonTheme(t);
populateButtonBean(widgetTheme);
}
protected ButtonTheme initButtonTheme(T t) {
ButtonTheme widgetTheme = (ButtonTheme) t.getWidgetTheme();
if (widgetTheme == null) {
widgetTheme = getButtonTheme();
updateButtonStyleBean(widgetTheme);
t.setWidgetTheme(widgetTheme);
}
return widgetTheme;
}
protected ButtonTheme getButtonTheme() {
return new ButtonTheme();
}
protected void assignFontSizePane(ButtonTheme buttonTheme) {
}
protected void assignFontSizeStyle(ButtonTheme buttonTheme) {
}
protected void populateButtonBean(ButtonTheme buttonTheme) {
if (buttonTheme.isFollowTheme()) {
styleSettingHead.setSelectedIndex(0);
} else {
styleSettingHead.setSelectedIndex(1);
colorSelectBox.setSelectObject(buttonTheme.getThemeColor());
if (buttonTheme.getStyleType() == WidgetThemeDisplayConstants.STYLE_1) {
style1.setSelected(true);
} else {
style2.setSelected(true);
}
assignFontSizePane(buttonTheme);
}
switchCard();
}
@Override
public void updateBean(T t) {
ButtonTheme widgetTheme = initButtonTheme(t);
updateCellButtonBean(widgetTheme);
}
protected void updateCellButtonBean(ButtonTheme buttonTheme) {
int selectIndex = styleSettingHead.getSelectedIndex();
buttonTheme.setFollowTheme(selectIndex == 0);
updateButtonStyleBean(buttonTheme);
}
protected void updateButtonStyleBean(ButtonTheme buttonTheme) {
buttonTheme.setThemeColor(colorSelectBox.getSelectObject());
buttonTheme.setStyleType(style1.isSelected() ? WidgetThemeDisplayConstants.STYLE_1 : WidgetThemeDisplayConstants.STYLE_2);
assignFontSizeStyle(buttonTheme);
switchCard();
}
@Override
@Nullable
public T updateBean() {
return null;
}
@Override
protected String title4PopupWindow() {
return "buttonSetting";
}
}

115
designer-form/src/main/java/com/fr/design/widgettheme/common/EditorSettingPane.java

@ -0,0 +1,115 @@
package com.fr.design.widgettheme.common;
import com.fr.widgettheme.theme.widget.style.BorderStyle;
import com.fr.design.widgettheme.BaseStyleSettingPane;
import com.fr.form.ui.Widget;
import com.fr.design.widgettheme.StyleSetting;
import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants;
import com.fr.widgettheme.theme.widget.theme.cell.EditorTheme;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
/**
* 设计器控件属性的高级设置增加主题样式设置项包括
* 文本控件/数字控件/密码控件/文本域控件/下拉框控件/下拉复选框控件/下拉树控件/日期控件
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/18
*/
public class EditorSettingPane<T extends Widget> extends BaseStyleSettingPane<T> {
public EditorSettingPane() {
super(Arrays.asList(
StyleSetting.THEME_COLOR,
StyleSetting.STYLE_TYPE,
StyleSetting.LINE_TYPE,
StyleSetting.BORDER_RADIUS
));
}
public EditorSettingPane(List<StyleSetting> styleSettingList) {
super(styleSettingList);
}
@Override
protected String title4PopupWindow() {
return "fieldEditorSetting";
}
protected void assignFontSizePane(EditorTheme widgetTheme) {
}
protected void assignFontSizeStyle(EditorTheme widgetTheme) {
}
@Override
public void populateBean(T t) {
EditorTheme widgetTheme = initEditorTheme(t);
populateEditorBean(widgetTheme);
}
protected EditorTheme initEditorTheme(T t) {
EditorTheme widgetTheme = (EditorTheme) t.getWidgetTheme();
if (widgetTheme == null) {
widgetTheme = getEditorTheme();
updateEditorStyleBean(widgetTheme);
t.setWidgetTheme(widgetTheme);
}
return widgetTheme;
}
protected EditorTheme getEditorTheme() {
return new EditorTheme();
}
protected void populateEditorBean(EditorTheme editorTheme) {
if (editorTheme.isFollowTheme()) {
styleSettingHead.setSelectedIndex(0);
} else {
styleSettingHead.setSelectedIndex(1);
colorSelectBox.setSelectObject(editorTheme.getThemeColor());
if (editorTheme.getStyleType() == WidgetThemeDisplayConstants.STYLE_1) {
style1.setSelected(true);
} else {
style2.setSelected(true);
}
lineComboBox.setSelectedLineStyle(editorTheme.getBorderStyle().getLineType());
borderRadiusSpinner.setValue(editorTheme.getBorderStyle().getRadius());
assignFontSizePane(editorTheme);
}
switchCard();
}
@Override
@Nullable
public T updateBean() {
return null;
}
@Override
public void updateBean(T t) {
EditorTheme widgetTheme = initEditorTheme(t);
updateEditorBean(widgetTheme);
}
protected void updateEditorBean(EditorTheme editorTheme) {
int selectIndex = styleSettingHead.getSelectedIndex();
editorTheme.setFollowTheme(selectIndex == 0);
updateEditorStyleBean(editorTheme);
}
protected void updateEditorStyleBean(EditorTheme editorTheme) {
editorTheme.setThemeColor(colorSelectBox.getSelectObject());
editorTheme.setStyleType(style1.isSelected() ? WidgetThemeDisplayConstants.STYLE_1 : WidgetThemeDisplayConstants.STYLE_2);
editorTheme.setBorderStyle(new BorderStyle((int) borderRadiusSpinner.getValue(), lineComboBox.getSelectedLineStyle()));
assignFontSizeStyle(editorTheme);
switchCard();
}
}

136
designer-form/src/main/java/com/fr/design/widgettheme/common/NormalButtonSettingPane.java

@ -0,0 +1,136 @@
package com.fr.design.widgettheme.common;
import com.fr.widgettheme.theme.widget.style.BorderStyle;
import com.fr.widgettheme.theme.widget.style.ButtonBackgroundStyle;
import com.fr.widgettheme.theme.bean.ButtonBackground;
import com.fr.design.widgettheme.BaseStyleSettingPane;
import com.fr.form.ui.FreeButton;
import com.fr.form.ui.Widget;
import com.fr.design.widgettheme.StyleSetting;
import com.fr.widgettheme.theme.widget.theme.cell.NormalButtonTheme;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
/**
* 设计器控件属性的高级设置增加主题样式设置项包括
* 按钮组件
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/27
*/
public class NormalButtonSettingPane<T extends Widget> extends BaseStyleSettingPane<T> {
public NormalButtonSettingPane() {
super(Arrays.asList(
StyleSetting.BTN_BACKGROUND,
StyleSetting.LINE_TYPE,
StyleSetting.BORDER_RADIUS
));
}
public NormalButtonSettingPane(List<StyleSetting> styleSettingList) {
super(styleSettingList);
}
@Override
public void populateBean(T t) {
NormalButtonTheme widgetTheme = initNormalButtonTheme(t);
if (t instanceof FreeButton && ((FreeButton) t).isCustomStyle()) {
initCustomStyle((FreeButton) t, widgetTheme);
}
populateNormalButtonBean(widgetTheme);
}
/**
* 根据freeButton自定义样式初始化widgetTheme
*/
protected void initCustomStyle(FreeButton freeButton, NormalButtonTheme widgetTheme) {
ButtonBackgroundStyle buttonBackgroundStyle = new ButtonBackgroundStyle(freeButton.getInitialBackground(), freeButton.getOverBackground(), freeButton.getClickBackground());
widgetTheme.setButtonBackgroundStyle(buttonBackgroundStyle);
widgetTheme.setFollowTheme(false);
}
protected void populateNormalButtonBean(NormalButtonTheme widgetTheme) {
if (widgetTheme.isFollowTheme()) {
styleSettingHead.setSelectedIndex(0);
} else {
styleSettingHead.setSelectedIndex(1);
lineComboBox.setSelectedLineStyle(widgetTheme.getBorderStyle().getLineType());
borderRadiusSpinner.setValue(widgetTheme.getBorderStyle().getRadius());
assignFontPane(widgetTheme);
buttonStyleDefinedPane.populate(ButtonBackground.create(widgetTheme.getButtonBackgroundStyle()));
}
switchCard();
}
protected void assignFontPane(NormalButtonTheme normalButtonTheme) {
}
protected void assignFontStyle(NormalButtonTheme normalButtonTheme) {
}
protected NormalButtonTheme initNormalButtonTheme(T t) {
NormalButtonTheme widgetTheme = (NormalButtonTheme) t.getWidgetTheme();
if (widgetTheme == null) {
widgetTheme = getDefaultNormalButtonTheme();
t.setWidgetTheme(widgetTheme);
}
return widgetTheme;
}
protected NormalButtonTheme getDefaultNormalButtonTheme() {
return new NormalButtonTheme();
}
@Override
public void updateBean(T t) {
NormalButtonTheme widgetTheme = initNormalButtonTheme(t);
int selectIndex = styleSettingHead.getSelectedIndex();
widgetTheme.setFollowTheme(selectIndex == 0);
updateNormalButtonStyleBean(widgetTheme);
if (t instanceof FreeButton) {
FreeButton freeButton = (FreeButton) t;
freeButton.setCustomStyle(!widgetTheme.isFollowTheme());
updateCustomStyle(freeButton, widgetTheme);
}
}
/**
* 更新freeButton的自定义样式
*/
protected void updateCustomStyle(FreeButton freeButton, NormalButtonTheme widgetTheme) {
ButtonBackgroundStyle backgroundStyle = widgetTheme.getButtonBackgroundStyle();
freeButton.setInitialBackground(backgroundStyle.getInitialBackground());
freeButton.setOverBackground(backgroundStyle.getOverBackground());
freeButton.setClickBackground(backgroundStyle.getClickBackground());
}
protected void updateNormalButtonStyleBean(NormalButtonTheme normalButtonTheme) {
assignFontStyle(normalButtonTheme);
normalButtonTheme.setButtonBackgroundStyle(buttonStyleDefinedPane.update());
normalButtonTheme.setBorderStyle(new BorderStyle((int) borderRadiusSpinner.getValue(), lineComboBox.getSelectedLineStyle()));
switchCard();
}
@Override
@Nullable
public T updateBean() {
return null;
}
@Override
protected String title4PopupWindow() {
return "normalButtonSetting";
}
}

107
designer-form/src/main/java/com/fr/design/widgettheme/common/TreeEditorSettingPane.java

@ -0,0 +1,107 @@
package com.fr.design.widgettheme.common;
import com.fr.design.widgettheme.StyleSetting;
import com.fr.design.widgettheme.BaseStyleSettingPane;
import com.fr.form.ui.TreeEditor;
import com.fr.widgettheme.theme.widget.theme.WidgetThemeDisplayConstants;
import com.fr.widgettheme.theme.widget.theme.cell.TreeTheme;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
/**
* 设计器控件属性的高级设置增加主题样式设置项包括
* 视图树
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/18
*/
public class TreeEditorSettingPane<T extends TreeEditor> extends BaseStyleSettingPane<T> {
public TreeEditorSettingPane() {
super(Arrays.asList(
StyleSetting.THEME_COLOR,
StyleSetting.STYLE_TYPE
));
}
public TreeEditorSettingPane(List<StyleSetting> styleSettingList) {
super(styleSettingList);
}
@Override
public void populateBean(T t) {
TreeTheme treeTheme = initEditorTheme(t);
populateTreeBean(treeTheme);
}
protected TreeTheme initEditorTheme(T t) {
TreeTheme widgetTheme = (TreeTheme) t.getWidgetTheme();
if (widgetTheme == null) {
widgetTheme = getTreeTheme();
updateTreeStyleBean(widgetTheme);
t.setWidgetTheme(widgetTheme);
}
return widgetTheme;
}
protected TreeTheme getTreeTheme() {
return new TreeTheme();
}
protected void populateTreeBean(TreeTheme treeTheme) {
if (treeTheme.isFollowTheme()) {
styleSettingHead.setSelectedIndex(0);
} else {
styleSettingHead.setSelectedIndex(1);
colorSelectBox.setSelectObject(treeTheme.getThemeColor());
if (treeTheme.getStyleType() == WidgetThemeDisplayConstants.STYLE_1) {
style1.setSelected(true);
} else {
style2.setSelected(true);
}
assignFontSizePane(treeTheme);
}
switchCard();
}
protected void assignFontSizePane(TreeTheme widgetTheme) {
}
protected void assignFontSizeStyle(TreeTheme widgetTheme) {
}
@Override
public void updateBean(T t) {
TreeTheme treeTheme = initEditorTheme(t);
updateTreeBean(treeTheme);
}
protected void updateTreeBean(TreeTheme treeTheme) {
int selectIndex = styleSettingHead.getSelectedIndex();
treeTheme.setFollowTheme(selectIndex == 0);
updateTreeStyleBean(treeTheme);
}
protected void updateTreeStyleBean(TreeTheme treeTheme) {
treeTheme.setThemeColor(colorSelectBox.getSelectObject());
treeTheme.setStyleType(style1.isSelected() ? WidgetThemeDisplayConstants.STYLE_1 : WidgetThemeDisplayConstants.STYLE_2);
assignFontSizeStyle(treeTheme);
switchCard();
}
@Override
@Nullable
public T updateBean() {
return null;
}
@Override
protected String title4PopupWindow() {
return "treeEditorSetting";
}
}

119
designer-form/src/main/java/com/fr/design/widgettheme/processor/WidgetThemeCreatorPaneAdder.java

@ -0,0 +1,119 @@
package com.fr.design.widgettheme.processor;
import com.fr.widgettheme.util.WidgetThemeDesignerUtils;
import com.fr.design.beans.BasicBeanPane;
import com.fr.form.parameter.FormSubmitButton;
import com.fr.form.ui.Button;
import com.fr.form.ui.CheckBox;
import com.fr.form.ui.CheckBoxGroup;
import com.fr.form.ui.ComboBox;
import com.fr.form.ui.ComboCheckBox;
import com.fr.form.ui.DateEditor;
import com.fr.form.ui.FreeButton;
import com.fr.form.ui.NumberEditor;
import com.fr.form.ui.Password;
import com.fr.form.ui.RadioGroup;
import com.fr.form.ui.TextArea;
import com.fr.form.ui.TextEditor;
import com.fr.form.ui.TreeComboBoxEditor;
import com.fr.form.ui.TreeEditor;
import com.fr.report.web.button.form.TreeNodeToggleButton;
import com.fr.report.web.button.write.AppendRowButton;
import com.fr.report.web.button.write.DeleteRowButton;
import com.fr.design.widgettheme.common.ButtonSettingPane;
import com.fr.design.widgettheme.common.EditorSettingPane;
import com.fr.design.widgettheme.common.NormalButtonSettingPane;
import com.fr.design.widgettheme.common.TreeEditorSettingPane;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 控件主题窗口创建处理类
* 当前类型被接受时添加对应pane到extraPaneList
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public class WidgetThemeCreatorPaneAdder {
private WidgetThemeCreatorPaneAdder() {}
/**
* editor相关处理类
*/
private static final Set<Class<?>> EDITOR_SET = new HashSet<>(Arrays.asList(
TextArea.class,
TextEditor.class,
NumberEditor.class,
Password.class,
ComboBox.class,
ComboCheckBox.class,
DateEditor.class,
TreeComboBoxEditor.class
));
/**
* normal相关处理类
*/
private static final Set<Class<?>> NORMAL_SET = new HashSet<>(Arrays.asList(
AppendRowButton.class,
FreeButton.class,
DeleteRowButton.class,
FormSubmitButton.class,
TreeNodeToggleButton.class,
Button.class
));
/**
* 遍历判断当前控件creator类型将符合条件的窗口添加到extraPaneList中
*
* @param creator 控件creator
* @param extraPaneList 列表
*/
public static <T> void add(Class<T> creator, List<BasicBeanPane<T>> extraPaneList) {
if(WidgetThemeDesignerUtils.enableWidgetEnhance()) {
acceptEditor(creator, extraPaneList);
acceptTree(creator, extraPaneList);
acceptNormal(creator, extraPaneList);
acceptButton(creator, extraPaneList);
}
}
private static <T> void insertShortCut(List<BasicBeanPane<T>> extraPaneList, BasicBeanPane pane) {
extraPaneList.add(0, pane);
}
private static <T> void acceptEditor(Class<?> creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = WidgetThemeDesignerUtils.isNewComboBoxTreeEditor(creator) || EDITOR_SET.contains(creator);
if (accept) {
insertShortCut(extraPaneList, new EditorSettingPane<>());
}
}
private static <T> void acceptTree(Class<?> creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator == TreeEditor.class;
if (accept) {
insertShortCut(extraPaneList, new TreeEditorSettingPane<>());
}
}
private static <T> void acceptNormal(Class<?> creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = NORMAL_SET.contains(creator);
if (accept) {
insertShortCut(extraPaneList, new NormalButtonSettingPane<>());
}
}
private static <T> void acceptButton(Class<?> creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator == CheckBox.class || creator == RadioGroup.class || creator == CheckBoxGroup.class;
if (accept) {
insertShortCut(extraPaneList, new ButtonSettingPane<>());
}
}
}

107
designer-form/src/main/java/com/fr/design/widgettheme/processor/WidgetThemeParaCreatorPaneAdder.java

@ -0,0 +1,107 @@
package com.fr.design.widgettheme.processor;
import com.fr.widgettheme.util.WidgetThemeDesignerUtils;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.designer.creator.XButton;
import com.fr.design.designer.creator.XCheckBox;
import com.fr.design.designer.creator.XCheckBoxGroup;
import com.fr.design.designer.creator.XComboBox;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XDateEditor;
import com.fr.design.designer.creator.XLabel;
import com.fr.design.designer.creator.XRadioGroup;
import com.fr.design.designer.creator.XTextArea;
import com.fr.design.designer.creator.XTreeComboBoxEditor;
import com.fr.design.designer.creator.XTreeEditor;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.creator.XWrapperedFieldEditor;
import com.fr.design.widgettheme.LabelSettingPane;
import com.fr.design.widgettheme.ParaButtonSettingPane;
import com.fr.design.widgettheme.ParaEditorSettingPane;
import com.fr.design.widgettheme.ParaTreeEditorSettingPane;
import com.fr.widgettheme.ParameterBackgroundStyleSettingPane;
import com.fr.design.widgettheme.common.NormalButtonSettingPane;
import java.util.List;
/**
* 参数面板控件主题窗口创建处理类
* 当前类型被接受时添加对应pane到extraPaneList
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public class WidgetThemeParaCreatorPaneAdder {
private WidgetThemeParaCreatorPaneAdder() {}
/**
* 处理对应的参数面板控件creator
* 当类型判断符合时,将扩展的pane添加到list
*
* @param creator 控件creator
* @param extraPaneList 扩展paneList
*/
public static <T> void add(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
if (WidgetThemeDesignerUtils.enableWidgetEnhance()) {
acceptEditor(creator, extraPaneList);
acceptRoot(creator, extraPaneList);
acceptTree(creator, extraPaneList);
acceptLabel(creator, extraPaneList);
acceptNormal(creator, extraPaneList);
acceptButton(creator, extraPaneList);
}
}
private static <T> void insertShortCut(List<BasicBeanPane<T>> extraPaneList, BasicBeanPane pane) {
extraPaneList.add(0, pane);
}
private static <T> void acceptEditor(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator instanceof XWrapperedFieldEditor
|| creator instanceof XTextArea
|| creator instanceof XComboBox
|| creator instanceof XDateEditor
|| creator instanceof XTreeComboBoxEditor
|| WidgetThemeDesignerUtils.isNewComboBoxTreeEditor(creator);
if (accept) {
insertShortCut(extraPaneList, new ParaEditorSettingPane<>());
}
}
private static <T> void acceptRoot(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator instanceof XWParameterLayout;
if (accept) {
insertShortCut(extraPaneList, new ParameterBackgroundStyleSettingPane());
}
}
private static <T> void acceptTree(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator instanceof XTreeEditor && !(creator instanceof XTreeComboBoxEditor);
if (accept) {
insertShortCut(extraPaneList, new ParaTreeEditorSettingPane<>());
}
}
private static <T> void acceptLabel(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator instanceof XLabel;
if (accept) {
insertShortCut(extraPaneList, new LabelSettingPane<>());
}
}
private static <T> void acceptNormal(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator instanceof XButton;
if (accept) {
insertShortCut(extraPaneList, new NormalButtonSettingPane<>());
}
}
private static <T> void acceptButton(XCreator creator, List<BasicBeanPane<T>> extraPaneList) {
boolean accept = creator instanceof XRadioGroup || creator instanceof XCheckBoxGroup || creator instanceof XCheckBox;
if (accept) {
insertShortCut(extraPaneList, new ParaButtonSettingPane<>());
}
}
}

20
designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java

@ -57,6 +57,10 @@ public class InformationCollector implements XMLReadable, XMLWriter {
*/
private static final long DELTA = 24 * 3600 * 1000L;
private static final long SEND_DELAY = 300 * 1000L;
/**
* 10分钟后再收集信息
*/
private static final long SEND_DELAY_4_ERROR_INFO = 300 * 1000L * 2;
private static final String FILE_NAME = "fr.info";
private static final String XML_START_STOP_LIST = "StartStopList";
private static final String XML_START_STOP = "StartStop";
@ -64,6 +68,8 @@ public class InformationCollector implements XMLReadable, XMLWriter {
private static final String ATTR_START = "start";
private static final String ATTR_STOP = "stop";
private static final String THREAD_NAME = "ErrorInfoCollector";
private static InformationCollector collector;
/**
@ -143,9 +149,22 @@ public class InformationCollector implements XMLReadable, XMLWriter {
*/
public void collectStartTime() {
this.current.setStartDate(dateToString());
dealWithErrorInfo();
sendInfo();
}
private void dealWithErrorInfo() {
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor(new NamedThreadFactory(THREAD_NAME));
service.schedule(() -> {
ErrorInfoUploader.getInstance().dealErrorInfo(false);
}, SEND_DELAY_4_ERROR_INFO, TimeUnit.MILLISECONDS);
service.shutdown();
}
/**
* 目前来看这些数据好像没啥用了但是还是先留着吧单独把错误信息拿出来用云端运维统一提交
*/
private void sendInfo() {
if (!DesignerEnvManager.getEnvManager().isJoinProductImprove() || !FRContext.isChineseEnv()) {
return;
@ -157,7 +176,6 @@ public class InformationCollector implements XMLReadable, XMLWriter {
SolidCollector.getInstance().sendToCloudCenterAndDeleteFile();
FocusPointMessageUploader.getInstance().sendToCloudCenter();
ChartInfoCollector.getInstance().sendPointInfo();
ErrorInfoUploader.getInstance().sendErrorInfo();
sendInfoSuccessCallback();
}, SEND_DELAY, TimeUnit.MILLISECONDS);
service.shutdown();

94
designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoUploader.java

@ -20,9 +20,10 @@ import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -37,6 +38,8 @@ public class ErrorInfoUploader {
public static final String SUFFIX = ".json";
public static final String FOLDER_NAME = "errorInfo";
private static final String CLOUD_KEY = "design.error";
private static ErrorInfoUploader collector;
// 在一台不能上网的电脑里发现了10w个errorinfo...
private static final int MAX_ERROR_SIZE = 2000;
@ -148,6 +151,15 @@ public class ErrorInfoUploader {
// 判断更新解决方案缓存.
checkUpdateSolution();
dealErrorInfo(true);
}
/**
* 处理错误信息
*
* @param needSend2Cloud 是否需要上传到云中心
*/
public void dealErrorInfo(boolean needSend2Cloud) {
//读取文件夹里的json, 加入上传队列中.
File folder = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FOLDER_NAME));
if (!folder.exists()) {
@ -164,41 +176,65 @@ public class ErrorInfoUploader {
}
try {
if (ArrayUtils.isNotEmpty(files)) {
JSONArray jsonArray = new JSONArray();
List<File> tempFiles = new ArrayList<>();
int count = 0;
for (File file : files) {
count++;
String filePath = file.getPath();
String suffix = filePath.substring(filePath.lastIndexOf("."));
if (suffix.endsWith(SUFFIX)) {
String content = IOUtils.inputStream2String(new FileInputStream(file));
if (content.length() > MAX_ERROR_SIZE) {
CommonIOUtils.deleteFile(file);
continue;
}
jsonArray.put(new JSONObject(content));
tempFiles.add(file);
if (jsonArray.length() == MAX_ITEMS || count == files.length) {
String url = CloudCenter.getInstance().acquireUrlByKind("design.error");
if (StringUtils.isBlank(url)) {
return;
}
if (sendErrorInfo(url, jsonArray)) {
deleteFiles(tempFiles);
}
jsonArray = new JSONArray();
}
dealFiles(files, needSend2Cloud);
} catch (Exception ignore) {
}
}
private void dealFiles(File[] files, boolean needSend2Cloud) throws IOException {
if (ArrayUtils.isNotEmpty(files)) {
JSONArray jsonArray = new JSONArray();
List<File> tempFiles = new ArrayList<>();
int count = 0;
for (File file : files) {
count++;
String filePath = file.getPath();
String suffix = filePath.substring(filePath.lastIndexOf("."));
if (suffix.endsWith(SUFFIX)) {
String content = IOUtils.inputStream2String(Files.newInputStream(file.toPath()));
if (content.length() > MAX_ERROR_SIZE) {
CommonIOUtils.deleteFile(file);
continue;
}
jsonArray.put(new JSONObject(content));
tempFiles.add(file);
if (jsonArray.length() == MAX_ITEMS || count == files.length) {
processInfos(jsonArray, needSend2Cloud, tempFiles);
}
}
}
} catch (Exception ignore) {
}
}
private void processInfos(JSONArray jsonArray, boolean needSend2Cloud, List<File> tempFiles) {
if (needSend2Cloud) {
String url = CloudCenter.getInstance().acquireUrlByKind(CLOUD_KEY);
if (StringUtils.isBlank(url)) {
return;
}
if (sendErrorInfo(url, jsonArray)) {
deleteFiles(tempFiles);
}
jsonArray = new JSONArray();
} else {
sendInfos4AnalysisAndClearFiles(jsonArray, tempFiles);
}
}
/**
* 提供给云端运维监听的方法(beforeExecute)
*
* @param jsonArray 要提交的信息
* @param tempFiles 要删除的文件
*/
private void sendInfos4AnalysisAndClearFiles(JSONArray jsonArray, List<File> tempFiles) {
deleteFiles(tempFiles);
}
private void deleteFiles(List<File> files) {
for (File file : files) {
CommonIOUtils.deleteFile(file);

18
designer-realize/src/main/java/com/fr/design/widget/ui/CheckBoxDefinePane.java

@ -10,11 +10,12 @@ 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.widgettheme.processor.WidgetThemeCreatorPaneAdder;
import com.fr.form.ui.CheckBox;
import com.fr.general.GeneralContext;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
@ -23,6 +24,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 复选框pane
*
* @author obo
* @version 11.0
* Created on 2023/11/13
*/
public class CheckBoxDefinePane extends AbstractDataModify<CheckBox> {
private UITextField text;
protected final List<BasicBeanPane<CheckBox>> extraPaneList = new ArrayList<>();
@ -30,6 +38,7 @@ public class CheckBoxDefinePane extends AbstractDataModify<CheckBox> {
protected static double F = TableLayout.FILL;
protected static double P = TableLayout.PREFERRED;
public CheckBoxDefinePane() {
this.iniComponents();
}
@ -60,7 +69,8 @@ public class CheckBoxDefinePane extends AbstractDataModify<CheckBox> {
protected void refreshExtraAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeCreatorPaneAdder.add(CheckBox.class, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<CheckBox>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<CheckBox> provider : providers) {
if (!provider.accept(CheckBox.class)) {
@ -89,8 +99,8 @@ public class CheckBoxDefinePane extends AbstractDataModify<CheckBox> {
/**
* 插入配置项面板
*
* @param index 插入的位置
* @param pane 配置项面板
* @param index 插入的位置
* @param pane 配置项面板
*/
protected void insertShortCut(int index, BasicBeanPane<CheckBox> pane) {
int size = extraPaneList.size();

12
designer-realize/src/main/java/com/fr/design/widget/ui/FieldEditorDefinePane.java

@ -14,11 +14,13 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.widgettheme.processor.WidgetThemeCreatorPaneAdder;
import com.fr.form.ui.FieldEditor;
import com.fr.general.GeneralContext;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
@ -30,6 +32,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 字段编辑pane
*
* @author obo
* @version 11.0
* Created on 2023/11/13
*/
public abstract class FieldEditorDefinePane<T extends FieldEditor> extends AbstractDataModify<T> {
protected UICheckBox allowBlankCheckBox;
// richer:错误信息,是所有控件共有的属性,所以放到这里来
@ -85,7 +94,8 @@ public abstract class FieldEditorDefinePane<T extends FieldEditor> extends Abstr
protected void refreshExtraAdvancedPane(Class cls) {
extraPaneList.clear();
boolean containsExtraPane = false;
WidgetThemeCreatorPaneAdder.add(cls, extraPaneList);
boolean containsExtraPane = !CollectionUtils.isEmpty(extraPaneList);
Set<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(cls)) {

2
designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

@ -143,6 +143,7 @@ import com.fr.stable.xml.ObjectXMLWriterFinder;
import com.fr.start.BBSGuestPaneProvider;
import com.fr.start.common.DesignerStartupExecutor;
import com.fr.start.common.DesignerStartupPool;
import com.fr.strongest.WidgetThemeListenerStarter;
import com.fr.task.Once;
import com.fr.workspace.WorkContext;
import com.fr.xml.ReportXMLUtils;
@ -210,6 +211,7 @@ public class DesignerActivator extends Activator implements Prepare {
storePassport();
AlphaFineHelper.switchConfig4Locale();
RecoverManager.register(new RecoverForDesigner());
WidgetThemeListenerStarter.start();
}, DesignerStartupPool.common());
CompletableFuture<Void> resourcePrepare = CompletableFuture.runAsync(() -> {

63
designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceActivator.java

@ -6,10 +6,15 @@ import com.fr.design.file.HistoryTemplateListCache;
import com.fr.event.Event;
import com.fr.event.Listener;
import com.fr.module.Activator;
import com.fr.module.ModuleContext;
import com.fr.module.engine.FineModule;
import com.fr.start.server.FineEmbedServer;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import com.fr.workspace.WorkspaceSwitchProcess;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
/**
@ -17,6 +22,46 @@ import java.util.concurrent.ExecutorService;
*/
public class DesignerWorkspaceActivator extends Activator {
private final Listener<Workspace> stopModuleAction = new Listener<Workspace>(Integer.MIN_VALUE) {
@Override
public void on(Event event, Workspace current) {
stopSub(EnvBasedModule.class);
recordModuleStop();
}
private void recordModuleStop() {
WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
Optional.ofNullable(process)
.ifPresent((e) -> e.recordModuleStopUsed(() -> {
FineModule module = (FineModule) ModuleContext.getModule(EnvBasedModule.class);
return module.profileStop();
}));
}
};
private final Listener<Workspace> startModuleAction = new Listener<Workspace>(Integer.MAX_VALUE) {
@Override
public void on(Event event, Workspace current) {
startSub(EnvBasedModule.class);
recordModuleStart();
}
private void recordModuleStart() {
WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
Optional.ofNullable(process)
.ifPresent((e) -> e.recordModuleStartUsed(() -> {
FineModule module = (FineModule) ModuleContext.getModule(EnvBasedModule.class);
return module.profile();
}));
}
};
@Override
public void start() {
@ -29,23 +74,9 @@ public class DesignerWorkspaceActivator extends Activator {
private void registerEnvListener() {
/*切换环境前,关闭所有相关模块,最后执行*/
listenEvent(WorkspaceEvent.BeforeSwitch, new Listener<Workspace>(Integer.MIN_VALUE) {
@Override
public void on(Event event, Workspace current) {
stopSub(EnvBasedModule.class);
}
});
listenEvent(WorkspaceEvent.BeforeSwitch, stopModuleAction);
/*切换环境后,重新启动所有相关模块,最先执行*/
listenEvent(WorkspaceEvent.AfterSwitch, new Listener<Workspace>(Integer.MAX_VALUE) {
@Override
public void on(Event event, Workspace current) {
startSub(EnvBasedModule.class);
}
});
listenEvent(WorkspaceEvent.AfterSwitch, startModuleAction);
/*切换环境前,存储一下打开的所有文件对象,要先于 关闭相关模块部分 被触发*/
listenEvent(WorkspaceEvent.BeforeSwitch, new Listener<Workspace>(Integer.MAX_VALUE) {

67
designer-realize/src/main/java/com/fr/strongest/WidgetThemeListenerStarter.java

@ -0,0 +1,67 @@
package com.fr.strongest;
import com.finebi.cbb.utils.StringUtils;
import com.fr.base.io.BaseBook;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.JTemplateEvent;
import com.fr.design.mainframe.JWorkBook;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.module.ModuleContext;
import com.fr.widgettheme.control.attr.WidgetDisplayEnhanceMarkAttr;
/**
* 控件属性增强监听器启动类
*
* @author obo
* @since 11.0
* Created on 2023/11/13
*/
public class WidgetThemeListenerStarter {
private WidgetThemeListenerStarter(){}
/**
* 启动对模版控件主题显示的监听开关
*/
public static void start() {
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
init();
}
});
}
private static void init() {
Listener<JTemplate> attrListener = new Listener<JTemplate>() {
@Override
public void on(Event event, JTemplate temp) {
dealWithJTemplate4Attr(temp);
}
};
if (ModuleContext.isDesignerStartup()) {
EventDispatcher.listen(JTemplateEvent.BEFORE_TEMPLATE_INIT, attrListener);
}
}
private static void dealWithJTemplate4Attr(JTemplate temp) {
if (temp instanceof JWorkBook || temp instanceof JForm) {
BaseBook workBook = (BaseBook) temp.getTarget();
if (isNeedAddAttr(temp, workBook)) {
WidgetDisplayEnhanceMarkAttr attr = new WidgetDisplayEnhanceMarkAttr();
attr.setWidgetEnhance(true);
workBook.addAttrMark(attr);
}
}
}
private static boolean isNeedAddAttr(JTemplate temp, BaseBook workBook) {
// 模板为新建模板(temp.isNewCreateTpl没法用,此时还没赋值)
return (StringUtils.isEmpty(workBook.getTemplateID()) || temp.isNewCreateTpl()) &&
workBook.getAttrMark(WidgetDisplayEnhanceMarkAttr.XML_TAG) == null;
}
}
Loading…
Cancel
Save