Browse Source

Merge pull request #12513 in DESIGN/design from release/11.0 to final/11.0

* commit '370b371a0ee4e621f273996d7a0b5fcb71b817da': (101 commits)
  REPORT-101478 【版本管理二期】部分配置项默认没有勾选
  REPORT-101483 【版本管理二期】数据迁移提示的弹窗以设备中央为准
  REPORT-98345 版本管理三期 迁移成功后,没刷新工具栏
  REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭 修改方法名
  REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭 修改方法名
  REPORT-100458 【版本管理二期】迁移弹窗,保留版本的输入框没有非法值校验
  REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭
  REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭
  REPORT-91839 模板版本管理二期 没设置启动页,启动的时候判断有点问题
  REPORT-100518 【版本管理二期】无磁盘写入权限,版本迁移无异常提示
  REPORT-101340 【版本管理二期】自动清理配置灰化时,hover提示没有
  REPORT-101060 【版本管理三期】删除无权限的版本,能删除成功
  REPORT-101166 【版本管理三期】集群环境,版本管理页面所有配置项都不可点
  REPORT-100954 【版本管理三期】版本中心弹窗交互问题
  REPORT-91839 模板版本管理二期 偶遇报错,不确定场景,加一下处理
  REPORT-101167 【版本管理一期】集群环境,保存版本不生效
  REPORT-100162 【版本管理二期】模板不在编辑状态,还是在触发自动保存
  REPORT-100633 【版本管理二期】取消勾选备注的版本不会被清理,备注的版本还是不会被清理
  REPORT-101289 【版本管理二期】数据迁移的提示弹窗位置没有居中
  REPORT-101293 【版本管理二期】模板未打开,点击版本管理点不开
  ...
new-design
superman 1 year ago
parent
commit
c1049a2f98
  1. 276
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  2. 6
      designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java
  3. 1
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java
  4. 20
      designer-base/src/main/java/com/fr/design/dialog/BasicPane.java
  5. 10
      designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java
  6. 2
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java
  7. 19
      designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java
  8. 80
      designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java
  9. 8
      designer-base/src/main/java/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java
  10. 19
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java
  11. 15
      designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java
  12. 7
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  13. 102
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java
  14. 8
      designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java
  15. 9
      designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java
  16. 31
      designer-base/src/main/java/com/fr/design/mainframe/vcs/RecycleAction.java
  17. 25
      designer-base/src/main/java/com/fr/design/mainframe/vcs/TableEntity.java
  18. 21
      designer-base/src/main/java/com/fr/design/mainframe/vcs/TableValueOperator.java
  19. 25
      designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsConfigManager.java
  20. 37
      designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsExceptionUtils.java
  21. 291
      designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsOperatorWorker.java
  22. 49
      designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsRecycleSettingHelper.java
  23. 113
      designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsTableEntity.java
  24. 239
      designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java
  25. 407
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/AbstractSupportSelectTablePane.java
  26. 26
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/EditFileVersionDialog.java
  27. 368
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecyclePane.java
  28. 103
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecycleSettingPane.java
  29. 32
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/ToolTipTableCellRenderer.java
  30. 59
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntEditor.java
  31. 39
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntSpinner.java
  32. 156
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsBatchProcessDetailPane.java
  33. 35
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellEditor.java
  34. 29
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellRender.java
  35. 227
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCenterPane.java
  36. 489
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovePanel.java
  37. 54
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovingExitOption.java
  38. 350
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsNewPane.java
  39. 40
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsOperatorPane.java
  40. 81
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsProgressDialog.java
  41. 13
      designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java
  42. 20
      designer-base/src/main/java/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java
  43. 4
      designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java
  44. 4
      designer-base/src/main/resources/com/fr/design/images/buttonicon/new_other_normal.svg
  45. 5
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_center_manager_normal.svg
  46. 5
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_center_open_normal.svg
  47. 7
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_operator_delete_normal.svg
  48. 5
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_operator_preview_normal.svg
  49. 5
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_operator_restore_normal.svg
  50. 7
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_delete_disabled.svg
  51. 7
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_delete_normal.svg
  52. 8
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_normal.svg
  53. 5
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_restore_disabled.svg
  54. 5
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_restore_normal.svg
  55. 3
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_search_normal.svg
  56. 4
      designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_sort_normal.svg
  57. 5
      designer-base/src/main/resources/com/fr/design/vcs/move_failed.svg
  58. 5
      designer-base/src/main/resources/com/fr/design/vcs/move_success.svg
  59. 3
      designer-base/src/main/resources/com/fr/design/vcs/vcs_move_icon.svg
  60. 29
      designer-base/src/test/java/com/fr/base/ClassHelperTest.java
  61. 2
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java
  62. 8
      designer-form/src/main/java/com/fr/design/actions/NewFormAction.java
  63. 27
      designer-form/src/main/java/com/fr/design/designer/creator/XEditorHolder.java
  64. 23
      designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java
  65. 2
      designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java
  66. 2
      designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FormWidgetValuePane.java
  67. 40
      designer-form/src/test/java/com/fr/design/mainframe/template/info/JFormProcessInfoTest.java
  68. 14
      designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java
  69. 8
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  70. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs1.png
  71. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs2.png
  72. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs3.png
  73. BIN
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs4.png
  74. 160
      designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/template_resource/local_templates.json
  75. 6
      designer-realize/src/test/java/com/fr/nx/app/designer/CptxAppTest.java

276
designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java

