Browse Source

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

release/11.0
Coral.Chen 2 years ago
parent
commit
7e0bf4d590
  1. 421
      designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java
  2. 8
      designer-base/src/main/java/com/fr/design/hyperlink/ReportletHyperlinkPane.java
  3. 27
      designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java
  4. 4
      designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java
  5. 62
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWorkspacePanel.java
  6. 1
      designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties
  7. 1
      designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties
  8. 1
      designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties
  9. 1
      designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties
  10. 10
      designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/ColorPickerPaneNumFiled.java
  11. 4
      designer-realize/src/main/java/com/fr/design/actions/cell/AbstractCellElementAction.java
  12. 5
      designer-realize/src/main/java/com/fr/design/actions/columnrow/ColumnWidthAction.java
  13. 4
      designer-realize/src/main/java/com/fr/design/actions/columnrow/RowHeightAction.java
  14. 135
      designer-realize/src/main/java/com/fr/design/actions/replace/action/ITChecker.java
  15. 2
      designer-realize/src/main/java/com/fr/design/actions/replace/action/content/component/ComponentType.java
  16. 158
      designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartCollectionFormulaAction.java
  17. 41
      designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartMapDataFormulaAction.java
  18. 3
      designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/highlight/javascript/SearchChartHyperPopLinkAction.java
  19. 56
      designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchChartJSAction.java
  20. 6
      designer-realize/src/main/java/com/fr/design/actions/replace/action/setting/CellGroupType.java
  21. 4
      designer-realize/src/main/java/com/fr/design/actions/replace/info/ComponentInfo.java
  22. 2
      designer-realize/src/main/java/com/fr/design/actions/replace/info/WidgetInfo.java
  23. 2
      designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITCheckDialog.java
  24. 47
      designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceMainDialog.java
  25. 50
      designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceNorthPanel.java
  26. 165
      designer-realize/src/main/java/com/fr/design/actions/replace/utils/SearchJSUtils.java
  27. 40
      designer-realize/src/main/java/com/fr/design/actions/replace/utils/ShowValueUtils.java
  28. 2
      designer-realize/src/main/java/com/fr/grid/GridUI.java
  29. 51
      designer-realize/src/main/java/com/fr/quickeditor/CellQuickEditor.java
  30. 4
      designer-realize/src/main/java/com/fr/quickeditor/cellquick/CellDSColumnEditor.java

421
designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java

