Browse Source
* commit '35143aad51b2a7534febcec445255560a87d122b': (68 commits) REPORT-98345 版本管理三期 迁移成功后,没刷新工具栏 REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭 修改方法名 REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭 修改方法名 REPORT-100458 【版本管理二期】迁移弹窗,保留版本的输入框没有非法值校验 REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭 REPORT-100958 【版本管理三期】还原或者预览版本,弹窗应该关闭 REPORT-91839 模板版本管理二期 没设置启动页,启动的时候判断有点问题 REPORT-100518 【版本管理二期】无磁盘写入权限,版本迁移无异常提示 REPORT-101340 【版本管理二期】自动清理配置灰化时,hover提示没有 REPORT-101060 【版本管理三期】删除无权限的版本,能删除成功 REPORT-101166 【版本管理三期】集群环境,版本管理页面所有配置项都不可点 REPORT-100954 【版本管理三期】版本中心弹窗交互问题 REPORT-91839 模板版本管理二期 偶遇报错,不确定场景,加一下处理 REPORT-101167 【版本管理一期】集群环境,保存版本不生效 REPORT-100162 【版本管理二期】模板不在编辑状态,还是在触发自动保存 REPORT-100633 【版本管理二期】取消勾选备注的版本不会被清理,备注的版本还是不会被清理 REPORT-101289 【版本管理二期】数据迁移的提示弹窗位置没有居中 REPORT-101293 【版本管理二期】模板未打开,点击版本管理点不开 fix: 只有选择关闭当前分类其它模板时才做类型比较 #REPORT-99959 fix: 关闭当前类型模板时,不判断其它类型模板是否保存 #REPORT-99959 ...feature/x
superman
1 year ago
36 changed files with 1602 additions and 315 deletions
@ -0,0 +1,37 @@
|
||||
package com.fr.design.mainframe.vcs; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.HashMap; |
||||
|
||||
/** |
||||
* 版本管理异常处理工具类 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/7/24 |
||||
*/ |
||||
public class VcsExceptionUtils { |
||||
|
||||
public static final HashMap<Class, String> EXCEPTION_MAP = new HashMap<Class, String>() { |
||||
{ |
||||
put(IOException.class, Toolkit.i18nText("Fine-Design_Vcs_Exception_IO")); |
||||
put(UnsupportedOperationException.class, Toolkit.i18nText("Fine-Design_Vcs_Exception_Un_Support")); |
||||
} |
||||
}; |
||||
|
||||
|
||||
/** |
||||
* 根据异常返回结果描述文案 |
||||
*/ |
||||
public static String createDetailByException(Exception e) { |
||||
for (Class key : EXCEPTION_MAP.keySet()) { |
||||
if (key.isAssignableFrom(e.getClass())) { |
||||
return EXCEPTION_MAP.get(key); |
||||
} |
||||
} |
||||
return Toolkit.i18nText("Fine-Design_Vcs_Exception_Unknown"); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,291 @@
|
||||
package com.fr.design.mainframe.vcs; |
||||
|
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.vcs.ui.VcsBatchProcessDetailPane; |
||||
import com.fr.design.mainframe.vcs.ui.VcsProgressDialog; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.report.entity.VcsEntity; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.workspace.WorkContext; |
||||
import com.fr.workspace.server.vcs.VcsOperator; |
||||
|
||||
import javax.swing.SwingWorker; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.concurrent.ExecutionException; |
||||
|
||||
/** |
||||
* 为版本中心、回收站、版本详情提供带进度条与结算面板的操作的worker |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/7/18 |
||||
*/ |
||||
public class VcsOperatorWorker { |
||||
private int count = 0; |
||||
|
||||
private static final int FREQ = 5; |
||||
|
||||
private String successStr; |
||||
|
||||
private String title; |
||||
|
||||
private String failedStr; |
||||
|
||||
private String everyFailedStr; |
||||
|
||||
private VcsProgressDialog dialog; |
||||
|
||||
|
||||
private static final String PREFIX = "(v."; |
||||
private static final String TAIL = ")"; |
||||
|
||||
public VcsOperatorWorker(String title, String dealingStr, String successStr, String failedStr, String everyFailedStr) { |
||||
this.title = title; |
||||
this.successStr = successStr; |
||||
this.failedStr = failedStr; |
||||
this.everyFailedStr = everyFailedStr; |
||||
dialog = new VcsProgressDialog(title, dealingStr); |
||||
} |
||||
|
||||
public VcsOperatorWorker(String everyFailedStr) { |
||||
this.title = StringUtils.EMPTY; |
||||
this.successStr = StringUtils.EMPTY; |
||||
this.failedStr = StringUtils.EMPTY; |
||||
this.everyFailedStr = everyFailedStr; |
||||
} |
||||
|
||||
/** |
||||
* 快速创建用于删除的worker |
||||
* |
||||
* @return |
||||
*/ |
||||
public static VcsOperatorWorker createDeleteWorker() { |
||||
return new VcsOperatorWorker( |
||||
Toolkit.i18nText("Fine-Design_Vcs_Delete_Progress_Title"), |
||||
Toolkit.i18nText("Fine-Design_Vcs_Delete_Progress_Tips"), |
||||
Toolkit.i18nText("Fine-Design_Vcs_Delete_Progress_Success"), |
||||
"Fine-Design_Vcs_Delete_Progress_Failed", |
||||
Toolkit.i18nText("Fine-Design_Vcs_Delete_Every_Failed")); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 快速创建用于还原的worker |
||||
* |
||||
* @return |
||||
*/ |
||||
public static VcsOperatorWorker createRestoreWorker() { |
||||
return new VcsOperatorWorker( |
||||
Toolkit.i18nText("Fine-Design_Vcs_Restore_Progress_Title"), |
||||
Toolkit.i18nText("Fine-Design_Vcs_Restore_Progress_Tips"), |
||||
Toolkit.i18nText("Fine-Design_Vcs_Restore_Progress_Success"), |
||||
"Fine-Design_Vcs_Restore_Progress_Failed", |
||||
Toolkit.i18nText("Fine-Design_Vcs_Restore_Every_Failed")); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 快速创建用于还原的worker |
||||
* |
||||
* @return |
||||
*/ |
||||
public static VcsOperatorWorker createUpdateWorker() { |
||||
return new VcsOperatorWorker(Toolkit.i18nText("Fine-Design_Vcs_Update_Every_Failed")); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 批量还原 |
||||
* |
||||
* @param vcsEntities 需要还原的版本 |
||||
*/ |
||||
public void batchRestore(List<VcsEntity> vcsEntities) { |
||||
List<String> failedList = new ArrayList<>(); |
||||
startProcess(vcsEntities, failedList, (vcsEntity, operator) -> { |
||||
String fileName = vcsEntity.getFilename(); |
||||
boolean result = true; |
||||
try { |
||||
operator.restoreVersion(fileName); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
result = false; |
||||
} |
||||
if (!result) { |
||||
failedList.add(fileName+PREFIX+vcsEntity.getVersion()+TAIL); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 批量删除 |
||||
* |
||||
* @param vcsEntities 需要删除的版本 |
||||
* @param all 是否需要删除所有版本 |
||||
*/ |
||||
public void batchDelete(List<VcsEntity> vcsEntities, boolean all) { |
||||
List<String> failedList = new ArrayList<>(); |
||||
startProcess(vcsEntities, failedList, (vcsEntity, operator) -> { |
||||
String fileName = vcsEntity.getFilename(); |
||||
boolean result = true; |
||||
try { |
||||
if (all) { |
||||
operator.deleteVersionForRecycle(fileName); |
||||
} else { |
||||
operator.deleteVersion(fileName, vcsEntity.getVersion()); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
result = false; |
||||
} |
||||
if (!result) { |
||||
failedList.add(fileName+PREFIX+vcsEntity.getVersion()+TAIL); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 删除指定模板的全部历史版本 |
||||
* |
||||
* @param entity VcsEntity |
||||
*/ |
||||
public void doDelete(VcsEntity entity) { |
||||
String fileName = entity.getFilename(); |
||||
start4Single(entity, (vcsEntity, operator) -> operator.deleteVersionForRecycle(fileName), fileName + everyFailedStr); |
||||
} |
||||
|
||||
/** |
||||
* 删除指定模板的指定版本 |
||||
* |
||||
* @param entity 版本 |
||||
*/ |
||||
public void deleteTargetVersion(VcsEntity entity) { |
||||
String fileName = entity.getFilename(); |
||||
int version = entity.getVersion(); |
||||
start4Single(entity, (vcsEntity, operator) -> { |
||||
operator.deleteVersion(fileName, version); |
||||
}, fileName + everyFailedStr); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 更新版本 |
||||
* |
||||
* @param entity 版本 |
||||
*/ |
||||
public void updateEntityAnnotation(VcsEntity entity) { |
||||
start4Single(entity, (vcsEntity, operator) -> { |
||||
operator.updateVersion(entity); |
||||
}, everyFailedStr); |
||||
} |
||||
|
||||
private void startProcess(List<VcsEntity> vcsEntities, List<String> failedList, VcsWorkerOperator workerOperator) { |
||||
try { |
||||
dialog.getProgressBar().setMaximum(vcsEntities.size()); |
||||
start4Batch(vcsEntities, failedList, workerOperator); |
||||
dialog.showDialog(); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 控制更新频率 |
||||
* |
||||
* @return 是否需要更新进度 |
||||
*/ |
||||
private boolean needPublish() { |
||||
return (count > FREQ && count % FREQ == 0) || count < FREQ; |
||||
} |
||||
|
||||
private void start4Single(VcsEntity entity, VcsWorkerOperator vcsWorkerOperator, String failedTip) { |
||||
new SwingWorker<Boolean, Void>() { |
||||
@Override |
||||
protected void done() { |
||||
try { |
||||
if (!get()) { |
||||
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), failedTip); |
||||
} |
||||
} catch (InterruptedException | ExecutionException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
@Override |
||||
protected Boolean doInBackground() throws Exception { |
||||
try { |
||||
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class); |
||||
vcsWorkerOperator.process(entity, operator); |
||||
} catch (Exception e) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
}.execute(); |
||||
} |
||||
|
||||
private void start4Batch(List<VcsEntity> vcsEntities, List<String> failedList, VcsWorkerOperator workerOperator) { |
||||
new SwingWorker<Boolean, Integer>() { |
||||
@Override |
||||
protected Boolean doInBackground() throws Exception { |
||||
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class); |
||||
for (VcsEntity vcsEntity : vcsEntities) { |
||||
workerOperator.process(vcsEntity, operator); |
||||
count++; |
||||
if (needPublish()) { |
||||
publish(count); |
||||
} |
||||
} |
||||
return failedList.isEmpty(); |
||||
} |
||||
@Override |
||||
protected void process(List<Integer> chunks) { |
||||
dialog.getProgressBar().setValue(chunks.get(chunks.size() - 1)); |
||||
} |
||||
@Override |
||||
protected void done() { |
||||
dialog.closeDialog(); |
||||
try { |
||||
showErrorDetailPane(get(), failedList, failedList.size(), vcsEntities.size() - failedList.size()); |
||||
} catch (InterruptedException | ExecutionException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
}.execute(); |
||||
} |
||||
|
||||
|
||||
private void showErrorDetailPane(boolean result, List<String> failedList, int failed, int success) { |
||||
if (result) { |
||||
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), successStr); |
||||
} else { |
||||
VcsBatchProcessDetailPane pane = new VcsBatchProcessDetailPane( |
||||
DesignerContext.getDesignerFrame(), |
||||
title, |
||||
Toolkit.i18nText(failedStr, failed, success) |
||||
); |
||||
for (String msg : failedList) { |
||||
pane.updateDetailArea(msg + everyFailedStr); |
||||
} |
||||
pane.show(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Vcs面板操作处理接口 |
||||
* |
||||
*/ |
||||
private interface VcsWorkerOperator { |
||||
|
||||
/** |
||||
* 处理 |
||||
* |
||||
* @param vcsEntity 版本 |
||||
* @param operator 操作类 |
||||
*/ |
||||
void process(VcsEntity vcsEntity, VcsOperator operator) throws Exception; |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -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; |
||||
|
||||
/** |
||||
* 版本管理常用操作 |
||||
* <p>便于版本管理面板快捷实现版本管理相关操作 |
||||
* |
||||
* @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<VcsEntity> 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<VcsEntity> 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); |
||||
} |
||||
} |
||||
} |
@ -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"); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.fr.design.mainframe.vcs.ui; |
||||
|
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.workspace.server.vcs.v2.move.VcsMoveService; |
||||
|
||||
import javax.swing.JOptionPane; |
||||
|
||||
/** |
||||
* 版本管理迁移检查 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/7/18 |
||||
*/ |
||||
public class VcsMovingExitOption { |
||||
|
||||
|
||||
/** |
||||
* 关闭前的检查 |
||||
* |
||||
* @return |
||||
*/ |
||||
public static boolean ShowDialogAndConfirmExit() { |
||||
return showDialogAndChoose(Toolkit.i18nText("Fine-Design_Vcs_Close_Tips")); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 切换环境前的检查 |
||||
* |
||||
* @return |
||||
*/ |
||||
public static boolean ShowDialogAndConfirmSwitch() { |
||||
return showDialogAndChoose(Toolkit.i18nText("Fine-Design_Vcs_Switch_Tips")); |
||||
} |
||||
|
||||
private static boolean showDialogAndChoose(String msg) { |
||||
if (VcsMoveService.getInstance().isMoving()) { |
||||
int result = FineJOptionPane.showConfirmDialog( |
||||
DesignerContext.getDesignerFrame(), |
||||
msg, |
||||
Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), |
||||
FineJOptionPane.YES_NO_OPTION |
||||
); |
||||
return result == JOptionPane.YES_OPTION; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
After Width: | Height: | Size: 874 B |
Loading…
Reference in new issue