@ -36,6 +36,8 @@ import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.mainframe.vcs.ui.UIPositiveIntEditor;
import com.fr.design.mainframe.vcs.ui.VcsMovePanel;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.unit.UnitConvertUtil;
import com.fr.design.utils.gui.GUICoreUtils;
@ -49,14 +51,22 @@ import com.fr.io.attr.ImageExportAttr;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.report.ReportConfigManager;
import com.fr.scheduler.tool.FineScheduler;
import com.fr.stable.Constants;
import com.fr.stable.os.OperatingSystem;
import com.fr.third.apache.logging.log4j.Level;
import com.fr.third.guava.collect.BiMap;
import com.fr.third.guava.collect.HashBiMap;
import com.fr.transaction.Configurations;
import com.fr.transaction.Worker;
import com.fr.transaction.WorkerAdaptor;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsConfig;
import com.fr.workspace.server.vcs.VcsOperator;
import com.fr.workspace.server.vcs.git.config.GcConfig;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanOperator;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanSchedule;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanService;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
@ -77,14 +87,7 @@ import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Window;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
@ -95,6 +98,7 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@ -122,6 +126,7 @@ public class PreferencePane extends BasicPane {
private static final int PREFERENCE_LABEL_MAX_WIDTH = 460;
private static final int OFFSET_HEIGHT = 60;
private static final int VCS_FILL_TOTAL = 5;
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
private static final String BACK_SLASH = "BACK_SLASH";
@ -149,6 +154,34 @@ public class PreferencePane extends BasicPane {
private static final Level[] LOG = {Level.FATAL, Level.ERROR, Level.WARN, Level.INFO, Level.DEBUG};
private static final int ONE_DAY_INT = 1;
private static final int ONE_WEEK_INT = 7;
private static final int ONE_MONTH_INT = 30;
private static final int THREE_MONTH_INT = 90;
private static final int SIX_MONTH_INT = 180;
private static final int ONE_DAY_INDEX = 0;
private static final int ONE_WEEK_INDEX = 1;
private static final int ONE_MONTH_INDEX = 2;
private static final int THREE_MONTH_INDEX = 3;
private static final int SIX_MONTH_INDEX = 4;
private static final String ONE_DAY = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_ONE_DAY");
private static final String ONE_WEEK = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_ONE_WEEK");
private static final String ONE_MONTH = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_ONE_MONTH");
private static final String THREE_MONTH = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_THREE_MONTH");
private static final String SIX_MONTH = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_SIX_MONTH");
private static final String[] INTERVAL = {
ONE_DAY,
ONE_WEEK,
ONE_MONTH,
THREE_MONTH,
SIX_MONTH
};
private static final int DEFAULT_INDEX = 3;
private BasicDialog basicDialog;
private boolean languageChanged; // 是否修改了设计器语言设置
//设置是否支持undo
private UICheckBox supportUndoCheckBox;
@ -186,10 +219,24 @@ public class PreferencePane extends BasicPane {
private UICheckBox cloudAnalyticsDelayCheckBox;
private UICheckBox vcsEnableCheckBox;
private UICheckBox useVcsAutoSaveScheduleCheckBox;
private UICheckBox useVcsAutoCleanScheduleCheckBox;
private UIComboBox autoCleanIntervalComboBox;
private UIComboBox autoCleanRetainIntervalComboBox;
private UIPositiveIntEditor autoSaveIntervalEditor;
private UICheckBox saveCommitCheckBox;
private UICheckBox useIntervalCheckBox;
private VcsMovePanel movePanel;
private JPanel saveIntervalPane;
private JPanel autoCleanPane;
private JPanel gcControlPane;
private UICheckBox startupPageEnabledCheckBox;
private IntegerEditor saveIntervalEditor;
private UIPositiveIntEditor saveIntervalEditor;
private UICheckBox gcEnableCheckBox;
private UIButton gcButton;
private UILabel remindVcsLabel;
@ -209,7 +256,15 @@ public class PreferencePane extends BasicPane {
private UIRadioButton previewRenderQuality;
private static final int DPI_SCALE_S = 1;
private static final int DPI_SCALE_M = 2;
private static final BiMap<Integer, Integer> INDEX_DAY_MAP = HashBiMap.create(new HashMap<Integer, Integer>() {
{
put(ONE_DAY_INDEX, ONE_DAY_INT);
put(ONE_WEEK_INDEX, ONE_WEEK_INT);
put(ONE_MONTH_INDEX, ONE_MONTH_INT);
put(SIX_MONTH_INDEX, SIX_MONTH_INT);
put(THREE_MONTH_INDEX, THREE_MONTH_INT);
}
});
public PreferencePane() {
this.initComponents();
}
@ -227,13 +282,26 @@ public class PreferencePane extends BasicPane {
JPanel advancePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
UIScrollPane adviceScrollPane = patchScroll(advancePane);
jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), adviceScrollPane);
//初始化vcs总面板
JPanel vcsParentPane = new JPanel();
CardLayout cardLayout = new CardLayout();
vcsParentPane.setLayout(cardLayout);
//vcs配置面板
JPanel vcsPane = new JPanel(new BorderLayout());
//添加滚动条
UIScrollPane vcsScrollPane = patchScroll(vcsPane);
//配置面板作为vcs总面板的一张卡片
vcsParentPane.add(vcsScrollPane, VcsMovePanel.SETTING);
jtabPane.addTab(i18nText("Fine-Design_Vcs_Title"), vcsParentPane);
contentPane.add(jtabPane, BorderLayout.NORTH);
createFunctionPane(generalPane);
createEditPane(generalPane);
createColorSettingPane(generalPane);
createVcsSettingPane(generalPane);
// vcsPane
createVcsSettingPane(vcsPane, vcsParentPane, cardLayout);
// ConfPane
JPanel confLocationPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
@ -345,21 +413,33 @@ public class PreferencePane extends BasicPane {
return generalPanelWithScroll;
}
private void createVcsSettingPane(JPanel generalPane) {
JPanel vcsPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Title"));
generalPane.add(vcsPane);
private void createVcsSettingPane(JPanel generalPane,JPanel parentPane, CardLayout cardLayout) {
//迁移面板
movePanel = createMovePane(cardLayout, parentPane);
generalPane.add(movePanel, BorderLayout.NORTH);
JPanel savePane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Save_Setting"));
JPanel vcsPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Clean_Setting"));
JPanel containPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
containPane.add(savePane);
containPane.add(vcsPane);
//填充一下面板
fillPane(containPane, VCS_FILL_TOTAL);
generalPane.add(containPane, BorderLayout.CENTER);
remindVcsLabel = new UILabel(i18nText("Fine-Design_Vcs_Remind"));
remindVcsLabel.setVisible(!VcsHelper.getInstance().needInit());
vcsEnableCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_SaveAuto"));
saveIntervalPane = createSaveIntervalPane();
saveCommitCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_No_Delete"));
saveIntervalEditor = new IntegerEditor(60);
saveIntervalEditor = new UIPositiveIntEditor(60);
useIntervalCheckBox = new UICheckBox();
savePane.add(vcsEnableCheckBox);
savePane.add(saveIntervalPane);
//gc面板
JPanel gcControlPane = createGcControlPane();
gcControlPane = createGcControlPane();
JPanel enableVcsPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
enableVcsPanel.add(vcsEnableCheckBox);
enableVcsPanel.add(remindVcsLabel);
JPanel intervalPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
final UILabel everyLabel = new UILabel(i18nText("Fine-Design_Vcs_Every"));
@ -368,6 +448,8 @@ public class PreferencePane extends BasicPane {
intervalPanel.add(everyLabel);
intervalPanel.add(saveIntervalEditor);
intervalPanel.add(delayLabel);
autoCleanPane = createAutoCleanPane();
checkAutoScheduleStartAndUpdateStatus();
vcsEnableCheckBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
@ -389,10 +471,104 @@ public class PreferencePane extends BasicPane {
});
vcsPane.add(enableVcsPanel);
vcsPane.add(intervalPanel);
vcsPane.add(saveCommitCheckBox);
vcsPane.add(gcControlPane);
if (VcsHelper.getInstance().isLegacyMode()) {
vcsPane.add(saveCommitCheckBox);
}
vcsPane.add(autoCleanPane);
boolean support = VcsHelper.getInstance().checkV2FunctionSupport();
saveIntervalPane.setVisible(support);
autoCleanPane.setVisible(support);
if (VcsHelper.getInstance().isLegacyMode()) {
// 老版本时才显示gc选项
vcsPane.add(gcControlPane);
}
}
private void fillPane(JPanel containPane, int total) {
for (int i = 0; i < total; i++) {
containPane.add(new JPanel());
}
}
private VcsMovePanel createMovePane(CardLayout cardLayout, JPanel parentPane) {
return new VcsMovePanel(cardLayout, parentPane, new VcsMovePanel.MoveCallBack(){
@Override
public void doCallBack(boolean useV2) {
saveIntervalPane.setVisible(useV2);
autoCleanPane.setVisible(useV2);
gcControlPane.setVisible(!useV2);
saveCommitCheckBox.setVisible(!useV2);
useVcsAutoCleanScheduleCheckBox.setSelected(useV2);
useVcsAutoSaveScheduleCheckBox.setSelected(useV2);
checkAutoScheduleStartAndUpdateStatus();
useVcsAutoSaveScheduleCheckBox.setEnabled(useV2);
}
}, basicDialog);
};
private JPanel createAutoCleanPane() {
JPanel autoCleanPane = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
useVcsAutoCleanScheduleCheckBox = new UICheckBox();
autoCleanIntervalComboBox = new UIComboBox(INTERVAL);
autoCleanIntervalComboBox.setSelectedIndex(DEFAULT_INDEX);
autoCleanRetainIntervalComboBox = new UIComboBox(INTERVAL);
autoCleanRetainIntervalComboBox.setSelectedIndex(DEFAULT_INDEX);
autoCleanPane.add(useVcsAutoCleanScheduleCheckBox);
autoCleanPane.add(new UILabel(i18nText("Fine-Design_Vcs_Auto_Clean_Every")));
autoCleanPane.add(autoCleanIntervalComboBox);
autoCleanPane.add(new UILabel(i18nText("Fine-Design_Vcs_Auto_Clean_Content")));
autoCleanPane.add(autoCleanRetainIntervalComboBox);
autoCleanPane.add(new UILabel(i18nText("Fine-Design_Vcs_Auto_Clean_Last")));
autoCleanPane.setVisible(false);
return autoCleanPane;
}
private void checkAutoScheduleStartAndUpdateStatus() {
if (!VcsHelper.getInstance().isLegacyMode()) {
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
return WorkContext.getCurrent().get(VcsAutoCleanOperator.class).isSupport();
}
@Override
protected void done() {
try {
boolean useAutoClean = get();
updateAutoCleanEnabled(useAutoClean);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}.execute();
} else {
updateAutoCleanEnabled(false);
}
}
private void updateAutoCleanEnabled(boolean b) {
useVcsAutoCleanScheduleCheckBox.setEnabled(b);
autoCleanIntervalComboBox.setEnabled(b);
autoCleanRetainIntervalComboBox.setEnabled(b);
if (autoCleanPane != null) {
autoCleanPane.setToolTipText(b ? null : Toolkit.i18nText("Fine-Design_Vcs_Server_Start_Hover"));
}
}
private JPanel createSaveIntervalPane() {
JPanel saveIntervalPane = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
useVcsAutoSaveScheduleCheckBox = new UICheckBox();
autoSaveIntervalEditor = new UIPositiveIntEditor(60);
saveIntervalPane.add(useVcsAutoSaveScheduleCheckBox);
saveIntervalPane.add(new UILabel(i18nText("Fine-Design_Vcs_Every")));
saveIntervalPane.add(autoSaveIntervalEditor);
saveIntervalPane.add(new UILabel(i18nText("Fine-Design_Vcs_Save_Delay")));
useVcsAutoSaveScheduleCheckBox.setEnabled(!VcsHelper.getInstance().isLegacyMode());
saveIntervalPane.setVisible(false);
return saveIntervalPane;
}
/**
* 模创建板版本gc 配置操作面板
*
@ -773,7 +949,8 @@ public class PreferencePane extends BasicPane {
defaultStringToFormulaBox.setSelected(false);
}
VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager();
if (WorkContext.getCurrent().isCluster()) {
//如果是集群并且是老版本则不可用
if (VcsHelper.getInstance().isLegacyMode() && WorkContext.getCurrent().isCluster()) {
vcsEnableCheckBox.setEnabled(false);
gcEnableCheckBox.setEnabled(false);
}
@ -796,6 +973,12 @@ public class PreferencePane extends BasicPane {
gcEnableCheckBox.setSelected(GcConfig.getInstance().isGcEnable());
gcButton.setEnabled(gcEnableCheckBox.isSelected());
useVcsAutoSaveScheduleCheckBox.setSelected(vcsConfigManager.isUseAutoSave());
useVcsAutoCleanScheduleCheckBox.setSelected(VcsConfig.getInstance().isUseV2AutoClean());
autoSaveIntervalEditor.setValue(vcsConfigManager.getAutoSaveInterval());
autoCleanIntervalComboBox.setSelectedIndex(getIndex(VcsConfig.getInstance().getV2CleanInterval()));
autoCleanRetainIntervalComboBox.setSelectedIndex(getIndex(VcsConfig.getInstance().getV2RetainInterval()));
gridLineColorTBButton.setColor(designerEnvManager.getGridLineColor());
paginationLineColorTBButton.setColor(designerEnvManager.getPaginationLineColor());
@ -883,6 +1066,14 @@ public class PreferencePane extends BasicPane {
}
}
private int getDay(int dateIndex) {
return INDEX_DAY_MAP.getOrDefault(dateIndex, THREE_MONTH_INT);
}
private int getIndex(int day) {
return INDEX_DAY_MAP.inverse().getOrDefault(day, THREE_MONTH_INDEX);
}
/**
* The method of update.
*/
@ -931,6 +1122,17 @@ public class PreferencePane extends BasicPane {
vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected());
vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected());
vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected());
vcsConfigManager.setUseAutoSave(this.useVcsAutoSaveScheduleCheckBox.isSelected());
vcsConfigManager.setAutoSaveInterval(this.autoSaveIntervalEditor.getValue());
Configurations.update(new WorkerAdaptor(VcsConfig.class) {
@Override
public void run() {
VcsConfig.getInstance().setUseV2AutoClean(useVcsAutoCleanScheduleCheckBox.isSelected());
VcsConfig.getInstance().setV2CleanInterval(getDay(autoCleanIntervalComboBox.getSelectedIndex()));
VcsConfig.getInstance().setV2RetainInterval(getDay(autoCleanRetainIntervalComboBox.getSelectedIndex()));
}
});
dealWithSchedule();
designerEnvManager.setStartupPageEnabled(this.startupPageEnabledCheckBox.isSelected());
Configurations.update(new Worker() {
@Override
@ -1005,6 +1207,36 @@ public class PreferencePane extends BasicPane {
}
private void dealWithSchedule() {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
boolean v2FunctionSupport = VcsHelper.getInstance().checkV2FunctionSupport();
if (v2FunctionSupport) {
//如果支持V2
if (useVcsAutoSaveScheduleCheckBox.isSelected()) {
FineLoggerFactory.getLogger().info("[VcsV2] start auto save!");
VcsHelper.getInstance().startAutoSave(autoSaveIntervalEditor.getValue());
} else {
VcsHelper.getInstance().stopAutoSave();
}
if (useVcsAutoCleanScheduleCheckBox.isEnabled()) {
if (useVcsAutoCleanScheduleCheckBox.isSelected()) {
FineLoggerFactory.getLogger().info("[VcsV2] start auto clean!");
WorkContext.getCurrent().get(VcsAutoCleanOperator.class).addOrUpdateVcsAutoCleanJob(
VcsAutoCleanService.VCS_AUTO_CLEAN_JOB_NAME,
getDay(autoCleanIntervalComboBox.getSelectedIndex()),
VcsAutoCleanSchedule.class);
} else {
WorkContext.getCurrent().get(VcsAutoCleanOperator.class).stopVcsAutoCleanJob(VcsAutoCleanService.VCS_AUTO_CLEAN_JOB_NAME);
}
}
}
return null;
}
}.execute();
}
// 如果语言设置改变了,则显示重启对话框
public void showRestartDialog() {
if (!languageChanged) {
@ -1033,12 +1265,14 @@ public class PreferencePane extends BasicPane {
@Override
public BasicDialog showWindow(Window window) {
return showWindow(window, new DialogActionAdapter() {
basicDialog = showWindow(window, new DialogActionAdapter() {
@Override
public void doOk() {
languageChanged = !ComparatorUtils.equals(languageComboBox.getSelectedItem(), DesignerEnvManager.getEnvManager(false).getLanguage());
}
});
movePanel.setParentDialog(basicDialog);
return basicDialog;
}
@Override

6
designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java

@ -7,6 +7,7 @@ import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.SaveSomeTemplatePane;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.vcs.ui.VcsMovingExitOption;
import com.fr.design.menu.KeySetUtils;
import com.fr.design.menu.MenuDef;
import com.fr.design.menu.SeparatorDef;
@ -60,6 +61,11 @@ public class SwitchExistEnv extends MenuDef {
* @param e 事件
*/
public void actionPerformed(ActionEvent e) {
//检查是否正在迁移,如果正在迁移就弹出弹窗让用户选择
if (!VcsMovingExitOption.ShowDialogAndConfirmSwitch()) {
//如果用户选择取消切换环境则返回,不然说明用户就是想切换,则往下走
return;
}
final String envName = getName();
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
DesignerWorkspaceInfo selectedEnv = envManager.getWorkspaceInfo(envName);

1
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java

@ -294,6 +294,7 @@ public class MultiTDTableDataPane extends AbstractTableDataPane<MultiTDTableData
tmp = tmp + "...";
tabledataName = new UILabel(tmp);
}
tabledataName.setToolTipText(name);
UILabel iconLabel = new UILabel(icon);
chekbox.addActionListener(tableDataCheckboxListener);
iconLabel.addMouseListener(chooseTableDataListener);

20
designer-base/src/main/java/com/fr/design/dialog/BasicPane.java

@ -75,6 +75,26 @@ public abstract class BasicPane extends JPanel {
return dg;
}
/**
* 显示小窗口并允许自定义需不需要按钮
*
* @param window 窗口
* @param isNeedButtonsPane 是否需要确定删除按钮
* @return 对话框
*/
public BasicDialog showSmallWindow(Window window, boolean isNeedButtonsPane) {
BasicDialog dg;
if (window instanceof Frame) {
dg = new DIALOG((Frame) window, isNeedButtonsPane);
} else {
dg = new DIALOG((Dialog) window, isNeedButtonsPane);
}
dg.setBasicDialogSize(BasicDialog.SMALL);
GUICoreUtils.centerWindow(dg);
dg.setResizable(false);
return dg;
}
/**
* 图表类型选择时 弹出的按钮大小, 不适合用最大最小, 因为图表大小 默认是规定好的, 那么界面大小也是必须配合.

10
designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java

@ -38,7 +38,7 @@ public abstract class NumberEditor<T extends Number> extends Editor<T> {
*/
public NumberEditor(T value, String name) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
numberField = new UINumberField();
numberField = createNumberField();
this.add(numberField, BorderLayout.CENTER);
this.numberField.addKeyListener(textKeyListener);
this.numberField.setHorizontalAlignment(UITextField.RIGHT);
@ -46,6 +46,14 @@ public abstract class NumberEditor<T extends Number> extends Editor<T> {
this.setName(name);
}
/**
* 创建NumberField对象
*
*/
protected UINumberField createNumberField() {
return new UINumberField();
}
/**
* 给numberField加键盘事件
*

2
designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java

@ -419,7 +419,7 @@ public class MultiTemplateTabPane extends JComponent {
public void closeOtherByOperatorType(String operatorType){
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false);
if (saveSomeTempaltePane.showSavePane()) {
if (saveSomeTempaltePane.showSavePane(null, false, true)) {
List<JTemplate<?, ?>> openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList();
JTemplate<?, ?>[] templates = new JTemplate<?, ?>[openedTemplate.size()];

19
designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java

@ -183,7 +183,19 @@ public class SaveSomeTemplatePane extends BasicPane {
* @return
*/
public boolean showSavePane(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave) {
initAndPopulate(option, judgeJTemplateMustSave);
return showSavePane(option, judgeJTemplateMustSave, false);
}
/**
* 显示保存模板提醒面板
*
* @param option 具体关闭操作
* @param judgeJTemplateMustSave 模板是否必须保存
* @param judgeSameTabType 是否只包含当前编辑的模板类型
* @return
*/
public boolean showSavePane(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave, boolean judgeSameTabType) {
initAndPopulate(option, judgeJTemplateMustSave, judgeSameTabType);
//如果有未保存的文件 ,则跳出保存对话框,选择要存储的项目
if (!unSavedTemplate.isEmpty()) {
dialog.setVisible(true);
@ -197,13 +209,16 @@ public class SaveSomeTemplatePane extends BasicPane {
return HistoryTemplateListPane.getInstance().getHistoryList();
}
private void initAndPopulate(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave) {
private void initAndPopulate(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave, boolean judgeSameTabType) {
java.util.List<JTemplate<?, ?>> opendedTemplate = getOpenedTemplatesToProcess();
JTemplate<?, ?> currentTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
int currentIndex = opendedTemplate.indexOf(currentTemplate);
for (int i = 0; i < opendedTemplate.size(); i++) {
//满足关闭条件的才继续判断文件是否发生了改动
boolean needClose = option == null || option.shouldClose(opendedTemplate.get(i), currentIndex, i);
if (judgeSameTabType) {
needClose &= ComparatorUtils.equals(opendedTemplate.get(i).getTemplateTabOperatorType(), currentTemplate.getTemplateTabOperatorType());
}
if (needClose && isneedToAdd(opendedTemplate.get(i), currentTemplate)) {
unSavedTemplate.add(opendedTemplate.get(i));
}

80
designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java

@ -18,6 +18,7 @@ import com.fr.design.lock.LockInfoDialog;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager;
import com.fr.design.mainframe.manager.search.searcher.control.pane.TemplateSearchRemindPane;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
@ -38,6 +39,7 @@ import java.util.UUID;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
@ -59,8 +61,10 @@ import java.util.Objects;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import com.fr.workspace.server.vcs.VcsOperator;
import org.jetbrains.annotations.Nullable;
@ -346,13 +350,7 @@ public class TemplateTreePane extends JPanel implements FileOperations {
YES_NO_OPTION)
== JOptionPane.YES_OPTION) {
// 删除所有选中的即可
if (!deleteNodes(Arrays.asList(treeNodes))) {
FineJOptionPane.showConfirmDialog(null,
Toolkit.i18nText("Fine-Design_Basic_Delete_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE);
}
deleteNodes(Arrays.asList(treeNodes));
}
} else {
@ -377,17 +375,9 @@ public class TemplateTreePane extends JPanel implements FileOperations {
YES_NO_OPTION)
== JOptionPane.YES_OPTION) {
// 删除其他
if (!deleteNodes(deletableNodes)) {
FineJOptionPane.showConfirmDialog(null,
Toolkit.i18nText("Fine-Design_Basic_Delete_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE);
}
deleteNodes(deletableNodes);
}
}
Set<FileNode> deletedFileNode = deletableNodes.stream().map(treeNode -> (FileNode) treeNode.getUserObject()).collect(Collectors.toSet());
refreshAfterDelete(deletedFileNode);
}
private void refreshAfterDelete(Set<FileNode> deletedPaths) {
@ -407,23 +397,53 @@ public class TemplateTreePane extends JPanel implements FileOperations {
}
}
private boolean deleteNodes(Collection<ExpandMutableTreeNode> nodes) {
boolean success = true;
for (ExpandMutableTreeNode treeNode : nodes) {
Object node = treeNode.getUserObject();
if (node instanceof FileNode) {
FileNodeFILE nodeFILE = new FileNodeFILE((FileNode) node);
if (nodeFILE.exists()) {
if (TemplateResourceManager.getResource().delete(nodeFILE)) {
HistoryTemplateListCache.getInstance().deleteFile(nodeFILE);
} else {
success = false;
private void deleteNodes(Collection<ExpandMutableTreeNode> nodes) {
new SwingWorker<Boolean,Void>(){
@Override
protected Boolean doInBackground() throws Exception {
boolean success = true;
for (ExpandMutableTreeNode treeNode : nodes) {
Object node = treeNode.getUserObject();
if (node instanceof FileNode) {
FileNodeFILE nodeFILE = new FileNodeFILE((FileNode) node);
if (nodeFILE.exists()) {
try {
WorkContext.getCurrent().get(VcsOperator.class).recycleVersion(VcsHelper.getInstance().getCurrentUsername(), VcsHelper.getInstance().dealWithFilePath(((FileNode) node).getEnvPath()));
} catch (Exception e) {
FineLoggerFactory.getLogger().error("[VcsV2] recycle {} failed", nodeFILE.getName());
return false;
}
if (TemplateResourceManager.getResource().delete(nodeFILE)) {
HistoryTemplateListCache.getInstance().deleteFile(nodeFILE);
} else {
success = false;
}
}
}
}
return success;
}
}
return success;
@Override
protected void done() {
try {
if (!get()) {
showErrorDialog();
}
Set<FileNode> deletedFileNode = nodes.stream().map(treeNode -> (FileNode) treeNode.getUserObject()).collect(Collectors.toSet());
refreshAfterDelete(deletedFileNode);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
private void showErrorDialog() {
FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Delete_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE);
}

8
designer-base/src/main/java/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java

@ -8,12 +8,14 @@
*/
package com.fr.design.gui.autocomplete;
import com.fr.stable.StringUtils;
import javax.swing.text.JTextComponent;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.text.JTextComponent;
/**
@ -186,7 +188,9 @@ public abstract class AbstractCompletionProvider
while (index<completions.size()) {
Completion c = completions.get(index);
if (Util.startsWithIgnoreCase(c.getInputText(), text)) {
String inputText = c.getInputText();
//当输入文本和补全项相等时,不再添加到补全项到窗口中
if (Util.startsWithIgnoreCase(inputText, text) && !StringUtils.equals(inputText, text)) {
retVal.add(c);
index++;
}

19
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java

@ -1,12 +1,10 @@
package com.fr.design.gui.autocomplete;
import com.fr.design.formula.FormulaPane;
import com.fr.stable.StringUtils;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
import java.awt.Window;
/**
* @author Hoky
@ -70,9 +68,18 @@ public class FormulaPaneAutoCompletion extends AutoCompletionWithExtraRefresh {
caret.setDot(start);
caret.moveDot(dot);
if (FormulaPane.containsParam(replacement)) {
textComp.replaceSelection(FormulaPane.getParamPrefix(replacement) + replacement);
int caretPosition = textComp.getCaretPosition();
textComp.setCaretPosition(caretPosition);
String selectedText = textComp.getSelectedText();
//找到选择文本(光标输入位置dot)进行补全
String text = textComp.getText().substring(0, dot);
int index = text.lastIndexOf(selectedText);
//获取replacement的前缀,replacement是不带前缀的,例如变量$$page_number,获取到的replacement是page_number
String paramPrefix = FormulaPane.getParamPrefix(replacement);
//当选择文本之前有和param前缀相同大小的字符串时,截取对比一下,如果内容相同,则前缀已经存在,不用再拼接了
String prefix = (index >= paramPrefix.length()) ? text.substring(index - paramPrefix.length(), index) : StringUtils.EMPTY;
if (!FormulaPane.getParamPrefix(replacement).equals(prefix)) {
replacement = paramPrefix + replacement;
}
textComp.replaceSelection(replacement);
} else {
textComp.replaceSelection(replacement + "()");
int caretPosition = textComp.getCaretPosition();

15
designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java

@ -4,6 +4,7 @@ import com.fr.base.BaseUtils;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.log.FineLoggerFactory;
import org.jetbrains.annotations.Nullable;
import javax.swing.JOptionPane;
import javax.swing.JTable;
@ -64,6 +65,20 @@ public abstract class UITableModelAdapter<T> extends AbstractTableModel implemen
return null;
}
/**
* 获取映射后的值
*
* @param row
* @return
*/
@Nullable
public T getConvertRowSelectedValue(int row) {
if (table.getSelectedRow() >= 0) {
return list.get(table.convertRowIndexToModel(row));
}
return null;
}
public void setColumnClass(Class<?>[] classes) {
this.classes = classes;
}

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

@ -34,6 +34,7 @@ import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.mainframe.vcs.ui.VcsMovingExitOption;
import com.fr.design.menu.ShortCut;
import com.fr.design.os.impl.MacOsAddListenerAction;
import com.fr.design.os.impl.SupportOSImpl;
@ -161,6 +162,12 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
@Override
public void windowClosing(WindowEvent e) {
//检查是否正在迁移,如果正在迁移就弹出弹窗让用户选择
if (!VcsMovingExitOption.ShowDialogAndConfirmExit()) {
//如果用户选择取消退出则返回,不然说明用户就是想退出,则往下走
return;
}
// 检查mini商城是否存在未结束的后台任务
if (!MiniShopDisposingChecker.check()) {
return;

102
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java

@ -16,6 +16,7 @@ import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.ResponseDataSourceChange;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.FileOperations;
import com.fr.design.file.FileToolbarStateChangeListener;
@ -34,8 +35,10 @@ import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager;
import com.fr.design.mainframe.manager.search.searcher.control.pane.TemplateTreeSearchToolbarPane;
import com.fr.design.mainframe.vcs.RecycleAction;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.mainframe.vcs.ui.FileVersionsPanel;
import com.fr.design.mainframe.vcs.ui.VcsNewPane;
import com.fr.design.menu.KeySetUtils;
import com.fr.design.menu.ShortCut;
import com.fr.design.menu.ToolBarDef;
@ -43,6 +46,7 @@ import com.fr.design.roleAuthority.RolesAlreadyEditedPane;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.worker.save.CallbackSaveWorker;
import com.fr.event.Event;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
@ -150,6 +154,8 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
private VcsAction vcsAction = new VcsAction();
private RecycleAction recycleAction = new RecycleAction();
//搜索
private SwitchAction switchAction = new SwitchAction();
private TemplateTreeSearchToolbarPane searchToolbarPane;
@ -325,13 +331,17 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
if (VcsHelper.getInstance().needInit()) {
vcsAction = new VcsAction();
if (!WorkContext.getCurrent().isCluster()) {
if (!isLegacyOnCluster()) {
vcsAction.setName(Toolkit.i18nText("Fine-Design_Vcs_Title"));
} else {
vcsAction.setName(Toolkit.i18nText("Fine-Design_Vcs_NotSupportRemote"));
}
toolbarDef.addShortCut(vcsAction);
//11.0.19及其之后加入回收站逻辑
if (VcsHelper.getInstance().checkV2FunctionSupport()) {
recycleAction = new RecycleAction();
toolbarDef.addShortCut(recycleAction);
}
}
}
@ -384,8 +394,11 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
private boolean isCurrentEditing(String path) {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String editing = jt.getEditingFILE().getPath();
return ComparatorUtils.equals(editing, path);
if (JTemplate.isValid(jt)) {
String editing = jt.getEditingFILE().getPath();
return ComparatorUtils.equals(editing, path);
}
return false;
}
/**
@ -492,15 +505,23 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
public void actionPerformed(ActionEvent e) {
String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath();
path = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, path);
boolean currentEditing = isCurrentEditing(path);
if (VcsHelper.getInstance().isLegacyMode()) {
// 如果模板已经打开了,关掉,避免出现2个同名tab(1个是模板,1个是版本)
closeOpenedTemplate(path, currentEditing);
FileVersionsPanel fileVersionTablePanel = FileVersionsPanel.getInstance();
fileVersionTablePanel.showFileVersionsPane();
stateChange();
} else {
checkTemplateSavedAndShowVcsNewPane(path, currentEditing);
}
boolean isCurrentEditing = isCurrentEditing(path);
// 如果模板已经打开了,关掉,避免出现2个同名tab(1个是模板,1个是版本)
closeOpenedTemplate(path, isCurrentEditing);
FileVersionsPanel fileVersionTablePanel = FileVersionsPanel.getInstance();
fileVersionTablePanel.showFileVersionsPane();
stateChange();
}
private void showVcsNewPane(String path) {
VcsNewPane panel = new VcsNewPane(path);
panel.showDialog();
}
/**
@ -509,7 +530,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
private void fireVcsActionChange(boolean enable) {
if (!DesignerEnvManager.getEnvManager().getVcsConfigManager().isVcsEnable()
|| VcsHelper.getInstance().isUnSelectedTemplate()
|| WorkContext.getCurrent().isCluster()) {
|| isLegacyOnCluster()) {
setEnabled(false);
return;
}
@ -556,6 +577,60 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
}
}
/**
* 如果指定模板已经打开
* <p>1.如果该模板已保存则正常打开新版本管理弹窗
* <p>2.如果该模板未保存触发保存逻辑
* <li>a.如果用户选择保存则保存并不关闭模板弹出新版本管理弹窗
* <li>b.如果用户选择不保存则关闭当前模板弹出新版本管理弹窗
* <li>c.如果用户选择取消, 则啥操作都不做
*
* @param path
* @param isCurrentEditing
*/
private void checkTemplateSavedAndShowVcsNewPane(String path, boolean isCurrentEditing) {
for (JTemplate jTemplate : HistoryTemplateListCache.getInstance().getHistoryList()) {
if (ComparatorUtils.equals(jTemplate.getEditingFILE().getPath(), path)) {
if (!jTemplate.isALLSaved()) {
MultiTemplateTabPane.getInstance().setIsCloseCurrent(isCurrentEditing);
MultiTemplateTabPane.getInstance().closeFormat(jTemplate);
confirmCloseAndShowVcsNewPane(jTemplate, path);
return;
}
}
}
showVcsNewPane(path);
}
private void confirmCloseAndShowVcsNewPane(JTemplate<?, ?> specifiedTemplate, String path) {
if (specifiedTemplate == null) {
return;
}
if (!specifiedTemplate.isALLSaved() && !DesignerMode.isVcsMode()) {
specifiedTemplate.stopEditing();
int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Would_You_Like_To_Save") + " \"" + specifiedTemplate.getEditingFILE() + "\" ?",
Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (returnVal == JOptionPane.YES_OPTION) {
CallbackSaveWorker worker = specifiedTemplate.save();
worker.addSuccessCallback(() -> {
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Template_Already_Saved", specifiedTemplate.getEditingFILE().getName()));
showVcsNewPane(path);
});
worker.start(specifiedTemplate.getRuntimeId());
} else if (returnVal == JOptionPane.NO_OPTION) {
closeTpl(specifiedTemplate);
showVcsNewPane(path);
}
} else {
showVcsNewPane(path);
}
}
private void closeTpl(JTemplate<?, ?> specifiedTemplate) {
HistoryTemplateListCache.getInstance().closeSelectedReport(specifiedTemplate);
MultiTemplateTabPane.getInstance().closeAndFreeLock(specifiedTemplate);
MultiTemplateTabPane.getInstance().activePrevTemplateAfterClose();
}
}
@ -810,6 +885,11 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
}
}
private boolean isLegacyOnCluster() {
// 老模式且为集群,用于代替之前的只判断集群逻辑
return WorkContext.getCurrent().isCluster() && VcsHelper.getInstance().isLegacyMode();
}
private String doCheck (String userInput, String suffix) {
String errorMsg = StringUtils.EMPTY;
if (selectedOperation.duplicated(userInput, suffix, true)) {

8
designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java

@ -29,11 +29,11 @@ public abstract class AbstractChartStylePane extends BasicPane {
protected void initPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
double e1 = 75;
double e = 155;
double labelWidth = 90;
double totalWidth = 155;
double p = TableLayout.PREFERRED;
double[] columnSize = {e1, e};
JPanel gapTableLayoutPane = TableLayoutHelper.createGapTableLayoutPane(getComponent(), getRows(p), columnSize, 20, LayoutConstants.VGAP_LARGE);
double[] columnSize = {labelWidth, totalWidth};
JPanel gapTableLayoutPane = TableLayoutHelper.createGapTableLayoutPane(getComponent(), getRows(p), columnSize, 5, LayoutConstants.VGAP_LARGE);
gapTableLayoutPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
UIScrollPane rightTopPane = new UIScrollPane(gapTableLayoutPane);
rightTopPane.setBorder(BorderFactory.createEmptyBorder());

9
designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java

@ -2,7 +2,6 @@ package com.fr.design.mainframe.theme.edit.chart;
import com.fr.base.BaseUtils;
import com.fr.base.FRContext;
import com.fr.base.Utils;
import com.fr.design.constants.LayoutConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.event.UIObserverListener;
@ -79,11 +78,11 @@ public class ChartFontPane extends BasicPane {
}
protected JPanel getContentPane(JPanel buttonPane) {
double e1 = 75;
double e = 155;
double labelWidth = 90;
double totalWidth = 155;
double p = TableLayout.PREFERRED;
double[] rows = {p, p, p};
double[] columnSize = {e1, e};
double[] columnSize = {labelWidth, totalWidth};
UILabel text = new UILabel(getUILabelText(), SwingConstants.LEFT);
Component[][] components = {
new Component[]{null, null},
@ -91,7 +90,7 @@ public class ChartFontPane extends BasicPane {
new Component[]{null, buttonPane}
};
return TableLayoutHelper.createGapTableLayoutPane(components, rows, columnSize, 20, LayoutConstants.VGAP_LARGE);
return TableLayoutHelper.createGapTableLayoutPane(components, rows, columnSize, 5, LayoutConstants.VGAP_LARGE);
}
public String getUILabelText() {

31
designer-base/src/main/java/com/fr/design/mainframe/vcs/RecycleAction.java

@ -0,0 +1,31 @@
package com.fr.design.mainframe.vcs;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.vcs.ui.RecycleSettingPane;
import java.awt.event.ActionEvent;
/**
* 回收站
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/4
*/
public class RecycleAction extends UpdateAction {
public RecycleAction() {
this.setSmallIcon("/com/fr/design/standard/vcslist/vcs_recycle", false);
this.setName(Toolkit.i18nText("Fine-Design_Vcs_Recycle"));
}
@Override
public void actionPerformed(ActionEvent e) {
RecycleSettingPane pane = new RecycleSettingPane();
BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame(), false);
dialog.setVisible(true);
}
}

25
designer-base/src/main/java/com/fr/design/mainframe/vcs/TableEntity.java

@ -0,0 +1,25 @@
package com.fr.design.mainframe.vcs;
/**
* 表格选中包装类
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/11
*/
public interface TableEntity {
/**
* 是否选中
*
* @return
*/
boolean isSelect();
/**
* 设置选中属性
*
* @param select
*/
void setSelect(boolean select);
}

21
designer-base/src/main/java/com/fr/design/mainframe/vcs/TableValueOperator.java

@ -0,0 +1,21 @@
package com.fr.design.mainframe.vcs;
/**
* 表格操作
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/11
*/
public interface TableValueOperator<T> {
/**
* 获取对应列的值
*
* @param o 表格内容
* @param columnIndex 列数
* @return 对应列的值
*/
Object getValue(T o, int columnIndex);
}

25
designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsConfigManager.java

@ -16,6 +16,10 @@ public class VcsConfigManager implements XMLReadable, XMLWriter {
private boolean useInterval = true;
private int saveInterval = 60;
private boolean useAutoSave = false;
private int autoSaveInterval = 15;
public static VcsConfigManager getInstance() {
return instance;
}
@ -48,6 +52,23 @@ public class VcsConfigManager implements XMLReadable, XMLWriter {
return saveInterval;
}
public int getAutoSaveInterval() {
return autoSaveInterval;
}
public void setAutoSaveInterval(int autoSaveInterval) {
this.autoSaveInterval = autoSaveInterval;
}
public boolean isUseAutoSave() {
return useAutoSave;
}
public void setUseAutoSave(boolean useAutoSave) {
this.useAutoSave = useAutoSave;
}
public void setSaveInterval(int saveInterval) {
this.saveInterval = saveInterval;
}
@ -59,6 +80,8 @@ public class VcsConfigManager implements XMLReadable, XMLWriter {
this.setSaveInterval(reader.getAttrAsInt("saveInterval", 60));
this.setUseInterval(reader.getAttrAsBoolean("useInterval", true));
this.setVcsEnable(reader.getAttrAsBoolean("vcsEnable", true));
this.setAutoSaveInterval(reader.getAttrAsInt("autoSaveInterval", 15));
this.setUseAutoSave(reader.getAttrAsBoolean("useAutoSave", true));
}
}
@ -69,6 +92,8 @@ public class VcsConfigManager implements XMLReadable, XMLWriter {
writer.attr("saveInterval", this.getSaveInterval());
writer.attr("useInterval", this.isUseInterval());
writer.attr("vcsEnable", this.isVcsEnable());
writer.attr("autoSaveInterval", this.getAutoSaveInterval());
writer.attr("useAutoSave", this.isUseAutoSave());
writer.end();
}
}

37
designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsExceptionUtils.java

@ -0,0 +1,37 @@
package com.fr.design.mainframe.vcs;
import com.fr.design.i18n.Toolkit;
import java.io.IOException;
import java.util.HashMap;
/**
* 版本管理异常处理工具类
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/24
*/
public class VcsExceptionUtils {
public static final HashMap<Class, String> EXCEPTION_MAP = new HashMap<Class, String>() {
{
put(IOException.class, Toolkit.i18nText("Fine-Design_Vcs_Exception_IO"));
put(UnsupportedOperationException.class, Toolkit.i18nText("Fine-Design_Vcs_Exception_Un_Support"));
}
};
/**
* 根据异常返回结果描述文案
*/
public static String createDetailByException(Exception e) {
for (Class key : EXCEPTION_MAP.keySet()) {
if (key.isAssignableFrom(e.getClass())) {
return EXCEPTION_MAP.get(key);
}
}
return Toolkit.i18nText("Fine-Design_Vcs_Exception_Unknown");
}
}

291
designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsOperatorWorker.java

@ -0,0 +1,291 @@
package com.fr.design.mainframe.vcs;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.vcs.ui.VcsBatchProcessDetailPane;
import com.fr.design.mainframe.vcs.ui.VcsProgressDialog;
import com.fr.log.FineLoggerFactory;
import com.fr.report.entity.VcsEntity;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import javax.swing.SwingWorker;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* 为版本中心回收站版本详情提供带进度条与结算面板的操作的worker
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/18
*/
public class VcsOperatorWorker {
private int count = 0;
private static final int FREQ = 5;
private String successStr;
private String title;
private String failedStr;
private String everyFailedStr;
private VcsProgressDialog dialog;
private static final String PREFIX = "(v.";
private static final String TAIL = ")";
public VcsOperatorWorker(String title, String dealingStr, String successStr, String failedStr, String everyFailedStr) {
this.title = title;
this.successStr = successStr;
this.failedStr = failedStr;
this.everyFailedStr = everyFailedStr;
dialog = new VcsProgressDialog(title, dealingStr);
}
public VcsOperatorWorker(String everyFailedStr) {
this.title = StringUtils.EMPTY;
this.successStr = StringUtils.EMPTY;
this.failedStr = StringUtils.EMPTY;
this.everyFailedStr = everyFailedStr;
}
/**
* 快速创建用于删除的worker
*
* @return
*/
public static VcsOperatorWorker createDeleteWorker() {
return new VcsOperatorWorker(
Toolkit.i18nText("Fine-Design_Vcs_Delete_Progress_Title"),
Toolkit.i18nText("Fine-Design_Vcs_Delete_Progress_Tips"),
Toolkit.i18nText("Fine-Design_Vcs_Delete_Progress_Success"),
"Fine-Design_Vcs_Delete_Progress_Failed",
Toolkit.i18nText("Fine-Design_Vcs_Delete_Every_Failed"));
}
/**
* 快速创建用于还原的worker
*
* @return
*/
public static VcsOperatorWorker createRestoreWorker() {
return new VcsOperatorWorker(
Toolkit.i18nText("Fine-Design_Vcs_Restore_Progress_Title"),
Toolkit.i18nText("Fine-Design_Vcs_Restore_Progress_Tips"),
Toolkit.i18nText("Fine-Design_Vcs_Restore_Progress_Success"),
"Fine-Design_Vcs_Restore_Progress_Failed",
Toolkit.i18nText("Fine-Design_Vcs_Restore_Every_Failed"));
}
/**
* 快速创建用于还原的worker
*
* @return
*/
public static VcsOperatorWorker createUpdateWorker() {
return new VcsOperatorWorker(Toolkit.i18nText("Fine-Design_Vcs_Update_Every_Failed"));
}
/**
* 批量还原
*
* @param vcsEntities 需要还原的版本
*/
public void batchRestore(List<VcsEntity> vcsEntities) {
List<String> failedList = new ArrayList<>();
startProcess(vcsEntities, failedList, (vcsEntity, operator) -> {
String fileName = vcsEntity.getFilename();
boolean result = true;
try {
operator.restoreVersion(fileName);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
result = false;
}
if (!result) {
failedList.add(fileName+PREFIX+vcsEntity.getVersion()+TAIL);
}
});
}
/**
* 批量删除
*
* @param vcsEntities 需要删除的版本
* @param all 是否需要删除所有版本
*/
public void batchDelete(List<VcsEntity> vcsEntities, boolean all) {
List<String> failedList = new ArrayList<>();
startProcess(vcsEntities, failedList, (vcsEntity, operator) -> {
String fileName = vcsEntity.getFilename();
boolean result = true;
try {
if (all) {
operator.deleteVersionForRecycle(fileName);
} else {
operator.deleteVersion(fileName, vcsEntity.getVersion());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
result = false;
}
if (!result) {
failedList.add(fileName+PREFIX+vcsEntity.getVersion()+TAIL);
}
});
}
/**
* 删除指定模板的全部历史版本
*
* @param entity VcsEntity
*/
public void doDelete(VcsEntity entity) {
String fileName = entity.getFilename();
start4Single(entity, (vcsEntity, operator) -> operator.deleteVersionForRecycle(fileName), fileName + everyFailedStr);
}
/**
* 删除指定模板的指定版本
*
* @param entity 版本
*/
public void deleteTargetVersion(VcsEntity entity) {
String fileName = entity.getFilename();
int version = entity.getVersion();
start4Single(entity, (vcsEntity, operator) -> {
operator.deleteVersion(fileName, version);
}, fileName + everyFailedStr);
}
/**
* 更新版本
*
* @param entity 版本
*/
public void updateEntityAnnotation(VcsEntity entity) {
start4Single(entity, (vcsEntity, operator) -> {
operator.updateVersion(entity);
}, everyFailedStr);
}
private void startProcess(List<VcsEntity> vcsEntities, List<String> failedList, VcsWorkerOperator workerOperator) {
try {
dialog.getProgressBar().setMaximum(vcsEntities.size());
start4Batch(vcsEntities, failedList, workerOperator);
dialog.showDialog();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
/**
* 控制更新频率
*
* @return 是否需要更新进度
*/
private boolean needPublish() {
return (count > FREQ && count % FREQ == 0) || count < FREQ;
}
private void start4Single(VcsEntity entity, VcsWorkerOperator vcsWorkerOperator, String failedTip) {
new SwingWorker<Boolean, Void>() {
@Override
protected void done() {
try {
if (!get()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), failedTip);
}
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
protected Boolean doInBackground() throws Exception {
try {
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class);
vcsWorkerOperator.process(entity, operator);
} catch (Exception e) {
return false;
}
return true;
}
}.execute();
}
private void start4Batch(List<VcsEntity> vcsEntities, List<String> failedList, VcsWorkerOperator workerOperator) {
new SwingWorker<Boolean, Integer>() {
@Override
protected Boolean doInBackground() throws Exception {
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class);
for (VcsEntity vcsEntity : vcsEntities) {
workerOperator.process(vcsEntity, operator);
count++;
if (needPublish()) {
publish(count);
}
}
return failedList.isEmpty();
}
@Override
protected void process(List<Integer> chunks) {
dialog.getProgressBar().setValue(chunks.get(chunks.size() - 1));
}
@Override
protected void done() {
dialog.closeDialog();
try {
showErrorDetailPane(get(), failedList, failedList.size(), vcsEntities.size() - failedList.size());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
private void showErrorDetailPane(boolean result, List<String> failedList, int failed, int success) {
if (result) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), successStr);
} else {
VcsBatchProcessDetailPane pane = new VcsBatchProcessDetailPane(
DesignerContext.getDesignerFrame(),
title,
Toolkit.i18nText(failedStr, failed, success)
);
for (String msg : failedList) {
pane.updateDetailArea(msg + everyFailedStr);
}
pane.show();
}
}
/**
* Vcs面板操作处理接口
*
*/
private interface VcsWorkerOperator {
/**
* 处理
*
* @param vcsEntity 版本
* @param operator 操作类
*/
void process(VcsEntity vcsEntity, VcsOperator operator) throws Exception;
}
}

49
designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsRecycleSettingHelper.java

@ -0,0 +1,49 @@
package com.fr.design.mainframe.vcs;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerAdaptor;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsConfig;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanOperator;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanService;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoRecycleSchedule;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 版本管理界面配置回收事件的处理类
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/21
*/
public class VcsRecycleSettingHelper {
private static ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("VcsRecycle"));
/**
* 更新任务
*
* @param day
*/
public static void updateJob(int day) {
executorService.execute(new Runnable() {
@Override
public void run() {
Configurations.update(new WorkerAdaptor(VcsConfig.class) {
@Override
public void run() {
VcsConfig.getInstance().setV2CleanRecycleInterval(day);
}
});
WorkContext.getCurrent().get(VcsAutoCleanOperator.class).addOrUpdateVcsAutoCleanJob(
VcsAutoCleanService.VCS_AUTO_CLEAN_RECYCLE_JOB_NAME,
1,
VcsAutoRecycleSchedule.class);
}
});
}
}

113
designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsTableEntity.java

@ -0,0 +1,113 @@
package com.fr.design.mainframe.vcs;
import com.fr.report.entity.VcsEntity;
import com.fr.stable.StringUtils;
/**
* 包装VcsEntity的用于表格展示与处理的类
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/10
*/
public class VcsTableEntity implements TableEntity{
private boolean select = false;
private static final String MB = "MB";
private static final String VERSION = "V.";
private static final double MB_SIZE = 1024.0 * 1024;
private VcsEntity entity;
public VcsTableEntity(VcsEntity entity) {
this.entity = entity;
}
/**
* 获取模板名
*
* @return 模板名
*/
public String getFilename() {
return entity.getFilename();
}
/**
* 获取版本大小
*
* @return 版本大小
*/
public String getSize() {
double size = entity.getSize()/MB_SIZE;
if (size == 0) {
return StringUtils.EMPTY;
}
return String.format("%.3f", size) + MB;
}
/**
* 获取修改时间
*
* @return 修改时间
*/
public String getTime() {
return entity.getTime().toLocaleString();
}
/**
* 获取用户名
*
* @return 用户名
*/
public String getUserName() {
return entity.getUsername();
}
/**
* 获取备注
*
* @return 备注
*/
public String getCommitMsg() {
return entity.getCommitMsg();
}
/**
* 获取版本号
*
* @return 版本号
*/
public String getVersion() {
return VERSION + entity.getVersion();
}
/**
* 获取删除时间
*
* @return 删除时间
*/
public String getDeleteTime() {
return entity.getDeleteTime().toLocaleString();
}
@Override
public boolean isSelect() {
return select;
}
@Override
public void setSelect(boolean select) {
this.select = select;
}
public VcsEntity getEntity() {
return entity;
}
public void setEntity(VcsEntity entity) {
this.entity = entity;
}
}

239
designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java

@ -2,6 +2,7 @@ package com.fr.design.mainframe.vcs.common;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.config.ConfigEvent;
import com.fr.design.DesignerEnvManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.TemplateTreePane;
@ -12,6 +13,10 @@ import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.JTemplateActionListener;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.mainframe.vcs.ui.FileVersionTable;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.ListenerAdaptor;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContext;
@ -20,16 +25,21 @@ import com.fr.report.entity.VcsEntity;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import com.fr.workspace.server.vcs.VcsOperator;
import com.fr.workspace.server.vcs.filesystem.VcsFileSystem;
import com.fr.workspace.server.vcs.git.config.GcConfig;
import javax.swing.Icon;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by XiaXiang on 2019/4/17.
@ -55,10 +65,86 @@ public class VcsHelper implements JTemplateActionListener {
private final static String SERVICE_NAME_MOVE = "moveVcs";
private static final VcsHelper INSTANCE = new VcsHelper();
private static ScheduledExecutorService saveSchedule;
private volatile boolean legacyMode;
private volatile boolean root;
public static VcsHelper getInstance() {
return INSTANCE;
}
private VcsHelper() {
VcsOperator op = WorkContext.getCurrent().get(VcsOperator.class);
// 开了设计器启动页面时一开始取不到VcsOperator,通过下面的切换环境事件再取,这边判断下
if (op != null) {
try {
legacyMode = op.isLegacyMode();
root = WorkContext.getCurrent().isLocal() || WorkContext.getCurrent().isRoot();
} catch (Exception e) {
legacyMode = true;
root = false;
FineLoggerFactory.getLogger().error("[VcsHelper] init first failed ", e.getMessage());
}
}
EventDispatcher.listen(ConfigEvent.READY, new ListenerAdaptor() {
@Override
protected void on(Event event) {
try {
legacyMode = WorkContext.getCurrent().get(VcsOperator.class).isLegacyMode();
FineLoggerFactory.getLogger().info("[VcsHelper] legacyMode:{}", legacyMode);
} catch (Exception e) {
//保险起见走老逻辑
legacyMode = true;
FineLoggerFactory.getLogger().error("[VcsHelper] get legacy failed", e.getMessage());
}
}
});
EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener<Workspace>() {
@Override
public void on(Event event, Workspace param) {
try {
root = WorkContext.getCurrent().isLocal() || WorkContext.getCurrent().isRoot() ;
} catch (Exception e) {
root = false;
FineLoggerFactory.getLogger().error("[VcsHelper] get root failed", e.getMessage());
}
}
});
}
/**
* 开始自动保存任务
*
* @param interval 时间间隔
*/
public void startAutoSave(int interval) {
stopAutoSave();
saveSchedule = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("VcsAutoSaveSchedule"));
saveSchedule.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
FineLoggerFactory.getLogger().info("[VcsV2] start to run auto save schedule");
JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (DesignerEnvManager.getEnvManager().getVcsConfigManager().isVcsEnable() && JTemplate.isValid(template)) {
fireAutoSaveVcs(template);
}
}
}, interval, interval, TimeUnit.MINUTES);
}
/**
* 停止任务
*/
public void stopAutoSave() {
if (saveSchedule != null && !saveSchedule.isShutdown()) {
saveSchedule.shutdown();
}
}
private int containsFolderCounts() {
TemplateFileTree fileTree = TemplateTreePane.getInstance().getTemplateFileTree();
if (fileTree.getSelectionPaths() == null) {
@ -93,18 +179,28 @@ public class VcsHelper implements JTemplateActionListener {
}
private String getEditingFilename() {
String vcsCacheDir = VcsFileSystem.getInstance().getVcsCacheRelativePath();
JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String editingFilePath = jt.getEditingFILE().getPath();
if (editingFilePath.startsWith(ProjectConstants.REPORTLETS_NAME)) {
editingFilePath = editingFilePath.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY);
} else if (editingFilePath.startsWith(vcsCacheDir)) {
editingFilePath = editingFilePath.replaceFirst(vcsCacheDir, StringUtils.EMPTY);
return dealWithFilePath(editingFilePath);
}
/**
* 处理传入的文件名使其符合Vcs规范
*
* @param filePath 文件路径
* @return 处理完的文件
*/
public String dealWithFilePath(String filePath) {
String vcsCacheDir = VcsFileSystem.getInstance().getVcsCacheRelativePath();
if (filePath.startsWith(ProjectConstants.REPORTLETS_NAME)) {
filePath = filePath.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY);
} else if (filePath.startsWith(vcsCacheDir)) {
filePath = filePath.replaceFirst(vcsCacheDir, StringUtils.EMPTY);
}
if (editingFilePath.startsWith(VCS_FILE_SLASH)) {
editingFilePath = editingFilePath.substring(1);
if (filePath.startsWith(VCS_FILE_SLASH)) {
filePath = filePath.substring(1);
}
return editingFilePath;
return filePath;
}
private boolean needDeleteVersion(VcsEntity entity) {
@ -133,24 +229,21 @@ public class VcsHelper implements JTemplateActionListener {
fireVcs.execute(new Runnable() {
@Override
public void run() {
String fileName = getEditingFilename();
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class);
VcsEntity entity = operator.getFileVersionByIndex(fileName, 0);
boolean replace = needDeleteVersion(entity);
int latestFileVersion = 0;
if (entity != null) {
latestFileVersion = entity.getVersion();
}
if (jt.getEditingFILE() instanceof VcsCacheFileNodeFile) {
operator.saveVersionFromCache(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1);
operator.saveVersionFromCache(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1, replace);
String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath();
FileVersionTable.getInstance().updateModel(1, WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst(VCS_FILE_SLASH, StringUtils.EMPTY)));
List<VcsEntity> updatedList = WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst(VCS_FILE_SLASH, StringUtils.EMPTY));
SwingUtilities.invokeLater(() -> FileVersionTable.getInstance().updateModel(1, updatedList));
} else {
operator.saveVersion(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1);
}
VcsEntity oldEntity = WorkContext.getCurrent().get(VcsOperator.class).getFileVersionByIndexAndUsername(fileName, getCurrentUsername(), 1);
if (needDeleteVersion(oldEntity)) {
operator.deleteVersion(oldEntity.getFilename(), oldEntity.getVersion());
operator.saveVersion(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1, replace);
}
if (GcConfig.getInstance().isGcEnable()) {
operator.gc();
@ -158,7 +251,9 @@ public class VcsHelper implements JTemplateActionListener {
}
});
fireVcs.shutdown();
if (!fireVcs.isShutdown()) {
fireVcs.shutdown();
}
}
/**
@ -188,12 +283,85 @@ public class VcsHelper implements JTemplateActionListener {
moveVcs.shutdown();
}
/**
* 判断是否为老模式
* @return 是否为老模式
*/
public boolean isLegacyMode() {
return legacyMode;
}
/**
* 更新当前的legacyMode状态
* <li>目前用在迁移结束后更新模式为新模式</li>
*
*/
public void updateLegacyMode() {
this.legacyMode = !legacyMode;
}
@Override
public void templateOpened(JTemplate<?, ?> jt) {
try {
if (checkAutoSaveSupport()) {
startAutoSave(VcsConfigManager.getInstance().getAutoSaveInterval());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
}
/**
* 响应版本管理自动保存
*
* <li>直接用template的file来保存的话相当于拿源文件来保存模板这样用户做的改动会丢失</li>
* <li>因此需要自己实现一下自动保存的逻辑将当前模板的数据导出,再拿这个Byte[]去做我们需要的保存处理</li>
* <li>保存后需要触发清理逻辑</li>
*
* @param jt 模板
*/
public void fireAutoSaveVcs(final JTemplate jt) {
String fileName = getEditingFilename();
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class);
VcsEntity entity = operator.getFileVersionByIndex(fileName, 0);
boolean replace = needDeleteVersion(entity);
int latestFileVersion = 0;
if (entity != null) {
latestFileVersion = entity.getVersion();
}
if (JTemplate.isValid(jt)) {
doSave(jt, fileName, latestFileVersion, replace, operator);
}
}
private void doSave(JTemplate jt, String fileName, int latestFileVersion, boolean replace, VcsOperator operator) {
if (jt.getEditingFILE() instanceof VcsCacheFileNodeFile) {
operator.saveVersionFromCache(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1, replace);
String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath();
List<VcsEntity> updatedList = WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst(VCS_FILE_SLASH, StringUtils.EMPTY));
SwingUtilities.invokeLater(() -> FileVersionTable.getInstance().updateModel(1, updatedList));
} else {
autoSave(jt, getCurrentUsername(), fileName, latestFileVersion + 1, replace, operator);
}
if (GcConfig.getInstance().isGcEnable()) {
operator.gc();
}
}
private void autoSave(JTemplate jt, String currentUsername, String fileName, int nowVersion, boolean replace, VcsOperator operator) {
try {
if (JTemplate.isValid(jt) && !jt.isALLSaved()) {
operator.autoSave(currentUsername, fileName, StringUtils.EMPTY, nowVersion, jt.exportData(), replace);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
}
/**
* 模板保存时 处理.
*
@ -203,13 +371,48 @@ public class VcsHelper implements JTemplateActionListener {
public void templateSaved(JTemplate<?, ?> jt) {
if (needInit()
&& DesignerEnvManager.getEnvManager().getVcsConfigManager().isVcsEnable()
&& !WorkContext.getCurrent().isCluster()) {
// 如果是集群,在新版本下才生效
&& (!WorkContext.getCurrent().isCluster() || !VcsHelper.getInstance().isLegacyMode())) {
fireVcs(jt);
}
}
@Override
public void templateClosed(JTemplate<?, ?> jt) {
try {
if (checkAutoSaveSupport()) {
stopAutoSave();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
}
/**
* 判断是否支持V2功能
*
* @return 支持返回true
*/
public boolean checkV2FunctionSupport() {
return !VcsHelper.getInstance().isLegacyMode() && root;
}
/**
* 判断是否支持迁移功能
*
* @return 支持返回true
*/
public boolean checkMoveFunctionSupport() {
return WorkContext.getCurrent().isLocal() || WorkContext.getCurrent().isRoot();
}
/**
* 是否支持自动保存
*
* @return 支持返回true
*/
public boolean checkAutoSaveSupport() {
return VcsConfigManager.getInstance().isUseAutoSave() && !VcsHelper.getInstance().isLegacyMode();
}
}

407
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/AbstractSupportSelectTablePane.java

@ -0,0 +1,407 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itableeditorpane.UITableEditAction;
import com.fr.design.gui.itableeditorpane.UITableEditorPane;
import com.fr.design.gui.itableeditorpane.UITableModelAdapter;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.vcs.TableEntity;
import com.fr.design.mainframe.vcs.TableValueOperator;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* 比较通用的带全选功能的表格面板
*
* <p>整体划分为north与center两个面板参考BorderLayout的布局,center部分用于置放表格表格部分支持全选north部分支持自定义用于展示各种标签按钮输入框</p>
* <p>获取数据的时候不需要用SwingWorker(内部已经实现)考虑到大部分表格内容的展现需要去获取数据而获取数据大部分都需要一定时间因此为了防止UI冻结在加载数据结束之前先展示进度条面板</p>
* <p>使用该面板你可能需要:</p>
* <li>自己封装一个实现TableEntity接口(该接口用于提供(选中/全选)功能)内部存放你要放入表格的类例如VcsEntity,参考VcsTableEntity</li>
* <li>初始化的时候赋予变量model值(如果有需要的话)该变量用于控制表格的数据类型,默认DefaultModel分为5列第一列为勾选框</li>
* <li>(一定要干的)初始化的时候赋予变量model内operators值,用于确认表格每一列getValueAt返回的值</li>
* <li>上面板也允许自定义重写initTableTopPane即可</li>
* <li>要使用该面板可以参考:RecyclePane</li>
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/11
*/
public abstract class AbstractSupportSelectTablePane<T extends TableEntity> extends BasicPane {
public static final Color DEFAULT_HEADER_COLOR = new Color(232, 232, 233);
public static final Color DEFAULT_SELECT_TABLE_ROW_COLOR = new ColorUIResource(200, 221, 233);
private CardLayout layout;
protected JPanel contentPane;
protected UITextField searchTextField = new UITextField();;
protected UILabel deleteLabel = new UILabel();
/**
* 整体面板的center部分,用来放表格
*/
protected UITableEditorPane<T> tableContentPane;
protected UITableModelAdapter<T> model;
/**
* 整体面板的north部分
*/
protected JPanel tableTopPane = new JPanel();
/**
* 整体面板
*/
protected JPanel tablePane = new JPanel();
private int selectCount = 0;
private static final String LOADING = "loading";
private static final String TABLE ="table";
protected List<T> entities;
protected TableValueOperator<T> operator;
public AbstractSupportSelectTablePane(String title, TableValueOperator<T> operators, String[] tableNames, boolean needBorder) {
this.operator = operators;
this.model = new DefaultModel(tableNames, new Class[]{
Boolean.class,
UILabel.class,
UILabel.class,
UILabel.class,
UILabel.class
});
init(title, needBorder);
}
public AbstractSupportSelectTablePane(String title, TableValueOperator<T> operators, boolean needBorder) {
this.operator = operators;
init(title, needBorder);
}
/**
* 初始化
*
*/
private void init(String title, boolean needBorder) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
contentPane = new JPanel();
layout = new CardLayout();
contentPane.setLayout(layout);
contentPane.add(new TipsPane(true), LOADING);
this.add(contentPane);
new SwingWorker<List<T>, Void>(){
@Override
protected List<T> doInBackground() {
return getTableList();
}
@Override
protected void done() {
try {
entities = get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
contentPane.add(createTablePane(title, needBorder), TABLE);
layout.show(contentPane, TABLE);
}
}.execute();
}
/**
* 获取表格数据
*
* @return 表格数据
*/
abstract protected List<T> getTableList();
private JPanel createTablePane(String title, boolean needBorder) {
tablePane = needBorder ? FRGUIPaneFactory.createTopVerticalTitledBorderPane(title) : new JPanel();
if (isNeedTopPane()) {
initTableTopPane();
initTopPaneListener();
}
initTableContentPane(entities);
tablePane.setLayout(new BorderLayout());
tablePane.add(tableTopPane, BorderLayout.NORTH);
tablePane.add(tableContentPane, BorderLayout.CENTER);
tableContentPane.getEditTable().getColumnModel().getColumn(0).setMaxWidth(50);
RowSorter<UITableModelAdapter<T>> sorter = new TableRowSorter<UITableModelAdapter<T>>(model) {
@Override
public boolean isSortable(int column) {
return column != 0;
}
};
tableContentPane.getEditTable().setRowSorter(sorter);
return tablePane;
}
/**
* 初始化表格面板
*
* @param entities 表格数据
*/
protected void initTableContentPane(List<T> entities) {
tableContentPane = new UITableEditorPane<>(model);
model.setList(entities);
JTable table = tableContentPane.getEditTable();
table.getTableHeader().setBackground(DEFAULT_HEADER_COLOR);
table.getTableHeader().setDefaultRenderer(new HeaderRenderer(tableContentPane.getEditTable()));
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = ((JTable) e.getSource()).rowAtPoint(e.getPoint());
int col = ((JTable) e.getSource()).columnAtPoint(e.getPoint());
if (col == 0) {
T entity = model.getConvertRowSelectedValue(row);
//改变面板的各个状态
changeComponentStatus(entity, row, col, table);
}
}
});
initExtraListener4Table(table);
}
/**
* 设定额外的表格事件
*
* @param table 表格
*/
protected void initExtraListener4Table(JTable table) {
//do nothing
}
/**
* 是否需要上面板
*
* @return
*/
protected boolean isNeedTopPane() {
return true;
}
private void changeComponentStatus(T entity, int row, int col, JTable table) {
boolean select = entity.isSelect();
entity.setSelect(!select);
table.setValueAt(entity.isSelect(), row, col);
if (select) {
selectCount--;
} else {
selectCount++;
}
//更新表头的勾选框状态
HeaderRenderer renderer = (HeaderRenderer) table.getTableHeader().getDefaultRenderer();
renderer.refreshHeader(table, selectCount >= table.getRowCount());
changeExtraComponentStatus();
}
/**
* 更新额外组件的状态
*/
protected void changeExtraComponentStatus() {
}
public int getSelectCount() {
return selectCount;
}
/**
* 初始化上面板
*/
abstract protected void initTableTopPane();
/**
* 初始化上面板事件
*/
abstract protected void initTopPaneListener();
/**
* 表头渲染
*/
public class HeaderRenderer implements TableCellRenderer {
JTableHeader tableHeader;
final UICheckBox selectBox;
public HeaderRenderer(JTable table) {
this.tableHeader = table.getTableHeader();
tableHeader.setCursor(new Cursor(Cursor.HAND_CURSOR));
selectBox = new UICheckBox();
selectBox.setSelected(false);
tableHeader.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 0) {
//获得选中列
int selectColumn = tableHeader.columnAtPoint(e.getPoint());
if (selectColumn == 0) {
boolean value = !selectBox.isSelected();
selectBox.setSelected(value);
selectAllOrNull(value);
selectCount = value ? table.getRowCount() : 0;
changeExtraComponentStatus();
tableHeader.repaint();
model.fireTableDataChanged();
}
}
}
private void selectAllOrNull(boolean value) {
int len = table.getRowCount();
for (T entity : model.getList()) {
entity.setSelect(value);
}
}
});
}
/**
* 刷新表头
*
* @param table
*/
public void refreshHeader(JTable table, boolean value) {
selectBox.setSelected(value);
int rowHeight = table.getRowHeight();
table.updateUI();
table.setRowHeight(rowHeight);
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row, int column) {
tableHeader = table.getTableHeader();
tableHeader.setReorderingAllowed(false);
String valueStr = (String) value;
UILabel label = new UILabel(valueStr);
if (needIcon4Head(column)) {
label.setIcon(IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_sort"));
label.setHorizontalTextPosition(JLabel.LEFT);
label.setHorizontalAlignment(SwingConstants.LEFT);
}
selectBox.setHorizontalAlignment(SwingConstants.CENTER);
selectBox.setBorderPainted(true);
JComponent component = (column == 0) ? selectBox : label;
component.setForeground(tableHeader.getForeground());
component.setBackground(tableHeader.getBackground());
component.setFont(tableHeader.getFont());
component.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return component;
}
}
@Override
protected String title4PopupWindow() {
return StringUtils.EMPTY;
}
/**
* 默认的数据model
*/
public class DefaultModel extends UITableModelAdapter<T> {
public DefaultModel(String[] tableNames, Class[] classes) {
super(tableNames);
setColumnClass(classes);
this.setDefaultEditor(Boolean.class, new BooleanEditor());
this.setDefaultRenderer(Boolean.class, new BooleanRenderer());
this.setDefaultRenderer(UILabel.class, new ToolTipTableCellRenderer());
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
T vcsEntity = this.getList().get(rowIndex);
return operator.getValue(vcsEntity, columnIndex);
}
@Override
public boolean isCellEditable(int row, int col) {
return col == 0;
}
@Override
public UITableEditAction[] createAction() {
return new UITableEditAction[0];
}
}
/**
* 用于展示指定风格的checkbox的Editor
*/
public class BooleanEditor extends DefaultCellEditor {
public BooleanEditor() {
super(new UICheckBox());
UICheckBox checkBox = (UICheckBox) getComponent();
checkBox.setHorizontalAlignment(UICheckBox.CENTER);
}
}
/**
* 用于展示指定风格的checkbox的渲染器
*/
public class BooleanRenderer extends UICheckBox implements TableCellRenderer, UIResource {
public BooleanRenderer() {
super();
setHorizontalAlignment(JLabel.CENTER);
setBorderPainted(true);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
setSelected((Boolean) table.getValueAt(row, 0));
setUI(getUICheckBoxUI());
setBorder(BorderFactory.createEmptyBorder());
setBackground(isSelected ? DEFAULT_SELECT_TABLE_ROW_COLOR : Color.WHITE);
return this;
}
}
/**
* 表头的某列是否需要icon
*
* @param col
* @return
*/
protected boolean needIcon4Head(int col) {
return col != 0;
}
}

26
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/EditFileVersionDialog.java

@ -81,12 +81,7 @@ public class EditFileVersionDialog extends UIDialog {
ok.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
entity.setCommitMsg(msgTestArea.getText());
WorkContext.getCurrent().get(VcsOperator.class).updateVersion(entity);
setVisible(false);
String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath();
FileVersionTable table = FileVersionTable.getInstance();
table.updateModel(table.getSelectedRow(), WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst("/", StringUtils.EMPTY)));
doOK();
}
});
@ -101,4 +96,23 @@ public class EditFileVersionDialog extends UIDialog {
public void checkValid() throws Exception {
}
/**
* 确定事件
*
*/
public void doOK() {
entity.setCommitMsg(msgTestArea.getText());
WorkContext.getCurrent().get(VcsOperator.class).updateVersion(entity);
setVisible(false);
String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath();
FileVersionTable table = FileVersionTable.getInstance();
table.updateModel(table.getSelectedRow(), WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst("/", StringUtils.EMPTY)));
}
public UITextArea getMsgTestArea() {
return msgTestArea;
}
}

368
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecyclePane.java

@ -0,0 +1,368 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.vcs.VcsOperatorWorker;
import com.fr.design.mainframe.vcs.TableEntity;
import com.fr.design.mainframe.vcs.TableValueOperator;
import com.fr.design.mainframe.vcs.VcsTableEntity;
import com.fr.report.entity.VcsEntity;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static com.fr.design.i18n.Toolkit.i18nText;
/**
* 回收面板
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/5
*/
public class RecyclePane extends AbstractSupportSelectTablePane<VcsTableEntity> {
public static final Icon ICON_SEARCH = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_recycle_search");
public static final Icon ICON_REFRESH = IconUtils.readSVGIcon("/com/fr/design/standard/vcslist/vcs_recycle_restore", IconUtils.ICON_TYPE_NORMAL);
public static final Icon ICON_REFRESH_DISABLE = IconUtils.readSVGIcon("/com/fr/design/standard/vcslist/vcs_recycle_restore", IconUtils.ICON_TYPE_DISABLED);
public static final Icon ICON_DELETE = IconUtils.readSVGIcon("/com/fr/design/standard/vcslist/vcs_recycle_delete", IconUtils.ICON_TYPE_NORMAL);
public static final Icon ICON_DELETE_DISABLE = IconUtils.readSVGIcon("/com/fr/design/standard/vcslist/vcs_recycle_delete", IconUtils.ICON_TYPE_DISABLED);
protected UITextField searchTextField;
protected UILabel deleteLabel;
protected UILabel restoreLabel;
private static final int COLUMNS_COUNT = 15;
private BasicDialog dialog;
private BasicDialog parentDialog;
private List<VcsTableEntity> tableEntities;
public RecyclePane() {
super(i18nText("Fine-Design_Vcs_Recycle"), (o, columnIndex) -> {
switch (columnIndex) {
case 0:
return o.isSelect();
case 1:
return o.getFilename();
case 2:
return o.getSize();
case 3:
return o.getDeleteTime();
case 4:
return o.getTime();
default:
return o;
}
}, new String[]{
StringUtils.EMPTY,
Toolkit.i18nText("Fine-Design_Vcs_Template"),
Toolkit.i18nText("Fine-Design_Vcs_Recycle_Size"),
Toolkit.i18nText("Fine-Design_Vcs_Delete_Time"),
Toolkit.i18nText("Fine-Design_Vcs_Time")
}, false);
}
public RecyclePane(String title, TableValueOperator<VcsTableEntity> operators, boolean needBorder) {
super(title, operators, needBorder);
}
@Override
protected List<VcsTableEntity> getTableList() {
List<VcsEntity> entityList = WorkContext.getCurrent().get(VcsOperator.class).getRecycleEntities();
List<VcsTableEntity> tableEntities = new ArrayList<>();
for (VcsEntity entity : entityList) {
tableEntities.add(new VcsTableEntity(entity));
}
updateTableList(tableEntities);
return tableEntities;
}
@Override
protected void initTableTopPane() {
tableTopPane = new JPanel();
tableTopPane.setLayout(new BorderLayout());
JPanel leftPane = new JPanel();
JPanel rightPane = new JPanel();
//左边面板,包含搜索icon+搜索框
if (isNeedSearch()) {
searchTextField = new UITextField();
searchTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Vcs_Start_Search"));
searchTextField.setColumns(COLUMNS_COUNT);
leftPane.add(new UILabel(ICON_SEARCH));
leftPane.add(searchTextField);
}
//右边面板,包括还原按钮+删除按钮
if (isNeedRestore()) {
restoreLabel = new UILabel(ICON_REFRESH);
restoreLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
restoreLabel.setDisabledIcon(ICON_REFRESH_DISABLE);
restoreLabel.setEnabled(false);
rightPane.add(restoreLabel);
}
if (isNeedDelete()) {
deleteLabel = new UILabel(ICON_DELETE);
deleteLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
deleteLabel.setDisabledIcon(ICON_DELETE_DISABLE);
deleteLabel.setEnabled(false);
rightPane.add(deleteLabel);
}
tableTopPane.add(leftPane, BorderLayout.EAST);
tableTopPane.add(rightPane, BorderLayout.WEST);
}
@Override
protected void changeExtraComponentStatus() {
boolean canUseLabel = getSelectCount() > 0;
if (restoreLabel != null) {
restoreLabel.setEnabled(canUseLabel);
}
if (deleteLabel != null) {
deleteLabel.setEnabled(canUseLabel);
}
}
@Override
protected void initTopPaneListener() {
initSearchTextFiledListener();
initRestoreListener();
initDeleteLabelListener();
}
private void initDeleteLabelListener() {
if (isNeedDelete()) {
deleteLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Delete"));
deleteLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
fireListener(new VcsResponseListener() {
@Override
public void doAfterChooseYes(List<VcsEntity> selectList) {
VcsOperatorWorker.createDeleteWorker().batchDelete(selectList, isNeedDeleteAllVersion());
}
}, true);
}
});
}
}
private void initRestoreListener() {
if (isNeedRestore()) {
restoreLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Restore"));
restoreLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
fireListener(new VcsResponseListener() {
@Override
public void doAfterChooseYes(List<VcsEntity> selectList) {
VcsOperatorWorker.createRestoreWorker().batchRestore(selectList);
}
}, false);
}
});
}
}
private void initSearchTextFiledListener() {
if (isNeedSearch()) {
searchTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String str = searchTextField.getText();
model.setList(tableEntities.stream().filter(entity -> entity.getEntity().getFilename().contains(str)).collect(Collectors.toList()));
model.fireTableDataChanged();
}
});
}
}
private void fireListener(VcsResponseListener listener, boolean isDelete) {
List<VcsEntity> selectList = model.getList().stream().filter(TableEntity::isSelect).map(VcsTableEntity::getEntity).collect(Collectors.toList());
if (selectList.size() > 0) {
int selVal = FineJOptionPane.showConfirmDialog(
RecyclePane.this,
isDelete ? getDeleteTip(selectList.size()) : getRestoreTip(selectList.size()),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (selVal == JOptionPane.YES_OPTION) {
tableEntities = model.getList().stream().filter(tableEntity -> !tableEntity.isSelect()).collect(Collectors.toList());
model.setList(tableEntities);
model.fireTableDataChanged();
listener.doAfterChooseYes(selectList);
}
}
}
/**
* 显示弹窗
*
*/
public void showDialog() {
dialog = this.showWindow(DesignerContext.getDesignerFrame(), false);
dialog.setVisible(true);
}
/**
* 依据父弹窗显示弹窗
*
* @param parent 父弹窗
*/
public void showDialog(BasicDialog parent) {
this.parentDialog = parent;
dialog = this.showWindow(parent, false);
initDialogListener(dialog);
dialog.setVisible(true);
}
protected void initDialogListener(BasicDialog dialog) {
}
/**
* 关闭弹窗,如果有父弹窗,则一起关闭,如果有属性配置的弹窗面板要保存再关闭
*
*/
public void saveSettingAndCloseDialog() {
if (dialog != null) {
dialog.doOK();
dialog.dispose();
}
if (parentDialog != null) {
parentDialog.doOK();
parentDialog.dispose();
}
}
public BasicDialog getDialog() {
return dialog;
}
public void setDialog(BasicDialog dialog) {
this.dialog = dialog;
}
public BasicDialog getParentDialog() {
return parentDialog;
}
public void setParentDialog(BasicDialog parentDialog) {
this.parentDialog = parentDialog;
}
/**
* 删除范围
*
* @return 默认删除全部版本
*/
protected boolean isNeedDeleteAllVersion() {
return true;
}
@Override
protected String title4PopupWindow() {
return i18nText("Fine-Design_Vcs_Recycle");
}
/**
* 删除提示
*
* @return 默认需要
*/
protected String getDeleteTip(int size) {
return Toolkit.i18nText("Fine-Design_Vcs_Delete_Select_All_Version_Forever", size);
}
/**
* 还原提示
*
* @return 默认需要
*/
protected String getRestoreTip(int size) {
return Toolkit.i18nText("Fine-Design_Vcs_Restore_Select_All_Version", size);
}
/**
* 是否需要还原功能
*
* @return 默认需要
*/
protected boolean isNeedRestore() {
return true;
}
/**
* 是否需要搜索功能
*
* @return 默认需要
*/
protected boolean isNeedSearch() {
return true;
}
/**
* 是否需要删除功能
*
* @return 默认需要
*/
protected boolean isNeedDelete() {
return true;
}
/**
* 更新数据列表
*
* @param entities
*/
public void updateTableList(List<VcsTableEntity> entities) {
tableEntities = entities;
}
/**
* 移除指定元素
*
* @param entity
*/
public void removeTarget(VcsTableEntity entity) {
tableEntities.remove(entity);
}
/**
* 版本管理按钮事件响应
*/
public interface VcsResponseListener {
/**
* 选择确认之后要做的事情
*
* @param selectList 所选上的内容
*/
void doAfterChooseYes(List<VcsEntity> selectList);
}
}

103
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecycleSettingPane.java

@ -0,0 +1,103 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.frpane.UITabbedPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
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.VerticalFlowLayout;
import com.fr.design.mainframe.vcs.VcsRecycleSettingHelper;
import com.fr.workspace.server.vcs.VcsConfig;
import javax.swing.JPanel;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* 回收站配置面板
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/21
*/
public class RecycleSettingPane extends BasicPane {
private static final int MIN_VALUE = 1;
private static final int MAX_VALUE = 999;
private static final int STEP = 1;
private static final int DEFAULT_VALUE = 30;
private UISpinner spinner;
private UIButton button;
public RecycleSettingPane() {
init();
}
private void init() {
this.setLayout(new BorderLayout());
UITabbedPane tabbedPane = new UITabbedPane();
//回收站内容
JPanel recyclePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
UIScrollPane recycleScrollPane = patchScroll(recyclePane);
tabbedPane.addTab(Toolkit.i18nText("Fine-Design_Vcs_Recycle_Content"), recycleScrollPane);
recyclePane.add(new RecyclePane());
//通用设置
JPanel settingPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
UIScrollPane settingScrollPane = patchScroll(settingPane);
tabbedPane.addTab(Toolkit.i18nText("Fine-Design_Basic_Carton_General_Settings"), settingScrollPane);
settingPane.add(createSchedulePane());
this.add(tabbedPane, BorderLayout.CENTER);
}
private JPanel createSchedulePane() {
JPanel schedulePane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 0);
JPanel spinnerPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane_First0();
JPanel buttonPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane_First0();
spinnerPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Recycle_Schedule")));
spinner = new UISpinner(MIN_VALUE, MAX_VALUE, STEP, DEFAULT_VALUE);
spinner.setValue(VcsConfig.getInstance().getV2CleanRecycleInterval());
spinnerPane.add(spinner);
spinnerPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Recycle_Schedule_Day")));
schedulePane.add(spinnerPane);
button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Save"));
initButtonListener();
buttonPane.add(button);
schedulePane.add(buttonPane);
return schedulePane;
}
private void initButtonListener() {
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
VcsRecycleSettingHelper.updateJob((int) spinner.getValue());
}
});
}
private UIScrollPane patchScroll(JPanel generalPane) {
UIScrollPane generalPanelWithScroll = new UIScrollPane(generalPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
generalPanelWithScroll.setBorder(new EmptyBorder(0, 0, 0, 0));
return generalPanelWithScroll;
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Vcs_Recycle");
}
}

32
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/ToolTipTableCellRenderer.java

@ -0,0 +1,32 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.general.GeneralUtils;
import com.fr.stable.StringUtils;
import javax.swing.JTable;
import javax.swing.JLabel;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
/**
* 带ToolTip的UILabel的表格渲染类
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/21
*/
public class ToolTipTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(component instanceof JLabel) {
String toolTipText = GeneralUtils.objectToString(value);
if (StringUtils.isNotEmpty(toolTipText)) {
((JLabel) component).setToolTipText(toolTipText);
}
}
return component;
}
}