@ -3,39 +3,28 @@
*/
package com.fr.design.data.datapane.preview;
import com.fr.base.BaseUtils;
import com.fr.base.TableData;
import com.fr.base.svg.IconUtils;
import com.fr.data.TableDataSource;
import com.fr.data.desensitize.base.DesensitizationTableData;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.EmbeddedTableData;
import com.fr.data.impl.NameDataModel;
import com.fr.data.operator.DataOperator;
import com.fr.design.DesignerEnvManager;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.preview.desensitization.TableDataPreviewDesensitizeManager;
import com.fr.design.data.datapane.preview.desensitization.model.DesensitizedPreviewTableModel;
import com.fr.design.data.datapane.preview.desensitization.view.setting.TableDataDesensitizationSettingPane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.frpane.UITabbedPane;
import com.fr.design.gui.ibutton.UIToggleButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.AutoProgressBar;
import com.fr.design.gui.itable.SortableJTable;
import com.fr.design.gui.itable.TableSorter;
import com.fr.design.gui.itextfield.UINumberField;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef;
import com.fr.design.ui.util.UIUtil;
import com.fr.function.TIME;
import com.fr.general.FRFont;
@ -50,7 +39,6 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
@ -69,19 +57,12 @@ import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CancellationException;
/**
* august PreviewTablePane一共提供5个共有的静态方法用来预览
*/
public class PreviewTablePane extends BasicPane {
private static final String DATA_DESENSITIZATION_CONFIG = Toolkit.i18nText("Fine-Design_Report_Desensitization_Config");
private static final String LEFT_BRACKET = "(";
private static final String RIGHT_BRACKET = ")";
private static final String COUNT = Toolkit.i18nText("Fine-Design_Report_Desensitization_Count");
private TableData tableData;
private DataModel dataModel;
private UINumberField maxPreviewNumberField;
@ -97,54 +78,6 @@ public class PreviewTablePane extends BasicPane {
private static PreviewTablePane THIS;
private EmbeddedTableData previewTableData;
private UILabel desensitizationLabel;
/**
* 用于refreshLabel的鼠标监听
*/
private final MouseAdapter refreshLabelMouseAdapter = new MouseAdapter() {
boolean mouseEntered = false;
boolean buttonPressed = false;
@Override
public void mouseEntered(MouseEvent e) { // 当鼠标进入时候调用.
mouseEntered = true;
if (!buttonPressed) {
refreshLabel.setBackground(java.awt.Color.WHITE);
refreshLabel.setOpaque(true);
refreshLabel.setBorder(BorderFactory.createLineBorder(java.awt.Color.GRAY));
}
}
@Override
public void mouseExited(MouseEvent e) {
mouseEntered = false;
refreshLabel.setOpaque(false);
refreshLabel.setBorder(BorderFactory.createEmptyBorder());
}
@Override
public void mousePressed(MouseEvent e) {
buttonPressed = true;
refreshLabel.setBackground(java.awt.Color.lightGray);
}
@Override
public void mouseReleased(MouseEvent e) {
buttonPressed = false;
if (mouseEntered) {
refreshLabel.setBackground(java.awt.Color.WHITE);
try {
populate(tableData);
if (dataModel != null) {
setRowsLimitTableModel();
}
} catch (Exception ignore) {
}
}
}
};
public static final PreviewTablePane getInstance() {
if (THIS == null) {
THIS = new PreviewTablePane();
@ -154,175 +87,91 @@ public class PreviewTablePane extends BasicPane {
private PreviewTablePane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
// northPane
this.add(initNorthPane(), BorderLayout.NORTH);
// centerPane
this.add(initCenterPane(), BorderLayout.CENTER);
// dialog
initDialog();
// progressBar
initProgressBar();
}
/**
* 初始化northPane
*
* @return
*/
private JComponent initNorthPane() {
JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
// 预览行数面板
northPane.add(initPreviewNumberPane(), BorderLayout.CENTER);
// 脱敏预览设置面板
northPane.add(initDesensitizationPane(), BorderLayout.EAST);
return northPane;
}
/**
* 初始化预览行数面板
*
* @return
*/
private JComponent initPreviewNumberPane() {
// elalke:预览行数
JPanel previewNumberPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
// 当前行数
this.add(previewNumberPanel, BorderLayout.NORTH);
JPanel currentPreviewPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
previewNumberPanel.add(currentPreviewPanel);
currentPreviewPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Current_Preview_Rows") + ":"));
currentRowsField = new UINumberField();
currentPreviewPanel.add(currentRowsField);
currentRowsField.setEditable(false);
currentRowsField.setColumns(4);
currentRowsField.setInteger(true);
// 最大行数
JPanel maxPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
previewNumberPanel.add(maxPanel);
maxPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Datasource_Maximum_Number_of_Preview_Rows") + ":"));
maxPreviewNumberField = new UINumberField();
maxPanel.add(maxPreviewNumberField);
maxPreviewNumberField.setColumns(4);
maxPreviewNumberField.setInteger(true);
maxPreviewNumberField.setValue(DesignerEnvManager.getEnvManager().getMaxNumberOrPreviewRow());
DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager();
maxPreviewNumberField.setValue(designerEnvManager.getMaxNumberOrPreviewRow());
maxPreviewNumberField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager();
designerEnvManager.setMaxNumberOrPreviewRow((int) ((UINumberField) evt.getSource()).getValue());
}
});
// 刷新按钮
initRefreshLabel();
previewNumberPanel.add(currentPreviewPanel);
previewNumberPanel.add(maxPanel);
previewNumberPanel.add(refreshLabel);
return previewNumberPanel;
}
private void initRefreshLabel() {
Icon refreshImage = IconUtils.readIcon("/com/fr/design/images/control/refresh");
Icon refreshImage = BaseUtils.readIcon("/com/fr/design/images/control/refresh.png");
refreshLabel = new UILabel(refreshImage);
refreshLabel.addMouseListener(refreshLabelMouseAdapter);
}
/**
* 初始化脱敏设置面板
*
* @return
*/
private JComponent initDesensitizationPane() {
JPanel desensitizationPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
// 初始化Label
desensitizationLabel = new UILabel(DATA_DESENSITIZATION_CONFIG);
desensitizationLabel.setForeground(UIConstants.NORMAL_BLUE);
desensitizationLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
TableDataDesensitizationSettingPane settingPane = new TableDataDesensitizationSettingPane((DesensitizationTableData) tableData);
settingPane.populateBean((DesensitizationTableData) tableData);
BasicDialog dialog = settingPane.showWindowWithCustomSize(SwingUtilities.getWindowAncestor(PreviewTablePane.this), new DialogActionAdapter() {
@Override
public void doOk() {
// 保存脱敏规则配置
settingPane.updateBean();
// 改变模板保存状态
JTemplate<?, ?> editingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (Objects.nonNull(editingTemplate)) {
editingTemplate.fireTargetModified(true);
}
// 刷新预览页面
refreshTable();
}
previewNumberPanel.add(refreshLabel);
refreshLabel.addMouseListener(new MouseAdapter() {
boolean mouseEntered = false;
boolean buttonPressed = false;
public void mouseEntered(MouseEvent e) { // 当鼠标进入时候调用.
mouseEntered = true;
if (!buttonPressed) {
refreshLabel.setBackground(java.awt.Color.WHITE);
refreshLabel.setOpaque(true);
refreshLabel.setBorder(BorderFactory.createLineBorder(java.awt.Color.GRAY));
}
}
@Override
public void doCancel() {
public void mouseExited(MouseEvent e) {
mouseEntered = false;
refreshLabel.setOpaque(false);
refreshLabel.setBorder(BorderFactory.createEmptyBorder());
}
}
}, BasicDialog.DEFAULT);
dialog.setVisible(true);
public void mousePressed(MouseEvent e) {
buttonPressed = true;
refreshLabel.setBackground(java.awt.Color.lightGray);
}
});
// 初始化分隔符
ToolBarDef toolbarDef = new ToolBarDef();
toolbarDef.addShortCut(SeparatorDef.DEFAULT);
UIToolbar toolBar = ToolBarDef.createJToolBar();
toolBar.setBorderPainted(false);
toolbarDef.updateToolBar(toolBar);
// 初始化预览按钮
UIToggleButton previewToggle = new UIToggleButton(new Icon[]{IconUtils.readIcon("/com/fr/design/images/m_file/preview"), IconUtils.readIcon("/com/fr/design/images/m_file/preview")}, true);
previewToggle.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Desensitization_Preview"));
previewToggle.setSelected(false);
previewToggle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 切换TableModel的脱敏状态
togglePreviewTableModelDesensitizeStatus();
// 刷新页面,展示
refreshTable();
public void mouseReleased(MouseEvent e) {
buttonPressed = false;
if (mouseEntered) {
refreshLabel.setBackground(java.awt.Color.WHITE);
try {
populate(tableData);
if (dataModel != null) {
setRowsLimitTableModel();
}
} catch (Exception e1) {
}
}
}
});
desensitizationPane.add(desensitizationLabel);
desensitizationPane.add(toolBar);
desensitizationPane.add(previewToggle);
return desensitizationPane;
}
/**
* 设置脱敏设置的个数
*
* @param model
*/
private void setDesensitizationCount(TableModel model) {
if (isDesensitizeOpened()) {
int count = model instanceof DesensitizedPreviewTableModel ? ((DesensitizedPreviewTableModel) model).getDesensitizeColumnsCount() : 0;
desensitizationLabel.setText(DATA_DESENSITIZATION_CONFIG + LEFT_BRACKET + count + RIGHT_BRACKET + COUNT);
} else {
desensitizationLabel.setText(DATA_DESENSITIZATION_CONFIG);
}
}
/**
* 初始化centerPane
*
* @return
*/
private JComponent initCenterPane() {
preveiwTable = new CopyableJTable(new TableSorter());
preveiwTable.setRowSelectionAllowed(false);
preveiwTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
return new JScrollPane(preveiwTable);
}
private void initDialog() {
this.add(new JScrollPane(preveiwTable), BorderLayout.CENTER);
if (this.dialog == null) {
this.dialog = this.showWindow(new JFrame());
}
}
private void initProgressBar() {
progressBar = new AutoProgressBar(this, Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) {
@Override
public void doMonitorCanceled() {
if (getWorker() != null) {
getWorker().cancel(true);
@ -333,7 +182,7 @@ public class PreviewTablePane extends BasicPane {
}
public AutoProgressBar getProgressBar() {
return PreviewTablePane.progressBar;
return this.progressBar;
}
@Override
@ -374,10 +223,9 @@ public class PreviewTablePane extends BasicPane {
}
/**
* 为预览表的columnIndex列着色.
*
* @param columnIndex 列索引值
* @param c 颜色
* elake:为预览表的columnIndex列着色.
* @param columnIndex
* @param c
*/
private void setPreviewTableColumnColor(final int columnIndex, final Color c) {
addLoadedListener(new LoadedEventListener() {
@ -385,7 +233,6 @@ public class PreviewTablePane extends BasicPane {
public void fireLoaded() {
TableColumn column = preveiwTable.getColumnModel().getColumn(columnIndex);
DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JComponent comp = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
comp.setBackground(c);
@ -406,7 +253,7 @@ public class PreviewTablePane extends BasicPane {
getInstance().preveiwTable = new SortableJTable(new TableSorter());
getInstance().preveiwTable.setRowSelectionAllowed(false);
getInstance().preveiwTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
PreviewTablePane.progressBar.close();
getInstance().progressBar.close();
getInstance().repaint();
}
@ -488,7 +335,6 @@ public class PreviewTablePane extends BasicPane {
private void previewTableDataSQL() throws Exception {
connectionBar = new AutoProgressBar(this, Toolkit.i18nText("Fine-Design_Basic_Utils_Now_Create_Connection"), "", 0, 100) {
@Override
public void doMonitorCanceled() {
getWorker().cancel(true);
getDialog().setVisible(false);
@ -503,49 +349,42 @@ public class PreviewTablePane extends BasicPane {
private void setPreviewTableColumnValue(final Graphics g) {
for (int i = 0; i < preveiwTable.getColumnModel().getColumnCount(); i++) {
TableColumn column = preveiwTable.getColumnModel().getColumn(i);
DefaultTableCellRenderer cellRenderer = getDefaultTableCellRenderer();
column.setCellRenderer(cellRenderer);
}
}
/**
* 默认表格格子渲染器
*
* @return
*/
private DefaultTableCellRenderer getDefaultTableCellRenderer() {
return new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JComponent comp = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Font f = table.getFont();
//默认在系统不支持 无法显示时 如自造的字 ,字体设置为空.
Font defaultShowFont = FRFont.getInstance("", f.getStyle(), f.getSize());
if (value instanceof String) {
String str = (String) value;
for (int j = 0; j < str.length(); j++) {
char c = str.charAt(j);
if (!f.canDisplay(c)) {
table.setFont(defaultShowFont);
DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JComponent comp = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Font f = table.getFont();
//默认在系统不支持 无法显示时 如自造的字 ,字体设置为空.
Font defaultShowFont = FRFont.getInstance("", f.getStyle(), f.getSize());
if (value instanceof String) {
String str = (String) value;
for (int j = 0; j < str.length(); j++) {
char c = str.charAt(j);
if (!f.canDisplay(c)) {
table.setFont(defaultShowFont);
}
}
}
return comp;
}
return comp;
}
};
};
column.setCellRenderer(cellRenderer);
}
}
private void setWorker() {
worker = new SwingWorker<TableModel, Void>() {
@Override
protected TableModel doInBackground() throws Exception {
worker = new SwingWorker<PreviewTableModel, Void>() {
protected PreviewTableModel doInBackground() throws Exception {
connectionBar.start();
try {
testDBTableDataConnection(tableData);
if (tableData instanceof DBTableData) {
boolean status = DataOperator.getInstance().testConnection(((DBTableData) tableData).getDatabase());
if (!status) {
throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"));
}
}
} finally {
// 将close操作放到EDT线程中
UIUtil.invokeLaterIfNeeded(() -> connectionBar.close());
@ -555,20 +394,22 @@ public class PreviewTablePane extends BasicPane {
// parameterInputDialog
// update之后的parameters,转成一个parameterMap,用于预览TableData
PreviewTableModel previewModel = new PreviewTableModel(previewTableData.createDataModel(null), (int) maxPreviewNumberField.getValue());
if (TableDataPreviewDesensitizeManager.getInstance().needDesensitize(tableData)) {
// 数据集预览脱敏
previewModel = TableDataPreviewDesensitizeManager.getInstance().desensitizeTableModel(tableData, previewModel);
for (int i = 0; i < previewTableData.getColumnCount(); i++) {
Class<?> cls = previewTableData.getColumnClass(i);
if (cls == Date.class || cls == TIME.class || cls == Timestamp.class) {
previewModel.dateIndexs.add(i);
}
}
dealWithPreviewTableModelColumnClass(previewModel, previewTableData);
return previewModel;
}
@Override
public void done() {
try {
TableModel model = get();
setPreviewTableModel(model);
PreviewTableModel model = get();
setModel(model);
setCurrentRows(model.getRowCount());
setPreviewTableColumnValue(getParent().getGraphics());
fireLoadedListener();
} catch (Exception e) {
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
@ -583,36 +424,6 @@ public class PreviewTablePane extends BasicPane {
};
}
/**
* 检查DBTableData连接
*
* @param tableData
* @throws Exception
*/
private void testDBTableDataConnection(TableData tableData) throws Exception {
if (tableData instanceof DBTableData) {
boolean status = DataOperator.getInstance().testConnection(((DBTableData) tableData).getDatabase());
if (!status) {
throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"));
}
}
}
/**
* 处理预览Model的列类型
*
* @param previewModel
* @param previewTableData
*/
private void dealWithPreviewTableModelColumnClass(PreviewTableModel previewModel, EmbeddedTableData previewTableData) {
for (int i = 0; i < previewTableData.getColumnCount(); i++) {
Class<?> cls = previewTableData.getColumnClass(i);
if (cls == Date.class || cls == TIME.class || cls == Timestamp.class) {
previewModel.dateIndexs.add(i);
}
}
}
/**
* 直接预览存储过程的一个返回数据集没有实际值和显示值
*
@ -721,61 +532,9 @@ public class PreviewTablePane extends BasicPane {
} catch (Exception e) {
previewModel = new PreviewTableModel((int) maxPreviewNumberField.getValue());
}
setPreviewTableModel(previewModel);
}
/**
* 切换TableModel的展示状态
*/
private void togglePreviewTableModelDesensitizeStatus() {
if (!isDesensitizeOpened()) {
// 未启用数据脱敏时,不需要切换
return;
}
TableSorter tableSorter = (TableSorter) preveiwTable.getModel();
TableModel originTableModel = tableSorter.getTableModel();
if (originTableModel instanceof DesensitizedPreviewTableModel) {
((DesensitizedPreviewTableModel) originTableModel).toggleNeedDesensite();
}
}
/**
* 刷新一下预览页面用于切换脱敏和非脱敏时的显示
*/
private void refreshTable() {
TableModel originTableModel = getCurrentTableModel();
setPreviewTableModel(originTableModel);
}
/**
* 获取当前的TableModel已经除掉了TableSorter的包装
*
* @return
*/
private TableModel getCurrentTableModel() {
TableSorter tableSorter = (TableSorter) preveiwTable.getModel();
return tableSorter.getTableModel();
}
/**
* 设置预览TableModel
*
* @param previewTableModel
*/
private void setPreviewTableModel(TableModel previewTableModel) {
setDesensitizationCount(previewTableModel);
setModel(previewTableModel);
setCurrentRows(previewTableModel.getRowCount());
setModel(previewModel);
setCurrentRows(previewModel.getRowCount());
fireLoadedListener();
}
/**
* 数据脱敏是否启用
* @return
*/
private boolean isDesensitizeOpened() {
return tableData instanceof DesensitizationTableData &&
((DesensitizationTableData) tableData).getDesensitizationConfig().isDesensitizeOpened();
}
}

8
designer-base/src/main/java/com/fr/design/hyperlink/ReportletHyperlinkPane.java

@ -158,6 +158,14 @@ public class ReportletHyperlinkPane extends AbstractHyperLinkPane<ReportletHyper
protected boolean needRenamePane() {
return false;
}
public ChartNoRename(HashMap hyperLinkEditorMap, boolean needRenamePace) {
super(hyperLinkEditorMap, needRenamePace);
}
public ChartNoRename() {
super();
}
}
public ReportletHyperNorthPane getNorthPane() {

27
designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.gui.itree.filetree.TemplateFileTree;
import com.fr.stable.StringUtils;
@ -19,8 +20,6 @@ public class JTemplateNameHelper {
private static final int PREFIX_NUM = 3000;
private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复
public static String newTemplateNameByIndex(String prefix) {
// 用于获取左侧模板的文件名,如左侧已包含"WorkBook1.cpt, WorkBook12.cpt, WorkBook177.cpt"
// 那么新建的文件名将被命名为"WorkBook178.cpt",即取最大数+1
@ -37,13 +36,33 @@ public class JTemplateNameHelper {
reportNum.add(index);
}
}
//把当前编辑面板的模板名也加进来判断
addHistoryTemplateName2List(reportNum, prefix);
Collections.sort(reportNum);
BigInteger idx = reportNum.size() > 0 ? reportNum.get(reportNum.size() - 1).add(BigInteger.valueOf(1)) : BigInteger.valueOf(1);
idx = idx.add(BigInteger.valueOf(currentIndex));
currentIndex++;
return prefix + idx;
}
/**
* 将当前打开的模板列表的模板名处理一下加进来以便于获取左侧模板文件名与当前模板列表的最大值
*
* @param reportNum 存储后缀的列表
* @param prefix 前缀
*/
private static void addHistoryTemplateName2List(List<BigInteger> reportNum, String prefix) {
int len = HistoryTemplateListCache.getInstance().getHistoryCount();
for (int i = 0; i < len; i++) {
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().get(i);
if (jTemplate != null) {
String templateName = jTemplate.getTemplateName();
BigInteger index = getFileNameIndex(prefix, templateName);
if (index != null) {
reportNum.add(index);
}
}
}
}
/**
* @return java.lang.Integer WorkBook11.cpt则返回11如果没有找到index返回null
* @Description 返回文件名中的index

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

@ -1,6 +1,7 @@
package com.fr.design.mainframe.vcs.common;
import com.fr.base.extension.FileExtension;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.DesignerEnvManager;
import com.fr.design.file.HistoryTemplateListCache;
@ -135,6 +136,9 @@ public class VcsHelper implements JTemplateActionListener {
public void run() {
String fileName = getEditingFilename();
if (FileExtension.VIS.matchExtension(fileName)) { // fvs文件先不做版本控制
return;
}
VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class);
VcsEntity entity = operator.getFileVersionByIndex(fileName, 0);
int latestFileVersion = 0;

62
designer-base/src/main/java/com/fr/startup/ui/StartupPageWorkspacePanel.java

@ -4,6 +4,7 @@ import com.fr.base.svg.IconUtils;
import com.fr.design.components.tooltip.ModernToolTip;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.FRGraphics2D;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.ColorUtils;
@ -17,6 +18,8 @@ import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.JViewport;
import javax.swing.RepaintManager;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
import java.awt.BasicStroke;
@ -28,9 +31,11 @@ import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.ImageObserver;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@ -127,9 +132,15 @@ public class StartupPageWorkspacePanel extends JPanel {
this.contentPanel = generateUnLimitContentPanel(this.partitions);
this.add(contentPanel, BorderLayout.NORTH);
}
private JComponent generateUnLimitContentPanel(List<List<StartupWorkspaceBean>> partitions) {
JComponent panel = generateUnLimitContentPanel0(partitions);
ColorUtils.transparentBackground(panel);
return panel;
}
private JComponent generateUnLimitContentPanel0(List<List<StartupWorkspaceBean>> partitions) {
JPanel workspaceDescWrapper = new JPanel();
workspaceDescWrapper.setLayout(new BorderLayout(0, 0));
workspaceDescWrapper.setBorder(new EmptyBorder(0, 0, 0, 0));
@ -142,16 +153,28 @@ public class StartupPageWorkspacePanel extends JPanel {
}
boolean needScroll = partitions.size() > 4;
if (needScroll) {
// 滚动条
UIScrollPane scrollPane = new UIScrollPane(workspaceDescPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new EmptyBorder(10, 0, 0, 0));
scrollPane.setPreferredSize(new Dimension(CONTENT_WIDTH, SCROLL_HEIGHT));
workspaceDescWrapper.add(scrollPane, BorderLayout.CENTER);
return workspaceDescWrapper;
return generateScrollUnLimitContentPanel(workspaceDescWrapper, workspaceDescPanel);
}
workspaceDescWrapper.add(workspaceDescPanel, BorderLayout.CENTER);
ColorUtils.transparentBackground(workspaceDescWrapper);
return workspaceDescWrapper;
}
@NotNull
private JPanel generateScrollUnLimitContentPanel(JPanel workspaceDescWrapper, JPanel workspaceDescPanel) {
// 滚动条
UIScrollPane scrollPane = new UIScrollPane(workspaceDescPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JViewport viewport = scrollPane.getViewport();
JViewport scrollViewport = new TransparentScrollViewPort();
// 动态画图
scrollViewport.addChangeListener(e -> repaintAll());
scrollViewport.setView(viewport.getView());
scrollPane.setViewport(scrollViewport);
scrollPane.setBorder(new EmptyBorder(10, 0, 0, 0));
scrollPane.setPreferredSize(new Dimension(CONTENT_WIDTH, SCROLL_HEIGHT));
workspaceDescWrapper.add(scrollPane, BorderLayout.CENTER);
return workspaceDescWrapper;
}
@ -580,4 +603,27 @@ public class StartupPageWorkspacePanel extends JPanel {
this.getRootPane().repaint();
}
/**
* 支持透明的滚动视图
*/
private class TransparentScrollViewPort extends JViewport {
/**
* 从而屏蔽掉 {@link RepaintManager.PaintManager#paintDoubleBuffered(JComponent, Image, Graphics, int, int, int, int)}
*
* @return 创建一个不会实际画图的 Graphics
*/
@Override
public Graphics getGraphics() {
Graphics graphics = super.getGraphics();
return new FRGraphics2D((Graphics2D) graphics) {
@Override
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
return true;
}
};
}
}
}

1
designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties

@ -15,6 +15,7 @@ com.fr.design.report.fit.firstColumn=120*20
com.fr.design.report.fit.column=160*20
com.fr.design.lock.LockInfoDialog=500*180
com.fr.design.mainframe.ForbiddenPane.refreshButton=75*24
com.fr.start.common.DesignerOpenEmptyPanel.createButton=120*24
com.fr.design.cell.expand.sort.pane=257*185
com.fr.design.sort.rule.item=125*20
com.fr.design.ds.column.sort.pane=250*180

1
designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties

@ -14,6 +14,7 @@ com.fr.design.report.fit.firstColumn=170*20
com.fr.design.report.fit.column=100*20
com.fr.design.lock.LockInfoDialog=500*180
com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24
com.fr.start.common.DesignerOpenEmptyPanel.createButton=70*24
com.fr.design.cell.expand.sort.pane=257*170
com.fr.design.sort.rule.item=125*20
com.fr.design.ds.column.sort.pane=250*165

1
designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties

@ -14,6 +14,7 @@ com.fr.design.report.fit.firstColumn=130*20
com.fr.design.report.fit.column=100*20
com.fr.design.lock.LockInfoDialog=500*180
com.fr.design.mainframe.ForbiddenPane.refreshButton=80*24
com.fr.start.common.DesignerOpenEmptyPanel.createButton=70*24
com.fr.design.cell.expand.sort.pane=267*165
com.fr.design.sort.rule.item=125*20
com.fr.design.ds.column.sort.pane=250*180

1
designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties

@ -14,6 +14,7 @@ com.fr.design.report.fit.firstColumn=80*20
com.fr.design.report.fit.column=100*20
com.fr.design.lock.LockInfoDialog=400*180
com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24
com.fr.start.common.DesignerOpenEmptyPanel.createButton=70*24
com.fr.design.cell.expand.sort.pane=227*155
com.fr.design.sort.rule.item=80*20
com.fr.design.ds.column.sort.pane=220*150

10
designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/ColorPickerPaneNumFiled.java

@ -6,6 +6,7 @@ import com.fr.module.ModuleContext;
import com.fr.value.ClearableLazyValue;
import org.jetbrains.annotations.NotNull;
import javax.swing.SwingUtilities;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -32,12 +33,9 @@ public class ColorPickerPaneNumFiled extends UINumberField {
@Override
protected void attributeChange() {
ses.getValue().schedule(new Runnable() {
@Override
public void run() {
// kuns: 默认修改500, 在地图修改系列颜色text时, 快速响应.
runChange();
}
ses.getValue().schedule(() -> {
// kuns: 默认修改500, 在地图修改系列颜色text时, 快速响应.
SwingUtilities.invokeLater(this::runChange);
}, 500, TimeUnit.MILLISECONDS);
}

4
designer-realize/src/main/java/com/fr/design/actions/cell/AbstractCellElementAction.java

@ -9,6 +9,7 @@ import com.fr.design.mainframe.ElementCasePane;
import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase;
import com.fr.grid.GridUtils;
import com.fr.grid.selection.CellSelection;
import com.fr.quickeditor.CellQuickEditor;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.core.SheetUtils;
import com.fr.report.elementcase.TemplateElementCase;
@ -76,6 +77,9 @@ public abstract class AbstractCellElementAction extends CellSelectionAction {
}
}
}
if (!ePane.isSelectedOneCell()) {
CellQuickEditor.record(CellQuickEditor.multipleOperationType.FILTER);
}
ePane.fireTargetModified();
}

5
designer-realize/src/main/java/com/fr/design/actions/columnrow/ColumnWidthAction.java

@ -4,8 +4,8 @@
package com.fr.design.actions.columnrow;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.grid.selection.CellSelection;
import com.fr.quickeditor.CellQuickEditor;
import com.fr.report.elementcase.ElementCase;
import com.fr.stable.unit.UNIT;
@ -32,6 +32,9 @@ public class ColumnWidthAction extends ColumnRowSizingAction {
for (int i = 0; i < columns.length; i++) {
report.setColumnWidth(columns[i], len);
}
if (columns.length > 1) {
CellQuickEditor.record(CellQuickEditor.multipleOperationType.HEIHT_AND_COLUMN);
}
}
protected UNIT getIndexLen(int index, ElementCase report){

4
designer-realize/src/main/java/com/fr/design/actions/columnrow/RowHeightAction.java

@ -6,6 +6,7 @@ package com.fr.design.actions.columnrow;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.grid.selection.CellSelection;
import com.fr.quickeditor.CellQuickEditor;
import com.fr.report.elementcase.ElementCase;
import com.fr.stable.unit.UNIT;
@ -32,6 +33,9 @@ public class RowHeightAction extends ColumnRowSizingAction {
for (int i = 0; i < rows.length; i++) {
report.setRowHeight(rows[i], len);
}
if (rows.length > 1) {
CellQuickEditor.record(CellQuickEditor.multipleOperationType.HEIHT_AND_COLUMN);
}
}
@Override

135
designer-realize/src/main/java/com/fr/design/actions/replace/action/ITChecker.java

@ -0,0 +1,135 @@
package com.fr.design.actions.replace.action;
import com.fr.design.actions.replace.info.Info;
import com.fr.design.i18n.Toolkit;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 校验JS公式控件组件
* 比较用户的所有对应类别的改动不论是否选中要替换只要整体类别改动过就算模板内容改动过
*
* @author Destiny.Lin
* @version 11.0
* created by Destiny.Lin on 2022-11-03
*/
public enum ITChecker {
/**
* 控件
*/
WIDGET_CHECK_TAG(Toolkit.i18nText("Fine-Design_Basic_Widget")),
/**
* 公式
*/
FORMULA_CHECK_TAG(Toolkit.i18nText("Fine-Design_Basic_Formula")),
/**
* JS
*/
JS_CHECK_TAG(Toolkit.i18nText("Fine-Design_Replace_JS")),
/**
* 组件
*/
COMPONENT_CHECK_TAG(Toolkit.i18nText("Fine-Design_Replace_Component"))
;
String name;
ITChecker(String name) {
this.name = name;
}
/**
* 匹配
*
* @param name 对应的检查类型
* @return 对应的检查checker
*/
@Nullable
public static ITChecker match(String name) {
ITChecker[] values = ITChecker.values();
for (ITChecker value : values) {
if (value.name.equals(name)) {
return value;
}
}
return null;
}
public static List<? extends Info> checkList = new ArrayList<>();
public static Map<String, Integer> appearTimesMap = new HashMap<>();
/**
* 更新对应的check列表
*
* @param list 查找后的searchList
*/
public static void updateCheckInfo(List<? extends Info> list) {
checkList = list;
updateCheckMapFromList(list);
}
/**
* 根据列表来更新对应元素的匹配Map
*
* @param list 更新后的checkList
*/
private static void updateCheckMapFromList(List<? extends Info> list) {
appearTimesMap.clear();
for (Info info : list) {
String showStr = info.getContent().getOldShowStr();
if (appearTimesMap.containsKey(showStr)) {
//如果已经存过了就个数+1
appearTimesMap.put(showStr, appearTimesMap.get(showStr) + 1);
} else {
//没有的话就把个数初始化为1个
appearTimesMap.put(showStr, 1);
}
}
}
/**
* 判断是否修改过
*
* @param list 重新获取的当前模板最新的list
* @return 修改过返回true
*/
public boolean isChanged(List<? extends Info> list) {
if (list.size() != checkList.size()) {
//如果总的数据的数量变了,就说明肯定修改过,没必要再进行下一步
return true;
}
return isChangedCheckByMap(list);
}
/**
* 通过检查Map来比较是否修改过
*
* @param list 传入的用于比较的list
* @return 修改过则返回true
*/
private boolean isChangedCheckByMap(List<? extends Info> list) {
for (Info info : list) {
String showStr = info.getContent().getOldShowStr();
if (appearTimesMap.containsKey(showStr)) {
//如果map中存在对应的值,就抵消,个数-1
appearTimesMap.put(showStr, appearTimesMap.get(showStr) - 1);
if (appearTimesMap.get(showStr) < 0) {
//如果map中的值小于0了,就说明数量对不上,修改过
return true;
}
} else {
//如果存在map中没存的值就没必要继续下去了,肯定改过
return true;
}
}
return false;
}
}

2
designer-realize/src/main/java/com/fr/design/actions/replace/action/content/component/ComponentType.java

@ -340,7 +340,7 @@ public enum ComponentType implements DealWithInfoValue {
String str = widget.getWidgetName();
info.updateOldStr(widget.getWidgetName(), findStr);
ShowValueUtils.updateAfterReplaceStr(info, str, findStr, replaceStr);
widget.setWidgetName(widget.getWidgetName().replaceAll(findStr, replaceStr));
widget.setWidgetName(ShowValueUtils.replaceAll(widget.getWidgetName(), findStr, replaceStr));
}
}

158
designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartCollectionFormulaAction.java

@ -13,15 +13,14 @@ import com.fr.chart.chartattr.Plot;
import com.fr.chart.chartattr.SwitchTitle;
import com.fr.chart.chartattr.Title;
import com.fr.chart.chartdata.NormalReportDataDefinition;
import com.fr.chart.chartdata.SeriesDefinition;
import com.fr.design.actions.replace.action.content.formula.highlight.javascript.SearchJSHighlightAction;
import com.fr.design.actions.replace.action.content.formula.widget.DictionaryType;
import com.fr.design.actions.replace.info.CellInfo;
import com.fr.design.actions.replace.info.FormulaInfo;
import com.fr.design.actions.replace.info.JSInfo;
import com.fr.design.actions.replace.info.base.ITContent;
import com.fr.design.actions.replace.utils.SearchJSUtils;
import com.fr.design.actions.replace.utils.ShowValueUtils;
import com.fr.design.i18n.Toolkit;
import com.fr.js.NameJavaScript;
@ -29,10 +28,14 @@ import com.fr.js.NameJavaScriptGroup;
import com.fr.plugin.chart.attr.axis.VanChartAlertValue;
import com.fr.plugin.chart.attr.axis.VanChartAxis;
import com.fr.plugin.chart.attr.axis.VanChartValueAxis;
import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot;
import com.fr.plugin.chart.custom.CustomDefinition;
import com.fr.plugin.chart.custom.CustomPlotFactory;
import com.fr.plugin.chart.custom.VanChartCustomPlot;
import com.fr.plugin.chart.custom.type.CustomPlotType;
import com.fr.report.cell.TemplateCellElement;
import com.fr.plugin.chart.drillmap.VanChartDrillMapPlot;
import com.fr.plugin.chart.map.VanChartMapPlot;
import com.fr.stable.StringUtils;
import java.util.List;
@ -104,6 +107,10 @@ public class SearchChartCollectionFormulaAction {
customContent.addOtherPos(CustomPlotFactory.getTitle(CustomPlotFactory.getCustomType(plot.getCustomPlotList().get(i))));
dealPlot(formulaInfos, customContent, plot.getCustomPlotList().get(i));
}
} else if (chart.getPlot() instanceof VanChartDrillMapPlot) {
ITContent drillContent = ITContent.copy(conditionContent);
drillContent.addOtherPos(Toolkit.i18nText("Fine-Design_Chart_Drill_Dir"));
dealNameJavaScriptGroup(formulaInfos, drillContent, ((VanChartDrillMapPlot) chart.getPlot()).getDrillUpHyperLink());
} else if (chart.getPlot() != null) {
dealPlot(formulaInfos, conditionContent, chart.getPlot());
}
@ -111,21 +118,41 @@ public class SearchChartCollectionFormulaAction {
}
private void dealPlot(List<FormulaInfo> formulaInfos, ITContent content, Plot plot) {
NameJavaScriptGroup javaScriptGroup = plot.getHotHyperLink();
if (SearchJSUtils.isCustomMapPlot(plot)) {
dealNameJavaScriptGroup(formulaInfos, ShowValueUtils.getCustomMapContent(content, Toolkit.i18nText("Fine-Design_Chart_Region_Map")), ((VanChartMapPlot) plot).getAreaHotHyperLink());
dealNameJavaScriptGroup(formulaInfos, ShowValueUtils.getCustomMapContent(content, Toolkit.i18nText("Fine-Design_Chart_LineMap")), ((VanChartMapPlot) plot).getLineHotHyperLink());
dealNameJavaScriptGroup(formulaInfos, ShowValueUtils.getCustomMapContent(content, Toolkit.i18nText("Fine-Design_Chart_PointMap")), ((VanChartMapPlot) plot).getPointHotHyperLink());
} else {
NameJavaScriptGroup javaScriptGroup = plot.getHotHyperLink();
dealNameJavaScriptGroup(formulaInfos, content, javaScriptGroup);
}
}
private void dealNameJavaScriptGroup(List<FormulaInfo> formulaInfos, ITContent content, NameJavaScriptGroup javaScriptGroup) {
if (javaScriptGroup != null) {
for (int i = 0; i < javaScriptGroup.size(); i++) {
ITContent formulaContent = ITContent.copy(content);
NameJavaScript javaScript = javaScriptGroup.getNameHyperlink(i);
content.addOtherPos(javaScript.getName());
formulaContent.addOtherPos(javaScript.getName());
SearchJSHighlightAction action = SearchJSHighlightAction.getInstance();
action.searchJSFormulaFromOther(formulaInfos, content, javaScript.getJavaScript());
action.searchJSFormulaFromOther(formulaInfos, formulaContent, javaScript.getJavaScript());
}
}
}
private void searchFormulaFromChartPresent(List<FormulaInfo> formulaInfos, ITContent content, TopDefinitionProvider provider) {
searchPresent4Formula(provider.getCategoryPresent(), content, formulaInfos);
searchPresent4Formula(provider.getSeriesPresent(), content, formulaInfos);
if (provider instanceof CustomDefinition) {
CustomDefinition definition = (CustomDefinition) provider;
Map<CustomPlotType, TopDefinitionProvider> map = definition.getDefinitionProviderMap();
for (CustomPlotType type : map.keySet()) {
ITContent customContent = ITContent.copy(content);
customContent.addOtherPos(CustomPlotFactory.getTitle(type));
searchFormulaFromChartPresent(formulaInfos, customContent, map.get(type));
}
} else {
searchPresent4Formula(provider.getCategoryPresent(), ShowValueUtils.getCustomMapContent(content, Toolkit.i18nText("Fine-Design_Chart_Category")), formulaInfos);
searchPresent4Formula(provider.getSeriesPresent(), ShowValueUtils.getCustomMapContent(content, Toolkit.i18nText("Fine-Design_Chart_Series")), formulaInfos);
}
}
private void searchPresent4Formula(Present present, ITContent content, List<FormulaInfo> formulaInfos) {
@ -195,36 +222,40 @@ public class SearchChartCollectionFormulaAction {
private void searchChartPatternFormulaFromAlertLine(List<FormulaInfo> formulaInfos, ITContent chartContent, Chart chart) {
if (chart.getPlot() != null) {
Axis xAxis = chart.getPlot().getxAxis();
Axis yAxis = chart.getPlot().getyAxis();
if (chart.getPlot() instanceof VanChartRectanglePlot) {
VanChartRectanglePlot plot = chart.getPlot();
for (VanChartAxis axis : plot.getXAxisList()) {
dealAlertLineFormula(formulaInfos, chartContent, axis);
}
for (VanChartAxis axis : plot.getYAxisList()) {
dealAlertLineFormula(formulaInfos, chartContent, axis);
}
} else {
dealAlertLineFormula(formulaInfos, chartContent, chart.getPlot().getxAxis());
dealAlertLineFormula(formulaInfos, chartContent, chart.getPlot().getyAxis());
}
}
}
private void dealAlertLineFormula(List<FormulaInfo> formulaInfos, ITContent chartContent, Axis axis) {
if (axis instanceof VanChartAxis) {
ITContent content = ITContent.copy(chartContent);
content.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Pattern"),
Toolkit.i18nText("Fine-Design_Chart_Background"),
Toolkit.i18nText("Fine-Design_Chart_Plot_Region"),
Toolkit.i18nText("Fine-Design_Chart_Alert_Line")
Toolkit.i18nText("Fine-Design_Chart_Alert_Line"),
((VanChartAxis) axis).getAxisName()
);
if (xAxis instanceof VanChartAxis) {
List<VanChartAlertValue> list = ((VanChartAxis) xAxis).getAlertValues();
for (VanChartAlertValue alertValue : list) {
//警戒线设置
dealAlertValue(formulaInfos, content, alertValue);
//提示文字
dealAlertContent(formulaInfos, content, alertValue);
}
}
if (yAxis instanceof VanChartAxis) {
List<VanChartAlertValue> list = ((VanChartAxis) yAxis).getAlertValues();
for (VanChartAlertValue alertValue : list) {
//警戒线设置
dealAlertValue(formulaInfos, content, alertValue);
//提示文字
dealAlertContent(formulaInfos, content, alertValue);
}
List<VanChartAlertValue> list = ((VanChartAxis) axis).getAlertValues();
for (VanChartAlertValue alertValue : list) {
//警戒线设置
dealAlertValue(formulaInfos, content, alertValue);
//提示文字
dealAlertContent(formulaInfos, content, alertValue);
}
}
}
private void dealAlertContent(List<FormulaInfo> formulaInfos, ITContent content, VanChartAlertValue alertValue) {
@ -247,39 +278,42 @@ public class SearchChartCollectionFormulaAction {
private void searchChartPatternFormulaFromAxisValue(List<FormulaInfo> formulaInfos, ITContent chartContent, Chart chart) {
if (chart.getPlot() != null) {
Axis xAxis = chart.getPlot().getxAxis();
Axis yAxis = chart.getPlot().getyAxis();
//样式-坐标轴-x轴
if (xAxis != null) {
//轴标题
ITContent xAxisContent = ITContent.copy(chartContent);
if (!chartContent.isFrm()) {
xAxisContent.addOtherPos(chart.getChartName());
}
xAxisContent.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Pattern"),
Toolkit.i18nText("Fine-Design_Chart_Axis"),
Toolkit.i18nText("Fine-Design_Chart_X_Axis")
);
dealTitle(formulaInfos, xAxisContent, xAxis.getTitle());
dealChartValueDefine(formulaInfos, xAxisContent, xAxis);
if (chart.getPlot() instanceof VanChartRectanglePlot) {
searchVanChartRectanglePlotAxisFormula(formulaInfos, chartContent, chart.getPlot(), chart);
} else {
Axis xAxis = chart.getPlot().getxAxis();
Axis yAxis = chart.getPlot().getyAxis();
//样式-坐标轴
dealAxisFormula(formulaInfos, chartContent, xAxis, chart);
dealAxisFormula(formulaInfos, chartContent, yAxis, chart);
}
}
}
//样式-坐标轴-y轴-轴标题
if (yAxis != null) {
ITContent yAxisContent = ITContent.copy(chartContent);
yAxisContent.addOtherPos(
chart.getChartName(),
Toolkit.i18nText("Fine-Design_Chart_Pattern"),
Toolkit.i18nText("Fine-Design_Chart_Axis"),
Toolkit.i18nText("Fine-Design_Chart_Y_Axis")
);
dealTitle(formulaInfos, yAxisContent, yAxis.getTitle());
dealChartValueDefine(formulaInfos, yAxisContent, yAxis);
}
private void searchVanChartRectanglePlotAxisFormula(List<FormulaInfo> formulaInfos, ITContent chartContent, VanChartRectanglePlot plot, Chart chart) {
for (VanChartAxis axis : plot.getXAxisList()) {
dealAxisFormula(formulaInfos, chartContent, axis, chart);
}
for (VanChartAxis axis : plot.getYAxisList()) {
dealAxisFormula(formulaInfos, chartContent, axis, chart);
}
}
private void dealAxisFormula(List<FormulaInfo> formulaInfos, ITContent chartContent, Axis axis, Chart chart) {
if (axis instanceof VanChartAxis) {
//轴标题
ITContent content = ITContent.copy(chartContent);
if (!chartContent.isFrm()) {
content.addOtherPos(chart.getChartName());
}
content.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Pattern"),
Toolkit.i18nText("Fine-Design_Chart_Axis"),
((VanChartAxis) axis).getAxisName()
);
dealTitle(formulaInfos, content, axis.getTitle());
dealChartValueDefine(formulaInfos, content, axis);
}
}
private void dealChartValueDefine(List<FormulaInfo> formulaInfos, ITContent axisContent, Axis axis) {

41
designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/chart/SearchChartMapDataFormulaAction.java

@ -34,11 +34,11 @@ public class SearchChartMapDataFormulaAction implements SearchChartDataFormula {
//流向地图
ITContent lineContent = ITContent.copy(content);
lineContent.addOtherPos(Toolkit.i18nText("Fine-Design_Chart_LineMap"));
dealLineDefinition(formulaInfos, content, mapDefinition.getLineDefinition());
dealLineDefinition(formulaInfos, lineContent, mapDefinition.getLineDefinition());
//点地图
ITContent pointContent = ITContent.copy(content);
pointContent.addOtherPos(Toolkit.i18nText("Fine-Design_Chart_PointMap"));
dealPointDefinition(formulaInfos, content, mapDefinition.getPointDefinition());
dealPointDefinition(formulaInfos, pointContent, mapDefinition.getPointDefinition());
}
}
@ -101,7 +101,7 @@ public class SearchChartMapDataFormulaAction implements SearchChartDataFormula {
formulaInfos.add(new FormulaInfo(endAreaNameContent));
}
//区域名
dealAreaName(formulaInfos, lineContent, definition.getCategoryName(), definition);
dealAreaName(formulaInfos, lineContent, definition.getCategoryName(), definition, true);
}
}
@ -160,18 +160,34 @@ public class SearchChartMapDataFormulaAction implements SearchChartDataFormula {
}
/**
* 处理区域名
* @param formulaInfos
* @param content
* @param object
* @param definition
* 处理区域名不用考虑特殊起名
* @param formulaInfos 存储信息的数据结构
* @param content ITContent
* @param object 分类
* @param definition 数据
*/
public void dealAreaName(List<FormulaInfo> formulaInfos, ITContent content, Object object, VanMapReportDefinition definition) {
dealAreaName(formulaInfos, content, object, definition, false);
}
/**
* 处理区域名特殊起名
* @param formulaInfos 存储信息的数据结构
* @param content ITContent
* @param object 分类
* @param definition 数据
* @param lineFlag 线地图的标志
*/
public void dealAreaName(List<FormulaInfo> formulaInfos, ITContent content, Object object, VanMapReportDefinition definition, boolean lineFlag) {
String str;
if (lineFlag) {
str = Toolkit.i18nText("Fine-Design_Chart_Start_Area_Name");
} else {
str = Toolkit.i18nText("Fine-Design_Chart_Area_Name");
}
if (object instanceof Formula) {
ITContent cateContent = ITContent.copy(content);
cateContent.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Area_Name")
);
cateContent.addOtherPos(str);
cateContent.setReplaceObject(object);
formulaInfos.add(new FormulaInfo(cateContent));
} else if (isFormulaString(object)) {
@ -179,12 +195,11 @@ public class SearchChartMapDataFormulaAction implements SearchChartDataFormula {
strContent.setHoldObject(definition);
strContent.setTag(SearchTag.CHART_AREA_NAME);
strContent.setReplaceObject(object);
strContent.addOtherPos(Toolkit.i18nText("Fine-Design_Chart_Area_Name"));
strContent.addOtherPos(str);
formulaInfos.add(new FormulaInfo(strContent));
}
}
/**
* 处理系列名&
*/

3
designer-realize/src/main/java/com/fr/design/actions/replace/action/content/formula/highlight/javascript/SearchChartHyperPopLinkAction.java

@ -27,7 +27,8 @@ public class SearchChartHyperPopLinkAction implements SearchJSFormula {
if (javaScript instanceof ChartHyperPoplink) {
ChartHyperPoplink chartHyperPoplink = (ChartHyperPoplink) javaScript;
if (chartHyperPoplink.getChartCollection() instanceof ChartCollection) {
SearchChartCollectionFormulaAction.getInstance().searchChartCollectionFormula(formulaInfos, content, (ChartCollection) chartHyperPoplink.getChartCollection());
ITContent chartContent = ITContent.copy(content);
SearchChartCollectionFormulaAction.getInstance().searchChartCollectionFormula(formulaInfos, chartContent, (ChartCollection) chartHyperPoplink.getChartCollection());
}
}
}

56
designer-realize/src/main/java/com/fr/design/actions/replace/action/content/js/SearchChartJSAction.java

@ -13,6 +13,7 @@ import com.fr.js.NameJavaScript;
import com.fr.js.NameJavaScriptGroup;
import com.fr.plugin.chart.attr.axis.VanChartAxis;
import com.fr.plugin.chart.attr.plot.VanChartPlot;
import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot;
import com.fr.plugin.chart.base.RefreshMoreLabel;
import com.fr.plugin.chart.base.VanChartHtmlLabel;
import com.fr.plugin.chart.custom.CustomPlotFactory;
@ -45,7 +46,7 @@ public class SearchChartJSAction {
*/
public void searchChartJS(ChartCollection chartCollection, ITContent content, List<JSInfo> jsInfos) {
List<Pair<VanChartHtmlLabel, String>> htmlLabels = SearchJSUtils.getHtmlLabel(chartCollection);
List<NameJavaScript> nameJavaScripts = SearchJSUtils.getNameJavaScript(chartCollection);
List<NameJavaScript> nameJavaScripts = SearchJSUtils.getNameJavaScript(chartCollection, content, jsInfos);
//图表-样式-标签以及图表-特效-条件显示
ITContent htmlITContent = ITContent.copy(content);
htmlITContent.addOtherPos(Toolkit.i18nText("Fine-Design_Chart_Chart"));
@ -117,29 +118,44 @@ public class SearchChartJSAction {
private void searchAxisJS(List<JSInfo> jsInfos, ITContent chartContent, Chart chart) {
if (chart.getPlot() != null) {
Axis xAxis = chart.getPlot().getxAxis();
Axis yAxis = chart.getPlot().getyAxis();
if (xAxis instanceof VanChartAxis) {
ITContent xAxisContent = ITContent.copy(chartContent);
xAxisContent.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Axis"),
Toolkit.i18nText("Fine-Design_Chart_X_Axis"),
Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Format")
);
dealAxisHtmlLabelJS(jsInfos, ((VanChartAxis) xAxis).getHtmlLabel(), xAxisContent);
if (chart.getPlot() instanceof VanChartRectanglePlot) {
searchVanChartRectanglePlotAxisJS(jsInfos, chartContent, chart.getPlot());
} else {
Axis xAxis = chart.getPlot().getxAxis();
Axis yAxis = chart.getPlot().getyAxis();
dealAxis(jsInfos, chartContent, xAxis);
dealAxis(jsInfos, chartContent, yAxis);
}
}
if (yAxis instanceof VanChartAxis) {
ITContent yAxisContent = ITContent.copy(chartContent);
yAxisContent.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Axis"),
Toolkit.i18nText("Fine-Design_Chart_Y_Axis"),
Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Format")
);
dealAxisHtmlLabelJS(jsInfos, ((VanChartAxis) yAxis).getHtmlLabel(), yAxisContent);
}
}
private void dealAxis(List<JSInfo> jsInfos, ITContent chartContent, Axis axis) {
if (axis instanceof VanChartAxis) {
ITContent yAxisContent = ITContent.copy(chartContent);
yAxisContent.addOtherPos(
Toolkit.i18nText("Fine-Design_Chart_Axis"),
((VanChartAxis) axis).getAxisName(),
Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Format")
);
dealAxisHtmlLabelJS(jsInfos, ((VanChartAxis) axis).getHtmlLabel(), yAxisContent);
}
}
/**
* 自定义的图表可以存放多个轴
* @param jsInfos 存储信息的数据结构
* @param chartContent ITContent
* @param plot 图表的VanChartRectanglePlot
*/
private void searchVanChartRectanglePlotAxisJS(List<JSInfo> jsInfos, ITContent chartContent, VanChartRectanglePlot plot) {
for (VanChartAxis axis : plot.getXAxisList()) {
dealAxis(jsInfos, chartContent, axis);
}
for (VanChartAxis axis : plot.getYAxisList()) {
dealAxis(jsInfos, chartContent, axis);
}
}
private void dealAxisHtmlLabelJS(List<JSInfo> jsInfos, VanChartHtmlLabel label, ITContent content) {

6
designer-realize/src/main/java/com/fr/design/actions/replace/action/setting/CellGroupType.java

@ -237,7 +237,11 @@ public enum CellGroupType {
*/
public void replace(Info info, String firstStr, String secondStr) {
FunctionGrouper grouper = new FunctionGrouper();
grouper.setDivideMode(getGroupType(secondStr));
if (StringUtils.equals(firstStr, SettingContent.DIGIT_SETTING_LIST)) {
grouper.setDivideMode(getGroupType(firstStr));
} else {
grouper.setDivideMode(getGroupType(secondStr));
}
CellElement cellElement = (CellElement) info.getContent().getReplaceObject();
DSColumn column = (DSColumn) cellElement.getValue();
column.setGrouper(grouper);

4
designer-realize/src/main/java/com/fr/design/actions/replace/info/ComponentInfo.java

@ -3,6 +3,7 @@ package com.fr.design.actions.replace.info;
import com.fr.design.actions.replace.action.content.component.ComponentType;
import com.fr.design.actions.replace.action.content.component.SearchComponentAction;
import com.fr.design.actions.replace.info.base.ITContent;
import com.fr.design.actions.replace.utils.ShowValueUtils;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.JTemplate;
import com.fr.form.ui.Widget;
@ -92,7 +93,8 @@ public class ComponentInfo implements Info {
}
SearchComponentAction.getInstance().search4Infos(jTemplate);
List<ComponentInfo> list = SearchComponentAction.getInstance().getComponentInfos();
String replacedName = ((Widget)this.getContent().getReplaceObject()).getWidgetName().replace(searchStr, replaceStr);
String replacedName = ShowValueUtils.replaceAll(((Widget)this.getContent().getReplaceObject()).getWidgetName(), searchStr, replaceStr);
for (ComponentInfo info : list) {
String widgetName = ((Widget)info.getContent().getReplaceObject()).getWidgetName();
if (StringUtils.equals(replacedName, widgetName)) {

2
designer-realize/src/main/java/com/fr/design/actions/replace/info/WidgetInfo.java

@ -156,7 +156,7 @@ public class WidgetInfo implements Info, DealWithInfoValue {
return false;
}
if (!this.isWaterMark() && this.isNeed2Check()) {
String replacedName = ((Widget)this.getContent().getReplaceObject()).getWidgetName().replace(searchStr, replaceStr);
String replacedName = ShowValueUtils.replaceAll(((Widget)this.getContent().getReplaceObject()).getWidgetName(), searchStr, replaceStr);
for (WidgetName name : CheckUtils.getNeed2CheckWidgetsName(jTemplate)) {
String widgetName = name.getName();
if (StringUtils.equals(replacedName, widgetName)) {

2
designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITCheckDialog.java

@ -44,7 +44,7 @@ public class ITCheckDialog extends UIDialog {
editorPane = new UITableEditorPane(editor);
editor.add(ITReplaceMainDialog.getCheckValidList());
UILabel label = new UILabel("<html>" + Toolkit.i18nText("Fine-Design_Replace_Check") + "<font color = 'rgb(236,124,125)'>" + ITReplaceMainDialog.contentReplaceFailedCount + "</font>" + Toolkit.i18nText("Fine-Design_Replace_Check_Tip"));
UILabel label = new UILabel("<html>" + Toolkit.i18nText("Fine-Design_Replace_Check", "<font color = 'rgb(236,124,125)'>" + ITReplaceMainDialog.contentReplaceFailedCount + "</font>"));
JPanel center = new JPanel(new BorderLayout());
UIButton location = new UIButton(Toolkit.i18nText("Fine-Design_Chart_Location"));
UIButton cancel = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));

47
designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceMainDialog.java

@ -1,6 +1,7 @@
package com.fr.design.actions.replace.ui;
import com.fr.design.actions.replace.action.ITChecker;
import com.fr.design.actions.replace.action.ShowSearchResultAction;
import com.fr.design.actions.replace.action.setting.SettingController;
@ -37,6 +38,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import static com.fr.design.actions.replace.ui.ITTableEditorPane.editTable;
import static com.fr.design.actions.replace.ui.ITTableEditorPane.getEditTable;
/**
@ -136,7 +138,7 @@ public class ITReplaceMainDialog extends UIDialog {
southPanel = new ITReplaceSouthPanel();
westPanel = new ITReplaceWestPanel();
initCloseListener();
//initCloseListener();
northPane.fitScreen(0, 0, jTemplate.getWidth());
JPanel center = new JPanel(new BorderLayout());
@ -210,10 +212,13 @@ public class ITReplaceMainDialog extends UIDialog {
* 模板内容替换相关
*/
private void replace4Content() {
String type = GeneralUtils.objectToString(northPane.getFindCombobox().getSelectedItem());
String searchStr = ((UITextField) (northPane.getFindInputCombobox().getEditor().getEditorComponent())).getText();
String replaceStr = ((UITextField) (northPane.getReplaceInputCombobox().getEditor().getEditorComponent())).getText();
clearContentCount();
if (isITReplaceValid() && checkTemplateChanged(searchContentResultList)) {
if (isITReplaceValid() && checkTemplateChanged(searchContentResultList, type)) {
ShowSearchResultAction searchAction = ShowSearchResultAction.match(GeneralUtils.objectToString(northPane.getFindCombobox().getSelectedItem()));
ITChecker.updateCheckInfo(searchAction.addMatchResult(searchStr, searchAction.showSearchValue(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate())));
if (StringUtils.equals(getSearchStr(), searchStr)) {
String str = GeneralUtils.objectToString(northPane.getFindCombobox().getSelectedItem());
//如果是控件或组件才要进行合法性校验
@ -252,13 +257,19 @@ public class ITReplaceMainDialog extends UIDialog {
* @param replaceStr
*/
public void replace(String searchStr, String replaceStr) {
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().fireTargetModified(true);
for (Info info : searchContentResultList) {
if (!info.getContent().isWrongful()) {
if (!info.getContent().isWrongful() && isSupportReplace(info)) {
info.setValue(info, searchStr, replaceStr, info.getContent().getOperatorArray());
contentReplaceCount++;
}
if (info.getContent().isWrongful()) {
contentReplaceFailedCount++;
}
if (info.getContent().isSelected()) {
info.getContent().setReplaced(true);
}
info.getContent().setReplaced(true);
}
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().fireTargetModified(true);
northPane.getResultLabel().setText(ShowValueUtils.getResultTip(searchContentResultList.size(), contentReplaceCount, contentReplaceFailedCount));
southPanel.getTableEditorPane().update();
northPane.refreshReplaceInputComboBoxItems();
@ -311,13 +322,10 @@ public class ITReplaceMainDialog extends UIDialog {
for (Info info : searchContentResultList) {
if (isAllow2Replace(info)) {
if (!info.isLegalValid(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(), searchStr, replaceStr)) {
contentReplaceFailedCount++;
checkValidList.add(info);
serialNumber.add(count);
info.getContent().setWrongful(true);
info.getContent().setReplaced(true);
} else {
contentReplaceCount++;
}
count++;
}
@ -338,10 +346,18 @@ public class ITReplaceMainDialog extends UIDialog {
}
private Boolean checkTemplateChanged(List<? extends Info> searchResultList) {
for (Info info : searchResultList) {
if (!info.getContent().isReplaced() && !info.checkValid()) {
return false;
private Boolean checkTemplateChanged(List<? extends Info> searchResultList, String type) {
ITChecker checker = ITChecker.match(type);
//对于JS、控件、组件、公式进行全量校验,不只针对当前选中的地方,这边先这样处理
if (checker != null) {
ShowSearchResultAction searchAction = ShowSearchResultAction.match(GeneralUtils.objectToString(northPane.getFindCombobox().getSelectedItem()));
return !checker.isChanged(searchAction.addMatchResult(searchStr, searchAction.showSearchValue(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate())));
} else {
//其他地方走各自的校验逻辑
for (Info info : searchResultList) {
if (!info.getContent().isReplaced() && !info.checkValid()) {
return false;
}
}
}
return true;
@ -436,7 +452,9 @@ public class ITReplaceMainDialog extends UIDialog {
ShowSearchResultAction searchAction = ShowSearchResultAction.match(GeneralUtils.objectToString(northPane.getFindCombobox().getSelectedItem()));
//搜索
if (searchAction != null) {
searchContentResultList = searchAction.addMatchResult(searchStr, searchAction.showSearchValue(jTemplate));
List<? extends Info> showValueList = searchAction.showSearchValue(jTemplate);
searchContentResultList = searchAction.addMatchResult(searchStr, showValueList);
ITChecker.updateCheckInfo(searchContentResultList);
itTableEditor.add(searchContentResultList);
northPane.getResultLabel().setText(ShowValueUtils.getResultTip(searchContentResultList.size(), contentReplaceCount, contentReplaceFailedCount));
}
@ -512,7 +530,6 @@ public class ITReplaceMainDialog extends UIDialog {
if (isInputStrValid(inputStr, extraStr)) {
String secondStr = GeneralUtils.objectToString(northPane.getReplaceSettingInputComboBox().getSelectedItem());
String thirdStr = GeneralUtils.objectToString(northPane.getReplaceExtraSettingComboBox().getSelectedItem());
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().fireTargetModified(true);
for (Info info : searchSettingResultList) {
if (isSupportReplace(info)) {
SettingController controller = SettingController.match(firstStr);
@ -523,10 +540,10 @@ public class ITReplaceMainDialog extends UIDialog {
}
}
}
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().fireTargetModified(true);
northPane.getSettingResultLabel().setText(ShowValueUtils.getResultTip(searchSettingResultList.size(), settingReplaceCount, settingReplaceFailedCount));
southPanel.getTableEditorPane().update();
ITTableEditorPane.getEditTable().repaint();
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().fireTargetModified();
} else {
search4Setting();
}

50
designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceNorthPanel.java

@ -5,6 +5,7 @@ import com.fr.design.actions.replace.action.setting.SettingContent;
import com.fr.design.actions.replace.action.setting.SettingController;
import com.fr.design.data.datapane.TableDataComboBox;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
@ -20,6 +21,8 @@ import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
@ -49,7 +52,7 @@ public class ITReplaceNorthPanel {
private UILabel resultLabel;
private UIComboBox findCombobox;
private UIComboBox rangeCombobox;
private JCheckBox matchRadioButton;
private UICheckBox matchRadioButton;
private UILabel iconLabel;
private UIComboBox findInputCombobox;
private UIComboBox replaceInputCombobox;
@ -199,7 +202,7 @@ public class ITReplaceNorthPanel {
super.setEditor(new ITComboBoxEditor());
}
};
matchRadioButton = new JCheckBox(Toolkit.i18nText("Fine-Design_Replace_WildCard"));
matchRadioButton = new UICheckBox(Toolkit.i18nText("Fine-Design_Replace_WildCard"));
matchRadioButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@ -317,6 +320,45 @@ public class ITReplaceNorthPanel {
refreshExtraComboBox(replaceSettingInputComboBox, replaceExtraSettingComboBox);
}
});
initInputComboBoxPopupListener(findSettingInputComboBox);
initInputComboBoxPopupListener(replaceSettingInputComboBox);
}
private void initInputComboBoxPopupListener(UIComboBox box) {
box.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
String str = GeneralUtils.objectToString(findSettingComboBox.getSelectedItem());
int findExtraIndex = findExtraSettingComboBox.getSelectedIndex();
int replaceExtraIndex = replaceExtraSettingComboBox.getSelectedIndex();
box.refreshBoxItems(SettingController.getSettingRefreshItems(str));
dealExtraItemSelect(findExtraSettingComboBox, findExtraIndex);
dealExtraItemSelect(replaceExtraSettingComboBox, replaceExtraIndex);
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
}
/**
* 重新设置额外下拉框的选中索引
* @param comboBox 额外下拉框
* @param index 索引
*/
private void dealExtraItemSelect(UIComboBox comboBox, int index) {
if (comboBox.getItemCount() > index) {
comboBox.setSelectedIndex(index);
}
}
/**
@ -661,11 +703,11 @@ public class ITReplaceNorthPanel {
this.rangeCombobox = rangeCombobox;
}
public JCheckBox getMatchRadioButton() {
public UICheckBox getMatchRadioButton() {
return matchRadioButton;
}
public void setMatchRadioButton(JCheckBox checkBox) {
public void setMatchRadioButton(UICheckBox checkBox) {
this.matchRadioButton = checkBox;
}

165
designer-realize/src/main/java/com/fr/design/actions/replace/utils/SearchJSUtils.java

@ -2,6 +2,7 @@ package com.fr.design.actions.replace.utils;
import com.fr.chart.base.DataSeriesCondition;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.chart.chartattr.Plot;
import com.fr.chart.chartglyph.ConditionAttr;
import com.fr.chart.chartglyph.ConditionCollection;
import com.fr.chart.web.ChartHyperPoplink;
@ -22,9 +23,14 @@ import com.fr.plugin.chart.attr.plot.VanChartPlot;
import com.fr.plugin.chart.base.AttrLabel;
import com.fr.plugin.chart.base.AttrTooltip;
import com.fr.plugin.chart.base.VanChartHtmlLabel;
import com.fr.plugin.chart.custom.CustomPlotFactory;
import com.fr.plugin.chart.custom.VanChartCustomPlot;
import com.fr.plugin.chart.custom.type.CustomPlotType;
import com.fr.plugin.chart.drillmap.VanChartDrillMapPlot;
import com.fr.plugin.chart.map.VanChartMapPlot;
import com.fr.plugin.chart.map.attr.AttrMapLabel;
import com.fr.plugin.chart.map.attr.AttrMapTooltip;
import com.fr.plugin.chart.type.MapType;
import com.fr.plugin.chart.vanchart.VanChart;
import com.fr.report.cell.Elem;
import com.fr.stable.StringUtils;
@ -58,6 +64,14 @@ public class SearchJSUtils {
*/
public static final String CATEGORY_LABEL = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Basic_Style"), Toolkit.i18nText("Fine-Design_Chart_Data_Label"), Toolkit.i18nText("Fine-Design_Chart_Category_Label"));
/**
* 条件属性
*/
public static final String CONDITION = ShowValueUtils.joinStr4Position(
Toolkit.i18nText("Fine-Design_Chart_Chart"),
Toolkit.i18nText("Fine-Design_Chart_Animation_Special"),
Toolkit.i18nText("Fine-Design_Chart_Interactive"));
/**
* 从Listener中获取JS
*/
@ -119,16 +133,60 @@ public class SearchJSUtils {
for (int i = 0; i < collection.getChartCount(); i++) {
if (collection.getChart(i) instanceof VanChart) {
VanChart chart = ((VanChart) collection.getChart(i));
int size = chart.getPlot().getConditionCollection().getConditionAttrSize();
ConditionCollection conditionCollection = chart.getPlot().getConditionCollection();
//如果是组合图
if (chart.getPlot() instanceof VanChartCustomPlot) {
VanChartCustomPlot plot = chart.getPlot();
for (VanChartPlot vanChartPlot : plot.getCustomPlotList()) {
dealPlotHtmlLabel(arrayList, vanChartPlot);
}
} else if (chart.getPlot() instanceof VanChartPlot){
dealPlotHtmlLabel(arrayList, chart.getPlot());
}
addAttrLabelHtmlLabel(chart, arrayList);
for (int j = 0; j < size; j++) {
searchConditionCollection(arrayList, conditionCollection.getConditionAttr(j));
}
}
}
}
private static void dealPlotHtmlLabel(List<Pair<VanChartHtmlLabel, String>> arrayList, VanChartPlot plot) {
//如果是组合地图
if (plot instanceof VanChartMapPlot) {
dealMapPlotHtmlLabel(arrayList, (VanChartMapPlot) plot);
} else {
dealCommonPlotHtmlLabel(arrayList, plot);
}
}
private static void dealMapPlotHtmlLabel(List<Pair<VanChartHtmlLabel, String>> arrayList, VanChartMapPlot plot) {
ConditionCollection area = plot.getConditionCollection();
ConditionCollection line = plot.getLineConditionCollection();
ConditionCollection point = plot.getPointConditionCollection();
dealMapCollectionHtmlLabel(arrayList, area, Toolkit.i18nText("Fine-Design_Chart_Region_Map"));
dealMapCollectionHtmlLabel(arrayList, line, Toolkit.i18nText("Fine-Design_Chart_LineMap"));
dealMapCollectionHtmlLabel(arrayList, point, Toolkit.i18nText("Fine-Design_Chart_PointMap"));
}
private static void dealMapCollectionHtmlLabel(List<Pair<VanChartHtmlLabel, String>> arrayList, ConditionCollection collection, String i18nText) {
for (int i = 0, size = collection.getConditionAttrSize(); i < size; i++) {
searchConditionCollection(arrayList, collection.getConditionAttr(i), i18nText);
}
}
private static void dealCommonPlotHtmlLabel(List<Pair<VanChartHtmlLabel, String>> arrayList, VanChartPlot plot) {
int size = plot.getConditionCollection().getConditionAttrSize();
CustomPlotType plotType = CustomPlotFactory.getCustomType(plot);
ConditionCollection conditionCollection = plot.getConditionCollection();
for (int j = 0; j < size; j++) {
if (plotType != null) {
searchConditionCollection(arrayList, conditionCollection.getConditionAttr(j), CustomPlotFactory.getTitle(plotType));
} else {
searchConditionCollection(arrayList, conditionCollection.getConditionAttr(j), StringUtils.EMPTY);
}
}
}
/**
* 将图表-样式-标签以及图表-样式-提示中的HtmlLabel加入数组
*
@ -140,15 +198,26 @@ public class SearchJSUtils {
//如果是地图类型要特殊处理
if (plot instanceof VanChartMapPlot) {
addMapJS2Array((VanChartMapPlot) plot, arrayList);
} else {
addAttrToolTipCondition2Array(plot, arrayList);
if (isAttrLabelExist(plot)) {
addAttrLabelDetail2Array(plot, arrayList);
addAttrSecondLabelDetail2Array(plot, arrayList);
} else if(plot instanceof VanChartCustomPlot){
for (VanChartPlot vanChartPlot : ((VanChartCustomPlot) plot).getCustomPlotList()) {
CustomPlotType plotType = CustomPlotFactory.getCustomType(vanChartPlot);
dealAttrLabelHtml4VanChartPlot(vanChartPlot, arrayList, CustomPlotFactory.getTitle(plotType));
}
} else {
dealAttrLabelHtml4VanChartPlot(plot, arrayList, StringUtils.EMPTY);
}
}
private static void dealAttrLabelHtml4VanChartPlot(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList, String str) {
addAttrToolTipCondition2Array(plot, arrayList, str);
if (isAttrLabelExist(plot)) {
addAttrLabelDetail2Array(plot, arrayList, str);
addAttrSecondLabelDetail2Array(plot, arrayList, str);
}
}
/**
* 用于处理地图类型图表中的样式中的JSAttrMapTooltip AttrMapLabel
*
@ -195,9 +264,9 @@ public class SearchJSUtils {
}
}
private static void addAttrToolTipCondition2Array(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList) {
private static void addAttrToolTipCondition2Array(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList, String str) {
if (isToolTipValid(plot.getAttrTooltipFromConditionCollection())) {
arrayList.add(new Pair<>(((AttrTooltip) plot.getAttrTooltipFromConditionCollection()).getContent().getHtmlLabel(), STYLE_TOOLTIP_CUSTOM));
arrayList.add(new Pair<>(((AttrTooltip) plot.getAttrTooltipFromConditionCollection()).getContent().getHtmlLabel(), ShowValueUtils.getChartOtherPos(STYLE_TOOLTIP_CUSTOM, str)));
}
}
@ -205,9 +274,9 @@ public class SearchJSUtils {
return tooltip instanceof AttrTooltip && ((AttrTooltip) tooltip).isEnable() && ((AttrTooltip) tooltip).getContent() != null && ((AttrTooltip) tooltip).getContent().getHtmlLabel() != null;
}
private static void addAttrLabelDetail2Array(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList) {
private static void addAttrLabelDetail2Array(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList, String str) {
if (isLabelDetailValid(plot)) {
arrayList.add(new Pair<>(plot.getAttrLabelFromConditionCollection().getAttrLabelDetail().getContent().getHtmlLabel(), STYLE_LABEL));
arrayList.add(new Pair<>(plot.getAttrLabelFromConditionCollection().getAttrLabelDetail().getContent().getHtmlLabel(), ShowValueUtils.getChartOtherPos(STYLE_LABEL, str)));
}
}
@ -217,9 +286,9 @@ public class SearchJSUtils {
&& plot.getAttrLabelFromConditionCollection().getAttrLabelDetail().getContent().getHtmlLabel() != null;
}
private static void addAttrSecondLabelDetail2Array(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList) {
private static void addAttrSecondLabelDetail2Array(VanChartPlot plot, List<Pair<VanChartHtmlLabel, String>> arrayList, String str) {
if (isSecondLabelDetailValid(plot)) {
arrayList.add(new Pair<>(plot.getAttrLabelFromConditionCollection().getSecondLabelDetail().getContent().getHtmlLabel(), CATEGORY_LABEL));
arrayList.add(new Pair<>(plot.getAttrLabelFromConditionCollection().getSecondLabelDetail().getContent().getHtmlLabel(), ShowValueUtils.getChartOtherPos(CATEGORY_LABEL, str)));
}
}
@ -239,21 +308,22 @@ public class SearchJSUtils {
* @param arrayList
* @param conditionAttr
*/
private static void searchConditionCollection(List<Pair<VanChartHtmlLabel, String>> arrayList, ConditionAttr conditionAttr) {
private static void searchConditionCollection(List<Pair<VanChartHtmlLabel, String>> arrayList, ConditionAttr conditionAttr, String name) {
int conditionSize = conditionAttr.getDataSeriesConditionCount();
for (int t = 0; t < conditionSize; t++) {
DataSeriesCondition condition = conditionAttr.getDataSeriesCondition(t);
String str = Toolkit.i18nText("Fine-Design_Chart_Animation_Special") + "-" + Toolkit.i18nText("Fine-Design_Chart_Condition_Display");
String str = ShowValueUtils.joinStr4Position(Toolkit.i18nText("Fine-Design_Chart_Animation_Special"), Toolkit.i18nText("Fine-Design_Chart_Condition_Display"));
if (StringUtils.isNotEmpty(conditionAttr.getName())) {
str += "-" + conditionAttr.getName();
str = ShowValueUtils.joinStr4Position(str, conditionAttr.getName());
}
str = ShowValueUtils.joinStr4Position(str, name);
if (condition instanceof AttrTooltip) {
arrayList.add(new Pair<>(((AttrTooltip) condition).getContent().getHtmlLabel(), str + "-" + Toolkit.i18nText("Fine-Design_Chart_Data_Point_Tooltip")));
arrayList.add(new Pair<>(((AttrTooltip) condition).getContent().getHtmlLabel(), ShowValueUtils.joinStr4Position(str, Toolkit.i18nText("Fine-Design_Chart_Data_Point_Tooltip"))));
}
if (condition instanceof AttrLabel) {
AttrLabel label = (AttrLabel) condition;
if (isAttrLabelValid(label)) {
arrayList.add(new Pair<>(label.getContent().getHtmlLabel(), str + "-" + Toolkit.i18nText("Fine-Design_Chart_Label")));
arrayList.add(new Pair<>(label.getContent().getHtmlLabel(), ShowValueUtils.joinStr4Position(str, Toolkit.i18nText("Fine-Design_Chart_Label"))));
}
}
@ -270,18 +340,65 @@ public class SearchJSUtils {
* @param chartCollection
* @return
*/
public static List<NameJavaScript> getNameJavaScript(ChartCollection chartCollection) {
public static List<NameJavaScript> getNameJavaScript(ChartCollection chartCollection, ITContent content, List<JSInfo> jsInfos) {
ArrayList<NameJavaScript> nameJavaScriptArrayList = new ArrayList<>();
for (int i = 0; i < chartCollection.getChartCount(); i++) {
if (chartCollection.getChart(i) instanceof VanChart) {
VanChart chart = ((VanChart) chartCollection.getChart(i));
NameJavaScriptGroup nameJavaScriptGroup = chart.getPlot().getHotHyperLink();
addNameJavaScript2Array(nameJavaScriptArrayList, nameJavaScriptGroup);
if (isCustomMapPlot(chart.getPlot())) {
dealMapNameJavaScript(content, chart.getPlot(), jsInfos);
} else if (chart.getPlot() instanceof VanChartDrillMapPlot) {
dealDrillNameJavaScript(content, chart.getPlot(), jsInfos);
} else {
NameJavaScriptGroup nameJavaScriptGroup = chart.getPlot().getHotHyperLink();
addNameJavaScript2Array(nameJavaScriptArrayList, nameJavaScriptGroup);
}
}
}
return nameJavaScriptArrayList;
}
private static void dealDrillNameJavaScript(ITContent content, VanChartDrillMapPlot plot, List<JSInfo> jsInfos) {
ITContent chartContent = ITContent.copy(content);
chartContent.addOtherPos(
CONDITION,
Toolkit.i18nText("Fine-Design_Chart_Drill_Dir")
);
List<NameJavaScript> list = new ArrayList<>();
addNameJavaScript2Array(list, plot.getDrillUpHyperLink());
addJSInfosFromNameJS(chartContent, list, jsInfos);
}
/**
* 是否是组合地图
* @param plot 图表的plot
* @return 是则返回true
*/
public static boolean isCustomMapPlot(Plot plot) {
return plot instanceof VanChartMapPlot && ((VanChartMapPlot) plot).getMapType() == MapType.CUSTOM;
}
/**
* 处理图表的交互属性可能存在多种地图
* @param content 存储信息的数据结构
* @param plot 图表的VanChartMapPlot
*/
private static void dealMapNameJavaScript(ITContent content, VanChartMapPlot plot, List<JSInfo> jsInfos) {
List<NameJavaScript> areaJavaScriptList = new ArrayList<>();
List<NameJavaScript> lineJavaScriptList = new ArrayList<>();
List<NameJavaScript> pointJavaScriptList = new ArrayList<>();
ITContent chartContent = ITContent.copy(content);
chartContent.addOtherPos(CONDITION);
addNameJavaScript2Array(areaJavaScriptList, plot.getAreaHotHyperLink());
addNameJavaScript2Array(lineJavaScriptList, plot.getLineHotHyperLink());
addNameJavaScript2Array(pointJavaScriptList, plot.getPointHotHyperLink());
addJSInfosFromNameJS(ShowValueUtils.getCustomMapContent(chartContent, Toolkit.i18nText("Fine-Design_Chart_Region_Map")), areaJavaScriptList, jsInfos);
addJSInfosFromNameJS(ShowValueUtils.getCustomMapContent(chartContent, Toolkit.i18nText("Fine-Design_Chart_LineMap")), lineJavaScriptList, jsInfos);
addJSInfosFromNameJS(ShowValueUtils.getCustomMapContent(chartContent, Toolkit.i18nText("Fine-Design_Chart_PointMap")), pointJavaScriptList, jsInfos);
}
private static void addNameJavaScript2Array(List<NameJavaScript> nameJavaScriptArrayList, NameJavaScriptGroup nameJavaScriptGroup) {
if (isNameJavaScriptGroupExist(nameJavaScriptGroup)) {
for (int j = 0; j < nameJavaScriptGroup.size(); j++) {

40
designer-realize/src/main/java/com/fr/design/actions/replace/utils/ShowValueUtils.java

@ -2,6 +2,7 @@ package com.fr.design.actions.replace.utils;
import com.fr.design.actions.replace.info.Info;
import com.fr.design.actions.replace.info.base.ITContent;
import com.fr.design.actions.replace.ui.ITReplaceMainDialog;
import com.fr.design.i18n.Toolkit;
import com.fr.stable.StableUtils;
@ -391,14 +392,47 @@ public class ShowValueUtils {
*/
public static String getResultTip(int findCount, int replaceCount, int failedCount) {
StringBuilder str = new StringBuilder();
str.append("<html>").append(Toolkit.i18nText("Fine-Design_Replace_Search_Finish")).append("<font color = 'rgb(61,153,249)'>").append(findCount).append("</font>").append(Toolkit.i18nText("Fine-Design_Replace_Result"));
str.append("<html>").append(Toolkit.i18nText("Fine-Design_Replace_Search_Finish", "<font color = 'rgb(61,153,249)'>" + findCount+ "</font>"));
if (replaceCount != 0) {
str.append(Toolkit.i18nText("Fine-Design_Replace_Also_Finish")).append("<font color = 'rgb(61,153,249)'>").append(replaceCount).append("</font>").append(Toolkit.i18nText("Fine-Design_Replace_Result_Count"));
str.append(Toolkit.i18nText("Fine-Design_Replace_Also_Finish", "<font color = 'rgb(61,153,249)'>" + replaceCount + "</font>"));
if (failedCount != 0) {
str.append(Toolkit.i18nText("Fine-Design_Replace_Have")).append("<font color = 'rgb(236,124,125)'>").append(failedCount).append("</font>").append(Toolkit.i18nText("Fine-Design_Replace_Can_Not_Replace"));
str.append(Toolkit.i18nText("Fine-Design_Replace_Have", "<font color = 'rgb(236,124,125)'>" + failedCount + "</font>"));
}
} else {
if (failedCount != 0) {
str.append(Toolkit.i18nText("Fine-Design_Replace_Also_Finish", "<font color = 'rgb(61,153,249)'>" + replaceCount + "</font>"));
str.append(Toolkit.i18nText("Fine-Design_Replace_Have", "<font color = 'rgb(236,124,125)'>" + failedCount + "</font>"));
}
}
return str.toString();
}
/**
* 返回图表类型的位置信息组合图就需要加上对应的类型名称
* @param str 基础信息
* @param customStyle 组合图的类型信息
* @return 组合后的位置信息
*/
public static String getChartOtherPos(String str, String customStyle) {
if (StringUtils.isNotEmpty(customStyle)) {
return joinStr4Position(str, customStyle);
} else {
return str;
}
}
/**
* 用于获取增加指定地图后缀的ITContent
* @param content 原ITContent
* @param str 后缀
* @return 处理后的新的ITContent
*/
public static ITContent getCustomMapContent(ITContent content, String str) {
ITContent resultContent = ITContent.copy(content);
resultContent.addOtherPos(str);
return resultContent;
}
}

2
designer-realize/src/main/java/com/fr/grid/GridUI.java

@ -51,7 +51,7 @@ import com.fr.stable.AssistUtils;
import com.fr.stable.ColumnRow;
import com.fr.stable.Constants;
import com.fr.stable.GraphDrawHelper;
import com.fr.stable.script.CalculatorUtils;
import com.fr.script.CalculatorUtils;
import com.fr.stable.unit.FU;
import com.fr.stable.unit.UNIT;
import com.fr.third.antlr.ANTLRException;

51
designer-realize/src/main/java/com/fr/quickeditor/CellQuickEditor.java

@ -455,6 +455,9 @@ public abstract class CellQuickEditor extends QuickEditor<ElementCasePane> {
if (updateStyle) {
// 防止频繁触发保存
if (!tc.isSelectedOneCell()) {
record(multipleOperationType.FORMAT);
}
fireTargetModified();
}
@ -469,4 +472,52 @@ public abstract class CellQuickEditor extends QuickEditor<ElementCasePane> {
return formatPane;
}
/**
* 用于适配记录批量操作的埋点数据
* 真正的埋点提交方案在云端运维插件中
*
* @param type 批量操作修改类型
* @return 批量修改类型名称用于云端运维埋点记录
*/
public static String record(multipleOperationType type) {
return type.getType();
}
/**
* 批量操作的类型
*/
public enum multipleOperationType {
/**
* 批量修改格式
*/
FORMAT("format"),
/**
* 批量修改数据列的数据设置
*/
TYPE_OF_DATA("type-of-data"),
/**
* 批量修改过滤条件
*/
FILTER("filter"),
/**
* 批量修改行高列宽
*/
HEIHT_AND_COLUMN("row-height-and-column-width");
private final String type;
multipleOperationType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
}

4
designer-realize/src/main/java/com/fr/quickeditor/cellquick/CellDSColumnEditor.java

@ -319,10 +319,12 @@ public class CellDSColumnEditor extends CellQuickEditor {
public void itemStateChanged(ItemEvent e) {
CellSelection selection = (CellSelection) tc.getSelection();
Set<TemplateCellElement> allCellElements = selection.getCellElements();
groupPane.update(allCellElements);
if (e == null || e.getStateChange() == ItemEvent.DESELECTED) {
//分组-高级-自定义点确定的时候传进来null的e,但是这时候应该触发保存
groupPane.update(allCellElements);
if (!tc.isSelectedOneCell()) {
CellQuickEditor.record(multipleOperationType.TYPE_OF_DATA);
}
fireTargetModified();
}
}

Loading…
Cancel
Save