* commit '0bd092cda48fbf2e8c89687510c97b237a19bcdd': (171 commits) REPORT-65371 【主题边框】附件截图,滚动条显示有问题 REPORT-65343 FR11-新自适应开发者调试-新建模板,直接点击开发者调试进行模板保存和预览,此时虽然弹出保存路径弹窗,但对话框弹窗还没有点击的时候模板web就打开了且报错,因为模板没保存成功;设计器端可以看到模板被关闭了 REPORT-65365 【主题边框】多次切换单元格样式后切换自定义,边框线有问题 REPORT-65358 【主题边框】单元格样式双线显示有问题 REPORT-65307 二轮冒烟测试-远程模板锁定优化-国际化问题-弹窗显示不全 REPORT-65170【主题边框】悬浮元素的预览图,右下的边框线看不到 REPORT-65192 公式合法性检测错误字符位置返回不正确 1.如果返回错误位置,则模糊处理 KERNEL-9928 重构水印加载 1.改成常量 KERNEL-9928 重构水印加载 1.适配一下面板 REPORT-65192 公式合法性检测错误字符位置返回不正确 1.处理一下极少出现的情况,默认返回0的位置吧。 REPORT-65170【主题边框】悬浮元素的预览图,右下的边框线看不到 REPORT-65090:将builder的形式换成普通的创建focusPoint的方式 REPORT-65124 【模板主题】单元格样式编辑的效果有问题 问题修复 REPORT-65125 【模板主题】双击数据列设置格式,没有保存成功 REPORT-64920 复制粘贴接口报错处理 CHART-22503 标题、图例、轴标题、轴标签、数据表等字符颜色控件-多余增加了自动 REPORT-65087 共享数据集兼容性问题 REPORT-65090:修复埋点格式错误bug REPORT-62611 远程设计websocket断开提示优化-toast弹窗在设计器界面居左后显示异常 ...fix-lag
@ -0,0 +1,12 @@
|
||||
package com.fr.common.exception; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2021/12/7 |
||||
*/ |
||||
public interface ThrowableHandler { |
||||
|
||||
boolean process(Throwable e); |
||||
|
||||
} |
@ -0,0 +1,17 @@
|
||||
package com.fr.design.actions.community; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.login.AbstractDesignerSSO; |
||||
import com.fr.general.CloudCenter; |
||||
|
||||
public class StudyPlanAction extends AbstractDesignerSSO { |
||||
public StudyPlanAction() { |
||||
this.setName(Toolkit.i18nText("Fine-Design_Study_Plan")); |
||||
this.setSmallIcon("/com/fr/design/images/bbs/studyPlan"); |
||||
} |
||||
|
||||
@Override |
||||
public String getJumpUrl() { |
||||
return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport"); |
||||
} |
||||
} |
@ -0,0 +1,180 @@
|
||||
package com.fr.design.cell; |
||||
|
||||
import com.fr.base.CellBorderSourceFlag; |
||||
import com.fr.base.CellBorderStyle; |
||||
import com.fr.base.Style; |
||||
import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.report.cell.TemplateCellElement; |
||||
|
||||
import javax.swing.JPanel; |
||||
import java.awt.AlphaComposite; |
||||
import java.awt.Color; |
||||
import java.awt.Composite; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.GridLayout; |
||||
import java.awt.Rectangle; |
||||
import java.awt.RenderingHints; |
||||
import java.awt.image.BufferedImage; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/9/3 |
||||
*/ |
||||
public class CellRectangleStylePreviewPane extends JPanel { |
||||
|
||||
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); |
||||
private final float transparentBackgroundWidth; |
||||
private final float transparentBackgroundHeight; |
||||
|
||||
private static final int ROW_COUNT = 2; |
||||
private static final int COLUMN_COUNT = 2; |
||||
|
||||
private final TemplateCellElement[][] cellElementGrid = new TemplateCellElement[ROW_COUNT][COLUMN_COUNT]; |
||||
private final int[][] borderSourceFlags = new int[ROW_COUNT][COLUMN_COUNT]; |
||||
private final CellStylePreviewPane[][] cellStylePreviewPaneGrid = new CellStylePreviewPane[ROW_COUNT][COLUMN_COUNT]; |
||||
|
||||
public CellRectangleStylePreviewPane(boolean supportInnerBorder) { |
||||
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); |
||||
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); |
||||
|
||||
setLayout(new GridLayout(2, 2)); |
||||
setOpaque(false); |
||||
setBackground(null); |
||||
|
||||
for (int r = 0; r < ROW_COUNT; r++) { |
||||
for (int c = 0; c < COLUMN_COUNT; c++) { |
||||
CellStylePreviewPane pane = new CellStylePreviewPane(c, r, COLUMN_COUNT, ROW_COUNT, false, false); |
||||
TemplateCellElement cellElement = DefaultThemedTemplateCellElementCase.createInstance(c, r); |
||||
int flags = CellBorderSourceFlag.INVALID_BORDER_SOURCE; |
||||
if (supportInnerBorder) { |
||||
flags = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; |
||||
if (r != 0) { |
||||
flags |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; |
||||
} |
||||
if (r != ROW_COUNT - 1) { |
||||
flags |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; |
||||
} |
||||
if (c != 0) { |
||||
flags |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; |
||||
} |
||||
if (c != COLUMN_COUNT - 1) { |
||||
flags |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; |
||||
} |
||||
} |
||||
|
||||
|
||||
pane.setStyle(cellElement.getStyle()); |
||||
add(pane); |
||||
|
||||
cellElementGrid[r][c] = cellElement; |
||||
borderSourceFlags[r][c] = flags; |
||||
cellStylePreviewPaneGrid[r][c] = pane; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void setPlainText(String text) { |
||||
cellStylePreviewPaneGrid[0][1].setPaintText(text); |
||||
cellStylePreviewPaneGrid[1][1].setPaintText(text); |
||||
repaint(); |
||||
} |
||||
|
||||
public void setStyle(Style style, CellBorderStyle borderStyle) { |
||||
for (int i = 0; i < ROW_COUNT; i++) { |
||||
for (int j = 0; j < COLUMN_COUNT; j++) { |
||||
CellStylePreviewPane pane = cellStylePreviewPaneGrid[i][j]; |
||||
TemplateCellElement cellElement = cellElementGrid[i][j]; |
||||
int flag = borderSourceFlags[i][j]; |
||||
cellElement.setStyle(CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, flag)); |
||||
|
||||
pane.setStyle(cellElement.getStyle()); |
||||
} |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
@Override |
||||
public void setPreferredSize(Dimension preferredSize) { |
||||
super.setPreferredSize(preferredSize); |
||||
int hw = preferredSize.width / 2; |
||||
int hh = preferredSize.height / 2; |
||||
cellStylePreviewPaneGrid[0][0].setPreferredSize(new Dimension(hw, hh)); |
||||
cellStylePreviewPaneGrid[0][1].setPreferredSize(new Dimension(hw, hh)); |
||||
cellStylePreviewPaneGrid[1][0].setPreferredSize(new Dimension(hw, hh)); |
||||
cellStylePreviewPaneGrid[1][1].setPreferredSize(new Dimension(hw, hh)); |
||||
} |
||||
|
||||
@Override |
||||
public Dimension getPreferredSize() { |
||||
Dimension d00 = cellStylePreviewPaneGrid[0][0].getPreferredSize(); |
||||
Dimension d01 = cellStylePreviewPaneGrid[0][1].getPreferredSize(); |
||||
Dimension d10 = cellStylePreviewPaneGrid[1][0].getPreferredSize(); |
||||
Dimension d11 = cellStylePreviewPaneGrid[1][1].getPreferredSize(); |
||||
|
||||
int width = Math.max(d00.width + d01.width, d10.width + d11.width); |
||||
int height = Math.max(d00.height + d10.height, d01.height + d11.height); |
||||
|
||||
return new Dimension(width, height); |
||||
} |
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.clearRect(0, 0, getWidth(), getHeight()); |
||||
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); |
||||
|
||||
paintTransparentBackground((Graphics2D) g, cellElementGrid[0][0].getStyle()); |
||||
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); |
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); |
||||
|
||||
super.paint(g); |
||||
} |
||||
|
||||
@Override |
||||
public Rectangle getBounds() { |
||||
return super.getBounds(); |
||||
} |
||||
|
||||
private void paintTransparentBackground(Graphics2D g2d, Style style) { |
||||
float alpha = computeTransparentBackgroundAlpha(style); |
||||
|
||||
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; |
||||
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; |
||||
float maxScale = Math.max(scaleWidth, scaleHeight); |
||||
|
||||
if (maxScale <= 1) { |
||||
scaleWidth = scaleHeight = 1; |
||||
} else { |
||||
scaleHeight = scaleWidth = maxScale; |
||||
} |
||||
|
||||
Composite oldComposite = g2d.getComposite(); |
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); |
||||
g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); |
||||
g2d.setComposite(oldComposite); |
||||
} |
||||
|
||||
private float computeTextColorBrightness(Style style) { |
||||
Color fontColor = style.getFRFont().getForeground(); |
||||
return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F; |
||||
} |
||||
|
||||
private float computeTransparentBackgroundAlpha(Style style) { |
||||
float textBrightness = computeTextColorBrightness(style); |
||||
|
||||
float alpha = 1.0F; |
||||
if (textBrightness < 50) { |
||||
alpha = 0.2F; |
||||
} else if (textBrightness < 160){ |
||||
alpha = 0.5F; |
||||
} |
||||
return alpha; |
||||
} |
||||
} |
@ -0,0 +1,52 @@
|
||||
package com.fr.design.config; |
||||
|
||||
import com.fr.general.IOUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StableUtils; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import java.io.BufferedInputStream; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.InputStream; |
||||
import java.util.Properties; |
||||
|
||||
public class DesignerProperties { |
||||
private static DesignerProperties holder = null; |
||||
private boolean supportLoginEntry = true; |
||||
|
||||
public DesignerProperties() { |
||||
String filePath = StableUtils.pathJoin(StableUtils.getInstallHome(), "/config/config.properties"); |
||||
InputStream is = null; |
||||
try { |
||||
is = new BufferedInputStream(new FileInputStream(filePath)); |
||||
Properties ps = new Properties(); |
||||
ps.load(is); |
||||
this.initProperties(ps); |
||||
} catch (FileNotFoundException e) { |
||||
// ignore
|
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e, e.getMessage()); |
||||
} finally { |
||||
IOUtils.close(is); |
||||
} |
||||
} |
||||
|
||||
public static DesignerProperties getInstance() { |
||||
if (holder == null) { |
||||
holder = new DesignerProperties(); |
||||
} |
||||
return holder; |
||||
} |
||||
|
||||
private void initProperties(Properties ps) { |
||||
String supportLoginEntry = ps.getProperty("supportLoginEntry"); |
||||
if (StringUtils.isNotEmpty(supportLoginEntry)) { |
||||
this.supportLoginEntry = Boolean.valueOf(supportLoginEntry); |
||||
} |
||||
} |
||||
|
||||
public boolean isSupportLoginEntry() { |
||||
return supportLoginEntry; |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
package com.fr.design.constants; |
||||
|
||||
public class TableDataConstants { |
||||
public static final String SEPARATOR = "_"; |
||||
} |
@ -0,0 +1,147 @@
|
||||
package com.fr.design.data.datapane.connect; |
||||
|
||||
import com.fr.data.impl.JDBCDatabaseConnection; |
||||
import com.fr.data.pool.DBCPConnectionPoolAttr; |
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.editor.editor.IntegerEditor; |
||||
import com.fr.design.gui.icombobox.UIComboBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.FocusEvent; |
||||
import java.awt.event.FocusListener; |
||||
|
||||
/** |
||||
* @author xiqiu |
||||
* @date 2021/11/22 |
||||
* @description |
||||
*/ |
||||
public class AdvancePane extends BasicPane { |
||||
private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor(); |
||||
private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")}); |
||||
private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor(); |
||||
private SpecialUITextField DBCP_VALIDATION_QUERY = new SpecialUITextField(); |
||||
|
||||
|
||||
public AdvancePane() { |
||||
|
||||
DBCP_VALIDATION_QUERY.addFocusListener(new JTextFieldHintListener(DBCP_VALIDATION_QUERY)); |
||||
; |
||||
double p = TableLayout.PREFERRED; |
||||
DBCP_VALIDATION_QUERY.setColumns(15); |
||||
double[] rowSizeDbcp = {p, p, p, p}; |
||||
double[] columnDbcp = {p, p}; |
||||
Component[][] comps = { |
||||
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE}, |
||||
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY}, |
||||
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW}, |
||||
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT} |
||||
}; |
||||
|
||||
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSizeDbcp, columnDbcp, 11, 11); |
||||
this.add(contextPane); |
||||
this.setPreferredSize(new Dimension(630, 120)); |
||||
this.setLayout(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); |
||||
} |
||||
|
||||
|
||||
public void populate(JDBCDatabaseConnection jdbcDatabase) { |
||||
DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr(); |
||||
if (dbcpAttr == null) { |
||||
dbcpAttr = new DBCPConnectionPoolAttr(); |
||||
jdbcDatabase.setDbcpAttr(dbcpAttr); |
||||
} |
||||
this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive()); |
||||
this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait()); |
||||
this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery()); |
||||
this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0); |
||||
|
||||
} |
||||
|
||||
public void update(JDBCDatabaseConnection jdbcDatabase) { |
||||
DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr(); |
||||
if (dbcpAttr == null) { |
||||
dbcpAttr = new DBCPConnectionPoolAttr(); |
||||
jdbcDatabase.setDbcpAttr(dbcpAttr); |
||||
} |
||||
dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue()); |
||||
dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue()); |
||||
dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText()); |
||||
dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return Toolkit.i18nText("Fine-Design_Basic_Advanced_Setup"); |
||||
} |
||||
|
||||
|
||||
private class JTextFieldHintListener implements FocusListener { |
||||
private SpecialUITextField textField; |
||||
|
||||
public JTextFieldHintListener(SpecialUITextField jTextField) { |
||||
this.textField = jTextField; |
||||
} |
||||
|
||||
@Override |
||||
public void focusGained(FocusEvent e) { |
||||
//获取焦点时,清空提示内容
|
||||
String temp = textField.getText(); |
||||
textField.setForeground(Color.BLACK); |
||||
textField.setTextOrigin(temp); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void focusLost(FocusEvent e) { |
||||
//失去焦点时,没有输入内容,显示提示内容
|
||||
String temp = textField.getTextOrigin(); |
||||
textField.setText(temp); |
||||
} |
||||
} |
||||
|
||||
private class SpecialUITextField extends UITextField { |
||||
|
||||
@Override |
||||
public String getText() { |
||||
String text = super.getText(); |
||||
if (isUseless(text)) { |
||||
return StringUtils.EMPTY; |
||||
} |
||||
return text; |
||||
} |
||||
|
||||
@Override |
||||
public void setText(String text) { |
||||
if (isUseless(text)) { |
||||
this.setForeground(Color.GRAY); |
||||
super.setText(Toolkit.i18nText("Fine-Design_Dbcp_Default_Query")); |
||||
} else { |
||||
this.setForeground(Color.BLACK); |
||||
super.setText(text); |
||||
} |
||||
} |
||||
|
||||
public String getTextOrigin() { |
||||
return super.getText(); |
||||
} |
||||
|
||||
public void setTextOrigin(String text) { |
||||
super.setText(text); |
||||
} |
||||
|
||||
private boolean isUseless(String text) { |
||||
return text == null || text.isEmpty() || Toolkit.i18nText("Fine-Design_Dbcp_Default_Query").equals(text); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,7 @@
|
||||
package com.fr.design.event; |
||||
|
||||
import java.awt.*; |
||||
|
||||
public interface ComponentChangeListener { |
||||
void initListener(Container changedComponent); |
||||
} |
@ -0,0 +1,6 @@
|
||||
package com.fr.design.event; |
||||
|
||||
|
||||
public interface ComponentChangeObserver { |
||||
void registerChangeListener(ComponentChangeListener uiChangeableListener); |
||||
} |
@ -1,77 +0,0 @@
|
||||
package com.fr.design.gui.icombobox; |
||||
|
||||
import com.fr.log.FineLoggerFactory; |
||||
|
||||
import javax.swing.JTree; |
||||
import javax.swing.SwingWorker; |
||||
import javax.swing.tree.TreeCellRenderer; |
||||
import java.util.concurrent.FutureTask; |
||||
|
||||
/** |
||||
* 模糊搜索前需执行完前置任务的TreeComboBox |
||||
* @author Lucian.Chen |
||||
* @version 10.0 |
||||
* Created by Lucian.Chen on 2021/4/14 |
||||
*/ |
||||
public class SearchPreTaskTreeComboBox extends FRTreeComboBox { |
||||
|
||||
/** |
||||
* 模糊搜索前任务 |
||||
*/ |
||||
private FutureTask<Void> preSearchTask; |
||||
|
||||
public SearchPreTaskTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) { |
||||
super(tree, renderer, editable); |
||||
} |
||||
|
||||
public FutureTask<Void> getPreSearchTask() { |
||||
return preSearchTask; |
||||
} |
||||
|
||||
public void setPreSearchTask(FutureTask<Void> preSearchTask) { |
||||
this.preSearchTask = preSearchTask; |
||||
} |
||||
|
||||
protected UIComboBoxEditor createEditor() { |
||||
return new SearchPreTaskComboBoxEditor(this); |
||||
} |
||||
|
||||
private class SearchPreTaskComboBoxEditor extends FrTreeSearchComboBoxEditor { |
||||
|
||||
public SearchPreTaskComboBoxEditor(FRTreeComboBox comboBox) { |
||||
super(comboBox); |
||||
} |
||||
|
||||
protected void changeHandler() { |
||||
if (isSetting()) { |
||||
return; |
||||
} |
||||
setPopupVisible(true); |
||||
new SwingWorker<Void, Void>() { |
||||
@Override |
||||
protected Void doInBackground() { |
||||
FutureTask<Void> task = getPreSearchTask(); |
||||
try { |
||||
// 确保模糊搜索前任务执行完成后,再进行模糊搜索
|
||||
if (task != null) { |
||||
task.get(); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
if (task != null) { |
||||
// 任务执行后置空,否则会被别的操作重复触发
|
||||
setPreSearchTask(null); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
// 模糊搜索
|
||||
search(); |
||||
} |
||||
}.execute(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,217 @@
|
||||
package com.fr.design.gui.icombobox; |
||||
|
||||
import com.fr.data.core.DataCoreUtils; |
||||
import com.fr.data.core.db.TableProcedure; |
||||
import com.fr.data.impl.Connection; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.data.datapane.ChoosePane; |
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.ArrayUtils; |
||||
import com.fr.stable.Filter; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.JTree; |
||||
import javax.swing.SwingWorker; |
||||
import javax.swing.tree.DefaultMutableTreeNode; |
||||
import javax.swing.tree.DefaultTreeModel; |
||||
import javax.swing.tree.TreeCellRenderer; |
||||
import javax.swing.tree.TreeNode; |
||||
import javax.swing.tree.TreePath; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.Enumeration; |
||||
|
||||
/** |
||||
* 实现模糊搜索表名的FRTreeComboBox |
||||
* FRTreeComboBox:搜索后滚动到首个匹配节点 |
||||
* SearchFRTreeComboBox:显示所有匹配的节点 |
||||
* |
||||
* @author Lucian.Chen |
||||
* @version 10.0 |
||||
* Created by Lucian.Chen on 2021/4/14 |
||||
*/ |
||||
public class TableSearchTreeComboBox extends FRTreeComboBox { |
||||
// 持有父容器,需要实时获取其他组件值
|
||||
private final ChoosePane parent; |
||||
|
||||
public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) { |
||||
super(tree, renderer); |
||||
this.parent = parent; |
||||
setUI(new TableSearchTreeComboBoxUI()); |
||||
} |
||||
|
||||
protected UIComboBoxEditor createEditor() { |
||||
return new TableSearchComboBoxEditor(this); |
||||
} |
||||
|
||||
@Override |
||||
protected String pathToString(TreePath path) { |
||||
Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); |
||||
if (obj instanceof TableProcedure) { |
||||
return ((TableProcedure) obj).getName(); |
||||
} |
||||
return super.pathToString(path); |
||||
} |
||||
|
||||
@Override |
||||
public void setSelectedItemString(String _name) { |
||||
super.setSelectedItemString(_name); |
||||
// 会因为连续两次选中的值一致,导致未触发编辑框联动
|
||||
this.getEditor().setItem(_name); |
||||
} |
||||
|
||||
/** |
||||
* 执行模糊搜索 |
||||
*/ |
||||
private void searchExecute() { |
||||
UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor(); |
||||
new SwingWorker<Void, Void>() { |
||||
@Override |
||||
protected Void doInBackground() { |
||||
processTableDataNames( |
||||
parent.getDSName(), |
||||
parent.getConnection(), |
||||
parent.getSchema(), |
||||
createFilter((String) searchEditor.getItem())); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
expandTree(); |
||||
// 输入框获取焦点
|
||||
searchEditor.getEditorComponent().requestFocus(); |
||||
} |
||||
}.execute(); |
||||
} |
||||
|
||||
private TableNameFilter createFilter(String text) { |
||||
return StringUtils.isEmpty(text) ? EMPTY_FILTER : new TableNameFilter(text); |
||||
} |
||||
|
||||
/** |
||||
* 查询数据库表,并构建节点目录 |
||||
* |
||||
* @param databaseName 数据库名 |
||||
* @param connection 数据连接 |
||||
* @param schema 模式 |
||||
* @param filter 模糊搜索过滤器 |
||||
*/ |
||||
private void processTableDataNames(String databaseName, Connection connection, String schema, TableNameFilter filter) { |
||||
if (tree == null) { |
||||
return; |
||||
} |
||||
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); |
||||
rootTreeNode.removeAllChildren(); |
||||
|
||||
if (connection == null) { |
||||
return; |
||||
} |
||||
try { |
||||
schema = StringUtils.isEmpty(schema) ? null : schema; |
||||
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(connection, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); |
||||
if (ArrayUtils.isNotEmpty(sqlTableArray)) { |
||||
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); |
||||
rootTreeNode.add(tableTreeNode); |
||||
addArrayNode(tableTreeNode, sqlTableArray, filter); |
||||
} |
||||
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(connection, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); |
||||
if (ArrayUtils.isNotEmpty(sqlViewArray)) { |
||||
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); |
||||
rootTreeNode.add(viewTreeNode); |
||||
addArrayNode(viewTreeNode, sqlViewArray, filter); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); |
||||
} |
||||
} |
||||
|
||||
private void addArrayNode(ExpandMutableTreeNode rootNode, TableProcedure[] sqlArray, TableNameFilter filter) { |
||||
if (sqlArray != null) { |
||||
for (TableProcedure procedure : sqlArray) { |
||||
if (filter.accept(procedure)) { |
||||
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(procedure); |
||||
rootNode.add(viewChildTreeNode); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 展开节点 |
||||
*/ |
||||
private void expandTree() { |
||||
((DefaultTreeModel) tree.getModel()).reload(); |
||||
// daniel 展开所有tree
|
||||
TreeNode root = (TreeNode) tree.getModel().getRoot(); |
||||
TreePath parent = new TreePath(root); |
||||
TreeNode node = (TreeNode) parent.getLastPathComponent(); |
||||
for (Enumeration e = node.children(); e.hasMoreElements(); ) { |
||||
TreeNode n = (TreeNode) e.nextElement(); |
||||
TreePath path = parent.pathByAddingChild(n); |
||||
tree.expandPath(path); |
||||
} |
||||
} |
||||
|
||||
private static final TableNameFilter EMPTY_FILTER = new TableNameFilter() { |
||||
public boolean accept(TableProcedure procedure) { |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* 表名模糊搜索实现 |
||||
*/ |
||||
private static class TableNameFilter implements Filter<TableProcedure> { |
||||
private String searchFilter; |
||||
|
||||
public TableNameFilter() { |
||||
} |
||||
|
||||
public TableNameFilter(String searchFilter) { |
||||
this.searchFilter = searchFilter.toLowerCase().trim(); |
||||
} |
||||
|
||||
// 表名匹配
|
||||
@Override |
||||
public boolean accept(TableProcedure procedure) { |
||||
return procedure.getName().toLowerCase().contains(searchFilter); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 重写FRTreeComboBoxUI,实现点击下拉时触发模糊搜索 |
||||
*/ |
||||
private class TableSearchTreeComboBoxUI extends FRTreeComboBoxUI { |
||||
|
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
searchExecute(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 重写输入框编辑器,实现输入框模糊搜索逻辑 |
||||
*/ |
||||
private class TableSearchComboBoxEditor extends FrTreeSearchComboBoxEditor { |
||||
|
||||
public TableSearchComboBoxEditor(FRTreeComboBox comboBox) { |
||||
super(comboBox); |
||||
} |
||||
|
||||
@Override |
||||
protected void changeHandler() { |
||||
if (isSetting()) { |
||||
return; |
||||
} |
||||
setPopupVisible(true); |
||||
this.item = textField.getText(); |
||||
searchExecute(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,122 @@
|
||||
package com.fr.design.lock; |
||||
|
||||
import com.fr.design.file.TemplateTreePane; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.DesignSizeI18nManager; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.DesignerFrameFileDealerPane; |
||||
import com.fr.design.utils.TemplateUtils; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.file.FileNodeFILE; |
||||
import com.fr.file.filetree.FileNode; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.StableUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
import com.fr.workspace.base.UserInfo; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.time.LocalDateTime; |
||||
import java.time.format.DateTimeFormatter; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2021/12/2 |
||||
*/ |
||||
public class LockInfoDialog extends JDialog { |
||||
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); |
||||
|
||||
public LockInfoDialog(UserInfo userInfo) { |
||||
super(DesignerContext.getDesignerFrame()); |
||||
JPanel panel = new JPanel(new BorderLayout()); |
||||
panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); |
||||
panel.add(createContentPane(userInfo), BorderLayout.CENTER); |
||||
panel.add(createControlPane(), BorderLayout.SOUTH); |
||||
this.getContentPane().add(panel); |
||||
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Title_Hint")); |
||||
this.setSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.lock.LockInfoDialog")); |
||||
this.setResizable(false); |
||||
this.setModal(true); |
||||
GUICoreUtils.centerWindow(this); |
||||
this.setVisible(true); |
||||
} |
||||
|
||||
private JPanel createContentPane(UserInfo userInfo) { |
||||
JPanel contentPanel = new JPanel(new BorderLayout()); |
||||
contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); |
||||
JPanel messagePane = new JPanel(new BorderLayout(13, 0)); |
||||
UILabel iconLabel = new UILabel(IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png")); |
||||
iconLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); |
||||
messagePane.add(iconLabel, BorderLayout.WEST); |
||||
UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Template_Lock_And_SaveAs_Tip")); |
||||
tipLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||
messagePane.add(tipLabel, BorderLayout.CENTER); |
||||
contentPanel.add(messagePane, BorderLayout.NORTH); |
||||
JPanel detailInfoPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); |
||||
detailInfoPane.setBorder(BorderFactory.createEmptyBorder(0, 45, 0,0)); |
||||
if (userInfo != null && StringUtils.isNotEmpty(userInfo.getUserName())) { |
||||
UILabel label = createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Holder", userInfo.getUserName())); |
||||
label .setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||
detailInfoPane.add(label); |
||||
} |
||||
if (userInfo != null && StringUtils.isNotEmpty(userInfo.getIp())) { |
||||
detailInfoPane.add(createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Holder_Ip", userInfo.getIp()) )); |
||||
} |
||||
detailInfoPane.add(createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Get_Time", FORMATTER.format(LocalDateTime.now())))); |
||||
contentPanel.add(detailInfoPane, BorderLayout.CENTER); |
||||
return contentPanel; |
||||
} |
||||
|
||||
private UILabel createLabel(String text) { |
||||
UILabel label = new UILabel(text); |
||||
label.setForeground(Color.GRAY); |
||||
label.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0)); |
||||
return label; |
||||
} |
||||
|
||||
private JPanel createControlPane() { |
||||
JPanel controlPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5)); |
||||
controlPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0,5)); |
||||
UIButton saveAsButton = new UIButton(Toolkit.i18nText("Fine_Design_Template_Lock_Save_As")); |
||||
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")); |
||||
saveAsButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
dispose(); |
||||
FileNode node = TemplateTreePane.getInstance().getFileNode(); |
||||
if (node == null) { |
||||
return; |
||||
} |
||||
final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getFilePath()); |
||||
TemplateUtils.createAndOpenTemplate(Toolkit.i18nText("Fine_Design_Template_Lock_Copy"), new FileNodeFILE(new FileNode(selectedFilePath, false)), true); |
||||
} |
||||
}); |
||||
cancelButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
dispose(); |
||||
} |
||||
}); |
||||
controlPane.add(saveAsButton); |
||||
controlPane.add(cancelButton); |
||||
return controlPane; |
||||
} |
||||
|
||||
|
||||
public static void show(UserInfo userInfo) { |
||||
DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode()); |
||||
new LockInfoDialog(userInfo); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,23 @@
|
||||
package com.fr.design.lock; |
||||
|
||||
import com.fr.report.lock.DefaultLockInfoOperator; |
||||
import com.fr.report.lock.LockInfoOperator; |
||||
import com.fr.start.server.FineEmbedServer; |
||||
import com.fr.workspace.WorkContext; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2021/12/8 |
||||
*/ |
||||
public class LockInfoUtils { |
||||
|
||||
public static boolean isCompatibleOperator() { |
||||
LockInfoOperator lockInfoOperator = WorkContext.getCurrent().get(LockInfoOperator.class); |
||||
return lockInfoOperator instanceof DefaultLockInfoOperator; |
||||
} |
||||
|
||||
public static boolean unableGetLockInfo() { |
||||
return WorkContext.getCurrent().isLocal() && !FineEmbedServer.isRunning(); |
||||
} |
||||
} |
@ -0,0 +1,190 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.design.file.HistoryTemplateListCache; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.DesignSizeI18nManager; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.guide.base.GuideView; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.workspace.WorkContext; |
||||
import com.fr.report.lock.LockInfoOperator; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Container; |
||||
import java.awt.Dimension; |
||||
import java.awt.Font; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.LayoutManager; |
||||
import java.awt.RenderingHints; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import javax.swing.ImageIcon; |
||||
import javax.swing.JButton; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JFrame; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingWorker; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2021/12/6 |
||||
*/ |
||||
public class ForbiddenPane extends JPanel { |
||||
|
||||
private static final ImageIcon LOCK_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/lock_template.png")); |
||||
private static final Color TIP_COLOR = new Color(108, 174, 235); |
||||
private static final Color BUTTON_COLOR = new Color(63, 155, 249); |
||||
private static final int Y_GAP = 10; |
||||
private static final int X_GAP = 10; |
||||
private static final int ARC = 4; |
||||
|
||||
private final UILabel lockLabel; |
||||
private final UILabel tipLabel; |
||||
private final JButton refreshButton; |
||||
|
||||
public ForbiddenPane() { |
||||
|
||||
setLayout(new LayoutManager() { |
||||
|
||||
@Override |
||||
public void removeLayoutComponent(Component comp) { |
||||
} |
||||
|
||||
@Override |
||||
public Dimension preferredLayoutSize(Container parent) { |
||||
return parent.getPreferredSize(); |
||||
} |
||||
|
||||
@Override |
||||
public Dimension minimumLayoutSize(Container parent) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void layoutContainer(Container parent) { |
||||
int width = parent.getParent().getWidth(); |
||||
int height = parent.getParent().getHeight(); |
||||
int lockLabelWidth = lockLabel.getPreferredSize().width; |
||||
int lockLabelHeight = lockLabel.getPreferredSize().height; |
||||
int lockLabelX = (width - lockLabelWidth) / 2; |
||||
int lockLabelY = (height - lockLabelHeight) / 2; |
||||
int tipLabelWidth = tipLabel.getPreferredSize().width; |
||||
int tipLabelHeight = tipLabel.getPreferredSize().height; |
||||
int tipLabelX = (width - tipLabelWidth) / 2 + X_GAP; |
||||
int tipLabelY = lockLabelY + lockLabelHeight; |
||||
int refreshButtonWidth = refreshButton.getPreferredSize().width; |
||||
int refreshButtonHeight = refreshButton.getPreferredSize().height; |
||||
int refreshButtonX = (width - refreshButtonWidth) / 2 + X_GAP; |
||||
int refreshButtonY = tipLabelY + refreshButtonHeight + Y_GAP; |
||||
lockLabel.setBounds(lockLabelX, lockLabelY, lockLabelWidth, lockLabelHeight); |
||||
tipLabel.setBounds(tipLabelX, tipLabelY, tipLabelWidth, tipLabelHeight); |
||||
refreshButton.setBounds(refreshButtonX, refreshButtonY, refreshButtonWidth, refreshButtonHeight); |
||||
} |
||||
|
||||
@Override |
||||
public void addLayoutComponent(String name, Component comp) { |
||||
} |
||||
}); |
||||
setBackground(Color.WHITE); |
||||
lockLabel = new UILabel(LOCK_ICON); |
||||
tipLabel = new UILabel(Toolkit.i18nText("Fine_Design_Template_Has_Been_Locked_Tip")); |
||||
Font labelFont = tipLabel.getFont(); |
||||
tipLabel.setFont(new Font(labelFont.getName(), labelFont.getStyle(), 14)); |
||||
tipLabel.setForeground(TIP_COLOR); |
||||
refreshButton = new JButton(Toolkit.i18nText("Fine-Design_Basic_Refresh")) { |
||||
@Override |
||||
public void paintComponent(Graphics g) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||
g2d.setColor(BUTTON_COLOR); |
||||
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), ARC, ARC); |
||||
super.paintComponent(g2d); |
||||
} |
||||
}; |
||||
refreshButton.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.ForbiddenPane.refreshButton")); |
||||
refreshButton.setForeground(Color.WHITE); |
||||
refreshButton.setBorderPainted(false); |
||||
refreshButton.setContentAreaFilled(false); |
||||
refreshButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
final JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
if (template == null) { |
||||
return; |
||||
} |
||||
// 展示下画面
|
||||
LoadingDialog loadingDialog = new LoadingDialog(); |
||||
loadingDialog.showDialog(); |
||||
new SwingWorker<Boolean, Void>(){ |
||||
|
||||
@Override |
||||
protected Boolean doInBackground() throws Exception { |
||||
return WorkContext.getCurrent().get(LockInfoOperator.class).isTplLocked(template.getEditingFILE().getPath()); |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
boolean unLocked; |
||||
loadingDialog.hideDialog(); |
||||
try { |
||||
unLocked = !get(); |
||||
if (unLocked) { |
||||
template.whenClose(); |
||||
JTemplate<?, ?> newTemplate = JTemplateFactory.createJTemplate(template.getEditingFILE()); |
||||
HistoryTemplateListCache.getInstance().replaceCurrentEditingTemplate(newTemplate); |
||||
DesignerContext.getDesignerFrame().addAndActivateJTemplate(newTemplate); |
||||
} |
||||
} catch (Exception e) { |
||||
loadingDialog.hideDialog(); |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
}.execute(); |
||||
} |
||||
}); |
||||
add(lockLabel); |
||||
add(tipLabel); |
||||
add(refreshButton); |
||||
} |
||||
} |
||||
|
||||
class LoadingDialog extends JDialog { |
||||
|
||||
private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/refreh_icon.png")); |
||||
|
||||
private GuideView guideView; |
||||
|
||||
public LoadingDialog() { |
||||
super(DesignerContext.getDesignerFrame()); |
||||
setLayout(new BorderLayout()); |
||||
this.getContentPane().setBackground(Color.WHITE); |
||||
this.setResizable(false); |
||||
this.setUndecorated(true); |
||||
this.setAlwaysOnTop(true); |
||||
this.setModal(false); |
||||
this.setSize(new Dimension(400, 100)); |
||||
this.add(new UILabel(LOADING_ICON, UILabel.CENTER), BorderLayout.NORTH); |
||||
this.add(new UILabel(Toolkit.i18nText(Toolkit.i18nText("Fine_Design_Template_Refresh")), UILabel.CENTER), BorderLayout.CENTER); |
||||
GUICoreUtils.centerWindow(this); |
||||
} |
||||
|
||||
public void showDialog() { |
||||
DesignerContext.getDesignerFrame().setExtendedState(JFrame.MAXIMIZED_BOTH); |
||||
guideView = new GuideView(DesignerContext.getDesignerFrame()); |
||||
GUICoreUtils.centerWindow(DesignerContext.getDesignerFrame(), guideView); |
||||
guideView.setBounds(DesignerContext.getDesignerFrame().getBounds()); |
||||
guideView.setVisible(true); |
||||
this.setVisible(true); |
||||
} |
||||
|
||||
public void hideDialog() { |
||||
this.dispose(); |
||||
guideView.dismissGuide(); |
||||
} |
||||
|
||||
} |
@ -1,4 +1,4 @@
|
||||
package com.fr.design.fit; |
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.stable.Constants; |
||||
import com.fr.stable.unit.LEN_UNIT; |
@ -1,4 +1,4 @@
|
||||
package com.fr.design.fit; |
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.design.fun.impl.AbstractReportLengthUNITProvider; |
||||
import com.fr.stable.unit.UNIT; |
@ -0,0 +1,17 @@
|
||||
package com.fr.design.mainframe.theme; |
||||
|
||||
import com.fr.workspace.WorkContext; |
||||
import com.fr.workspace.server.theme.SupportThemedCellInnerBorderFeature; |
||||
import com.fr.workspace.server.theme.ThemedCellBorderFeature; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/11/26 |
||||
*/ |
||||
public class ThemedFeatureController { |
||||
public static boolean isCellStyleSupportInnerBorder() { |
||||
ThemedCellBorderFeature controller = WorkContext.getCurrent().get(ThemedCellBorderFeature.class); |
||||
return controller instanceof SupportThemedCellInnerBorderFeature; |
||||
} |
||||
} |
@ -0,0 +1,135 @@
|
||||
package com.fr.design.utils; |
||||
|
||||
import com.fr.base.extension.FileExtension; |
||||
import com.fr.base.io.BaseBook; |
||||
import com.fr.design.file.HistoryTemplateListCache; |
||||
import com.fr.design.file.TemplateTreePane; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.design.worker.save.SaveFailureHandler; |
||||
import com.fr.file.FILE; |
||||
import com.fr.file.FILEChooserPane; |
||||
import com.fr.file.filter.ChooseFileFilter; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.ArrayUtils; |
||||
import com.fr.stable.CoreConstants; |
||||
import com.fr.stable.ProductConstants; |
||||
import com.fr.workspace.WorkContext; |
||||
import com.fr.workspace.server.lock.TplOperator; |
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.OutputStream; |
||||
import javax.swing.SwingWorker; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2021/12/5 |
||||
*/ |
||||
public class TemplateUtils { |
||||
|
||||
public static void createAndOpenTemplate(String prefix, FILE file, boolean needOpen) { |
||||
String fileName = file.getName(); |
||||
String oldPath = file.getPath(); |
||||
int indexOfLastDot = fileName.lastIndexOf(CoreConstants.DOT); |
||||
if (indexOfLastDot < 0) { |
||||
return; |
||||
} |
||||
String suffix = fileName.substring(indexOfLastDot + 1); |
||||
FILEChooserPane fileChooserPane = FILEChooserPane.getInstance(true, true); |
||||
fileChooserPane.setFileNameTextField(prefix + fileName, suffix); |
||||
FileExtension fileExtension = FileExtension.parse(suffix); |
||||
fileChooserPane.addChooseFILEFilter(new ChooseFileFilter(fileExtension, ProductConstants.APP_NAME + Toolkit.i18nText("Fine-Design_Report_Template_File"))); |
||||
fileChooserPane.disableFileNameTextFiled(); |
||||
int result = fileChooserPane.showSaveDialog(DesignerContext.getDesignerFrame(), suffix); |
||||
fileChooserPane.enableFileNameTextFiled(); |
||||
|
||||
if (isCancel(result)) { |
||||
return; |
||||
} |
||||
|
||||
if (isOk(result)) { |
||||
file = fileChooserPane.getSelectedFILE(); |
||||
_createAndOpenTemplate(file, oldPath, needOpen); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
private static void _createAndOpenTemplate(FILE file, String oldPath, boolean needOpen){ |
||||
new SwingWorker<Void, Void>() { |
||||
|
||||
@Override |
||||
protected Void doInBackground() throws Exception { |
||||
byte[] content = new byte[0]; |
||||
if (!needOpen) { |
||||
// 从当前编辑模板中生成备份文件
|
||||
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
||||
BaseBook target = template.getTarget(); |
||||
if (target != null) { |
||||
target.export(outputStream); |
||||
content = outputStream.toByteArray(); |
||||
} |
||||
} else { |
||||
content = WorkContext.getWorkResource().readFully(oldPath); |
||||
} |
||||
if (ArrayUtils.isEmpty(content)) { |
||||
throw new Exception(oldPath + " content is empty" ); |
||||
} |
||||
OutputStream out = null; |
||||
try { |
||||
// 加锁
|
||||
WorkContext.getCurrent().get(TplOperator.class).saveAs(file.getPath()); |
||||
out = file.asOutputStream(); |
||||
out.write(content); |
||||
} finally { |
||||
try { |
||||
if (out != null) { |
||||
out.close(); |
||||
} |
||||
} finally { |
||||
// 解锁
|
||||
WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(file.getPath()); |
||||
} |
||||
|
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
try { |
||||
get(); |
||||
if (needOpen) { |
||||
DesignerContext.getDesignerFrame().openTemplate(file); |
||||
} |
||||
// 备份成功刷新下目录树 展示出来备份的模板
|
||||
TemplateTreePane.getInstance().refresh(); |
||||
} catch (Exception e) { |
||||
SaveFailureHandler.getInstance().process(e); |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
}.execute(); |
||||
|
||||
} |
||||
|
||||
private static boolean isCancel(int result) { |
||||
return result == FILEChooserPane.CANCEL_OPTION || |
||||
result == FILEChooserPane.JOPTIONPANE_CANCEL_OPTION; |
||||
} |
||||
|
||||
private static boolean isOk(int result) { |
||||
return result == FILEChooserPane.JOPTIONPANE_OK_OPTION || |
||||
result == FILEChooserPane.OK_OPTION; |
||||
} |
||||
|
||||
public static String createLockeTemplatedName(JTemplate<?, ?> template, String name) { |
||||
int index = name.lastIndexOf(CoreConstants.DOT); |
||||
if (index < 0 || !template.isForbidden()) { |
||||
return name; |
||||
} |
||||
return name.substring(0, index) + Toolkit.i18nText("Fine_Design_Template_Has_Been_Locked") + name.substring(index); |
||||
} |
||||
} |
@ -0,0 +1,122 @@
|
||||
package com.fr.design.worker.save; |
||||
|
||||
import com.fr.common.exception.ThrowableHandler; |
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.file.HistoryTemplateListCache; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.design.ui.util.UIUtil; |
||||
import com.fr.design.utils.TemplateUtils; |
||||
import com.fr.file.FileNodeFILE; |
||||
import com.fr.file.filetree.FileNode; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.report.UnLockedException; |
||||
import com.fr.workspace.exception.DiskSpaceFullException; |
||||
import com.fr.report.InconsistentLockException; |
||||
import java.awt.Frame; |
||||
import javax.swing.JOptionPane; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2021/12/7 |
||||
*/ |
||||
public class SaveFailureHandler implements ThrowableHandler { |
||||
|
||||
private static final SaveFailureHandler INSTANCE = new SaveFailureHandler(); |
||||
|
||||
public static SaveFailureHandler getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
@Override |
||||
public boolean process(Throwable e) { |
||||
UIUtil.invokeLaterIfNeeded(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
for (Handler handler : Handler.values()) { |
||||
try { |
||||
if (handler.process(e)) { |
||||
break; |
||||
} |
||||
} catch (Exception ignored) { |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
return true; |
||||
} |
||||
|
||||
public enum Handler implements ThrowableHandler { |
||||
|
||||
FullDisk { |
||||
@Override |
||||
public boolean process(Throwable e) { |
||||
if (e.getCause() instanceof DiskSpaceFullException |
||||
|| e instanceof DiskSpaceFullException |
||||
|| e.getCause().getCause() instanceof DiskSpaceFullException) { |
||||
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), |
||||
Toolkit.i18nText("Fine_Design_Template_Save_Failed_By_Full_Disk"), |
||||
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
||||
JOptionPane.WARNING_MESSAGE, |
||||
IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png")); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
}, |
||||
UnLocked { |
||||
@Override |
||||
public boolean process(Throwable e) { |
||||
if (e.getCause() instanceof UnLockedException || e instanceof UnLockedException) { |
||||
processByBack(Toolkit.i18nText("Fine_Design_Template_Has_Been_UnLocked")); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
}, |
||||
|
||||
InconsistentLock { |
||||
@Override |
||||
public boolean process(Throwable e) { |
||||
if (e.getCause() instanceof InconsistentLockException || e instanceof InconsistentLockException) { |
||||
processByBack(Toolkit.i18nText("Fine_Design_Template_Save_Failed_By_Lock_Inconsistency")); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
}, |
||||
|
||||
Other { |
||||
@Override |
||||
public boolean process(Throwable e) { |
||||
boolean minimized = (DesignerContext.getDesignerFrame().getExtendedState() & Frame.ICONIFIED ) != 0; |
||||
FineJOptionPane.showMessageDialog( |
||||
minimized ? null : DesignerContext.getDesignerFrame(), |
||||
Toolkit.i18nText("Fine-Design-Basic_Save_Failure"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), |
||||
JOptionPane.ERROR_MESSAGE); |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
|
||||
protected void processByBack(String tip) { |
||||
int option = FineJOptionPane.showOptionDialog(DesignerContext.getDesignerFrame(), |
||||
tip, |
||||
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
||||
JOptionPane.YES_NO_OPTION, |
||||
JOptionPane.WARNING_MESSAGE, |
||||
IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"), |
||||
new Object[] {Toolkit.i18nText("Fine_Design_Template_SaveAs_Backup"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null); |
||||
if (option == JOptionPane.YES_OPTION) { |
||||
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
if (template != null) { |
||||
TemplateUtils.createAndOpenTemplate(Toolkit.i18nText("Fine_Design_Template_Backup"), new FileNodeFILE(new FileNode(template.getPath(), false)), false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 655 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 1.5 KiB |