59
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntEditor.java

@ -0,0 +1,59 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.editor.editor.IntegerEditor;
import com.fr.design.gui.itextfield.UIIntNumberField;
import com.fr.design.gui.itextfield.UINumberField;
import com.fr.stable.StringUtils;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
/**
* 正整数输入框
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/25
*/
public class UIPositiveIntEditor extends IntegerEditor {
private static final int DEFAULT_COLUMNS = 4;
private static final int MIN = 1;
private static final int MAX = 99999;
private static final int DEFAULT_VALUE = 60;
public UIPositiveIntEditor(Integer value) {
super(value);
numberField.setMaxValue(MAX);
numberField.setMinValue(MIN);
initNumberFieldListener();
}
public UIPositiveIntEditor(Integer value, Integer min, Integer max) {
super(value);
numberField.setMaxValue(max);
numberField.setMinValue(min);
initNumberFieldListener();
}
private void initNumberFieldListener() {
numberField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
if (StringUtils.isEmpty(numberField.getTextValue())) {
numberField.setValue(DEFAULT_VALUE);
}
}
});
}
@Override
protected UINumberField createNumberField() {
UIIntNumberField field = new UIIntNumberField();
field.setColumns(DEFAULT_COLUMNS);
return field;
}
}

39
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntSpinner.java

