Merge in DESIGN/design from ~DESTINY.LIN/design:feature/x to feature/x * commit 'bfb3f7f31214c0ebc333a37736244d15be515a50': REPORT-98345 版本管理三期 修改代码规范 REPORT-98345 版本管理三期 修改代码规范 REPORT-98345 版本管理三期 修改线程池,修改代码规范,添加部分注释 REPORT-98345 版本管理三期 提交总体代码feature/x
@ -0,0 +1,31 @@ |
|||||||
|
package com.fr.design.mainframe.vcs; |
||||||
|
|
||||||
|
import com.fr.design.actions.UpdateAction; |
||||||
|
import com.fr.design.dialog.BasicDialog; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.vcs.ui.RecyclePane; |
||||||
|
|
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* 回收站 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/4 |
||||||
|
*/ |
||||||
|
public class RecycleAction extends UpdateAction { |
||||||
|
|
||||||
|
public RecycleAction() { |
||||||
|
this.setSmallIcon("/com/fr/design/standard/vcslist/vcs_recycle"); |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Vcs_Recycle")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
RecyclePane pane = new RecyclePane(); |
||||||
|
BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame(), false); |
||||||
|
dialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.fr.design.mainframe.vcs; |
||||||
|
|
||||||
|
/** |
||||||
|
* 表格选中包装类 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/11 |
||||||
|
*/ |
||||||
|
public interface TableEntity { |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否选中 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
boolean isSelect(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置选中属性 |
||||||
|
* |
||||||
|
* @param select |
||||||
|
*/ |
||||||
|
void setSelect(boolean select); |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package com.fr.design.mainframe.vcs; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 表格操作 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/11 |
||||||
|
*/ |
||||||
|
public interface TableValueOperator<T> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取对应列的值 |
||||||
|
* |
||||||
|
* @param o 表格内容 |
||||||
|
* @param columnIndex 列数 |
||||||
|
* @return 对应列的值 |
||||||
|
*/ |
||||||
|
Object getValue(T o, int columnIndex); |
||||||
|
} |
@ -0,0 +1,162 @@ |
|||||||
|
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,108 @@ |
|||||||
|
package com.fr.design.mainframe.vcs; |
||||||
|
|
||||||
|
import com.fr.report.entity.VcsEntity; |
||||||
|
|
||||||
|
/** |
||||||
|
* 包装VcsEntity的用于表格展示与处理的类 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/10 |
||||||
|
*/ |
||||||
|
public class VcsTableEntity implements TableEntity{ |
||||||
|
|
||||||
|
private boolean select = false; |
||||||
|
|
||||||
|
private static final String MB = "MB"; |
||||||
|
|
||||||
|
private static final String VERSION = "V."; |
||||||
|
private static final double MB_SIZE = 1024.0; |
||||||
|
private VcsEntity entity; |
||||||
|
|
||||||
|
|
||||||
|
public VcsTableEntity(VcsEntity entity) { |
||||||
|
this.entity = entity; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取模板名 |
||||||
|
* |
||||||
|
* @return 模板名 |
||||||
|
*/ |
||||||
|
public String getFilename() { |
||||||
|
return entity.getFilename(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取版本大小 |
||||||
|
* |
||||||
|
* @return 版本大小 |
||||||
|
*/ |
||||||
|
public String getSize() { |
||||||
|
return String.format("%.2f",entity.getSize()/MB_SIZE) + MB; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取修改时间 |
||||||
|
* |
||||||
|
* @return 修改时间 |
||||||
|
*/ |
||||||
|
public String getTime() { |
||||||
|
return entity.getTime().toLocaleString(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取用户名 |
||||||
|
* |
||||||
|
* @return 用户名 |
||||||
|
*/ |
||||||
|
public String getUserName() { |
||||||
|
return entity.getUsername(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 获取备注 |
||||||
|
* |
||||||
|
* @return 备注 |
||||||
|
*/ |
||||||
|
public String getCommitMsg() { |
||||||
|
return entity.getCommitMsg(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取版本号 |
||||||
|
* |
||||||
|
* @return 版本号 |
||||||
|
*/ |
||||||
|
public String getVersion() { |
||||||
|
return VERSION + entity.getVersion(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取删除时间 |
||||||
|
* |
||||||
|
* @return 删除时间 |
||||||
|
*/ |
||||||
|
public String getDeleteTime() { |
||||||
|
return entity.getDeleteTime().toLocaleString(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isSelect() { |
||||||
|
return select; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setSelect(boolean select) { |
||||||
|
this.select = select; |
||||||
|
} |
||||||
|
|
||||||
|
public VcsEntity getEntity() { |
||||||
|
return entity; |
||||||
|
} |
||||||
|
|
||||||
|
public void setEntity(VcsEntity entity) { |
||||||
|
this.entity = entity; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,370 @@ |
|||||||
|
package com.fr.design.mainframe.vcs.ui; |
||||||
|
|
||||||
|
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane; |
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditAction; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableModelAdapter; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.mainframe.vcs.TableEntity; |
||||||
|
import com.fr.design.mainframe.vcs.TableValueOperator; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.DefaultCellEditor; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JLabel; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.JTable; |
||||||
|
import javax.swing.SwingConstants; |
||||||
|
import javax.swing.SwingWorker; |
||||||
|
import javax.swing.UIManager; |
||||||
|
import javax.swing.plaf.ColorUIResource; |
||||||
|
import javax.swing.plaf.UIResource; |
||||||
|
import javax.swing.table.JTableHeader; |
||||||
|
import javax.swing.table.TableCellRenderer; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.util.List; |
||||||
|
import java.util.concurrent.ExecutionException; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 比较通用的带全选功能的表格面板 |
||||||
|
* |
||||||
|
* <p>整体划分为north与center两个面板(参考BorderLayout的布局),center部分用于置放表格,表格部分支持全选,north部分支持自定义,用于展示各种标签按钮输入框</p> |
||||||
|
* <p>获取数据的时候不需要用SwingWorker(内部已经实现),考虑到大部分表格内容的展现需要去获取数据,而获取数据大部分都需要一定时间,因此为了防止UI冻结,在加载数据结束之前先展示进度条面板</p> |
||||||
|
* <p>使用该面板你可能需要:</p> |
||||||
|
* <li>自己封装一个实现TableEntity接口(该接口用于提供(选中/全选)功能),内部存放你要放入表格的类,例如VcsEntity,参考VcsTableEntity</li> |
||||||
|
* <li>初始化的时候赋予变量model值(如果有需要的话),该变量用于控制表格的数据类型,默认DefaultModel——分为5列,第一列为勾选框</li> |
||||||
|
* <li>(一定要干的)初始化的时候赋予变量model内operators值,用于确认表格每一列getValueAt返回的值</li> |
||||||
|
* <li>上面板也允许自定义,重写initTableTopPane即可</li> |
||||||
|
* <li>要使用该面板可以参考:RecyclePane</li> |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/11 |
||||||
|
*/ |
||||||
|
public abstract class AbstractSupportSelectTablePane<T extends TableEntity> extends BasicPane { |
||||||
|
|
||||||
|
public static final Color DEFAULT_HEADER_COLOR = new Color(232, 232, 233); |
||||||
|
public static final Color DEFAULT_SELECT_TABLE_ROW_COLOR = new ColorUIResource(200, 221, 233); |
||||||
|
private CardLayout layout; |
||||||
|
|
||||||
|
|
||||||
|
protected JPanel contentPane; |
||||||
|
|
||||||
|
protected UITextField searchTextField = new UITextField();; |
||||||
|
|
||||||
|
protected UILabel deleteLabel = new UILabel(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 整体面板的center部分,用来放表格 |
||||||
|
*/ |
||||||
|
protected UITableEditorPane<T> tableContentPane; |
||||||
|
|
||||||
|
protected UITableModelAdapter<T> model; |
||||||
|
/** |
||||||
|
* 整体面板的north部分 |
||||||
|
*/ |
||||||
|
protected JPanel tableTopPane = new JPanel(); |
||||||
|
/** |
||||||
|
* 整体面板 |
||||||
|
*/ |
||||||
|
protected JPanel tablePane = new JPanel(); |
||||||
|
|
||||||
|
private int selectCount = 0; |
||||||
|
private static final String LOADING = "loading"; |
||||||
|
private static final String TABLE ="table"; |
||||||
|
|
||||||
|
protected List<T> entities; |
||||||
|
|
||||||
|
protected TableValueOperator<T> operator; |
||||||
|
|
||||||
|
|
||||||
|
public AbstractSupportSelectTablePane(String title, TableValueOperator<T> operators, String[] tableNames, boolean needBorder) { |
||||||
|
this.operator = operators; |
||||||
|
this.model = new DefaultModel(tableNames, new Class[]{ |
||||||
|
Boolean.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class |
||||||
|
|
||||||
|
}); |
||||||
|
init(title, needBorder); |
||||||
|
} |
||||||
|
|
||||||
|
public AbstractSupportSelectTablePane(String title, TableValueOperator<T> operators, boolean needBorder) { |
||||||
|
this.operator = operators; |
||||||
|
init(title, needBorder); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化 |
||||||
|
* |
||||||
|
*/ |
||||||
|
private void init(String title, boolean needBorder) { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
contentPane = new JPanel(); |
||||||
|
layout = new CardLayout(); |
||||||
|
contentPane.setLayout(layout); |
||||||
|
contentPane.add(new TipsPane(true), LOADING); |
||||||
|
this.add(contentPane); |
||||||
|
new SwingWorker<List<T>, Void>(){ |
||||||
|
@Override |
||||||
|
protected List<T> doInBackground() { |
||||||
|
return getTableList(); |
||||||
|
} |
||||||
|
@Override |
||||||
|
protected void done() { |
||||||
|
try { |
||||||
|
entities = get(); |
||||||
|
} catch (InterruptedException | ExecutionException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
contentPane.add(createTablePane(title, needBorder), TABLE); |
||||||
|
layout.show(contentPane, TABLE); |
||||||
|
} |
||||||
|
}.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取表格数据 |
||||||
|
* |
||||||
|
* @return 表格数据 |
||||||
|
*/ |
||||||
|
abstract protected List<T> getTableList(); |
||||||
|
|
||||||
|
private JPanel createTablePane(String title, boolean needBorder) { |
||||||
|
tablePane = needBorder ? FRGUIPaneFactory.createTopVerticalTitledBorderPane(title) : new JPanel(); |
||||||
|
if (isNeedTopPane()) { |
||||||
|
initTableTopPane(); |
||||||
|
initTopPaneListener(); |
||||||
|
} |
||||||
|
initTableContentPane(entities); |
||||||
|
tablePane.setLayout(new BorderLayout()); |
||||||
|
tablePane.add(tableTopPane, BorderLayout.NORTH); |
||||||
|
tablePane.add(tableContentPane, BorderLayout.CENTER); |
||||||
|
tableContentPane.getEditTable().getColumnModel().getColumn(0).setMaxWidth(50); |
||||||
|
return tablePane; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化表格面板 |
||||||
|
* |
||||||
|
* @param entities 表格数据 |
||||||
|
*/ |
||||||
|
protected void initTableContentPane(List<T> entities) { |
||||||
|
tableContentPane = new UITableEditorPane<>(model); |
||||||
|
model.setList(entities); |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
table.getTableHeader().setBackground(DEFAULT_HEADER_COLOR); |
||||||
|
table.getTableHeader().setDefaultRenderer(new HeaderRenderer(tableContentPane.getEditTable())); |
||||||
|
table.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
int row = ((JTable) e.getSource()).rowAtPoint(e.getPoint()); |
||||||
|
int col = ((JTable) e.getSource()).columnAtPoint(e.getPoint()); |
||||||
|
if (col == 0) { |
||||||
|
T entity = model.getSelectedValue(); |
||||||
|
//改变面板的各个状态
|
||||||
|
changeComponentStatus(entity, row, col, table); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
initExtraListener4Table(table); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设定额外的表格事件 |
||||||
|
* |
||||||
|
* @param table 表格 |
||||||
|
*/ |
||||||
|
protected void initExtraListener4Table(JTable table) { |
||||||
|
//do nothing
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否需要上面板 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
protected boolean isNeedTopPane() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private void changeComponentStatus(T entity, int row, int col, JTable table) { |
||||||
|
boolean select = entity.isSelect(); |
||||||
|
entity.setSelect(!select); |
||||||
|
table.setValueAt(entity.isSelect(), row, col); |
||||||
|
if (select) { |
||||||
|
selectCount--; |
||||||
|
} else { |
||||||
|
selectCount++; |
||||||
|
} |
||||||
|
//更新表头的勾选框状态
|
||||||
|
HeaderRenderer renderer = (HeaderRenderer) table.getTableHeader().getDefaultRenderer(); |
||||||
|
renderer.refreshHeader(table, selectCount >= table.getRowCount()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化上面板 |
||||||
|
*/ |
||||||
|
abstract protected void initTableTopPane(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 初始化上面板事件 |
||||||
|
*/ |
||||||
|
abstract protected void initTopPaneListener(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 表头渲染 |
||||||
|
*/ |
||||||
|
public class HeaderRenderer implements TableCellRenderer { |
||||||
|
JTableHeader tableHeader; |
||||||
|
final UICheckBox selectBox; |
||||||
|
|
||||||
|
public HeaderRenderer(JTable table) { |
||||||
|
this.tableHeader = table.getTableHeader(); |
||||||
|
selectBox = new UICheckBox(); |
||||||
|
selectBox.setSelected(false); |
||||||
|
tableHeader.addMouseListener(new MouseAdapter() { |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
if (e.getClickCount() > 0) { |
||||||
|
//获得选中列
|
||||||
|
int selectColumn = tableHeader.columnAtPoint(e.getPoint()); |
||||||
|
if (selectColumn == 0) { |
||||||
|
boolean value = !selectBox.isSelected(); |
||||||
|
selectBox.setSelected(value); |
||||||
|
selectAllOrNull(value); |
||||||
|
selectCount = value ? table.getRowCount() : 0; |
||||||
|
tableHeader.repaint(); |
||||||
|
model.fireTableDataChanged(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void selectAllOrNull(boolean value) { |
||||||
|
int len = table.getRowCount(); |
||||||
|
for (T entity : model.getList()) { |
||||||
|
entity.setSelect(value); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 刷新表头 |
||||||
|
* |
||||||
|
* @param table |
||||||
|
*/ |
||||||
|
public void refreshHeader(JTable table, boolean value) { |
||||||
|
selectBox.setSelected(value); |
||||||
|
int rowHeight = table.getRowHeight(); |
||||||
|
table.updateUI(); |
||||||
|
table.setRowHeight(rowHeight); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellRendererComponent(JTable table, |
||||||
|
Object value, |
||||||
|
boolean isSelected, |
||||||
|
boolean hasFocus, |
||||||
|
int row, int column) { |
||||||
|
tableHeader = table.getTableHeader(); |
||||||
|
tableHeader.setReorderingAllowed(false); |
||||||
|
String valueStr = (String) value; |
||||||
|
JLabel label = new JLabel(valueStr); |
||||||
|
label.setHorizontalAlignment(SwingConstants.LEFT); |
||||||
|
selectBox.setHorizontalAlignment(SwingConstants.CENTER); |
||||||
|
selectBox.setBorderPainted(true); |
||||||
|
JComponent component = (column == 0) ? selectBox : label; |
||||||
|
component.setForeground(tableHeader.getForeground()); |
||||||
|
component.setBackground(tableHeader.getBackground()); |
||||||
|
component.setFont(tableHeader.getFont()); |
||||||
|
component.setBorder(UIManager.getBorder("TableHeader.cellBorder")); |
||||||
|
return component; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 默认的数据model |
||||||
|
*/ |
||||||
|
public class DefaultModel extends UITableModelAdapter<T> { |
||||||
|
|
||||||
|
public DefaultModel(String[] tableNames, Class[] classes) { |
||||||
|
super(tableNames); |
||||||
|
setColumnClass(classes); |
||||||
|
this.setDefaultEditor(Boolean.class, new BooleanEditor()); |
||||||
|
this.setDefaultRenderer(Boolean.class, new BooleanRenderer()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) { |
||||||
|
T vcsEntity = this.getList().get(rowIndex); |
||||||
|
return operator.getValue(vcsEntity, columnIndex); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isCellEditable(int row, int col) { |
||||||
|
return col == 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public UITableEditAction[] createAction() { |
||||||
|
return new UITableEditAction[0]; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 用于展示指定风格的checkbox的Editor |
||||||
|
*/ |
||||||
|
public class BooleanEditor extends DefaultCellEditor { |
||||||
|
public BooleanEditor() { |
||||||
|
super(new UICheckBox()); |
||||||
|
UICheckBox checkBox = (UICheckBox) getComponent(); |
||||||
|
checkBox.setHorizontalAlignment(UICheckBox.CENTER); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 用于展示指定风格的checkbox的渲染器 |
||||||
|
*/ |
||||||
|
public class BooleanRenderer extends UICheckBox implements TableCellRenderer, UIResource { |
||||||
|
public BooleanRenderer() { |
||||||
|
super(); |
||||||
|
setHorizontalAlignment(JLabel.CENTER); |
||||||
|
setBorderPainted(true); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, |
||||||
|
boolean isSelected, boolean hasFocus, int row, int column) { |
||||||
|
setSelected((Boolean) table.getValueAt(row, 0)); |
||||||
|
setUI(getUICheckBoxUI()); |
||||||
|
setBorder(BorderFactory.createEmptyBorder()); |
||||||
|
setBackground(isSelected ? DEFAULT_SELECT_TABLE_ROW_COLOR : Color.WHITE); |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
@ -0,0 +1,266 @@ |
|||||||
|
package com.fr.design.mainframe.vcs.ui; |
||||||
|
|
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
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.vcs.TableEntity; |
||||||
|
import com.fr.design.mainframe.vcs.TableValueOperator; |
||||||
|
import com.fr.design.mainframe.vcs.VcsTableEntity; |
||||||
|
import com.fr.report.entity.VcsEntity; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.vcs.VcsOperator; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import static com.fr.design.i18n.Toolkit.i18nText; |
||||||
|
|
||||||
|
/** |
||||||
|
* 回收面板 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/5 |
||||||
|
*/ |
||||||
|
public class RecyclePane extends AbstractSupportSelectTablePane<VcsTableEntity> { |
||||||
|
public static final Icon ICON_SEARCH = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_recycle_search"); |
||||||
|
public static final Icon ICON_REFRESH = IconUtils.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"); |
||||||
|
|
||||||
|
protected UITextField searchTextField; |
||||||
|
|
||||||
|
protected UILabel deleteLabel; |
||||||
|
|
||||||
|
protected UILabel restoreLabel; |
||||||
|
|
||||||
|
private static final int COLUMNS_COUNT = 15; |
||||||
|
|
||||||
|
public RecyclePane() { |
||||||
|
super(i18nText("Fine-Design_Vcs_Recycle"), (o, columnIndex) -> { |
||||||
|
switch (columnIndex) { |
||||||
|
case 0: |
||||||
|
return o.isSelect(); |
||||||
|
case 1: |
||||||
|
return o.getFilename(); |
||||||
|
case 2: |
||||||
|
return o.getSize(); |
||||||
|
case 3: |
||||||
|
return o.getDeleteTime(); |
||||||
|
case 4: |
||||||
|
return o.getTime(); |
||||||
|
default: |
||||||
|
return o; |
||||||
|
|
||||||
|
} |
||||||
|
}, new String[]{ |
||||||
|
StringUtils.EMPTY, |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Template"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Recycle_Size"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Delete_Time"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Time") |
||||||
|
}, true); |
||||||
|
} |
||||||
|
|
||||||
|
public RecyclePane(String title, TableValueOperator<VcsTableEntity> operators, boolean needBorder) { |
||||||
|
super(title, operators, needBorder); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected List<VcsTableEntity> getTableList() { |
||||||
|
List<VcsEntity> entityList = WorkContext.getCurrent().get(VcsOperator.class).getRecycleEntities(); |
||||||
|
List<VcsTableEntity> tableEntities = new ArrayList<>(); |
||||||
|
for (VcsEntity entity : entityList) { |
||||||
|
tableEntities.add(new VcsTableEntity(entity)); |
||||||
|
} |
||||||
|
return tableEntities; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initTableTopPane() { |
||||||
|
tableTopPane = new JPanel(); |
||||||
|
tableTopPane.setLayout(new BorderLayout()); |
||||||
|
JPanel leftPane = new JPanel(); |
||||||
|
JPanel rightPane = new JPanel(); |
||||||
|
//左边面板,包含搜索icon+搜索框
|
||||||
|
if (isNeedSearch()) { |
||||||
|
searchTextField = new UITextField(); |
||||||
|
searchTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Vcs_Start_Search")); |
||||||
|
searchTextField.setColumns(COLUMNS_COUNT); |
||||||
|
leftPane.add(new UILabel(ICON_SEARCH)); |
||||||
|
leftPane.add(searchTextField); |
||||||
|
} |
||||||
|
//右边面板,包括还原按钮+删除按钮
|
||||||
|
if (isNeedRestore()) { |
||||||
|
restoreLabel = new UILabel(ICON_REFRESH); |
||||||
|
restoreLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
||||||
|
rightPane.add(restoreLabel); |
||||||
|
} |
||||||
|
if (isNeedDelete()) { |
||||||
|
deleteLabel = new UILabel(ICON_DELETE); |
||||||
|
deleteLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
||||||
|
rightPane.add(deleteLabel); |
||||||
|
} |
||||||
|
tableTopPane.add(leftPane, BorderLayout.EAST); |
||||||
|
tableTopPane.add(rightPane, BorderLayout.WEST); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initTopPaneListener() { |
||||||
|
initSearchTextFiledListener(); |
||||||
|
initRestoreListener(); |
||||||
|
initDeleteLabelListener(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initDeleteLabelListener() { |
||||||
|
if (isNeedDelete()) { |
||||||
|
deleteLabel.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
fireListener(new VcsResponseListener() { |
||||||
|
@Override |
||||||
|
public void doAfterChooseYes(List<VcsEntity> selectList) { |
||||||
|
VcsService.getInstance().doDelete(selectList, isNeedDeleteAllVersion()); |
||||||
|
} |
||||||
|
}, true); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void initRestoreListener() { |
||||||
|
if (isNeedRestore()) { |
||||||
|
restoreLabel.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
fireListener(new VcsResponseListener() { |
||||||
|
@Override |
||||||
|
public void doAfterChooseYes(List<VcsEntity> selectList) { |
||||||
|
VcsService.getInstance().doRestore(selectList); |
||||||
|
} |
||||||
|
}, false); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void initSearchTextFiledListener() { |
||||||
|
if (isNeedSearch()) { |
||||||
|
searchTextField.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
String str = searchTextField.getText(); |
||||||
|
List<VcsTableEntity> entityList = model.getList(); |
||||||
|
model.setList(entityList.stream().filter(entity -> entity.getEntity().getFilename().contains(str)).collect(Collectors.toList())); |
||||||
|
model.fireTableDataChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void fireListener(VcsResponseListener listener, boolean isDelete) { |
||||||
|
List<VcsEntity> selectList = model.getList().stream().filter(TableEntity::isSelect).map(VcsTableEntity::getEntity).collect(Collectors.toList()); |
||||||
|
if (selectList.size() > 0) { |
||||||
|
int selVal = FineJOptionPane.showConfirmDialog( |
||||||
|
RecyclePane.this, |
||||||
|
isDelete ? getDeleteTip(selectList.size()) : getRestoreTip(selectList.size()), |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Confirm"), |
||||||
|
JOptionPane.OK_CANCEL_OPTION, |
||||||
|
JOptionPane.QUESTION_MESSAGE); |
||||||
|
if (selVal == JOptionPane.YES_OPTION) { |
||||||
|
model.setList(model.getList().stream().filter(tableEntity -> !tableEntity.isSelect()).collect(Collectors.toList())); |
||||||
|
model.fireTableDataChanged(); |
||||||
|
listener.doAfterChooseYes(selectList); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 删除范围 |
||||||
|
* |
||||||
|
* @return 默认删除全部版本 |
||||||
|
*/ |
||||||
|
protected boolean isNeedDeleteAllVersion() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return i18nText("Fine-Design_Vcs_Recycle"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除提示 |
||||||
|
* |
||||||
|
* @return 默认需要 |
||||||
|
*/ |
||||||
|
protected String getDeleteTip(int size) { |
||||||
|
return Toolkit.i18nText("Fine-Design_Vcs_Delete_Select_All_Version_Forever", size); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 还原提示 |
||||||
|
* |
||||||
|
* @return 默认需要 |
||||||
|
*/ |
||||||
|
protected String getRestoreTip(int size) { |
||||||
|
return Toolkit.i18nText("Fine-Design_Vcs_Restore_Select_All_Version", size); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否需要还原功能 |
||||||
|
* |
||||||
|
* @return 默认需要 |
||||||
|
*/ |
||||||
|
protected boolean isNeedRestore() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否需要搜索功能 |
||||||
|
* |
||||||
|
* @return 默认需要 |
||||||
|
*/ |
||||||
|
protected boolean isNeedSearch() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否需要删除功能 |
||||||
|
* |
||||||
|
* @return 默认需要 |
||||||
|
*/ |
||||||
|
protected boolean isNeedDelete() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 版本管理按钮事件响应 |
||||||
|
*/ |
||||||
|
public interface VcsResponseListener { |
||||||
|
|
||||||
|
/** |
||||||
|
* 选择确认之后要做的事情 |
||||||
|
* |
||||||
|
* @param selectList 所选上的内容 |
||||||
|
*/ |
||||||
|
void doAfterChooseYes(List<VcsEntity> selectList); |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,192 @@ |
|||||||
|
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.i18n.Toolkit; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.vcs.VcsService; |
||||||
|
|
||||||
|
import com.fr.design.mainframe.vcs.VcsTableEntity; |
||||||
|
import com.fr.file.FileNodeFILE; |
||||||
|
import com.fr.file.filetree.FileNode; |
||||||
|
import com.fr.report.entity.VcsEntity; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.project.ProjectConstants; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.vcs.VcsOperator; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import javax.swing.JTable; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 版本中心面板 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/13 |
||||||
|
*/ |
||||||
|
public class VcsCenterPane extends VcsNewPane { |
||||||
|
|
||||||
|
private UILabel manager; |
||||||
|
private UILabel open; |
||||||
|
private UILabel delete; |
||||||
|
|
||||||
|
private static final Icon MANAGER_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_center_manager"); |
||||||
|
private static final Icon DELETE_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_delete"); |
||||||
|
private static final Icon OPEN_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_center_open"); |
||||||
|
private static final Class[] CLASSES = new Class[]{ |
||||||
|
Boolean.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
VcsOperatorPane.class |
||||||
|
}; |
||||||
|
|
||||||
|
private static final int OPERATOR_COL = 4; |
||||||
|
private static final String[] COLUMN_NAMES = new String[]{ |
||||||
|
StringUtils.EMPTY, |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Template"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Time"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Size"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Operator") |
||||||
|
}; |
||||||
|
|
||||||
|
private static final String TITLE = Toolkit.i18nText("Fine-Design_Vcs_Center"); |
||||||
|
|
||||||
|
public VcsCenterPane() { |
||||||
|
super(TITLE, (o, columnIndex) -> { |
||||||
|
switch (columnIndex) { |
||||||
|
case 0: |
||||||
|
return o.isSelect(); |
||||||
|
case 1: |
||||||
|
return o.getFilename(); |
||||||
|
case 2: |
||||||
|
return o.getTime(); |
||||||
|
case 3: |
||||||
|
return o.getSize(); |
||||||
|
default: |
||||||
|
return o; |
||||||
|
} |
||||||
|
}, false, COLUMN_NAMES, CLASSES, OPERATOR_COL); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public VcsOperatorPane createOperatorPane() { |
||||||
|
manager = new UILabel(MANAGER_ICON); |
||||||
|
open = new UILabel(OPEN_ICON); |
||||||
|
delete = new UILabel(DELETE_ICON); |
||||||
|
initManagerListener(); |
||||||
|
initOpenListener(); |
||||||
|
initDeleteListener(); |
||||||
|
List<JComponent> components = new ArrayList<>(); |
||||||
|
components.add(manager); |
||||||
|
components.add(open); |
||||||
|
components.add(delete); |
||||||
|
return new VcsOperatorPane(components); |
||||||
|
} |
||||||
|
|
||||||
|
private void initDeleteListener() { |
||||||
|
delete.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn()); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
VcsEntity entity = ((VcsTableEntity) o).getEntity(); |
||||||
|
String fileName = entity.getFilename(); |
||||||
|
int selVal = FineJOptionPane.showConfirmDialog( |
||||||
|
VcsCenterPane.this, |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Center_Delete", fileName), |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Confirm"), |
||||||
|
JOptionPane.OK_CANCEL_OPTION, |
||||||
|
JOptionPane.QUESTION_MESSAGE); |
||||||
|
if (selVal == JOptionPane.YES_OPTION) { |
||||||
|
VcsService.getInstance().deleteEntity(entity); |
||||||
|
} |
||||||
|
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(getTemplateTruePath(fileName), false))); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void initOpenListener() { |
||||||
|
open.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn()); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
VcsEntity entity = ((VcsTableEntity) o).getEntity(); |
||||||
|
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(getTemplateTruePath(entity.getFilename()), false))); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void initManagerListener() { |
||||||
|
manager.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn()); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
VcsEntity entity = ((VcsTableEntity) o).getEntity(); |
||||||
|
VcsNewPane pane = new VcsNewPane(getTemplateTruePath(entity.getFilename())) { |
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return entity.getFilename()+Toolkit.i18nText("Fine-Design_Vcs_Version_Tips"); |
||||||
|
} |
||||||
|
}; |
||||||
|
BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame(), false); |
||||||
|
dialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected List<VcsTableEntity> getTableList() { |
||||||
|
List<VcsEntity> entities = WorkContext.getCurrent().get(VcsOperator.class).getEveryVersion(); |
||||||
|
List<VcsTableEntity> tableEntities = new ArrayList<>(); |
||||||
|
for (VcsEntity entity : entities) { |
||||||
|
tableEntities.add(new VcsTableEntity(entity)); |
||||||
|
} |
||||||
|
return tableEntities; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return TITLE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private String getTemplateTruePath(String filename) { |
||||||
|
return StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, filename); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String getDeleteTip(int size) { |
||||||
|
return Toolkit.i18nText("Fine-Design_Vcs_Delete_Select_All_Version"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean isNeedTopPane() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean isNeedRestore() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,339 @@ |
|||||||
|
package com.fr.design.mainframe.vcs.ui; |
||||||
|
|
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.design.dialog.FineJOptionPane; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.file.MultiTemplateTabPane; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.design.mainframe.vcs.TableValueOperator; |
||||||
|
import com.fr.design.mainframe.vcs.VcsService; |
||||||
|
import com.fr.design.mainframe.vcs.VcsTableEntity; |
||||||
|
import com.fr.design.mainframe.vcs.common.VcsCacheFileNodeFile; |
||||||
|
import com.fr.design.mainframe.vcs.common.VcsHelper; |
||||||
|
import com.fr.file.FileNodeFILE; |
||||||
|
import com.fr.file.filetree.FileNode; |
||||||
|
import com.fr.report.entity.VcsEntity; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.vcs.VcsOperator; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import javax.swing.JTable; |
||||||
|
import javax.swing.SwingWorker; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.awt.event.MouseMotionAdapter; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.concurrent.ExecutionException; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 版本管理交互优化新面板 |
||||||
|
* <li>采用表格的形式展现</li> |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2023/7/11 |
||||||
|
*/ |
||||||
|
public class VcsNewPane extends RecyclePane { |
||||||
|
|
||||||
|
private String filePath = StringUtils.EMPTY; |
||||||
|
|
||||||
|
protected static int OPERATOR_COL = 5; |
||||||
|
|
||||||
|
protected static int EDIT_COL = 4; |
||||||
|
|
||||||
|
|
||||||
|
private static final int DOUBLE_CLICK_COUNT = 2; |
||||||
|
protected VcsOperatorPane operatorPane; |
||||||
|
private static final Icon PREVIEW_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_preview"); |
||||||
|
private static final Icon DELETE_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_delete"); |
||||||
|
private static final Icon RESTORE_ICON = IconUtils.readIcon("/com/fr/design/standard/vcslist/vcs_operator_restore"); |
||||||
|
|
||||||
|
private UILabel restore; |
||||||
|
private UILabel delete; |
||||||
|
private UILabel preview; |
||||||
|
private static final String TITLE = Toolkit.i18nText("Fine-Design_Vcs_Title"); |
||||||
|
private static final String[] COLUMN_NAMES = new String[]{ |
||||||
|
StringUtils.EMPTY, |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Version"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Time"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_User"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Annotation"), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Operator") |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
private static final Class[] CLASSES = new Class[]{ |
||||||
|
Boolean.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
UILabel.class, |
||||||
|
VcsOperatorPane.class |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
public VcsNewPane(String filePath) { |
||||||
|
super(TITLE, (o, columnIndex) -> { |
||||||
|
switch (columnIndex) { |
||||||
|
case 0: |
||||||
|
return o.isSelect(); |
||||||
|
case 1: |
||||||
|
return o.getVersion(); |
||||||
|
case 2: |
||||||
|
return o.getTime(); |
||||||
|
case 3: |
||||||
|
return o.getUserName(); |
||||||
|
case 4: |
||||||
|
return o.getCommitMsg(); |
||||||
|
default: |
||||||
|
return o; |
||||||
|
} |
||||||
|
}, false); |
||||||
|
this.filePath = filePath; |
||||||
|
initModel(COLUMN_NAMES, CLASSES, OPERATOR_COL); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void initModel(String[] columns, Class[] classes, int operatorCol) { |
||||||
|
this.model = new DefaultModel(columns, classes) { |
||||||
|
@Override |
||||||
|
public boolean isCellEditable(int row, int col) { |
||||||
|
return col == 0 || col == operatorCol; |
||||||
|
} |
||||||
|
}; |
||||||
|
this.operatorPane = createOperatorPane(); |
||||||
|
this.model.setDefaultEditor(VcsOperatorPane.class, operatorPane); |
||||||
|
this.model.setDefaultRenderer(VcsOperatorPane.class, operatorPane); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public VcsNewPane(String title, TableValueOperator<VcsTableEntity> operators, boolean needBorder, String[] columns, Class[] classes, int operatorCol) { |
||||||
|
super(title, operators, needBorder); |
||||||
|
initModel(columns, classes, operatorCol); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建操作面板 |
||||||
|
* |
||||||
|
* @return 操作面板 |
||||||
|
*/ |
||||||
|
public VcsOperatorPane createOperatorPane() { |
||||||
|
restore = new UILabel(RESTORE_ICON); |
||||||
|
delete = new UILabel(DELETE_ICON); |
||||||
|
preview = new UILabel(PREVIEW_ICON); |
||||||
|
initPreviewListener(); |
||||||
|
initDeleteListener(); |
||||||
|
initRestoreListener(); |
||||||
|
List<JComponent> list = new ArrayList<>(); |
||||||
|
list.add(restore); |
||||||
|
list.add(delete); |
||||||
|
list.add(preview); |
||||||
|
return new VcsOperatorPane(list); |
||||||
|
} |
||||||
|
|
||||||
|
private void initRestoreListener() { |
||||||
|
restore.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn()); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
VcsEntity entity = ((VcsTableEntity) o).getEntity(); |
||||||
|
int selVal = FineJOptionPane.showConfirmDialog( |
||||||
|
VcsNewPane.this, |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Restore_This_Version_Tips"), |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Confirm"), |
||||||
|
JOptionPane.OK_CANCEL_OPTION, |
||||||
|
JOptionPane.QUESTION_MESSAGE); |
||||||
|
if (selVal == JOptionPane.YES_OPTION) { |
||||||
|
restoreEntity(entity); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void restoreEntity(VcsEntity entity) { |
||||||
|
new SwingWorker<Void, Void>() { |
||||||
|
@Override |
||||||
|
protected Void doInBackground() throws Exception { |
||||||
|
//step1.设置还原的用户名
|
||||||
|
entity.setUsername(VcsHelper.getInstance().getCurrentUsername()); |
||||||
|
//step2.rollback到指定版本
|
||||||
|
WorkContext.getCurrent().get(VcsOperator.class).rollbackTo(entity); |
||||||
|
return null; |
||||||
|
} |
||||||
|
@Override |
||||||
|
protected void done() { |
||||||
|
//step3.如果原来原模板已经打开则关闭原模板,打开rollback后的新模板
|
||||||
|
List<JTemplate<?, ?>> templateList = HistoryTemplateListCache.getInstance().getHistoryList(); |
||||||
|
for (JTemplate<?, ?> template : templateList) { |
||||||
|
if (StringUtils.equals(filePath, template.getPath())) { |
||||||
|
MultiTemplateTabPane.getInstance().setIsCloseCurrent(HistoryTemplateListCache.getInstance().isCurrentEditingFile(filePath)); |
||||||
|
MultiTemplateTabPane.getInstance().closeFormat(template); |
||||||
|
MultiTemplateTabPane.getInstance().closeSpecifiedTemplate(template); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(filePath, false))); |
||||||
|
} |
||||||
|
}.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void initDeleteListener() { |
||||||
|
delete.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
int row = table.getEditingColumn(); |
||||||
|
Object o = table.getValueAt(table.getEditingRow(), row); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
VcsEntity entity = ((VcsTableEntity) o).getEntity(); |
||||||
|
int selVal = FineJOptionPane.showConfirmDialog( |
||||||
|
VcsNewPane.this, |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Delete_This_Version_Tips"), |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Confirm"), |
||||||
|
JOptionPane.OK_CANCEL_OPTION, |
||||||
|
JOptionPane.QUESTION_MESSAGE); |
||||||
|
if (selVal == JOptionPane.YES_OPTION) { |
||||||
|
model.getList().remove(o); |
||||||
|
model.fireTableDataChanged(); |
||||||
|
VcsService.getInstance().deleteEntity(entity.getFilename(), entity.getVersion()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void initPreviewListener() { |
||||||
|
preview.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
JTable table = tableContentPane.getEditTable(); |
||||||
|
Object o = table.getValueAt(table.getEditingRow(), table.getEditingColumn()); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
VcsEntity entity = ((VcsTableEntity) o).getEntity(); |
||||||
|
previewEntity(entity); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void previewEntity(VcsEntity entity) { |
||||||
|
new SwingWorker<String, Void>() { |
||||||
|
@Override |
||||||
|
protected String doInBackground() throws Exception { |
||||||
|
//step1.将指定版本的历史文件读取出来,加上前缀放到cache中
|
||||||
|
VcsOperator vcsOperator = WorkContext.getCurrent().get(VcsOperator.class); |
||||||
|
String fileOfVersion = vcsOperator.getFileOfFileVersion( |
||||||
|
entity.getFilename(), |
||||||
|
entity.getVersion(), |
||||||
|
Toolkit.i18nText("Fine-Design_Vcs_Prefix", entity.getVersion())); |
||||||
|
return fileOfVersion; |
||||||
|
} |
||||||
|
@Override |
||||||
|
protected void done() { |
||||||
|
try { |
||||||
|
//step2.再打开cache中的模板
|
||||||
|
DesignerContext.getDesignerFrame().openTemplate(new VcsCacheFileNodeFile(new FileNode(get(), false))); |
||||||
|
} catch (InterruptedException | ExecutionException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
}.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean isNeedDeleteAllVersion() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected List<VcsTableEntity> getTableList() { |
||||||
|
List<VcsEntity> entityList = WorkContext.getCurrent().get(VcsOperator.class).getVersions(VcsHelper.getInstance().dealWithFilePath(filePath)); |
||||||
|
List<VcsTableEntity> tableEntities = new ArrayList<>(); |
||||||
|
for (VcsEntity entity : entityList) { |
||||||
|
tableEntities.add(new VcsTableEntity(entity)); |
||||||
|
} |
||||||
|
return tableEntities; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return TITLE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String getDeleteTip(int size) { |
||||||
|
return Toolkit.i18nText("Fine-Design_Vcs_Delete_Versions_Tips", size); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean isNeedRestore() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean isNeedSearch() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void initExtraListener4Table(JTable table) { |
||||||
|
table.addMouseMotionListener(new MouseMotionAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseMoved(MouseEvent e) { |
||||||
|
Point point = e.getPoint(); |
||||||
|
int row = table.rowAtPoint(point); |
||||||
|
int col = table.columnAtPoint(point); |
||||||
|
if (col != 0) { |
||||||
|
table.editCellAt(row, col); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
initEditListener(table); |
||||||
|
} |
||||||
|
|
||||||
|
private void initEditListener(JTable table) { |
||||||
|
table.addMouseListener(new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
if (e.getClickCount() == DOUBLE_CLICK_COUNT) { |
||||||
|
Point point = e.getPoint(); |
||||||
|
int row = table.rowAtPoint(point); |
||||||
|
int col = table.columnAtPoint(point); |
||||||
|
if (col == EDIT_COL) { |
||||||
|
Object o = table.getValueAt(row, OPERATOR_COL); |
||||||
|
if (o instanceof VcsTableEntity) { |
||||||
|
showDialog(((VcsTableEntity) o).getEntity()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void showDialog(VcsEntity entity) { |
||||||
|
EditFileVersionDialog dialog = new EditFileVersionDialog(entity) { |
||||||
|
@Override |
||||||
|
public void doOK() { |
||||||
|
entity.setCommitMsg(getMsgTestArea().getText()); |
||||||
|
VcsService.getInstance().updateEntityAnnotation(entity); |
||||||
|
setVisible(false); |
||||||
|
model.fireTableDataChanged(); |
||||||
|
} |
||||||
|
}; |
||||||
|
dialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
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 static com.fr.design.mainframe.vcs.ui.AbstractSupportSelectTablePane.DEFAULT_SELECT_TABLE_ROW_COLOR; |
||||||
|
|
||||||
|
/** |
||||||
|
* 操作面板,用于置放常用的操作label |
||||||
|
* <p>例如 删除、还原、预览、打开模板等</p> |
||||||
|
* <li>负责表格渲染 与 操作按钮置蓝+设定cursor</li> |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @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 VcsOperatorPane(List<JComponent> iconJComponentMap) { |
||||||
|
init(iconJComponentMap); |
||||||
|
} |
||||||
|
|
||||||
|
private void init(List<JComponent> iconJComponentMap) { |
||||||
|
contentPane = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); |
||||||
|
for (JComponent value : iconJComponentMap) { |
||||||
|
value.setForeground(DETAIL_FONT_COLOR); |
||||||
|
value.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
||||||
|
contentPane.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; |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 400 B |
After Width: | Height: | Size: 523 B |
After Width: | Height: | Size: 366 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 973 B |
After Width: | Height: | Size: 342 B |
After Width: | Height: | Size: 360 B |
After Width: | Height: | Size: 706 B |
After Width: | Height: | Size: 904 B |
After Width: | Height: | Size: 890 B |