diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 3ab832a019..91d67edf8d 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java @@ -36,6 +36,7 @@ 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; @@ -64,6 +65,8 @@ 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; @@ -177,6 +180,8 @@ public class PreferencePane extends BasicPane { private static final int DEFAULT_INDEX = 3; + private BasicDialog basicDialog; + private boolean languageChanged; // 是否修改了设计器语言设置 //设置是否支持undo private UICheckBox supportUndoCheckBox; @@ -221,7 +226,7 @@ public class PreferencePane extends BasicPane { private UIComboBox autoCleanIntervalComboBox; private UIComboBox autoCleanRetainIntervalComboBox; - private IntegerEditor autoSaveIntervalEditor; + private UIPositiveIntEditor autoSaveIntervalEditor; private UICheckBox saveCommitCheckBox; private UICheckBox useIntervalCheckBox; private VcsMovePanel movePanel; @@ -231,7 +236,7 @@ public class PreferencePane extends BasicPane { private JPanel gcControlPane; private UICheckBox startupPageEnabledCheckBox; - private IntegerEditor saveIntervalEditor; + private UIPositiveIntEditor saveIntervalEditor; private UICheckBox gcEnableCheckBox; private UIButton gcButton; private UILabel remindVcsLabel; @@ -426,7 +431,7 @@ public class PreferencePane extends BasicPane { 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); @@ -444,6 +449,7 @@ public class PreferencePane extends BasicPane { intervalPanel.add(saveIntervalEditor); intervalPanel.add(delayLabel); autoCleanPane = createAutoCleanPane(); + checkAutoScheduleStartAndUpdateStatus(); vcsEnableCheckBox.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { @@ -465,10 +471,13 @@ public class PreferencePane extends BasicPane { }); vcsPane.add(enableVcsPanel); vcsPane.add(intervalPanel); - vcsPane.add(saveCommitCheckBox); + if (VcsHelper.getInstance().isLegacyMode()) { + vcsPane.add(saveCommitCheckBox); + } vcsPane.add(autoCleanPane); - saveIntervalPane.setVisible(!VcsHelper.getInstance().isLegacyMode()); - autoCleanPane.setVisible(!VcsHelper.getInstance().isLegacyMode()); + boolean support = VcsHelper.getInstance().checkV2FunctionSupport(); + saveIntervalPane.setVisible(support); + autoCleanPane.setVisible(support); if (VcsHelper.getInstance().isLegacyMode()) { // 老版本时才显示gc选项 vcsPane.add(gcControlPane); @@ -488,12 +497,13 @@ public class PreferencePane extends BasicPane { saveIntervalPane.setVisible(useV2); autoCleanPane.setVisible(useV2); gcControlPane.setVisible(!useV2); + saveCommitCheckBox.setVisible(!useV2); useVcsAutoCleanScheduleCheckBox.setSelected(useV2); useVcsAutoSaveScheduleCheckBox.setSelected(useV2); - useVcsAutoCleanScheduleCheckBox.setEnabled(useV2 && FineScheduler.getInstance().isStarted()); + checkAutoScheduleStartAndUpdateStatus(); useVcsAutoSaveScheduleCheckBox.setEnabled(useV2); } - }); + }, basicDialog); }; private JPanel createAutoCleanPane() { @@ -509,15 +519,45 @@ public class PreferencePane extends BasicPane { 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"))); - useVcsAutoCleanScheduleCheckBox.setEnabled(!VcsHelper.getInstance().isLegacyMode() && FineScheduler.getInstance().isStarted()); autoCleanPane.setVisible(false); return autoCleanPane; } + private void checkAutoScheduleStartAndUpdateStatus() { + if (!VcsHelper.getInstance().isLegacyMode()) { + new SwingWorker() { + @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 IntegerEditor(60); + autoSaveIntervalEditor = new UIPositiveIntEditor(60); saveIntervalPane.add(useVcsAutoSaveScheduleCheckBox); saveIntervalPane.add(new UILabel(i18nText("Fine-Design_Vcs_Every"))); saveIntervalPane.add(autoSaveIntervalEditor); @@ -909,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); } @@ -1179,11 +1220,16 @@ public class PreferencePane extends BasicPane { } else { VcsHelper.getInstance().stopAutoSave(); } - if (useVcsAutoCleanScheduleCheckBox.isSelected()) { - FineLoggerFactory.getLogger().info("[VcsV2] start auto clean!"); - WorkContext.getCurrent().get(VcsAutoCleanOperator.class).addOrUpdateVcsAutoCleanJob(getDay(autoCleanIntervalComboBox.getSelectedIndex())); - } else { - WorkContext.getCurrent().get(VcsAutoCleanOperator.class).stopVcsAutoCleanJob(); + 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; @@ -1219,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 diff --git a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java index 75626441bf..5b77b9571a 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java +++ b/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; + } + /** * 图表类型选择时 弹出的按钮大小, 不适合用最大最小, 因为图表大小 默认是规定好的, 那么界面大小也是必须配合. diff --git a/designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java b/designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java index d811ad89b7..26b81f8a4b 100644 --- a/designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java +++ b/designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java @@ -38,7 +38,7 @@ public abstract class NumberEditor extends Editor { */ 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 extends Editor { this.setName(name); } + /** + * 创建NumberField对象 + * + */ + protected UINumberField createNumberField() { + return new UINumberField(); + } + /** * 给numberField加键盘事件 * diff --git a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java index 6658fc6638..be7c8c1953 100644 --- a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java +++ b/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> openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList(); JTemplate[] templates = new JTemplate[openedTemplate.size()]; diff --git a/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java b/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java index 0bdd48b359..1517309ef1 100644 --- a/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java +++ b/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> 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)); } diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java index 74f26aaf80..2f8b1cd206 100644 --- a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java +++ b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java @@ -18,7 +18,6 @@ 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.VcsService; import com.fr.design.mainframe.vcs.common.VcsHelper; import com.fr.file.FILE; import com.fr.file.FileNodeFILE; @@ -65,6 +64,7 @@ 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; @@ -378,8 +378,6 @@ public class TemplateTreePane extends JPanel implements FileOperations { deleteNodes(deletableNodes); } } - Set deletedFileNode = deletableNodes.stream().map(treeNode -> (FileNode) treeNode.getUserObject()).collect(Collectors.toSet()); - refreshAfterDelete(deletedFileNode); } private void refreshAfterDelete(Set deletedPaths) { @@ -409,7 +407,12 @@ public class TemplateTreePane extends JPanel implements FileOperations { if (node instanceof FileNode) { FileNodeFILE nodeFILE = new FileNodeFILE((FileNode) node); if (nodeFILE.exists()) { - VcsService.getInstance().doRecycle(VcsHelper.getInstance().dealWithFilePath(((FileNode) node).getEnvPath())); + 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 { @@ -426,6 +429,8 @@ public class TemplateTreePane extends JPanel implements FileOperations { if (!get()) { showErrorDialog(); } + Set deletedFileNode = nodes.stream().map(treeNode -> (FileNode) treeNode.getUserObject()).collect(Collectors.toSet()); + refreshAfterDelete(deletedFileNode); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java index 6ef68afe7e..747cf6aef5 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java @@ -46,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; @@ -337,7 +338,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } toolbarDef.addShortCut(vcsAction); //11.0.19及其之后加入回收站逻辑 - if (!VcsHelper.getInstance().isLegacyMode()) { + if (VcsHelper.getInstance().checkV2FunctionSupport()) { recycleAction = new RecycleAction(); toolbarDef.addShortCut(recycleAction); } @@ -393,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; } /** @@ -501,22 +505,25 @@ 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()) { - boolean currentEditing = isCurrentEditing(path); // 如果模板已经打开了,关掉,避免出现2个同名tab(1个是模板,1个是版本) closeOpenedTemplate(path, currentEditing); FileVersionsPanel fileVersionTablePanel = FileVersionsPanel.getInstance(); fileVersionTablePanel.showFileVersionsPane(); stateChange(); } else { - VcsNewPane panel = new VcsNewPane(path); - BasicDialog dialog = panel.showWindow(DesignerContext.getDesignerFrame(), false); - dialog.setVisible(true); + checkTemplateSavedAndShowVcsNewPane(path, currentEditing); } } + private void showVcsNewPane(String path) { + VcsNewPane panel = new VcsNewPane(path); + panel.showDialog(); + } + /** * 版本管理可用状态的监控 */ @@ -570,6 +577,60 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } } + /** + * 如果指定模板已经打开: + *

1.如果该模板已保存,则正常打开新版本管理弹窗 + *

2.如果该模板未保存,触发保存逻辑 + *

  • a.如果用户选择保存,则保存并不关闭模板,弹出新版本管理弹窗 + *
  • b.如果用户选择不保存,则关闭当前模板,弹出新版本管理弹窗 + *
  • 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(); + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/RecycleAction.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/RecycleAction.java index b074f17f8f..acd89f668d 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/RecycleAction.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/RecycleAction.java @@ -4,7 +4,7 @@ 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.RecyclePane; +import com.fr.design.mainframe.vcs.ui.RecycleSettingPane; import java.awt.event.ActionEvent; @@ -24,7 +24,7 @@ public class RecycleAction extends UpdateAction { @Override public void actionPerformed(ActionEvent e) { - RecyclePane pane = new RecyclePane(); + RecycleSettingPane pane = new RecycleSettingPane(); BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame(), false); dialog.setVisible(true); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsExceptionUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsExceptionUtils.java new file mode 100644 index 0000000000..9ab310bbac --- /dev/null +++ b/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 EXCEPTION_MAP = new HashMap() { + { + 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"); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsOperatorWorker.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsOperatorWorker.java new file mode 100644 index 0000000000..b59ac3c128 --- /dev/null +++ b/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 vcsEntities) { + List 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 vcsEntities, boolean all) { + List 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 vcsEntities, List 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() { + @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 vcsEntities, List failedList, VcsWorkerOperator workerOperator) { + new SwingWorker() { + @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 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 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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsRecycleSettingHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsRecycleSettingHelper.java new file mode 100644 index 0000000000..3e6a5bab96 --- /dev/null +++ b/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); + } + }); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsService.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsService.java deleted file mode 100644 index e83b0212e9..0000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsService.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.fr.design.mainframe.vcs; - -import com.fr.concurrent.NamedThreadFactory; -import com.fr.design.mainframe.vcs.common.VcsHelper; -import com.fr.log.FineLoggerFactory; -import com.fr.report.entity.VcsEntity; -import com.fr.workspace.WorkContext; -import com.fr.workspace.server.vcs.VcsOperator; - -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * 版本管理常用操作 - *

    便于版本管理面板快捷实现版本管理相关操作 - * - * @author Destiny.Lin - * @since 11.0 - * Created on 2023/7/10 - */ -public class VcsService { - - private static final String SERVICE = "VcsService"; - private static final VcsService INSTANCE = new VcsService(); - - private static final ExecutorService executorService = Executors.newFixedThreadPool(5, new NamedThreadFactory(SERVICE)); - - /** - * 获取单例 - * - * @return - */ - public static VcsService getInstance() { - return INSTANCE; - } - - private VcsService() { - } - - /** - * 回收模板 - * - * @param filename - */ - public void doRecycle(String filename) { - try { - WorkContext.getCurrent().get(VcsOperator.class).recycleVersion(VcsHelper.getInstance().getCurrentUsername(), filename); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - - /** - * 从回收站还原版本 - * - * @param vcsEntities - */ - public void doRestore(List vcsEntities) { - try { - executorService.execute(new Runnable() { - @Override - public void run() { - VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class); - for (VcsEntity vcsEntity : vcsEntities) { - String fileName = vcsEntity.getFilename(); - operator.restoreVersion(fileName); - } - } - }); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - - /** - * 删除对应列表中所有模板的指定的历史版本 - * - * @param vcsEntities - */ - public void doDelete(List vcsEntities, boolean all) { - try { - executorService.execute(new Runnable() { - @Override - public void run() { - VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class); - for (VcsEntity vcsEntity : vcsEntities) { - String fileName = vcsEntity.getFilename(); - if (all) { - operator.deleteVersionForRecycle(fileName); - } else { - operator.deleteVersion(fileName, vcsEntity.getVersion()); - } - } - } - }); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - /** - * 删除指定模板的全部历史版本 - * - * @param entity VcsEntity - */ - public void deleteEntity(VcsEntity entity) { - try { - executorService.execute(new Runnable() { - @Override - public void run() { - VcsOperator vcsOperator = WorkContext.getCurrent().get(VcsOperator.class); - String fileName = entity.getFilename(); - vcsOperator.deleteVersionForRecycle(fileName); - } - }); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - /** - * 删除指定模板的指定版本 - * - * @param fileName 文件名 - * @param version 版本号 - */ - public void deleteEntity(String fileName, int version) { - try { - executorService.execute(new Runnable() { - @Override - public void run() { - VcsOperator vcsOperator = WorkContext.getCurrent().get(VcsOperator.class); - vcsOperator.deleteVersion(fileName, version); - } - }); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - /** - * 更新版本 - * - * @param entity 版本 - */ - public void updateEntityAnnotation(VcsEntity entity) { - try { - executorService.execute(new Runnable() { - @Override - public void run() { - VcsOperator vcsOperator = WorkContext.getCurrent().get(VcsOperator.class); - vcsOperator.updateVersion(entity); - } - }); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsTableEntity.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsTableEntity.java index 200aa38e7a..0739bb16b2 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsTableEntity.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsTableEntity.java @@ -1,6 +1,7 @@ package com.fr.design.mainframe.vcs; import com.fr.report.entity.VcsEntity; +import com.fr.stable.StringUtils; /** * 包装VcsEntity的用于表格展示与处理的类 @@ -16,7 +17,7 @@ public class VcsTableEntity implements TableEntity{ private static final String MB = "MB"; private static final String VERSION = "V."; - private static final double MB_SIZE = 1024.0; + private static final double MB_SIZE = 1024.0 * 1024; private VcsEntity entity; @@ -39,7 +40,11 @@ public class VcsTableEntity implements TableEntity{ * @return 版本大小 */ public String getSize() { - return String.format("%.2f",entity.getSize()/MB_SIZE) + MB; + double size = entity.getSize()/MB_SIZE; + if (size == 0) { + return StringUtils.EMPTY; + } + return String.format("%.3f", size) + MB; } /** diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java index 2a78159217..bd3551256a 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java @@ -15,6 +15,7 @@ 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; @@ -24,6 +25,8 @@ 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; @@ -66,6 +69,8 @@ public class VcsHelper implements JTemplateActionListener { private volatile boolean legacyMode; + private volatile boolean root; + public static VcsHelper getInstance() { return INSTANCE; } @@ -74,7 +79,14 @@ public class VcsHelper implements JTemplateActionListener { VcsOperator op = WorkContext.getCurrent().get(VcsOperator.class); // 开了设计器启动页面时一开始取不到VcsOperator,通过下面的切换环境事件再取,这边判断下 if (op != null) { - legacyMode = op.isLegacyMode(); + 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 @@ -89,6 +101,18 @@ public class VcsHelper implements JTemplateActionListener { } } }); + EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener() { + @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()); + } + + } + }); } /** @@ -327,7 +351,7 @@ public class VcsHelper implements JTemplateActionListener { private void autoSave(JTemplate jt, String currentUsername, String fileName, int nowVersion, boolean replace, VcsOperator operator) { try { - if (JTemplate.isValid(jt)) { + if (JTemplate.isValid(jt) && !jt.isALLSaved()) { operator.autoSave(currentUsername, fileName, StringUtils.EMPTY, nowVersion, jt.exportData(), replace); } } catch (Exception e) { @@ -347,7 +371,8 @@ 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); } } @@ -370,7 +395,7 @@ public class VcsHelper implements JTemplateActionListener { * @return 支持返回true */ public boolean checkV2FunctionSupport() { - return !VcsHelper.getInstance().isLegacyMode() && (WorkContext.getCurrent().isLocal() || WorkContext.getCurrent().isRoot()); + return !VcsHelper.getInstance().isLegacyMode() && root; } /** diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/AbstractSupportSelectTablePane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/AbstractSupportSelectTablePane.java index 7c2d56b509..75733121de 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/AbstractSupportSelectTablePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/AbstractSupportSelectTablePane.java @@ -1,5 +1,6 @@ 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; @@ -219,6 +220,17 @@ public abstract class AbstractSupportSelectTablePane exte //更新表头的勾选框状态 HeaderRenderer renderer = (HeaderRenderer) table.getTableHeader().getDefaultRenderer(); renderer.refreshHeader(table, selectCount >= table.getRowCount()); + changeExtraComponentStatus(); + } + + /** + * 更新额外组件的状态 + */ + protected void changeExtraComponentStatus() { + } + + public int getSelectCount() { + return selectCount; } @@ -242,6 +254,7 @@ public abstract class AbstractSupportSelectTablePane exte 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() { @@ -254,6 +267,7 @@ public abstract class AbstractSupportSelectTablePane exte selectBox.setSelected(value); selectAllOrNull(value); selectCount = value ? table.getRowCount() : 0; + changeExtraComponentStatus(); tableHeader.repaint(); model.fireTableDataChanged(); } @@ -290,8 +304,12 @@ public abstract class AbstractSupportSelectTablePane exte tableHeader = table.getTableHeader(); tableHeader.setReorderingAllowed(false); String valueStr = (String) value; - JLabel label = new JLabel(valueStr); - label.setHorizontalAlignment(SwingConstants.LEFT); + 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; @@ -320,6 +338,7 @@ public abstract class AbstractSupportSelectTablePane exte setColumnClass(classes); this.setDefaultEditor(Boolean.class, new BooleanEditor()); this.setDefaultRenderer(Boolean.class, new BooleanRenderer()); + this.setDefaultRenderer(UILabel.class, new ToolTipTableCellRenderer()); } @Override @@ -375,5 +394,14 @@ public abstract class AbstractSupportSelectTablePane exte } + /** + * 表头的某列是否需要icon + * + * @param col 列 + * @return + */ + protected boolean needIcon4Head(int col) { + return col != 0; + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecyclePane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecyclePane.java index e829318174..4b0f8e9763 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecyclePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecyclePane.java @@ -1,11 +1,13 @@ 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.vcs.VcsService; +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; @@ -37,8 +39,10 @@ import static com.fr.design.i18n.Toolkit.i18nText; */ public class RecyclePane extends AbstractSupportSelectTablePane { public static final Icon ICON_SEARCH = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_recycle_search"); - public static final Icon ICON_REFRESH = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_recycle_restore"); - public static final Icon ICON_DELETE = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_recycle_delete"); + 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; @@ -47,6 +51,10 @@ public class RecyclePane extends AbstractSupportSelectTablePane protected UILabel restoreLabel; private static final int COLUMNS_COUNT = 15; + private BasicDialog dialog; + + private BasicDialog parentDialog; + private List tableEntities; public RecyclePane() { super(i18nText("Fine-Design_Vcs_Recycle"), (o, columnIndex) -> { @@ -71,7 +79,7 @@ public class RecyclePane extends AbstractSupportSelectTablePane Toolkit.i18nText("Fine-Design_Vcs_Recycle_Size"), Toolkit.i18nText("Fine-Design_Vcs_Delete_Time"), Toolkit.i18nText("Fine-Design_Vcs_Time") - }, true); + }, false); } public RecyclePane(String title, TableValueOperator operators, boolean needBorder) { @@ -86,6 +94,7 @@ public class RecyclePane extends AbstractSupportSelectTablePane for (VcsEntity entity : entityList) { tableEntities.add(new VcsTableEntity(entity)); } + updateTableList(tableEntities); return tableEntities; } @@ -108,17 +117,33 @@ public class RecyclePane extends AbstractSupportSelectTablePane 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(); @@ -128,13 +153,14 @@ public class RecyclePane extends AbstractSupportSelectTablePane 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 selectList) { - VcsService.getInstance().doDelete(selectList, isNeedDeleteAllVersion()); + VcsOperatorWorker.createDeleteWorker().batchDelete(selectList, isNeedDeleteAllVersion()); } }, true); } @@ -144,13 +170,14 @@ public class RecyclePane extends AbstractSupportSelectTablePane 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 selectList) { - VcsService.getInstance().doRestore(selectList); + VcsOperatorWorker.createRestoreWorker().batchRestore(selectList); } }, false); } @@ -164,8 +191,7 @@ public class RecyclePane extends AbstractSupportSelectTablePane @Override public void actionPerformed(ActionEvent e) { String str = searchTextField.getText(); - List entityList = model.getList(); - model.setList(entityList.stream().filter(entity -> entity.getEntity().getFilename().contains(str)).collect(Collectors.toList())); + model.setList(tableEntities.stream().filter(entity -> entity.getEntity().getFilename().contains(str)).collect(Collectors.toList())); model.fireTableDataChanged(); } }); @@ -173,6 +199,7 @@ public class RecyclePane extends AbstractSupportSelectTablePane } + private void fireListener(VcsResponseListener listener, boolean isDelete) { List selectList = model.getList().stream().filter(TableEntity::isSelect).map(VcsTableEntity::getEntity).collect(Collectors.toList()); if (selectList.size() > 0) { @@ -183,7 +210,8 @@ public class RecyclePane extends AbstractSupportSelectTablePane JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (selVal == JOptionPane.YES_OPTION) { - model.setList(model.getList().stream().filter(tableEntity -> !tableEntity.isSelect()).collect(Collectors.toList())); + tableEntities = model.getList().stream().filter(tableEntity -> !tableEntity.isSelect()).collect(Collectors.toList()); + model.setList(tableEntities); model.fireTableDataChanged(); listener.doAfterChooseYes(selectList); } @@ -191,6 +219,61 @@ public class RecyclePane extends AbstractSupportSelectTablePane } + /** + * 显示弹窗 + * + */ + 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; + } + /** * 删除范围 * @@ -250,6 +333,25 @@ public class RecyclePane extends AbstractSupportSelectTablePane return true; } + + /** + * 更新数据列表 + * + * @param entities + */ + public void updateTableList(List entities) { + tableEntities = entities; + } + + /** + * 移除指定元素 + * + * @param entity + */ + public void removeTarget(VcsTableEntity entity) { + tableEntities.remove(entity); + } + /** * 版本管理按钮事件响应 */ diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecycleSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/RecycleSettingPane.java new file mode 100644 index 0000000000..0653aad05f --- /dev/null +++ b/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"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/ToolTipTableCellRenderer.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/ToolTipTableCellRenderer.java new file mode 100644 index 0000000000..bfb10e2057 --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntEditor.java new file mode 100644 index 0000000000..797d8bd1ef --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntSpinner.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/UIPositiveIntSpinner.java new file mode 100644 index 0000000000..3753cf817c --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsBatchProcessDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsBatchProcessDetailPane.java new file mode 100644 index 0000000000..4421b7f301 --- /dev/null +++ b/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); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellEditor.java new file mode 100644 index 0000000000..9baebaebe1 --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellRender.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCellRender.java new file mode 100644 index 0000000000..952c52a060 --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCenterPane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCenterPane.java index 0da23fa3dd..efe622566b 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCenterPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsCenterPane.java @@ -2,11 +2,12 @@ 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.VcsService; +import com.fr.design.mainframe.vcs.VcsOperatorWorker; import com.fr.design.mainframe.vcs.VcsTableEntity; import com.fr.file.FileNodeFILE; @@ -83,8 +84,11 @@ public class VcsCenterPane extends VcsNewPane { @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(); @@ -111,7 +115,10 @@ public class VcsCenterPane extends VcsNewPane { JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (selVal == JOptionPane.YES_OPTION) { - VcsService.getInstance().deleteEntity(entity); + VcsOperatorWorker.createDeleteWorker().doDelete(entity); + removeTarget((VcsTableEntity) o); + model.getList().remove(o); + model.fireTableDataChanged(); } DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(getTemplateTruePath(fileName), false))); } @@ -119,6 +126,12 @@ public class VcsCenterPane extends VcsNewPane { }); } + + @Override + protected boolean needIcon4Head(int col) { + return col != 0 && col != OPERATOR_COL; + } + private void initOpenListener() { open.addMouseListener(new MouseAdapter() { @Override @@ -127,6 +140,7 @@ public class VcsCenterPane extends VcsNewPane { 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))); } } @@ -147,8 +161,7 @@ public class VcsCenterPane extends VcsNewPane { return entity.getFilename()+Toolkit.i18nText("Fine-Design_Vcs_Version_Tips"); } }; - BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame(), false); - dialog.setVisible(true); + pane.showDialog(getDialog()); } } }); @@ -161,9 +174,21 @@ public class VcsCenterPane extends VcsNewPane { 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; @@ -194,4 +219,9 @@ public class VcsCenterPane extends VcsNewPane { protected boolean isNeedSearch() { return true; } + + @Override + protected boolean isNeedDeleteAllVersion() { + return true; + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovePanel.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovePanel.java index 5dacb65e91..cd3e6f09a6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovePanel.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsMovePanel.java @@ -5,6 +5,7 @@ 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; @@ -14,8 +15,11 @@ 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; @@ -25,6 +29,7 @@ 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; @@ -37,6 +42,9 @@ 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; + /** * 迁移面板 @@ -75,6 +83,8 @@ public class VcsMovePanel extends BasicPane { public static final String FAILED = "FAILED"; public static boolean moving = false; + + private BasicDialog parentDialog; private UILabel vcsUpdateExistLabel = new UILabel(); private UILabel vcsUpdateFireLabel = new UILabel(); @@ -103,7 +113,7 @@ public class VcsMovePanel extends BasicPane { //全部放弃 private UIRadioButton moveNothingButton; - private UISpinner spinner; + private UIPositiveIntSpinner spinner; private MoveCallBack callBack; @@ -112,11 +122,12 @@ public class VcsMovePanel extends BasicPane { private boolean visible = false; - public VcsMovePanel(CardLayout cardLayout, JPanel parentPane, MoveCallBack callBack) { + 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)); //初始化顶部的面板 @@ -228,7 +239,7 @@ public class VcsMovePanel extends BasicPane { moveAllPane.add(moveAllButton); moveDefaultPanel.add(moveDefaultButton); moveDefaultPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Default_Text_Left"))); - spinner = new UISpinner(MIN_VALUE, MAX_VALUE, STEP, DEFAULT_VALUE); + 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); @@ -238,7 +249,9 @@ public class VcsMovePanel extends BasicPane { } 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(); @@ -259,9 +272,7 @@ public class VcsMovePanel extends BasicPane { @Override public void actionPerformed(ActionEvent e) { VcsCenterPane vcsCenterPane = new VcsCenterPane(); - BasicDialog dialog = vcsCenterPane.showWindow(DesignerContext.getDesignerFrame(), false); - dialog.setVisible(true); - + vcsCenterPane.showDialog(parentDialog); } }); } @@ -273,18 +284,7 @@ public class VcsMovePanel extends BasicPane { BasicDialog dlg = choosePane.showMediumWindow(SwingUtilities.getWindowAncestor(VcsMovePanel.this), new DialogActionAdapter() { @Override public void doOk() { - //进度条面板 - initProcessPane(); - VcsMovePanel.this.getParentCard().next(getParentPane()); - VcsMoveStrategy strategy; - if (moveDefaultButton.isSelected()) { - strategy = VcsMoveStrategy.createNumStrategy((int) spinner.getValue()); - } else if (moveNothingButton.isSelected()) { - strategy = VcsMoveStrategy.ALL_GIVE_UP; - } else { - strategy = VcsMoveStrategy.ALL_RETAIN; - } - new MoveWorker(strategy).execute(); + createConfirmPane(); } }); dlg.setVisible(true); @@ -292,6 +292,42 @@ public class VcsMovePanel extends BasicPane { }); } + 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(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(); @@ -324,15 +360,19 @@ public class VcsMovePanel extends BasicPane { private void doAfterMove() { visible = !VcsHelper.getInstance().isLegacyMode(); - if (visible) { - updatePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(); - updatePane.add(new UIButton(Toolkit.i18nText("Fine-Design_Vcs_Center"))); - } - updatePane.setVisible(!visible); + 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() { @@ -347,7 +387,7 @@ public class VcsMovePanel extends BasicPane { return parentPane; } - private void initFailedPane() { + 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")); @@ -355,7 +395,7 @@ public class VcsMovePanel extends BasicPane { 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")); + failedTipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Move_Failed_Tip", detail)); initStatusPane(failedTipLabel, failedIconLabel, failedLabel, failedButton, body, FAILED, failedPane); } @@ -381,6 +421,7 @@ public class VcsMovePanel extends BasicPane { private class MoveWorker extends SwingWorker { private VcsMoveStrategy strategy; + private String detail = StringUtils.EMPTY; public MoveWorker(VcsMoveStrategy strategy) { this.strategy = strategy; @@ -403,6 +444,7 @@ public class VcsMovePanel extends BasicPane { }, strategy); } catch (Exception e) { VcsMoveService.getInstance().stopMoving(); + detail = VcsExceptionUtils.createDetailByException(e); return false; } return true; @@ -421,8 +463,9 @@ public class VcsMovePanel extends BasicPane { initSuccessPane(); VcsMovePanel.this.getParentCard().show(getParentPane(), SUCCESS); VcsHelper.getInstance().updateLegacyMode(); + DesignerFrameFileDealerPane.getInstance().refreshDockingView(); } else { - initFailedPane(); + initFailedPane(detail); VcsMovePanel.this.getParentCard().show(getParentPane(), FAILED); FineLoggerFactory.getLogger().error("[VcsV2] Vcs move failed!"); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsNewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsNewPane.java index 0916062ccb..3a949b85d6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsNewPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsNewPane.java @@ -9,7 +9,7 @@ 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.VcsService; +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; @@ -111,8 +111,9 @@ public class VcsNewPane extends RecyclePane { } }; this.operatorPane = createOperatorPane(); - this.model.setDefaultEditor(VcsOperatorPane.class, operatorPane); - this.model.setDefaultRenderer(VcsOperatorPane.class, operatorPane); + this.model.setDefaultEditor(VcsOperatorPane.class, new VcsCellEditor(createOperatorPane())); + this.model.setDefaultRenderer(VcsOperatorPane.class, new VcsCellRender(createOperatorPane())); + this.model.setDefaultRenderer(UILabel.class, new ToolTipTableCellRenderer()); } @@ -128,8 +129,11 @@ public class VcsNewPane extends RecyclePane { */ 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(); @@ -156,6 +160,7 @@ public class VcsNewPane extends RecyclePane { JOptionPane.QUESTION_MESSAGE); if (selVal == JOptionPane.YES_OPTION) { restoreEntity(entity); + VcsNewPane.this.saveSettingAndCloseDialog(); } } } @@ -209,7 +214,7 @@ public class VcsNewPane extends RecyclePane { if (selVal == JOptionPane.YES_OPTION) { model.getList().remove(o); model.fireTableDataChanged(); - VcsService.getInstance().deleteEntity(entity.getFilename(), entity.getVersion()); + VcsOperatorWorker.createDeleteWorker().deleteTargetVersion(entity); } } } @@ -225,6 +230,7 @@ public class VcsNewPane extends RecyclePane { if (o instanceof VcsTableEntity) { VcsEntity entity = ((VcsTableEntity) o).getEntity(); previewEntity(entity); + VcsNewPane.this.saveSettingAndCloseDialog(); } } }); @@ -329,11 +335,16 @@ public class VcsNewPane extends RecyclePane { @Override public void doOK() { entity.setCommitMsg(getMsgTestArea().getText()); - VcsService.getInstance().updateEntityAnnotation(entity); + VcsOperatorWorker.createUpdateWorker().updateEntityAnnotation(entity); setVisible(false); model.fireTableDataChanged(); } }; dialog.setVisible(true); } + + @Override + protected boolean needIcon4Head(int col) { + return col != 0 && col != OPERATOR_COL; + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsOperatorPane.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsOperatorPane.java index 9da20d8a54..ce4db1e0d7 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsOperatorPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsOperatorPane.java @@ -3,20 +3,15 @@ package com.fr.design.mainframe.vcs.ui; import com.fr.design.layout.FRGUIPaneFactory; - -import javax.swing.AbstractCellEditor; - import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.JTable; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; + + import java.awt.*; -import java.util.List; +import java.util.List; -import static com.fr.design.mainframe.vcs.ui.AbstractSupportSelectTablePane.DEFAULT_SELECT_TABLE_ROW_COLOR; /** * 操作面板,用于置放常用的操作label @@ -27,37 +22,19 @@ import static com.fr.design.mainframe.vcs.ui.AbstractSupportSelectTablePane.DEFA * @since 11.0 * Created on 2023/7/13 */ -public class VcsOperatorPane extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { - private JPanel contentPane; - - private static final Color DETAIL_FONT_COLOR = new Color(65, 155, 249); +public class VcsOperatorPane extends JPanel { public VcsOperatorPane(List iconJComponentMap) { init(iconJComponentMap); } + private void init(List iconJComponentMap) { - contentPane = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); for (JComponent value : iconJComponentMap) { - value.setForeground(DETAIL_FONT_COLOR); value.setCursor(new Cursor(Cursor.HAND_CURSOR)); - contentPane.add(value); + this.add(value); } } - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - return contentPane; - } - - @Override - public Object getCellEditorValue() { - return contentPane; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - contentPane.setBackground(isSelected ? DEFAULT_SELECT_TABLE_ROW_COLOR : Color.WHITE); - return contentPane; - } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsProgressDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsProgressDialog.java new file mode 100644 index 0000000000..33b57e1f3e --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java index 018bc75aeb..bad481e7af 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/DataBindingEditor.java @@ -29,8 +29,8 @@ public class DataBindingEditor extends Editor { 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 { } }); 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() { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java index 4f5c7f28f3..48199a5e6b 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java +++ b/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); diff --git a/designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_sort_normal.svg b/designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_sort_normal.svg new file mode 100644 index 0000000000..01d9ffeb5f --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/standard/vcslist/vcs_sort_normal.svg @@ -0,0 +1,4 @@ + + + + diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XEditorHolder.java b/designer-form/src/main/java/com/fr/design/designer/creator/XEditorHolder.java index 8bcacb7d26..3291159a3a 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XEditorHolder.java +++ b/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"; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java index 0555cf1723..801a342197 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java +++ b/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; + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java index 24ed004fff..87f7465490 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java @@ -1208,7 +1208,7 @@ public class FormDesigner extends TargetComponent

    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; } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FormWidgetValuePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FormWidgetValuePane.java index 6943085ecf..7a69292ce5 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FormWidgetValuePane.java +++ b/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 编辑器