@ -0,0 +1,39 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.gui.itextfield.UIIntNumberField;
import com.fr.design.gui.itextfield.UINumberField;
/**
* 只允许输入正整数的Spinner
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/25
*/
public class UIPositiveIntSpinner extends UISpinner {
private static final int DEFAULT_COLUMNS = 5;
public UIPositiveIntSpinner() {
}
public UIPositiveIntSpinner(double minValue, double maxValue, double dierta) {
super(minValue, maxValue, dierta);
}
public UIPositiveIntSpinner(double minValue, double maxValue, double dierta, double defaultValue) {
super(minValue, maxValue, dierta, defaultValue);
}
public UIPositiveIntSpinner(double minValue, double maxValue, double dierta, double defaultValue, boolean fillNegativeNumber) {
super(minValue, maxValue, dierta, defaultValue, fillNegativeNumber);
}
@Override
protected UINumberField initNumberField() {
UIIntNumberField field = new UIIntNumberField();
field.setColumns(DEFAULT_COLUMNS);
return field;
}
}

156
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsBatchProcessDetailPane.java

@ -0,0 +1,156 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 处理结果详细面板
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/19
*/
public class VcsBatchProcessDetailPane {
private UILabel message = new UILabel();
private UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Report_OK"));
private UILabel uiLabel = new UILabel();
private UILabel directUiLabel = new UILabel();
private UILabel detailLabel = new UILabel();
private JPanel upPane;
private JPanel midPane;
private JPanel downPane;
private JPanel hiddenPanel;
private JTextArea jta;
private JDialog dialog;
public static final Dimension DEFAULT = new Dimension(380, 150);
public static final Dimension DEFAULT_PRO = new Dimension(380, 270);
public VcsBatchProcessDetailPane(Frame parent, String title, String msg) {
init(parent, title, msg);
}
private void init(Frame parent, String title, String msg) {
message.setBorder(BorderFactory.createEmptyBorder(8, 5, 0, 0));
message.setText(msg);
dialog = new JDialog(parent, title, true);
dialog.setSize(DEFAULT);
JPanel jp = new JPanel();
initUpPane();
initDownPane();
initMidPane();
initHiddenPanel();
initListener();
jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS));
jp.add(upPane);
jp.add(midPane);
jp.add(hiddenPanel);
jp.add(downPane);
hiddenPanel.setVisible(false);
dialog.add(jp);
dialog.setResizable(false);
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(parent));
}
private void initDownPane() {
downPane = new JPanel();
downPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 9));
downPane.add(cancelButton);
}
private void initUpPane() {
upPane = new JPanel();
uiLabel = new UILabel(UIManager.getIcon("OptionPane.errorIcon"));
upPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
upPane.add(uiLabel);
upPane.add(message);
}
private void initMidPane() {
midPane = new JPanel();
midPane.add(directUiLabel);
midPane.add(detailLabel);
midPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0));
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Look_Detail"));
detailLabel.setForeground(Color.BLUE);
detailLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right"));
}
private void initHiddenPanel() {
hiddenPanel = new JPanel();
hiddenPanel.setLayout(new BorderLayout(2, 0));
hiddenPanel.add(new JPanel(), BorderLayout.WEST);
hiddenPanel.add(new JPanel(), BorderLayout.EAST);
JPanel borderPanel = new JPanel();
borderPanel.setLayout(new BorderLayout());
jta = new JTextArea();
JScrollPane jsp = new JScrollPane(jta);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jta.setEditable(false);
borderPanel.add(jsp, BorderLayout.CENTER);
hiddenPanel.add(borderPanel);
}
/**
* 补充更详细的报错信息
*
* @param message 信息
*/
public void updateDetailArea(String message) {
jta.append(message + "\n");
}
private void initListener() {
detailLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (hiddenPanel.isVisible()) {
hiddenPanel.setVisible(false);
dialog.setSize(DEFAULT);
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Look_Detail"));
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right"));
} else {
dialog.setSize(DEFAULT_PRO);
hiddenPanel.setVisible(true);
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Hide_Detail"));
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.down"));
}
}
});
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
hiddenPanel.removeAll();
dialog.dispose();
}
});
}
/**
* 显示面板
*/
public void show() {
dialog.setVisible(true);
}
}

35
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellEditor.java

@ -0,0 +1,35 @@
package com.fr.design.mainframe.vcs.ui;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import java.awt.*;
import static com.fr.design.mainframe.vcs.ui.AbstractSupportSelectTablePane.DEFAULT_SELECT_TABLE_ROW_COLOR;
/**
* Vcs的表格Editor
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/20
*/
public class VcsCellEditor extends AbstractCellEditor implements TableCellEditor {
private final VcsOperatorPane vcsPanel;
public VcsCellEditor(VcsOperatorPane vcsPanel) {
this.vcsPanel = vcsPanel;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
vcsPanel.setBackground(isSelected ? DEFAULT_SELECT_TABLE_ROW_COLOR : Color.WHITE);
return vcsPanel;
}
@Override
public Object getCellEditorValue() {
return vcsPanel;
}
}

29
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellRender.java

@ -0,0 +1,29 @@
package com.fr.design.mainframe.vcs.ui;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import static com.fr.design.mainframe.vcs.ui.AbstractSupportSelectTablePane.DEFAULT_SELECT_TABLE_ROW_COLOR;
/**
* Vcs的表格Render
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/20
*/
public class VcsCellRender implements TableCellRenderer {
private final VcsOperatorPane vcsPanel;
public VcsCellRender(VcsOperatorPane vcsPanel) {
this.vcsPanel = vcsPanel;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
vcsPanel.setBackground(isSelected ? DEFAULT_SELECT_TABLE_ROW_COLOR : Color.WHITE);
return vcsPanel;
}
}

227
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCenterPane.java

@ -0,0 +1,227 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.vcs.VcsOperatorWorker;
import com.fr.design.mainframe.vcs.VcsTableEntity;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.report.entity.VcsEntity;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
/**
* 版本中心面板
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/13
*/
public class VcsCenterPane extends VcsNewPane {
private UILabel manager;
private UILabel open;
private UILabel delete;
private static final Icon MANAGER_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_center_manager");
private static final Icon DELETE_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_delete");
private static final Icon OPEN_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_center_open");
private static final Class[] CLASSES = new Class[]{
Boolean.class,
UILabel.class,
UILabel.class,
UILabel.class,
VcsOperatorPane.class
};
private static final int OPERATOR_COL = 4;
private static final String[] COLUMN_NAMES = new String[]{
StringUtils.EMPTY,
Toolkit.i18nText("Fine-Design_Vcs_Template"),
Toolkit.i18nText("Fine-Design_Vcs_Time"),
Toolkit.i18nText("Fine-Design_Vcs_Size"),
Toolkit.i18nText("Fine-Design_Vcs_Operator")
};
private static final String TITLE = Toolkit.i18nText("Fine-Design_Vcs_Center");
public VcsCenterPane() {
super(TITLE, (o, columnIndex) -> {
switch (columnIndex) {
case 0:
return o.isSelect();
case 1:
return o.getFilename();
case 2:
return o.getTime();
case 3:
return o.getSize();
default:
return o;
}
}, false, COLUMN_NAMES, CLASSES, OPERATOR_COL);
}
@Override
public VcsOperatorPane createOperatorPane() {
manager = new UILabel(MANAGER_ICON);
manager.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Manager"));
open = new UILabel(OPEN_ICON);
open.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Open"));
delete = new UILabel(DELETE_ICON);
delete.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Delete"));
initManagerListener();
initOpenListener();
initDeleteListener();
List<JComponent> components = new ArrayList<>();
components.add(manager);
components.add(open);
components.add(delete);
return new VcsOperatorPane(components);
}
private void initDeleteListener() {
delete.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = tableContentPane.getEditTable();
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn());
if (o instanceof VcsTableEntity) {
VcsEntity entity = ((VcsTableEntity) o).getEntity();
String fileName = entity.getFilename();
int selVal = FineJOptionPane.showConfirmDialog(
VcsCenterPane.this,
Toolkit.i18nText("Fine-Design_Vcs_Center_Delete", fileName),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (selVal == JOptionPane.YES_OPTION) {
VcsOperatorWorker.createDeleteWorker().doDelete(entity);
removeTarget((VcsTableEntity) o);
model.getList().remove(o);
model.fireTableDataChanged();
}
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(getTemplateTruePath(fileName), false)));
}
}
});
}
@Override
protected boolean needIcon4Head(int col) {
return col != 0 && col != OPERATOR_COL;
}
private void initOpenListener() {
open.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = tableContentPane.getEditTable();
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn());
if (o instanceof VcsTableEntity) {
VcsEntity entity = ((VcsTableEntity) o).getEntity();
saveSettingAndCloseDialog();
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(getTemplateTruePath(entity.getFilename()), false)));
}
}
});
}
private void initManagerListener() {
manager.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = tableContentPane.getEditTable();
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn());
if (o instanceof VcsTableEntity) {
VcsEntity entity = ((VcsTableEntity) o).getEntity();
VcsNewPane pane = new VcsNewPane(getTemplateTruePath(entity.getFilename())) {
@Override
protected String title4PopupWindow() {
return entity.getFilename()+Toolkit.i18nText("Fine-Design_Vcs_Version_Tips");
}
};
pane.showDialog(getDialog());
}
}
});
}
@Override
protected List<VcsTableEntity> getTableList() {
List<VcsEntity> entities = WorkContext.getCurrent().get(VcsOperator.class).getEveryVersion();
List<VcsTableEntity> tableEntities = new ArrayList<>();
for (VcsEntity entity : entities) {
tableEntities.add(new VcsTableEntity(entity));
}
updateTableList(tableEntities);
return tableEntities;
}
@Override
protected void initDialogListener(BasicDialog dialog) {
dialog.addDialogActionListener(new DialogActionAdapter() {
@Override
public void doOk() {
getParentDialog().doOK();
getParentDialog().dispose();
}
});
}
@Override
protected String title4PopupWindow() {
return TITLE;
}
private String getTemplateTruePath(String filename) {
return StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, filename);
}
@Override
protected String getDeleteTip(int size) {
return Toolkit.i18nText("Fine-Design_Vcs_Delete_Select_All_Version");
}
@Override
protected boolean isNeedTopPane() {
return true;
}
@Override
protected boolean isNeedRestore() {
return false;
}
@Override
protected boolean isNeedSearch() {
return true;
}
@Override
protected boolean isNeedDeleteAllVersion() {
return true;
}
}

489
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovePanel.java

@ -0,0 +1,489 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.ModernUIProgressBarUI;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.mainframe.vcs.VcsExceptionUtils;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.ThemeUtils;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.general.FRFont;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.server.vcs.v2.move.VcsMoveService;
import com.fr.workspace.server.vcs.v2.move.VcsMoveStrategy;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import static javax.swing.JOptionPane.YES_NO_CANCEL_OPTION;
import static javax.swing.JOptionPane.YES_OPTION;
/**
* 迁移面板
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/6/13
*/
public class VcsMovePanel extends BasicPane {
private static final FRFont FONT = DesignUtils
.getDefaultGUIFont()
.applySize(14)
.applyStyle(FRFont.BOLD);
private static final Color BACK_GROUND_COLOR = new Color(202,232,255);
//提示字体的颜色,直接模仿其他面板的写法
private static final Color TIP_COLOR = new Color(51, 51, 52, (int)Math.round(0.5 * 255));
private static final Color LABEL_COLOR = new Color(34,149,233);
private static final int MIN_VALUE = 1;
private static final int MAX_VALUE = 999;
private static final int STEP = 1;
private static final int DEFAULT_VALUE = 5;
public static final String SETTING = "SETTING";
public static final String PROCESS = "PROCESS";
public static final String SUCCESS = "SUCCESS";
public static final String FAILED = "FAILED";
public static boolean moving = false;
private BasicDialog parentDialog;
private UILabel vcsUpdateExistLabel = new UILabel();
private UILabel vcsUpdateFireLabel = new UILabel();
private UIButton centerButton;
private BasicPane choosePane;
private CardLayout parentCard;
private JPanel parentPane;
private static final JProgressBar PROGRESS_BAR = new JProgressBar();
private JPanel progressPanel;
private UILabel tipLabel;
private UIButton successButton;
private UILabel iconLabel;
private UILabel successLabel;
private UILabel successTipLabel;
private UIButton failedButton;
private UILabel failedIconLabel;
private UILabel failedLabel;
private UILabel failedTipLabel;
//保留全部
private UIRadioButton moveAllButton;
//默认选项,保留部分
private UIRadioButton moveDefaultButton;
//全部放弃
private UIRadioButton moveNothingButton;
private UIPositiveIntSpinner spinner;
private MoveCallBack callBack;
private JPanel updatePane;
private boolean visible = false;
public VcsMovePanel(CardLayout cardLayout, JPanel parentPane, MoveCallBack callBack, BasicDialog parentDialog) {
this.parentCard = cardLayout;
this.parentPane = parentPane;
this.callBack = callBack;
this.setLayout(new BorderLayout());
this.parentDialog = parentDialog;
updatePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane();
updatePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 0));
//初始化顶部的面板
initVcsLabel(updatePane);
//initVcsChoosePane
initVcsChoosePane();
//初始化listener
initListener();
this.add(updatePane);
checkVisible();
//如果已经在迁移
if (VcsMoveService.getInstance().isMoving()) {
initProcessPane();
VcsMovePanel.this.getParentCard().show(getParentPane(), PROCESS);
}
}
private void checkVisible() {
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
return VcsHelper.getInstance().checkMoveFunctionSupport();
}
@Override
protected void done() {
try {
boolean useMove = get();
VcsMovePanel.this.setVisible(useMove);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
private void initProcessPane() {
JPanel processPane = new JPanel();
JPanel body = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
PROGRESS_BAR.setStringPainted(true);
PROGRESS_BAR.setUI(new ModernUIProgressBarUI());
PROGRESS_BAR.setBorderPainted(false);
PROGRESS_BAR.setOpaque(false);
PROGRESS_BAR.setBorder(null);
PROGRESS_BAR.setSize(BasicDialog.MEDIUM);
body.add(PROGRESS_BAR);
body.add(new UILabel(StringUtils.BLANK));
tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_While_Moving"));
tipLabel.setAlignmentX(CENTER_ALIGNMENT);
body.add(tipLabel);
processPane.add(body);
processPane.setLayout(FRGUIPaneFactory.createCenterLayout(body, 0.5f, 0.5f));
parentPane.add(processPane, PROCESS);
}
private void initVcsChoosePane() {
choosePane = new BasicPane() {
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Vcs_Deal_With_Entry");
}
};
VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP);
layout.setAlignLeft(true);
choosePane.setLayout(layout);
//初始化上方的文字板块
initTopDesc();
//初始化中间区域的单选框
initRadioButton();
//初始化下方的Tip描述
initTipDesc();
}
private void initTopDesc() {
UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_How_To_Deal_With_Entry"));
choosePane.add(label);
}
private void initTipDesc() {
UILabel descLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Desc"));
UILabel firstLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Tips_First"));
UILabel secondLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Tips_Second"));
descLabel.setForeground(TIP_COLOR);
firstLabel.setForeground(TIP_COLOR);
secondLabel.setForeground(TIP_COLOR);
choosePane.add(descLabel);
choosePane.add(firstLabel);
choosePane.add(secondLabel);
}
private void initRadioButton() {
//保留全部
moveAllButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Vcs_Move_All"));
//默认选项,保留部分
moveDefaultButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Vcs_Move_Default"));
//全部放弃
moveNothingButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Vcs_Move_Nothing"));
// 将按钮"保留部分"设置为选中状态
moveDefaultButton.setSelected(true);
// 创建一个按钮组,添加三个按钮
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(moveAllButton);
buttonGroup.add(moveDefaultButton);
buttonGroup.add(moveNothingButton);
JPanel moveDefaultPanel = new JPanel();
JPanel moveAllPane = new JPanel();
JPanel moveNothingPane = new JPanel();
moveAllPane.add(moveAllButton);
moveDefaultPanel.add(moveDefaultButton);
moveDefaultPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Default_Text_Left")));
spinner = new UIPositiveIntSpinner(MIN_VALUE, MAX_VALUE, STEP, DEFAULT_VALUE);
moveDefaultPanel.add(spinner);
moveDefaultPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Default_Text_Right")));
moveNothingPane.add(moveNothingButton);
choosePane.add(moveAllPane);
choosePane.add(moveDefaultPanel);
choosePane.add(moveNothingPane);
}
private void initVcsLabel(JPanel parent) {
parent.removeAll();
if (!VcsHelper.getInstance().isLegacyMode()) {
parent.setBackground(ThemeUtils.BACK_COLOR);
centerButton = new UIButton(Toolkit.i18nText("Fine-Design_Vcs_Center"));
parent.add(centerButton);
initVcsCenterListener();
} else {
parent.setBackground(BACK_GROUND_COLOR);
vcsUpdateExistLabel = new UILabel(IconUtils.readIcon("/com/fr/design/vcs/vcs_move_icon.svg"));
vcsUpdateExistLabel.setText(Toolkit.i18nText("Fine-Design_Vcs_Can_Update"));
vcsUpdateFireLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Update"));
vcsUpdateFireLabel.setForeground(LABEL_COLOR);
vcsUpdateFireLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
parent.add(vcsUpdateExistLabel);
parent.add(vcsUpdateFireLabel);
}
}
private void initVcsCenterListener() {
centerButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
VcsCenterPane vcsCenterPane = new VcsCenterPane();
vcsCenterPane.showDialog(parentDialog);
}
});
}
private void initListener() {
vcsUpdateFireLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
BasicDialog dlg = choosePane.showMediumWindow(SwingUtilities.getWindowAncestor(VcsMovePanel.this), new DialogActionAdapter() {
@Override
public void doOk() {
createConfirmPane();
}
});
dlg.setVisible(true);
}
});
}
private void createConfirmPane() {
VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP);
layout.setAlignLeft(true);
JPanel panel = new JPanel();
panel.setLayout(layout);
UILabel titleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Tip_Title"));
UILabel firstLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Tip_First"));
UILabel secondLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Tip_Second"));
titleLabel.setForeground(TIP_COLOR);
firstLabel.setForeground(TIP_COLOR);
secondLabel.setForeground(TIP_COLOR);
panel.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Right_Now")));
panel.add(titleLabel);
panel.add(firstLabel);
panel.add(secondLabel);
int value = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(DesignerContext.getDesignerFrame()), panel, Toolkit.i18nText("Fine-Design_Vcs_Move_Title"), JOptionPane.YES_NO_OPTION);
processMove(value);
}
private void processMove(int value) {
if (value == YES_OPTION) {
//进度条面板
initProcessPane();
VcsMovePanel.this.getParentCard().next(getParentPane());
VcsMoveStrategy strategy;
if (moveDefaultButton.isSelected()) {
strategy = VcsMoveStrategy.createStrategy((int) spinner.getValue());
} else if (moveNothingButton.isSelected()) {
strategy = VcsMoveStrategy.createStrategy(0);
} else {
strategy = VcsMoveStrategy.createStrategy(Integer.MAX_VALUE);
}
new MoveWorker(strategy).execute();
}
}
private void initSuccessPane() {
JPanel successPane = new JPanel();
JPanel body = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
successButton = new UIButton(Toolkit.i18nText("Fine-Design_Vcs_Move_Success_Go"));
initSuccessButtonListener();
iconLabel = new UILabel(IconUtils.readIcon("/com/fr/design/vcs/move_success.svg"));
successLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Success"));
successLabel.setFont(FONT);
successTipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Success_Tip"));
initStatusPane(successTipLabel, iconLabel, successLabel, successButton, body, SUCCESS, successPane);
}
private void initSuccessButtonListener() {
successButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doAfterMove();
}
});
}
private void initFailedButtonListener() {
failedButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doAfterMove();
}
});
}
private void doAfterMove() {
visible = !VcsHelper.getInstance().isLegacyMode();
initVcsLabel(updatePane);
updatePane.setVisible(visible);
callBack.doCallBack(visible);
parentCard.show(parentPane, SETTING);
}
public BasicDialog getParentDialog() {
return parentDialog;
}
public void setParentDialog(BasicDialog parentDialog) {
this.parentDialog = parentDialog;
}
@Override
protected String title4PopupWindow() {
return StringUtils.EMPTY;
}
public CardLayout getParentCard() {
return parentCard;
}
public JPanel getParentPane() {
return parentPane;
}
private void initFailedPane(String detail) {
JPanel failedPane = new JPanel();
JPanel body = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
failedButton = new UIButton(Toolkit.i18nText("Fine-Design_Vcs_Move_Failed_Go"));
initFailedButtonListener();
failedIconLabel = new UILabel(IconUtils.readIcon("/com/fr/design/vcs/move_failed.svg"));
failedLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Failed"));
failedLabel.setFont(FONT);
failedTipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Failed_Tip", detail));
initStatusPane(failedTipLabel, failedIconLabel, failedLabel, failedButton, body, FAILED, failedPane);
}
private void initStatusPane(UILabel tipLabel, UILabel iconLabel, UILabel label, UIButton button, JPanel body, String tag,JPanel statusPane) {
tipLabel.setForeground(TIP_COLOR);
body.add(iconLabel);
body.add(new UILabel(StringUtils.BLANK));
body.add(label);
body.add(new UILabel(StringUtils.BLANK));
body.add(tipLabel);
body.add(new UILabel(StringUtils.BLANK));
body.add(button);
statusPane.add(body);
statusPane.setLayout(FRGUIPaneFactory.createCenterLayout(body, 0.5f, 0.5f));
parentPane.add(statusPane, tag);
iconLabel.setAlignmentX(CENTER_ALIGNMENT);
label.setAlignmentX(CENTER_ALIGNMENT);
button.setAlignmentX(CENTER_ALIGNMENT);
tipLabel.setAlignmentX(CENTER_ALIGNMENT);
}
private class MoveWorker extends SwingWorker<Boolean, Integer> {
private VcsMoveStrategy strategy;
private String detail = StringUtils.EMPTY;
public MoveWorker(VcsMoveStrategy strategy) {
this.strategy = strategy;
}
@Override
protected Boolean doInBackground() throws Exception {
try {
//开始迁移
VcsMoveService.getInstance().startMove(new VcsMoveService.BaseMoveServiceWhileMoving() {
@Override
public void publishProgress() {
int num = VcsMoveService.getInstance().getCurrentMove();
publish(num);
}
@Override
public void prepare4Move() {
PROGRESS_BAR.setMaximum(VcsMoveService.getInstance().getTotal());
}
}, strategy);
} catch (Exception e) {
VcsMoveService.getInstance().stopMoving();
detail = VcsExceptionUtils.createDetailByException(e);
return false;
}
return true;
}
@Override
protected void process(List<Integer> chunks) {
PROGRESS_BAR.setValue(chunks.get(chunks.size() - 1));
}
@Override
protected void done() {
VcsMoveService.getInstance().stopMoving();
try {
if (get()) {
initSuccessPane();
VcsMovePanel.this.getParentCard().show(getParentPane(), SUCCESS);
VcsHelper.getInstance().updateLegacyMode();
DesignerFrameFileDealerPane.getInstance().refreshDockingView();
} else {
initFailedPane(detail);
VcsMovePanel.this.getParentCard().show(getParentPane(), FAILED);
FineLoggerFactory.getLogger().error("[VcsV2] Vcs move failed!");
}
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
/**
* 迁移回调事件
*
*/
public static class MoveCallBack {
/**
* 处理回调
*/
public void doCallBack(boolean visible){}
}
}

54
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovingExitOption.java

@ -0,0 +1,54 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.workspace.server.vcs.v2.move.VcsMoveService;
import javax.swing.JOptionPane;
/**
* 版本管理迁移检查
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/18
*/
public class VcsMovingExitOption {
/**
* 关闭前的检查
*
* @return
*/
public static boolean ShowDialogAndConfirmExit() {
return showDialogAndChoose(Toolkit.i18nText("Fine-Design_Vcs_Close_Tips"));
}
/**
* 切换环境前的检查
*
* @return
*/
public static boolean ShowDialogAndConfirmSwitch() {
return showDialogAndChoose(Toolkit.i18nText("Fine-Design_Vcs_Switch_Tips"));
}
private static boolean showDialogAndChoose(String msg) {
if (VcsMoveService.getInstance().isMoving()) {
int result = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
msg,
Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
FineJOptionPane.YES_NO_OPTION
);
return result == JOptionPane.YES_OPTION;
}
return true;
}
}

350
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsNewPane.java

@ -0,0 +1,350 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MultiTemplateTabPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.vcs.TableValueOperator;
import com.fr.design.mainframe.vcs.VcsOperatorWorker;
import com.fr.design.mainframe.vcs.VcsTableEntity;
import com.fr.design.mainframe.vcs.common.VcsCacheFileNodeFile;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.report.entity.VcsEntity;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
* 版本管理交互优化新面板
* <li>采用表格的形式展现</li>
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/11
*/
public class VcsNewPane extends RecyclePane {
private String filePath = StringUtils.EMPTY;
protected static int OPERATOR_COL = 5;
protected static int EDIT_COL = 4;
private static final int DOUBLE_CLICK_COUNT = 2;
protected VcsOperatorPane operatorPane;
private static final Icon PREVIEW_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_preview");
private static final Icon DELETE_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_delete");
private static final Icon RESTORE_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_restore");
private UILabel restore;
private UILabel delete;
private UILabel preview;
private static final String TITLE = Toolkit.i18nText("Fine-Design_Vcs_Title");
private static final String[] COLUMN_NAMES = new String[]{
StringUtils.EMPTY,
Toolkit.i18nText("Fine-Design_Vcs_Version"),
Toolkit.i18nText("Fine-Design_Vcs_Time"),
Toolkit.i18nText("Fine-Design_Vcs_User"),
Toolkit.i18nText("Fine-Design_Vcs_Annotation"),
Toolkit.i18nText("Fine-Design_Vcs_Operator")
};
private static final Class[] CLASSES = new Class[]{
Boolean.class,
UILabel.class,
UILabel.class,
UILabel.class,
UILabel.class,
VcsOperatorPane.class
};
public VcsNewPane(String filePath) {
super(TITLE, (o, columnIndex) -> {
switch (columnIndex) {
case 0:
return o.isSelect();
case 1:
return o.getVersion();
case 2:
return o.getTime();
case 3:
return o.getUserName();
case 4:
return o.getCommitMsg();
default:
return o;
}
}, false);
this.filePath = filePath;
initModel(COLUMN_NAMES, CLASSES, OPERATOR_COL);
}
private void initModel(String[] columns, Class[] classes, int operatorCol) {
this.model = new DefaultModel(columns, classes) {
@Override
public boolean isCellEditable(int row, int col) {
return col == 0 || col == operatorCol;
}
};
this.operatorPane = createOperatorPane();
this.model.setDefaultEditor(VcsOperatorPane.class, new VcsCellEditor(createOperatorPane()));
this.model.setDefaultRenderer(VcsOperatorPane.class, new VcsCellRender(createOperatorPane()));
this.model.setDefaultRenderer(UILabel.class, new ToolTipTableCellRenderer());
}
public VcsNewPane(String title, TableValueOperator<VcsTableEntity> operators, boolean needBorder, String[] columns, Class[] classes, int operatorCol) {
super(title, operators, needBorder);
initModel(columns, classes, operatorCol);
}
/**
* 创建操作面板
*
* @return 操作面板
*/
public VcsOperatorPane createOperatorPane() {
restore = new UILabel(RESTORE_ICON);
restore.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Restore"));
delete = new UILabel(DELETE_ICON);
delete.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Delete"));
preview = new UILabel(PREVIEW_ICON);
preview.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_ToolTip_Preview"));
initPreviewListener();
initDeleteListener();
initRestoreListener();
List<JComponent> list = new ArrayList<>();
list.add(restore);
list.add(delete);
list.add(preview);
return new VcsOperatorPane(list);
}
private void initRestoreListener() {
restore.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = tableContentPane.getEditTable();
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn());
if (o instanceof VcsTableEntity) {
VcsEntity entity = ((VcsTableEntity) o).getEntity();
int selVal = FineJOptionPane.showConfirmDialog(
VcsNewPane.this,
Toolkit.i18nText("Fine-Design_Vcs_Restore_This_Version_Tips"),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (selVal == JOptionPane.YES_OPTION) {
restoreEntity(entity);
VcsNewPane.this.saveSettingAndCloseDialog();
}
}
}
});
}
private void restoreEntity(VcsEntity entity) {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
//step1.设置还原的用户名
entity.setUsername(VcsHelper.getInstance().getCurrentUsername());
//step2.rollback到指定版本
WorkContext.getCurrent().get(VcsOperator.class).rollbackTo(entity);
return null;
}
@Override
protected void done() {
//step3.如果原来原模板已经打开则关闭原模板,打开rollback后的新模板
List<JTemplate<?, ?>> templateList = HistoryTemplateListCache.getInstance().getHistoryList();
for (JTemplate<?, ?> template : templateList) {
if (StringUtils.equals(filePath, template.getPath())) {
MultiTemplateTabPane.getInstance().setIsCloseCurrent(HistoryTemplateListCache.getInstance().isCurrentEditingFile(filePath));
MultiTemplateTabPane.getInstance().closeFormat(template);
MultiTemplateTabPane.getInstance().closeSpecifiedTemplate(template);
break;
}
}
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(filePath, false)));
}
}.execute();
}
private void initDeleteListener() {
delete.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = tableContentPane.getEditTable();
int row = table.getEditingColumn();
Object o = table.getValueAt(table.getEditingRow(), row);
if (o instanceof VcsTableEntity) {
VcsEntity entity = ((VcsTableEntity) o).getEntity();
int selVal = FineJOptionPane.showConfirmDialog(
VcsNewPane.this,
Toolkit.i18nText("Fine-Design_Vcs_Delete_This_Version_Tips"),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (selVal == JOptionPane.YES_OPTION) {
model.getList().remove(o);
model.fireTableDataChanged();
VcsOperatorWorker.createDeleteWorker().deleteTargetVersion(entity);
}
}
}
});
}
private void initPreviewListener() {
preview.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JTable table = tableContentPane.getEditTable();
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn());
if (o instanceof VcsTableEntity) {
VcsEntity entity = ((VcsTableEntity) o).getEntity();
previewEntity(entity);
VcsNewPane.this.saveSettingAndCloseDialog();
}
}
});
}
private void previewEntity(VcsEntity entity) {
new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws Exception {
//step1.将指定版本的历史文件读取出来,加上前缀放到cache中
VcsOperator vcsOperator = WorkContext.getCurrent().get(VcsOperator.class);
String fileOfVersion = vcsOperator.getFileOfFileVersion(
entity.getFilename(),
entity.getVersion(),
Toolkit.i18nText("Fine-Design_Vcs_Prefix", entity.getVersion()));
return fileOfVersion;
}
@Override
protected void done() {
try {
//step2.再打开cache中的模板
DesignerContext.getDesignerFrame().openTemplate(new VcsCacheFileNodeFile(new FileNode(get(), false)));
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
@Override
protected boolean isNeedDeleteAllVersion() {
return false;
}
@Override
protected List<VcsTableEntity> getTableList() {
List<VcsEntity> entityList = WorkContext.getCurrent().get(VcsOperator.class).getVersions(VcsHelper.getInstance().dealWithFilePath(filePath));
List<VcsTableEntity> tableEntities = new ArrayList<>();
for (VcsEntity entity : entityList) {
tableEntities.add(new VcsTableEntity(entity));
}
return tableEntities;
}
@Override
protected String title4PopupWindow() {
return TITLE;
}
@Override
protected String getDeleteTip(int size) {
return Toolkit.i18nText("Fine-Design_Vcs_Delete_Versions_Tips", size);
}
@Override
protected boolean isNeedRestore() {
return false;
}
@Override
protected boolean isNeedSearch() {
return false;
}
@Override
protected void initExtraListener4Table(JTable table) {
table.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Point point = e.getPoint();
int row = table.rowAtPoint(point);
int col = table.columnAtPoint(point);
if (col != 0) {
table.editCellAt(row, col);
}
}
});
initEditListener(table);
}
private void initEditListener(JTable table) {
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == DOUBLE_CLICK_COUNT) {
Point point = e.getPoint();
int row = table.rowAtPoint(point);
int col = table.columnAtPoint(point);
if (col == EDIT_COL) {
Object o = table.getValueAt(row, OPERATOR_COL);
if (o instanceof VcsTableEntity) {
showDialog(((VcsTableEntity) o).getEntity());
}
}
}
}
});
}
private void showDialog(VcsEntity entity) {
EditFileVersionDialog dialog = new EditFileVersionDialog(entity) {
@Override
public void doOK() {
entity.setCommitMsg(getMsgTestArea().getText());
VcsOperatorWorker.createUpdateWorker().updateEntityAnnotation(entity);
setVisible(false);
model.fireTableDataChanged();
}
};
dialog.setVisible(true);
}
@Override
protected boolean needIcon4Head(int col) {
return col != 0 && col != OPERATOR_COL;
}
}

40
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsOperatorPane.java

@ -0,0 +1,40 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.layout.FRGUIPaneFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import java.awt.*;
import java.util.List;
/**
* 操作面板用于置放常用的操作label
* <p>例如 删除还原预览打开模板等</p>
* <li>负责表格渲染 操作按钮置蓝+设定cursor</li>
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/13
*/
public class VcsOperatorPane extends JPanel {
public VcsOperatorPane(List<JComponent> iconJComponentMap) {
init(iconJComponentMap);
}
private void init(List<JComponent> iconJComponentMap) {
this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout());
for (JComponent value : iconJComponentMap) {
value.setCursor(new Cursor(Cursor.HAND_CURSOR));
this.add(value);
}
}
}

81
designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsProgressDialog.java

@ -0,0 +1,81 @@
package com.fr.design.mainframe.vcs.ui;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.ModernUIProgressBarUI;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.stable.StringUtils;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import static java.awt.Component.CENTER_ALIGNMENT;
/**
* Vcs操作进度条面板
*
* @author Destiny.Lin
* @since 11.0
* Created on 2023/7/18
*/
public class VcsProgressDialog{
private JProgressBar progressBar = new JProgressBar();
private UILabel tipLabel;
private BasicPane processPane;
private BasicDialog dialog;
public VcsProgressDialog(String title, String dealingStr) {
processPane = new BasicPane() {
@Override
protected String title4PopupWindow() {
return title;
}
};
JPanel body = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
progressBar.setStringPainted(true);
progressBar.setUI(new ModernUIProgressBarUI());
progressBar.setBorderPainted(false);
progressBar.setOpaque(false);
progressBar.setBorder(null);
progressBar.setSize(BasicDialog.MEDIUM);
progressBar.setValue(0);
body.add(progressBar);
body.add(new UILabel(StringUtils.BLANK));
tipLabel = new UILabel(dealingStr);
tipLabel.setAlignmentX(CENTER_ALIGNMENT);
body.add(tipLabel);
processPane.add(body);
processPane.setLayout(FRGUIPaneFactory.createCenterLayout(body, 0.5f, 0.5f));
}
/**
* 展示面板
*
*/
public void showDialog() {
dialog = processPane.showSmallWindow(DesignerContext.getDesignerFrame(), false);
dialog.setVisible(true);
}
/**
* 关闭面板
*
*/
public void closeDialog() {
dialog.setVisible(false);
}
public JProgressBar getProgressBar() {
return progressBar;
}
public void setProgressBar(JProgressBar progressBar) {
this.progressBar = progressBar;
}
}

13
designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java

@ -29,8 +29,8 @@ public class DataBindingEditor extends Editor<DataBinding> {
private final static int HORI_GAP = 1;
private final static int VER_GAP = 7;
private TableDataComboBox tableDataComboBox;
private LazyComboBox columnNameComboBox;
protected TableDataComboBox tableDataComboBox;
protected LazyComboBox columnNameComboBox;
private ItemListener tableDataComboBoxListener = new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
boolean isInit = columnNameComboBox.getSelectedIndex() == -1;
@ -87,9 +87,16 @@ public class DataBindingEditor extends Editor<DataBinding> {
}
});
columnNameComboBox.setEditable(true);
addComboBoxesAndSetPosition();
columnNameComboBox.addItemListener(columnNameComboboxListener);
}
/**
* 根据需求不同调整下拉框的位置
*/
protected void addComboBoxesAndSetPosition() {
this.add(tableDataComboBox, BorderLayout.NORTH);
this.add(columnNameComboBox, BorderLayout.CENTER);
columnNameComboBox.addItemListener(columnNameComboboxListener);
}
protected TableDataSource getTableDataSource() {

20
designer-base/src/main/java/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java

@ -5,6 +5,7 @@
package com.fr.design.mainframe.widget.editors;
import java.awt.Component;
import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@ -30,6 +31,7 @@ public class WidgetValueEditor extends AbstractPropertyEditor {
/**
* 根据类型创建
* 服务器 - 控件管理
* @param type 类型
* @param onlyServer 是否是服务器
* @return 编辑器
@ -41,7 +43,7 @@ public class WidgetValueEditor extends AbstractPropertyEditor {
case DataControl.TYPE_FORMULA:
return new FormulaEditor(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Parameter_Formula"));
case DataControl.TYPE_DATABINDING:
return onlyServer ? new ServerDataBindingEditor() : new DataBindingEditor();
return onlyServer ? new WidgetValueServerDataBindingEditor() : new WidgetValueDataBindingEditor();
case DataControl.TYPE_STRING:
return new TextEditor();
case DataControl.TYPE_BOOLEAN:
@ -70,6 +72,22 @@ public class WidgetValueEditor extends AbstractPropertyEditor {
}
return editor;
}
private static class WidgetValueDataBindingEditor extends DataBindingEditor {
@Override
protected void addComboBoxesAndSetPosition() {
this.add(tableDataComboBox, BorderLayout.CENTER);
this.add(columnNameComboBox, BorderLayout.EAST);
}
}
private static class WidgetValueServerDataBindingEditor extends ServerDataBindingEditor {
@Override
protected void addComboBoxesAndSetPosition() {
this.add(tableDataComboBox, BorderLayout.CENTER);
this.add(columnNameComboBox, BorderLayout.EAST);
}
}
public WidgetValueEditor(Object o) {
this(o, false);

4
designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java

@ -79,6 +79,7 @@ public class ColorSelectDialog extends MiddleChartDialog{
this.seletePane = seletePane;
initComponent();
this.pane.populate(initialColor);
this.setLocationRelativeTo(null);
}
private void initComponent() {
@ -87,7 +88,8 @@ public class ColorSelectDialog extends MiddleChartDialog{
this.setBasicDialogSize(545,500);
this.setResizable(false);
this.applyClosingAction();
this.applyEscapeAction();
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));

4
designer-base/src/main/resources/com/fr/design/images/buttonicon/new_other_normal.svg

@ -0,0 +1,4 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.5 15.6727V0.672668H11.2731L14.5 4.36054V15.6727H0.5Z" stroke="#333334"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 5.17267H6V7.17267H4V5.17267ZM3 4.17267H4H6H7V5.17267V7.17267V8.17267H6H4H3V7.17267V5.17267V4.17267ZM4 10.1727H6V12.1727H4V10.1727ZM3 9.17267H4H6H7V10.1727V12.1727V13.1727H6H4H3V12.1727V10.1727V9.17267ZM9 6.17267C9 6.72495 9.44772 7.17267 10 7.17267C10.5523 7.17267 11 6.72495 11 6.17267C11 5.62038 10.5523 5.17267 10 5.17267C9.44772 5.17267 9 5.62038 9 6.17267ZM10 4.17267C8.89543 4.17267 8 5.0681 8 6.17267C8 7.27724 8.89543 8.17267 10 8.17267C11.1046 8.17267 12 7.27724 12 6.17267C12 5.0681 11.1046 4.17267 10 4.17267ZM9 12.1727V10.1727H11V12.1727H9ZM8 9.17267H9H11H12V10.1727V12.1727V13.1727H11H9H8V12.1727V10.1727V9.17267Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 885 B

5
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_center_manager_normal.svg

@ -0,0 +1,5 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#231;&#137;&#136;&#230;&#156;&#172;&#231;&#174;&#161;&#231;&#144;&#134;">
<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M2 2.5H14V14.5H2V2.5ZM1 15.5V1.5H15V15.5H1ZM5.75 4.5H4.25L7.25 10.5H8.75L11.75 4.5H10.25L8 9L5.75 4.5ZM12 11.5V12.5H4V11.5H12Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

5
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_center_open_normal.svg

@ -0,0 +1,5 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#230;&#137;&#147;&#229;&#188;&#128;&#230;&#168;&#161;&#230;&#157;&#191;">
<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M8.55349 5.73077L8.25543 5.39831L6.55349 3.5H2V11.2333L2.875 7.5H9.90625H13V5.73077H9H8.55349ZM14 7.5H14.9729H16L15.7656 8.5L14.125 15.5H2.0271H1V14.5V3.5V2.5H2H7L9 4.73077H13H14V5.73077V7.5ZM2.26147 14.5L3.66772 8.5H9.90625H14.7385L13.3323 14.5H2.26147Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 523 B

7
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_operator_delete_normal.svg

@ -0,0 +1,7 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#229;&#136;&#160;&#233;&#153;&#164;">
<g id="icon/delete">
<path id="Combined-Shape" d="M11 1.5V3.5H15V4.5H13V15.5H3V4.5H1V3.5H5V1.5H11ZM12 4.5H4V14.5H12V4.5ZM7 6.5V12.5H6V6.5H7ZM10 6.5V12.5H9V6.5H10ZM10 2.5H6V3.5H10V2.5Z" fill="#333334"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 366 B

5
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_operator_preview_normal.svg

@ -0,0 +1,5 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#233;&#162;&#132;&#232;&#167;&#136;">
<path id="Combined Shape" fill-rule="evenodd" clip-rule="evenodd" d="M3 14.5H7V15.5H2V1.5H9H10L14 5.5V8.5H13V6.5H10H9V5.5V2.5H3V14.5ZM10 2.914V5.5H12.586L10 2.914ZM9.5 7.5C11.4329 7.5 13 9.06712 13 11C13 11.6067 12.8456 12.1774 12.5739 12.6749C12.6206 12.7078 12.6651 12.7452 12.7069 12.787L13.7129 13.793C14.1039 14.184 14.1039 14.816 13.7129 15.207C13.5179 15.402 13.2619 15.5 13.0059 15.5C12.7499 15.5 12.4939 15.402 12.2989 15.207L11.2929 14.201C11.2516 14.1599 11.2147 14.116 11.1821 14.07C10.6829 14.3441 10.1097 14.5 9.5 14.5C7.56712 14.5 6 12.9329 6 11C6 9.06712 7.56712 7.5 9.5 7.5ZM7 11.0006C7 9.62232 8.12167 8.50065 9.5 8.50065C10.8783 8.50065 12 9.62232 12 11.0006C12 12.379 10.8783 13.5006 9.5 13.5006C8.12167 13.5006 7 12.379 7 11.0006Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 929 B

5
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_operator_restore_normal.svg

@ -0,0 +1,5 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#229;&#136;&#183;&#230;&#150;&#176;">
<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M13.924 2.15774C13.924 1.82637 13.6553 1.55774 13.324 1.55774C12.9926 1.55774 12.724 1.82637 12.724 2.15774V4.59914C11.6284 3.54744 10.1397 2.90004 8.50002 2.90004C5.13109 2.90004 2.40002 5.6311 2.40002 9.00004C2.40002 12.369 5.13109 15.1 8.50002 15.1C11.1941 15.1 13.4787 13.354 14.2871 10.9335C14.3921 10.6191 14.2223 10.2793 13.908 10.1743C13.5937 10.0693 13.2538 10.239 13.1489 10.5533C12.4991 12.4989 10.6624 13.9 8.50002 13.9C5.79383 13.9 3.60002 11.7062 3.60002 9.00004C3.60002 6.29384 5.79383 4.10004 8.50002 4.10004C9.8643 4.10004 11.0983 4.65709 11.9873 5.55774H9.32397C8.9926 5.55774 8.72397 5.82637 8.72397 6.15774C8.72397 6.48911 8.9926 6.75774 9.32397 6.75774H13.324C13.6553 6.75774 13.924 6.48911 13.924 6.15774V2.15774Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 973 B

7
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_delete_disabled.svg

@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#229;&#136;&#160;&#233;&#153;&#164;" opacity="0.3">
<g id="icon/delete">
<path id="Combined-Shape" d="M11 1V3H15V4H13V15H3V4H1V3H5V1H11ZM12 4H4V14H12V4ZM7 6V12H6V6H7ZM10 6V12H9V6H10ZM10 2H6V3H10V2Z" fill="#333334"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 342 B

7
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_delete_normal.svg

@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="&#231;&#138;&#182;&#230;&#128;&#129;=&#230;&#173;&#163;&#229;&#184;&#184;">
<g id="icon/delete">
<path id="Combined-Shape" d="M11 1V3H15V4H13V15H3V4H1V3H5V1H11ZM12 4H4V14H12V4ZM7 6V12H6V6H7ZM10 6V12H9V6H10ZM10 2H6V3H10V2Z" fill="#333334"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 360 B

8
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_normal.svg

@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#229;&#155;&#158;&#230;&#148;&#182;&#231;&#171;&#153;">
<g id="icon/delete">
<path id="Combined-Shape" d="M11 1V3H15V4H13V15H3V4H1V3H5V1H11ZM12 4H4V14H12V4ZM10 2H6V3H10V2Z" fill="#333334"/>
</g>
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M9.4255 7.5425L8.5 6H7.5L5.93265 8.61225L6.79415 8.84308L8 6.83333L8.8005 8.1675L9.4255 7.5425ZM9.95583 8.42638L9.33083 9.05138L10.5 11H8.86391L9.09598 11.8661L11 11.8661L11.5 11L9.95583 8.42638ZM8.06071 11.8661L7.82864 11H5.5L6.25902 9.73497L5.39752 9.50413L4.5 11L5 11.8672L5.00064 11.8661L8.06071 11.8661Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 706 B

5
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_restore_disabled.svg

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#232;&#191;&#152;&#229;&#142;&#159;" opacity="0.3">
<path id="Union" d="M2.39418 1.6C2.39418 1.26863 2.66281 1 2.99418 1C3.32555 1 3.59418 1.26863 3.59418 1.6V4.0414C4.68979 2.9897 6.17846 2.3423 7.81813 2.3423C11.1871 2.3423 13.9181 5.07336 13.9181 8.4423C13.9181 11.8112 11.1871 14.5423 7.81813 14.5423C5.12408 14.5423 2.83941 12.7962 2.03106 10.3757C1.92609 10.0614 2.0958 9.72152 2.41011 9.61655C2.72441 9.51159 3.0643 9.68129 3.16927 9.9956C3.81901 11.9412 5.65572 13.3423 7.81813 13.3423C10.5243 13.3423 12.7181 11.1485 12.7181 8.4423C12.7181 5.7361 10.5243 3.5423 7.81813 3.5423C6.45385 3.5423 5.2199 4.09935 4.33089 5H6.99418C7.32555 5 7.59418 5.26863 7.59418 5.6C7.59418 5.93137 7.32555 6.2 6.99418 6.2H2.99418C2.66281 6.2 2.39418 5.93137 2.39418 5.6V1.6Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 904 B

5
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_restore_normal.svg

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="icon &#232;&#191;&#152;&#229;&#142;&#159;">
<path id="Union" d="M2.39418 1.6C2.39418 1.26863 2.66281 1 2.99418 1C3.32555 1 3.59418 1.26863 3.59418 1.6V4.0414C4.68979 2.9897 6.17846 2.3423 7.81813 2.3423C11.1871 2.3423 13.9181 5.07336 13.9181 8.4423C13.9181 11.8112 11.1871 14.5423 7.81813 14.5423C5.12408 14.5423 2.83941 12.7962 2.03106 10.3757C1.92609 10.0614 2.0958 9.72152 2.41011 9.61655C2.72441 9.51159 3.0643 9.68129 3.16927 9.9956C3.81901 11.9412 5.65572 13.3423 7.81813 13.3423C10.5243 13.3423 12.7181 11.1485 12.7181 8.4423C12.7181 5.7361 10.5243 3.5423 7.81813 3.5423C6.45385 3.5423 5.2199 4.09935 4.33089 5H6.99418C7.32555 5 7.59418 5.26863 7.59418 5.6C7.59418 5.93137 7.32555 6.2 6.99418 6.2H2.99418C2.66281 6.2 2.39418 5.93137 2.39418 5.6V1.6Z" fill="#333334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 890 B

3
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_recycle_search_normal.svg

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Combined Shape" fill-rule="evenodd" clip-rule="evenodd" d="M5.5 11C2.46243 11 0 8.53757 0 5.5C0 2.46243 2.46243 0 5.5 0C8.53757 0 11 2.46243 11 5.5C11 6.75785 10.5778 7.91707 9.86726 8.84367L13.7881 12.7645C14.0707 13.0471 14.0707 13.5054 13.7881 13.7881C13.5054 14.0707 13.0471 14.0707 12.7645 13.7881L8.84367 9.86726C7.91707 10.5778 6.75785 11 5.5 11ZM10 5.5C10 7.98528 7.98528 10 5.5 10C3.01472 10 1 7.98528 1 5.5C1 3.01472 3.01472 1 5.5 1C7.98528 1 10 3.01472 10 5.5Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 603 B

4
designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_sort_normal.svg

@ -0,0 +1,4 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.2462 6.17654C14.3492 6.30778 14.2557 6.5 14.0889 6.5H11.9999V13.9768C11.9999 14.0873 11.9104 14.1768 11.7999 14.1768H11.1999C11.0895 14.1768 10.9999 14.0873 10.9999 13.9768V6.5H8.91119C8.74436 6.5 8.65086 6.30779 8.75384 6.17654L11.3426 2.87732C11.4227 2.77527 11.5772 2.77527 11.6573 2.87731L14.2462 6.17654Z" fill="#333334"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.04297 10.801C2.93999 10.6698 3.03349 10.4775 3.20032 10.4775H5.28927V3.00074C5.28927 2.89028 5.37881 2.80074 5.48927 2.80074H6.08927C6.19972 2.80074 6.28927 2.89028 6.28927 3.00074V10.4775H8.378C8.54482 10.4775 8.63832 10.6698 8.53534 10.801L5.94661 14.1002C5.86653 14.2023 5.712 14.2023 5.63192 14.1002L3.04297 10.801Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 874 B

5
designer-base/src/main/resources/com/fr/design/vcs/move_failed.svg

@ -0,0 +1,5 @@
<svg width="64" height="65" viewBox="0 0 64 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M32 60.5C16.536 60.5 4 47.964 4 32.5C4 17.036 16.536 4.5 32 4.5C47.464 4.5 60 17.036 60 32.5C60 47.964 47.464 60.5 32 60.5Z" fill="#EB1D1F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M44 24.1928L23.692 44.4995L20 40.8075L40.308 20.4995L44 24.1928Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.308 44.5L20 24.1933L23.692 20.5L44 40.8067L40.308 44.5Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 549 B

5
designer-base/src/main/resources/com/fr/design/vcs/move_success.svg

@ -0,0 +1,5 @@
<svg width="58" height="59" viewBox="0 0 58 59" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M29 58.5C12.9837 58.5 0 45.5163 0 29.5C0 13.4837 12.9837 0.5 29 0.5C45.0163 0.5 58 13.4837 58 29.5C58 45.5163 45.0163 58.5 29 58.5Z" fill="#16C153"/>
<rect x="20.66" y="39.8213" width="32.1738" height="5.52381" transform="rotate(-45 20.66 39.8213)" fill="white"/>
<rect x="14.9535" y="26.7378" width="18.7954" height="5.52381" transform="rotate(45 14.9535 26.7378)" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 533 B

3
designer-base/src/main/resources/com/fr/design/vcs/vcs_move_icon.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="M15 8C15 4.13435 11.8656 1 8 1C4.13435 1 1 4.13435 1 8C1 11.8656 4.13435 15 8 15C11.8656 15 15 11.8656 15 8ZM7.43333 5.70798C7.27778 5.55242 7.2 5.36353 7.2 5.14131C7.2 4.91909 7.27778 4.7302 7.43333 4.57464C7.58889 4.41909 7.77778 4.34131 8 4.34131C8.22222 4.34131 8.41111 4.41909 8.56667 4.57464C8.72222 4.7302 8.8 4.91909 8.8 5.14131C8.8 5.36353 8.72222 5.55242 8.56667 5.70798C8.41111 5.86353 8.22222 5.94131 8 5.94131C7.77778 5.94131 7.58889 5.86353 7.43333 5.70798ZM8 11.7787C7.6134 11.7787 7.3 11.4653 7.3 11.0787V7.47868C7.3 7.09208 7.6134 6.77868 8 6.77868C8.3866 6.77868 8.7 7.09208 8.7 7.47868V11.0787C8.7 11.4653 8.3866 11.7787 8 11.7787Z" fill="#419BF9"/>
</svg>

After

Width:  |  Height:  |  Size: 821 B

29
designer-base/src/test/java/com/fr/base/ClassHelperTest.java

@ -1,29 +0,0 @@
package com.fr.base;
import com.fr.form.main.Form;
import com.fr.invoke.ClassHelper;
import com.fr.main.impl.WorkBook;
import java.util.Set;
import junit.framework.TestCase;
import org.junit.Assert;
/**
* @author hades
* @version 10.0
* Created by hades on 2020/12/28
*/
public class ClassHelperTest extends TestCase {
public void testGetClassLoaders() {
WorkBook workBook = new WorkBook();
Set<ClassLoader> set = ClassHelper.getClassLoaders(workBook);
Assert.assertFalse(set.isEmpty());
Form form = new Form();
Set<ClassLoader> set1 = ClassHelper.getClassLoaders(form);
Assert.assertFalse(set1.isEmpty());
}
}

2
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java

@ -19,7 +19,7 @@ public class TransformResultInfoTest {
resultInfo2.getTransformLog());
TransformResultInfo resultInfo3 = TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "unsupport");
Assert.assertEquals("unsupport\n" +
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"),
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_X_Unsupport_Tip"),
resultInfo3.getTransformLog());
}

8
designer-form/src/main/java/com/fr/design/actions/NewFormAction.java

@ -6,16 +6,12 @@ import com.fr.design.widget.ui.designer.NewFormPane;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER;
public class NewFormAction extends UpdateAction {
public NewFormAction() {
this.setMenuKeySet(NEW_FORM);
this.setName(getMenuKeySet().getMenuKeySetName());
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setName(getMenuKeySet().getMenuName());
this.setSmallIcon("/com/fr/design/images/buttonicon/new_form3");
this.setAccelerator(getMenuKeySet().getKeyStroke());
}
@ -33,7 +29,7 @@ public class NewFormAction extends UpdateAction {
public static final MenuKeySet NEW_FORM = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'F';
return 0;
}
@Override

27
designer-form/src/main/java/com/fr/design/designer/creator/XEditorHolder.java

@ -44,9 +44,7 @@ public class XEditorHolder extends XWidgetCreator {
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);
editingMouseListener.startEditing(this, adapter.getDesignerEditor(), adapter);
Rectangle rect = this.getBounds();
int min = rect.x + rect.width / 2 - editingMouseListener.getMinMoveSize();
int max = rect.x + rect.width / 2 + editingMouseListener.getMinMoveSize();
if (e.getX() > min && e.getX() < max) {
if (checkMouseEditRangeValid(e, rect, editingMouseListener)) {
ToolTipEditor.getInstance().showToolTip((XEditorHolder) this, e.getXOnScreen(),
e.getYOnScreen());
}
@ -54,6 +52,29 @@ public class XEditorHolder extends XWidgetCreator {
}
}
/**
* 判断当前鼠标事件是否在可编辑区域内
*
* @param e 鼠标事件
* @param rect 区域
* @param editingMouseListener 位置处理器
* @return 是否位于可编辑区
*/
private boolean checkMouseEditRangeValid(MouseEvent e, Rectangle rect, EditingMouseListener editingMouseListener) {
int horizontalValue = editingMouseListener.getDesigner().getHorizontalScaleValue();
int verticalValue = editingMouseListener.getDesigner().getVerticalScaleValue();
int minMoveSize = editingMouseListener.getMinMoveSize();
int minHorizontal = rect.x + rect.width / 2 - minMoveSize - horizontalValue;
int maxHorizontal = rect.x + rect.width / 2 + minMoveSize - horizontalValue;
int minVertical = rect.y + rect.height / 2 - minMoveSize - verticalValue;
int maxVertical = rect.y + rect.height / 2 + minMoveSize - verticalValue;
boolean xRangeValid = e.getX() > minHorizontal && e.getX() < maxHorizontal;
boolean yRangeValid = e.getY() > minVertical && e.getY() < maxVertical;
return xRangeValid && yRangeValid;
}
@Override
protected String getIconName() {
return "text_field_16.png";

23
designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java

@ -279,9 +279,7 @@ public class EditingMouseListener extends MouseInputAdapter {
if (component instanceof XEditorHolder) {
XEditorHolder xcreator = (XEditorHolder) component;
Rectangle rect = xcreator.getBounds();
int min = rect.x + rect.width / 2 - minMoveSize;
int max = rect.x + rect.width / 2 + minMoveSize;
if (e.getX() > min && e.getX() < max) {
if (checkCreatorRangeValid(e, rect)) {
if (designer.getCursor().getType() != Cursor.HAND_CURSOR) {
designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@ -673,8 +671,8 @@ public class EditingMouseListener extends MouseInputAdapter {
currentEditor = designerEditor;
currentXCreator = creator;
Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2);
bounds.x += (rect.x - designer.getArea().getHorizontalValue());
bounds.y += (rect.y - designer.getArea().getVerticalValue());
bounds.x += (rect.x - designer.getHorizontalScaleValue());
bounds.y += (rect.y - designer.getVerticalScaleValue());
designerEditor.getEditorTarget().setBounds(bounds);
designer.add(designerEditor.getEditorTarget());
designer.invalidate();
@ -747,4 +745,19 @@ public class EditingMouseListener extends MouseInputAdapter {
refreshTopXCreator(false);
}
/**
* 判断当前鼠标移动事件是否在Creator有效范围内
*/
private boolean checkCreatorRangeValid(MouseEvent e, Rectangle rect) {
int horizontalValue = designer.getHorizontalScaleValue();
int verticalValue = designer.getVerticalScaleValue();
int minHorizontal = rect.x + rect.width / 2 - minMoveSize - horizontalValue;
int maxHorizontal = rect.x + rect.width / 2 + minMoveSize - horizontalValue;
int minVertical = rect.y + rect.height / 2 - minMoveSize - verticalValue;
int maxVertical = rect.y + rect.height / 2 + minMoveSize - verticalValue;
boolean xRangeValid = e.getX() > minHorizontal && e.getX() < maxHorizontal;
boolean yRangeValid = e.getY() > minVertical && e.getY() < maxVertical;
return xRangeValid && yRangeValid;
}
}

2
designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java

@ -1208,7 +1208,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
public XLayoutContainer getRootContainer(int y) {
XLayoutContainer container = y < paraHeight - formArea.getVerticalValue() ? paraComponent : rootComponent;
XLayoutContainer container = y < paraHeight - formArea.getVerticalValue() / scale ? paraComponent : rootComponent;
if (container == null) {
container = rootComponent;
}

2
designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FormWidgetValuePane.java

@ -63,7 +63,7 @@ public class FormWidgetValuePane extends JPanel {
/**
* 根据类型创建
*
* 设计器右侧控件设置 - 属性
* @param type 类型
* @param onlyServer 是否是服务器
* @return 编辑器

40
designer-form/src/test/java/com/fr/design/mainframe/template/info/JFormProcessInfoTest.java

@ -1,7 +1,9 @@
package com.fr.design.mainframe.template.info;
import com.fr.base.background.ColorBackground;
import com.fr.base.svg.IconUtils;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase;
import com.fr.form.main.Form;
import com.fr.form.ui.CardSwitchButton;
@ -20,15 +22,53 @@ import com.fr.json.JSONArray;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.report.cell.DefaultTemplateCellElement;
import com.fr.report.worksheet.FormElementCase;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import javax.swing.Icon;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
/**
* Created by kerry on 2020-05-08
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Toolkit.class, IconUtils.class})
@PowerMockIgnore({"javax.management.*"})
public class JFormProcessInfoTest {
@Before
public void setUp() throws Exception {
PowerMock.mockStatic(Toolkit.class);
PowerMock.mockStatic(IconUtils.class);
EasyMock.expect(Toolkit.i18nText(EasyMock.anyString())).andReturn("ignore").anyTimes();
EasyMock.expect(IconUtils.readIcon(EasyMock.anyString())).andReturn(new Icon() {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
// do nothing
}
@Override
public int getIconWidth() {
return 0;
}
@Override
public int getIconHeight() {
return 0;
}
}).anyTimes();
PowerMock.replayAll();
}
@Test
public void testHasTestECReport() {
Form form = new Form();

14
designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java

@ -84,20 +84,20 @@ public class ImageExportPane extends AbstractExportPane {
private void initGlobalSettings() {
globalResolutionBtnS = new UIRadioButton("96dpi", true);
globalResolutionBtnM = new UIRadioButton("192dpi");
globalResolutionBtnS = new UIRadioButton("96dpi");
globalResolutionBtnM = new UIRadioButton("192dpi", true);
globalResolutionBtnL = new UIRadioButton("300dpi");
wrapButtonsInButtonGroup(globalResolutionBtnS, globalResolutionBtnM, globalResolutionBtnL);
globalFormatJpg = new UIRadioButton("jpg", true);
globalFormatPng = new UIRadioButton("png");
globalFormatJpg = new UIRadioButton("jpg");
globalFormatPng = new UIRadioButton("png", true);
wrapButtonsInButtonGroup(globalFormatJpg, globalFormatPng);
globalRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First"), true);
globalRenderSpeed = new UIRadioButton(Toolkit.i18nText(("Fine-Design_Image_Export_Speed_Priority")));
globalRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First"));
globalRenderSpeed = new UIRadioButton(Toolkit.i18nText(("Fine-Design_Image_Export_Speed_Priority")), true);
wrapButtonsInButtonGroup(globalRenderQuality, globalRenderSpeed);
templateThumbnail = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Thumbnail"));
templateThumbnail = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Thumbnail"), true);
templatePaging = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Paging"));
wrapButtonsInButtonGroup(templateThumbnail, templatePaging);
}

8
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -213,14 +213,18 @@ public class MainDesigner extends BaseDesigner {
ArrayList<ShortCut> shortCuts = new ArrayList<ShortCut>();
// shortCuts.add(new NewWorkBookXAction());
shortCuts.add(new NewWorkBookAction());
// 决策报表、聚合报表归入其他
MenuDef newOtherFileMenuDef = new MenuDef(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_M_New_Other_Template"));
newOtherFileMenuDef.setIconPath("/com/fr/design/images/buttonicon/new_other");
try {
if (DesignModuleFactory.getNewFormAction() != null) {
shortCuts.add((ShortCut) DesignModuleFactory.getNewFormAction().newInstance());
newOtherFileMenuDef.addShortCut((ShortCut) DesignModuleFactory.getNewFormAction().newInstance());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
shortCuts.add(new NewPolyReportAction());
newOtherFileMenuDef.addShortCut(new NewPolyReportAction());
shortCuts.add(newOtherFileMenuDef);
return shortCuts.toArray(new ShortCut[0]);
}

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

BIN
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/images/local_fvs4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

160
designer-realize/src/main/resources/com/fr/design/mainframe/alphafine/template_resource/local_templates.json

File diff suppressed because one or more lines are too long

6
designer-realize/src/test/java/com/fr/nx/app/designer/CptxAppTest.java

@ -4,7 +4,6 @@ import com.fr.file.AbstractFILE;
import com.fr.file.FILE;
import com.fr.main.impl.WorkBook;
import com.fr.nx.cptx.utils.CptxFileUtils;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
@ -42,12 +41,9 @@ public class CptxAppTest {
}
};
WorkBook workBook = new WorkBook();
EasyMock.expect(CptxFileUtils.getWorkBook(file.getPath()))
.andReturn(workBook).once()
.andReturn(null).once();
PowerMock.replay(CptxFileUtils.class);
Assert.assertSame(workBook, new CptxApp().asIOFile(file));
Assert.assertTrue(workBook.equals(new CptxApp().asIOFile(file)));
Assert.assertNotNull(new CptxApp().asIOFile(file));

Loading…
Cancel
Save