* commit '9e60a27c9c34d1ad2389191e05489250ee2bec34': (94 commits) 合并冲突 REPORT-64601 公式编辑器首次进入的时候光标位置不正确 1.放到swing执行队列队尾。 REPORT-64601 公式编辑器首次进入的时候光标位置不正确 1.修改代码。 REPORT-64601 公式编辑器首次进入的时候光标位置不正确 1.加载完公式编辑器后异步请求一下光标; REPORT-64451 最新官网jar包,11.0设计器切换成英文,新建决策报表异常 REPORT-64811 保持设计器商城下载reu文件名中的版本信息 REPORT-64506 && REPORT-64457 && REPORT-64456 && REPORT-64425 && REPORT-64422 REPORT-64702【frm设计器界面修改】新&旧模式下,新拖入的报表块,组件尺寸是250*150,进入报表块编辑,悬浮虚线看到的尺寸也是250*150,但退出编辑,拖拽调整报表块尺寸时,虚线范围比刚才看到的大了 REPORT-64022:面板添加一个提示 REPORT-64412 连续选中两次同一选项,编辑框值不对 CHART-21877 fix:fvs.cpt 批量设置单元格背景颜色后 单元格字体是黑色 REPORT-64527 && REPORT-64525 && REPORT-64489 && REPORT-64485 && REPORT-64466 && REPORT-64463 && REPORT-64462 && REPORT-64460 CHART-22076 fix:fvs.cpt 单元格设置超链删除超链 文本白色 REPORT-64606 插件修改active逻辑重构-插件校验未通过,没有被禁用 【问题原因】未适配插件管理里的插件运行状态 【改动思路】1. 传递正确的插件管理里请求的插件运行状态;2. 当isActive与isRunning不匹配时,保证可以正确的启用或禁用插件 【review建议】无 REPORT-55241:修改没有开启固定分页时固定分页的数值 REPORT-55241:修改一下代码格式 REPORT-64642 【主题边框】左侧预览图中单元格设置逻辑调整 REPORT-63808 【主题优化】格式单独拿出来以后,发现数据列的弹窗配置中没有格式项 REPORT-55241:添加报表引擎属性埋点 REPORT-64656 设计器操作,双击已打开的模板,不会定位到对应模板 ...bugfix/11.0
@ -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,104 @@ |
|||||||
|
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.report.cell.TemplateCellElement; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.GridLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/3 |
||||||
|
*/ |
||||||
|
public class CellRectangleStylePreviewPane extends JPanel { |
||||||
|
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) { |
||||||
|
setLayout(new GridLayout(2, 2)); |
||||||
|
|
||||||
|
for (int r = 0; r < ROW_COUNT; r++) { |
||||||
|
for (int c = 0; c < COLUMN_COUNT; c++) { |
||||||
|
CellStylePreviewPane pane = new CellStylePreviewPane(); |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
@ -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,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,121 @@ |
|||||||
|
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.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(400, 160); |
||||||
|
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,189 @@ |
|||||||
|
package com.fr.design.mainframe; |
||||||
|
|
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
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(new Dimension(68, 24)); |
||||||
|
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.Constants; |
||||||
import com.fr.stable.unit.LEN_UNIT; |
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.design.fun.impl.AbstractReportLengthUNITProvider; |
||||||
import com.fr.stable.unit.UNIT; |
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,113 @@ |
|||||||
|
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.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) { |
||||||
|
for (Handler handler : Handler.values()) { |
||||||
|
if (handler.process(e)) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
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: 2.1 KiB |
After Width: | Height: | Size: 2.1 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 |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 175 B |
After Width: | Height: | Size: 166 B |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 210 B |
After Width: | Height: | Size: 208 B |
@ -1,115 +0,0 @@ |
|||||||
package com.fr.design.actions; |
|
||||||
|
|
||||||
|
|
||||||
import com.fr.base.iofile.attr.MobileOnlyTemplateAttrMark; |
|
||||||
import com.fr.design.designer.creator.XLayoutContainer; |
|
||||||
import com.fr.design.designer.creator.XWAbsoluteBodyLayout; |
|
||||||
import com.fr.design.designer.creator.XWFitLayout; |
|
||||||
import com.fr.design.dialog.BasicDialog; |
|
||||||
import com.fr.design.dialog.DialogActionAdapter; |
|
||||||
import com.fr.design.fit.NewJForm; |
|
||||||
import com.fr.design.fit.common.AdaptiveSwitchUtil; |
|
||||||
import com.fr.design.fit.common.TemplateTool; |
|
||||||
import com.fr.design.form.mobile.FormMobileAttrPane; |
|
||||||
import com.fr.design.mainframe.DesignerContext; |
|
||||||
import com.fr.design.mainframe.FormArea; |
|
||||||
import com.fr.design.mainframe.FormDesigner; |
|
||||||
import com.fr.design.mainframe.JForm; |
|
||||||
import com.fr.design.mainframe.WidgetPropertyPane; |
|
||||||
import com.fr.file.FILE; |
|
||||||
import com.fr.form.main.Form; |
|
||||||
import com.fr.form.main.mobile.FormMobileAttr; |
|
||||||
import com.fr.record.analyzer.EnableMetrics; |
|
||||||
import com.fr.stable.StringUtils; |
|
||||||
|
|
||||||
import java.awt.event.ActionEvent; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by fanglei on 2016/11/14. |
|
||||||
*/ |
|
||||||
@EnableMetrics |
|
||||||
public class NewFormMobileAttrAction extends FormMobileAttrAction { |
|
||||||
|
|
||||||
public NewFormMobileAttrAction(JForm jf) { |
|
||||||
super(jf); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 执行动作 |
|
||||||
* |
|
||||||
* @return 是否执行成功 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void actionPerformed(ActionEvent e) { |
|
||||||
final JForm jf = getEditingComponent(); |
|
||||||
if (jf == null) { |
|
||||||
return; |
|
||||||
} |
|
||||||
final Form formTpl = jf.getTarget(); |
|
||||||
FormMobileAttr mobileAttr = formTpl.getFormMobileAttr(); |
|
||||||
|
|
||||||
final FormMobileAttrPane mobileAttrPane = new FormMobileAttrPane(); |
|
||||||
mobileAttrPane.populateBean(mobileAttr); |
|
||||||
|
|
||||||
final boolean oldMobileOnly = mobileAttr.isMobileOnly(); |
|
||||||
final boolean oldAdaptive = mobileAttr.isAdaptivePropertyAutoMatch(); |
|
||||||
BasicDialog dialog = mobileAttrPane.showWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { |
|
||||||
@Override |
|
||||||
public void doOk() { |
|
||||||
FormMobileAttr formMobileAttr = mobileAttrPane.updateBean(); |
|
||||||
if (formMobileAttr.isMobileOnly() && jf.getTarget().getAttrMark(MobileOnlyTemplateAttrMark.XML_TAG) == null) { |
|
||||||
// 如果是老模板,选择手机专属之后需要另存为
|
|
||||||
FILE editingFILE = jf.getEditingFILE(); |
|
||||||
if (editingFILE != null && editingFILE.exists()) { |
|
||||||
String fileName = editingFILE.getName().substring(0, editingFILE.getName().length() - jf.suffix().length()) + "_mobile"; |
|
||||||
if (!jf.saveAsTemplate(true, fileName)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
// 放到后面。如果提前 return 了,则仍然处于未设置状态,不要添加
|
|
||||||
jf.getTarget().addAttrMark(new MobileOnlyTemplateAttrMark()); |
|
||||||
} |
|
||||||
// 设置移动端属性并刷新界面
|
|
||||||
formTpl.setFormMobileAttr(formMobileAttr); // 会调整 body 的自适应布局,放到最后
|
|
||||||
boolean changeSize = (!oldMobileOnly && formMobileAttr.isMobileOnly()) || (oldMobileOnly && !formMobileAttr.isMobileOnly()); |
|
||||||
if (changeSize) { |
|
||||||
((FormArea)jf.getFormDesign().getParent()).onMobileAttrModified(); |
|
||||||
} |
|
||||||
//改变布局为自适应布局,只在移动端属性设置保存后改变一次
|
|
||||||
boolean changeLayout = !oldAdaptive && formMobileAttr.isAdaptivePropertyAutoMatch(); |
|
||||||
if (changeLayout) { |
|
||||||
jf.getFormDesign().getSelectionModel().setSelectedCreator(jf.getFormDesign().getRootComponent()); |
|
||||||
doChangeBodyLayout(); |
|
||||||
WidgetPropertyPane.getInstance().refreshDockingView(); |
|
||||||
} |
|
||||||
jf.fireTargetModified(); |
|
||||||
FILE editingFILE = jf.getEditingFILE(); |
|
||||||
if(editingFILE != null && editingFILE.exists()){ |
|
||||||
JForm jForm = getEditingComponent(); |
|
||||||
TemplateTool.saveForm(jForm); |
|
||||||
if (jForm instanceof NewJForm) { |
|
||||||
AdaptiveSwitchUtil.switch2OldUI(); |
|
||||||
} |
|
||||||
}else { |
|
||||||
AdaptiveSwitchUtil.switch2OldUIMode(); |
|
||||||
NewJForm mobileJForm = new NewJForm(jf.getTarget(), jf.getEditingFILE()); |
|
||||||
//设置临时的id,和新建的模板区分
|
|
||||||
mobileJForm.getTarget().setTemplateID(StringUtils.EMPTY); |
|
||||||
TemplateTool.resetTabPaneEditingTemplate(mobileJForm); |
|
||||||
TemplateTool.activeAndResizeTemplate(mobileJForm); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
dialog.setVisible(true); |
|
||||||
} |
|
||||||
|
|
||||||
private void doChangeBodyLayout(){ |
|
||||||
FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); |
|
||||||
XLayoutContainer rootLayout = formDesigner.getRootComponent(); |
|
||||||
if (rootLayout.getComponentCount() == 1 && rootLayout.getXCreator(0).acceptType(XWAbsoluteBodyLayout.class)) { |
|
||||||
rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(0); |
|
||||||
} |
|
||||||
((XWFitLayout)formDesigner.getRootComponent()).switch2FitBodyLayout(rootLayout); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
@ -0,0 +1,20 @@ |
|||||||
|
package com.fr.design.fit.common; |
||||||
|
|
||||||
|
import com.fr.base.DefaultAutoChangeLine; |
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.stable.unit.UNIT; |
||||||
|
|
||||||
|
import java.awt.Font; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class NewUIModeAutoChangeLine extends DefaultAutoChangeLine { |
||||||
|
@Override |
||||||
|
public List<String> textAutoChangeLine(String text, Font font, Style style, UNIT unitWidth, int resolution) { |
||||||
|
return autoChangeLine(text, font, style, unitWidth, resolution); |
||||||
|
} |
||||||
|
|
||||||
|
protected double calculateShowWidth(double paintWidth, Style style, int resolution) { |
||||||
|
return paintWidth - style.getPaddingLeft() - style.getPaddingRight() - style.getBorderLeftWidth(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,69 @@ |
|||||||
|
package com.fr.design.fit.common; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.base.DefaultRotationTextDrawProvider; |
||||||
|
import com.fr.base.GraphHelper; |
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.design.mainframe.PX; |
||||||
|
import com.fr.stable.Constants; |
||||||
|
|
||||||
|
import java.awt.Font; |
||||||
|
import java.awt.FontMetrics; |
||||||
|
import java.awt.Graphics2D; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class NewUIModeRotationDraw extends DefaultRotationTextDrawProvider { |
||||||
|
@Override |
||||||
|
public void drawRotationText(Graphics2D g2d, String text, Style style, Font rfont, int width, int height, int horizontalAlignment, int resolution) { |
||||||
|
FontMetrics cellFM = GraphHelper.getFontMetrics(rfont); |
||||||
|
List lineTextList = BaseUtils.getLineTextList(text, style, rfont, height, width, resolution, new NewUIModeAutoChangeLine()); |
||||||
|
drawRotationText(g2d, lineTextList, style, cellFM, width, height, horizontalAlignment, resolution); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected int calculateTextWidth(int width, Style style) { |
||||||
|
return width - style.getPaddingRight(); |
||||||
|
} |
||||||
|
|
||||||
|
protected double calculateTextX(Style style, int width, int textWidth, int horizontalAlignment, int resolution) { |
||||||
|
double textX = padding2PixExcludeRight(style.getPaddingLeft(), resolution); |
||||||
|
if (horizontalAlignment == Constants.CENTER) { |
||||||
|
textX += (width - textWidth - textX) / 2f; |
||||||
|
} else if (horizontalAlignment == Constants.RIGHT) { |
||||||
|
textX = width - style.getPaddingRight() - textWidth; |
||||||
|
} |
||||||
|
return textX; |
||||||
|
} |
||||||
|
|
||||||
|
protected int toPXWithResolution(double pt, int resolution) { |
||||||
|
return (int) PX.toPixWithResolution(pt, resolution); |
||||||
|
} |
||||||
|
|
||||||
|
protected double padding2PixExcludeRight(int padding, int resolution) { |
||||||
|
return PX.toPixWithResolution(padding, resolution); |
||||||
|
} |
||||||
|
|
||||||
|
protected int calculateTextY(Style style, int height, int textHeight, int textAscent, List lineTextList, int resolution) { |
||||||
|
// 计算Y的高度.
|
||||||
|
int textY = 0; |
||||||
|
int textAllHeight = textHeight * lineTextList.size(); |
||||||
|
double spacingBefore = toPXWithResolution(style.getSpacingBefore(), resolution); |
||||||
|
double spacingAfter = toPXWithResolution(style.getSpacingAfter(), resolution); |
||||||
|
double lineSpacing = toPXWithResolution(style.getLineSpacing(), resolution); |
||||||
|
textAllHeight += spacingBefore + spacingAfter + lineSpacing * lineTextList.size(); |
||||||
|
if (style.getVerticalAlignment() == Constants.TOP) { |
||||||
|
} else if (style.getVerticalAlignment() == Constants.CENTER) { |
||||||
|
if (height > textAllHeight) {// 如果所有文本的高度小于当前可以绘区域的高度,就从0开始画字符.
|
||||||
|
textY = (height - textAllHeight) / 2; |
||||||
|
} |
||||||
|
} else if (style.getVerticalAlignment() == Constants.BOTTOM) { |
||||||
|
if (height > textAllHeight) { |
||||||
|
textY = height - textAllHeight; |
||||||
|
} |
||||||
|
} |
||||||
|
textY += textAscent;// 在绘画的时候,必须添加Ascent的高度.
|
||||||
|
textY += spacingBefore + lineSpacing;//james:加上"段前间距"+“行间距”
|
||||||
|
return textY; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,835 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. |
|
||||||
*/ |
|
||||||
package com.fr.design.fit.common; |
|
||||||
|
|
||||||
import com.fr.base.AutoChangeLineAndDrawManager; |
|
||||||
import com.fr.base.BaseFormula; |
|
||||||
import com.fr.base.BaseUtils; |
|
||||||
import com.fr.base.GraphHelper; |
|
||||||
import com.fr.base.ImageProvider; |
|
||||||
import com.fr.base.Painter; |
|
||||||
import com.fr.base.Style; |
|
||||||
import com.fr.base.Utils; |
|
||||||
import com.fr.base.background.ColorBackground; |
|
||||||
import com.fr.base.chart.BaseChartCollection; |
|
||||||
import com.fr.base.chart.result.WebChartIDInfo; |
|
||||||
import com.fr.code.BarcodeImpl; |
|
||||||
import com.fr.code.bar.BarcodeException; |
|
||||||
import com.fr.code.bar.core.BarCodeUtils; |
|
||||||
import com.fr.code.bar.core.BarcodeAttr; |
|
||||||
import com.fr.data.DataUtils; |
|
||||||
import com.fr.data.PresentationType; |
|
||||||
import com.fr.data.condition.ListCondition; |
|
||||||
import com.fr.file.ResultChangeWhenExport; |
|
||||||
import com.fr.form.ui.Widget; |
|
||||||
import com.fr.general.Background; |
|
||||||
import com.fr.general.ComparatorUtils; |
|
||||||
import com.fr.general.FRFont; |
|
||||||
import com.fr.general.ImageWithSuffix; |
|
||||||
import com.fr.log.FineLoggerFactory; |
|
||||||
import com.fr.plugin.ExtraClassManager; |
|
||||||
import com.fr.report.cell.CellElement; |
|
||||||
import com.fr.report.cell.FloatElement; |
|
||||||
import com.fr.report.cell.TemplateCellElement; |
|
||||||
import com.fr.report.cell.cellattr.CellExpandAttr; |
|
||||||
import com.fr.report.cell.cellattr.CellGUIAttr; |
|
||||||
import com.fr.report.cell.cellattr.core.CellUtils; |
|
||||||
import com.fr.report.cell.cellattr.core.ResultSubReport; |
|
||||||
import com.fr.report.cell.cellattr.core.group.DSColumn; |
|
||||||
import com.fr.report.core.Html2ImageUtils; |
|
||||||
import com.fr.report.core.ReportUtils; |
|
||||||
import com.fr.script.Calculator; |
|
||||||
import com.fr.stable.Constants; |
|
||||||
import com.fr.stable.CoreConstants; |
|
||||||
import com.fr.stable.StringUtils; |
|
||||||
import com.fr.stable.bridge.ObjectHolder; |
|
||||||
import com.fr.stable.fun.AutoChangeLineAndDrawProcess; |
|
||||||
import com.fr.stable.fun.FontProcessor; |
|
||||||
import com.fr.stable.html.Tag; |
|
||||||
import com.fr.stable.unit.FU; |
|
||||||
import com.fr.stable.unit.PT; |
|
||||||
import com.fr.stable.unit.UNIT; |
|
||||||
import com.fr.stable.web.Repository; |
|
||||||
|
|
||||||
import javax.swing.ImageIcon; |
|
||||||
import java.awt.AlphaComposite; |
|
||||||
import java.awt.Color; |
|
||||||
import java.awt.Font; |
|
||||||
import java.awt.FontMetrics; |
|
||||||
import java.awt.Graphics2D; |
|
||||||
import java.awt.Image; |
|
||||||
import java.awt.Paint; |
|
||||||
import java.awt.Rectangle; |
|
||||||
import java.awt.font.TextAttribute; |
|
||||||
import java.awt.geom.GeneralPath; |
|
||||||
import java.awt.image.BufferedImage; |
|
||||||
import java.util.Hashtable; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* The util for paint. |
|
||||||
*/ |
|
||||||
public class PaintUtils { |
|
||||||
// Add by Denny
|
|
||||||
public static final int CELL_MARK_SIZE = 6; |
|
||||||
public static final Color CELL_HIGHT_LIGHT_MARK_COLOR = new Color(255, 0, 55); |
|
||||||
public static final Color CELL_PRESENT_MARK_COLOR = new Color(0, 255, 200); |
|
||||||
public static final Color CELL_PAGINATION_MARK_COLOR = new Color(55, 255, 0); |
|
||||||
public static final Color CELL_RESULT_MARK_COLOR = new Color(200, 0, 255); |
|
||||||
public static final Color CELL_CONDITION_FILTER_MARK_COLOR = new Color(255, 200, 0); |
|
||||||
public static final Color CELL_PARAMETER_FILTER_MARK_CONLR = new Color(0, 55, 255); |
|
||||||
|
|
||||||
public static final Color CELL_DIRECTION_MARK_COLOR = Color.gray; |
|
||||||
private static final int UNIT_SIZE = 4; |
|
||||||
|
|
||||||
//原值是15,矩形线条会缺失,加1px绘制没问题。这地方有水印,但是貌似不是水印影响,未找到线条被挡住的原因
|
|
||||||
private static final int WIDGET_WIDTH = 16; |
|
||||||
private static final int WIDGET_HEIGHT = 16; |
|
||||||
|
|
||||||
// Suppresses default constructor, ensuring non-instantiability.
|
|
||||||
private PaintUtils() { |
|
||||||
} |
|
||||||
|
|
||||||
// font attributes map cache
|
|
||||||
private static Hashtable fontAttributeMapCache = new Hashtable(); |
|
||||||
|
|
||||||
/* |
|
||||||
* 用于在Grid里面画CellElement的Content + Background |
|
||||||
* |
|
||||||
* 不画Border,是因为在Grid里面先画所有单元格的Content + Background,再画所有单元格的Border(peter认为这可以提高速度) |
|
||||||
*/ |
|
||||||
public static void paintGridCellContent(Graphics2D g2d, TemplateCellElement cell, int width, int height, int resolution) { |
|
||||||
int cell_mark_size = CELL_MARK_SIZE; |
|
||||||
// denny_Grid
|
|
||||||
// 左上角: 条件高亮, 形态
|
|
||||||
int leftUpCount = 0; |
|
||||||
int rightUpCount = 0; |
|
||||||
int leftDownCount = 0; |
|
||||||
GraphHelper.applyRenderingHints(g2d); |
|
||||||
if (paintHighlightGroupMarkWhenExsit(g2d, cell, leftUpCount)) { |
|
||||||
leftUpCount++; |
|
||||||
} |
|
||||||
if (paintPresentMarkWhenExsit(g2d, cell, leftUpCount)) { |
|
||||||
leftUpCount++; |
|
||||||
} |
|
||||||
if (paintPaginationMarkWhenExsit(g2d, cell, width, rightUpCount)) { |
|
||||||
rightUpCount++; |
|
||||||
} |
|
||||||
paintWidgetMarkWhenExsit(g2d, cell, width, height); |
|
||||||
paintExpandMarkWhenExsit(g2d, cell); |
|
||||||
Object value = cell.getValue(); |
|
||||||
if (value == null) {// 先判断是否是空.
|
|
||||||
return; |
|
||||||
} |
|
||||||
if (paintResultMarkWhenExsit(g2d, value, width, rightUpCount)) { |
|
||||||
rightUpCount++; |
|
||||||
} |
|
||||||
|
|
||||||
if (paintDSColumnParametermarkWhenExsit(g2d, value, height, leftDownCount)) { |
|
||||||
leftDownCount++; |
|
||||||
} |
|
||||||
|
|
||||||
if (paintDSColumnConditionmarkWhenExsit(g2d, value, height, leftDownCount)) { |
|
||||||
leftDownCount++; |
|
||||||
} |
|
||||||
// 画value,但因为是在Grid里面画,所以画Formula.content
|
|
||||||
if (value instanceof BaseFormula) { |
|
||||||
value = ((BaseFormula) value).getContent(); |
|
||||||
} |
|
||||||
if (value instanceof ImageWithSuffix) { |
|
||||||
value = ((ImageWithSuffix) value).getFineImage(); |
|
||||||
} |
|
||||||
if (value instanceof BaseChartCollection) { |
|
||||||
value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height); |
|
||||||
} |
|
||||||
// Carl:当是子报表时,在格子里画一个子报表的图
|
|
||||||
/* |
|
||||||
* alex:TODO 此处在Grid里面画ChartCollection和SubReport都只画一个图表,这种做法,很不雅 |
|
||||||
*/ |
|
||||||
if (value instanceof ResultSubReport) { |
|
||||||
value = BaseUtils.readImage("/com/fr/base/images/report/painter/subReport.png"); |
|
||||||
GraphHelper.paintImage(g2d, width, height, (Image) value, Constants.IMAGE_CENTER, |
|
||||||
BaseUtils.getAlignment4Horizontal(cell.getStyle(), value), cell.getStyle().getVerticalAlignment(), |
|
||||||
width > 16 ? 16 : width, height > 16 ? 16 : height); |
|
||||||
} else { |
|
||||||
renderContent(g2d, value, cell.getStyle(), width, height, resolution); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static void renderContent(Graphics2D g2d, Object value, Style style, int width, int height, int resolution) { |
|
||||||
if (value != null && width != 0 && height != 0) { |
|
||||||
if (style == null) { |
|
||||||
style = Style.DEFAULT_STYLE.deriveImageLayout(1); |
|
||||||
} |
|
||||||
|
|
||||||
if (value instanceof BaseFormula) { |
|
||||||
value = ((BaseFormula) value).getResult(); |
|
||||||
} |
|
||||||
|
|
||||||
if (value instanceof Painter) { |
|
||||||
((Painter)value).paint(g2d, width, height, resolution, style); |
|
||||||
} else if (value instanceof ImageProvider) { |
|
||||||
Style.paintImageContent(g2d, ((ImageProvider) value).getImage(), style, width, height, resolution); |
|
||||||
} else if (value instanceof Image) { |
|
||||||
Style.paintImageContent(g2d, (Image) value, style, width, height, resolution); |
|
||||||
} else { |
|
||||||
String var6 = Style.valueToText(value, style.getFormat()); |
|
||||||
NewFormStyle.paintCellStyleString2(g2d, width, height, var6, style, resolution); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static boolean paintHighlightGroupMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) { |
|
||||||
if (cell.getHighlightGroup() != null && cell.getHighlightGroup().size() > 0) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
|
|
||||||
g2d.setPaint(CELL_HIGHT_LIGHT_MARK_COLOR); |
|
||||||
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); |
|
||||||
polyline.moveTo(0, 0); |
|
||||||
polyline.lineTo(0, CELL_MARK_SIZE); |
|
||||||
polyline.lineTo(CELL_MARK_SIZE, 0); |
|
||||||
GraphHelper.fill(g2d, polyline); |
|
||||||
|
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean paintPresentMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) { |
|
||||||
if (cell.getPresent() != null) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
|
|
||||||
g2d.setPaint(CELL_PRESENT_MARK_COLOR); |
|
||||||
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); |
|
||||||
polyline.moveTo(0 + left_up_count * CELL_MARK_SIZE, 0); |
|
||||||
polyline.lineTo(0 + left_up_count * CELL_MARK_SIZE, 6); |
|
||||||
polyline.lineTo(CELL_MARK_SIZE + left_up_count * CELL_MARK_SIZE, 0); |
|
||||||
GraphHelper.fill(g2d, polyline); |
|
||||||
|
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean paintPaginationMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int ringt_up_count) { |
|
||||||
// 右上角: 标记是否有分页
|
|
||||||
if (isRightTopMarker(cell)) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
|
|
||||||
g2d.setPaint(CELL_PAGINATION_MARK_COLOR); |
|
||||||
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); |
|
||||||
polyline.moveTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, 0); |
|
||||||
polyline.lineTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, CELL_MARK_SIZE); |
|
||||||
polyline.lineTo(width - 1 - (ringt_up_count + 1) * CELL_MARK_SIZE, 0); |
|
||||||
GraphHelper.fill(g2d, polyline); |
|
||||||
|
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean isRightTopMarker(TemplateCellElement cell) { |
|
||||||
return cell.getCellPageAttr() != null && (cell.getCellPageAttr().isPageAfterColumn() |
|
||||||
|| cell.getCellPageAttr().isPageBeforeColumn() |
|
||||||
|| cell.getCellPageAttr().isPageAfterRow() |
|
||||||
|| cell.getCellPageAttr().isPageBeforeRow()); |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean paintResultMarkWhenExsit(Graphics2D g2d, Object value, int width, int ringt_up_count) { |
|
||||||
//右上角标记是否自定义显示
|
|
||||||
if (value instanceof DSColumn && ((DSColumn) value).getResult() != null) { |
|
||||||
if (!ComparatorUtils.equals(((DSColumn) value).getResult(), "$$$")) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
|
|
||||||
g2d.setPaint(CELL_RESULT_MARK_COLOR); |
|
||||||
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); |
|
||||||
polyline.moveTo(width - ringt_up_count * CELL_MARK_SIZE - 1, 0); |
|
||||||
polyline.lineTo(width - ringt_up_count * CELL_MARK_SIZE - 1, CELL_MARK_SIZE); |
|
||||||
polyline.lineTo(width - (ringt_up_count + 1) * CELL_MARK_SIZE - 1, 0); |
|
||||||
GraphHelper.fill(g2d, polyline); |
|
||||||
|
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private static void paintWidgetMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int height) { |
|
||||||
// 右下角:是否填报, 设置为4时,三角太小了,不知何故,设置为6
|
|
||||||
if (cell.getWidget() != null) { |
|
||||||
Widget widget = cell.getWidget(); |
|
||||||
Image img = ((ImageIcon) ReportUtils.createWidgetIcon(widget.getClass())).getImage(); |
|
||||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.67f)); |
|
||||||
g2d.drawImage(img, width - 15, height - 15, WIDGET_WIDTH, WIDGET_HEIGHT, null); |
|
||||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static void paintExpandMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell) { |
|
||||||
CellExpandAttr cellExpandAttr = cell.getCellExpandAttr(); |
|
||||||
if (cellExpandAttr != null) { |
|
||||||
if (cellExpandAttr.getDirection() == Constants.TOP_TO_BOTTOM) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
g2d.setPaint(CELL_DIRECTION_MARK_COLOR); |
|
||||||
GraphHelper.drawLine(g2d, 2, 0, 2, 5); |
|
||||||
GraphHelper.drawLine(g2d, 2, 5, 0, 2); |
|
||||||
GraphHelper.drawLine(g2d, 2, 5, 4, 2); |
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
} else if (cellExpandAttr.getDirection() == Constants.LEFT_TO_RIGHT) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
g2d.setPaint(CELL_DIRECTION_MARK_COLOR); |
|
||||||
GraphHelper.drawLine(g2d, 0, 2, 5, 2); |
|
||||||
GraphHelper.drawLine(g2d, 5, 2, 2, 0); |
|
||||||
GraphHelper.drawLine(g2d, 5, 2, 2, 4); |
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean paintDSColumnConditionmarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) { |
|
||||||
// 左下角:数据列(DSColumn)相关:比如条件过滤
|
|
||||||
if (value instanceof DSColumn && ((DSColumn) value).getCondition() != null) { |
|
||||||
if (((DSColumn) value).getCondition() instanceof ListCondition && |
|
||||||
((ListCondition) ((DSColumn) value).getCondition()).getJoinConditionCount() == 0) { |
|
||||||
// do nothing
|
|
||||||
} else { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
|
|
||||||
g2d.setPaint(CELL_CONDITION_FILTER_MARK_COLOR); |
|
||||||
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); |
|
||||||
polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1); |
|
||||||
polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1); |
|
||||||
polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE); |
|
||||||
GraphHelper.fill(g2d, polyline); |
|
||||||
|
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean paintDSColumnParametermarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) { |
|
||||||
// 左下角:动态注入参数
|
|
||||||
if (value instanceof DSColumn && ((DSColumn) value).getParameters() != null) { |
|
||||||
if (((DSColumn) value).getParameters().length > 0) { |
|
||||||
Paint oldPaint = g2d.getPaint(); |
|
||||||
|
|
||||||
g2d.setPaint(CELL_PARAMETER_FILTER_MARK_CONLR); |
|
||||||
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); |
|
||||||
polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1); |
|
||||||
polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1); |
|
||||||
polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE); |
|
||||||
GraphHelper.fill(g2d, polyline); |
|
||||||
|
|
||||||
g2d.setPaint(oldPaint); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* 画悬浮元素 |
|
||||||
* |
|
||||||
* 仅根据宽度 + 高度画 |
|
||||||
*/ |
|
||||||
//b:此方法在grid和tohtml的时候都被调用,所以对formula会有冲突,暂时这么改,应该考虑分开的,也可以根据result来判断,但是那么写好像不妥
|
|
||||||
public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, int width, int height, int resolution) { |
|
||||||
Style.paintBackground(g2d, flotEl.getStyle(), width, height); |
|
||||||
|
|
||||||
Object value = flotEl.getValue(); |
|
||||||
if (value instanceof BaseFormula) { |
|
||||||
value = ((BaseFormula) value).getContent(); |
|
||||||
} |
|
||||||
if (value instanceof BaseChartCollection) { |
|
||||||
value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height); |
|
||||||
} |
|
||||||
//图片需要切割一下
|
|
||||||
if (value instanceof Image) { |
|
||||||
value = CellUtils.value2ImageWithBackground(value, resolution, flotEl.getStyle(), width, height); |
|
||||||
} |
|
||||||
Style.paintContent(g2d, value, flotEl.getStyle(), width, height, resolution); |
|
||||||
|
|
||||||
Style.paintBorder(g2d, flotEl.getStyle(), width, height); |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* 画悬浮元素flotEl |
|
||||||
* |
|
||||||
* 也就是画三个东西:背景 + 内容 + 边框 |
|
||||||
*/ |
|
||||||
public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, Rectangle paintRectangle, Rectangle clipRectangle, int resolution) { |
|
||||||
// 画悬浮元素的背景
|
|
||||||
Style.paintBackground(g2d, flotEl.getStyle(), paintRectangle, clipRectangle); |
|
||||||
|
|
||||||
Object value = flotEl.getValue(); |
|
||||||
if (value instanceof ResultChangeWhenExport) { |
|
||||||
value = ((ResultChangeWhenExport) value).changeThis(); |
|
||||||
} |
|
||||||
// 画悬浮元素的内容
|
|
||||||
Style.paintContent(g2d, value, resolution, flotEl.getStyle(), paintRectangle, clipRectangle); |
|
||||||
// 画悬浮元素的边框
|
|
||||||
Style.paintBorder(g2d, flotEl.getStyle(), paintRectangle, clipRectangle); |
|
||||||
} |
|
||||||
|
|
||||||
public static void paintHTMLContent(Graphics2D g2d, String value, int resolution, Style style, Rectangle paintRectangle, Rectangle clipRectangle) { |
|
||||||
Style.paintContent(g2d, createHTMLContentBufferedImage(value, paintRectangle, 0, 0, style), resolution, style, paintRectangle, clipRectangle); |
|
||||||
} |
|
||||||
|
|
||||||
public static void paintTag(Painter painter, Repository repo, int width, int height, Style style, Tag tag) { |
|
||||||
painter.paintTag(repo, width, height, style, tag); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 如果用户希望以HTML方式展示String,这个时候先value变成图片 |
|
||||||
* |
|
||||||
* @param value 值 |
|
||||||
* @param paintRectangle 绘制范围 |
|
||||||
* @param x x坐标 |
|
||||||
* @param y y坐标 |
|
||||||
* @param style 当前格子样式 |
|
||||||
* @return BufferedImage 返回图片. |
|
||||||
*/ |
|
||||||
public static BufferedImage createHTMLContentBufferedImage(String value, Rectangle paintRectangle, int x, int y, Style style) { |
|
||||||
return Html2ImageUtils.createHTMLContentBufferedImage(value, paintRectangle, x, y, style); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* see <code>BaseUtils.getLineTextList</code>, 等于BaseUtils.getLineTextList().size() |
|
||||||
* Denny: 为了提高速度和性能,才单独拿出来的 |
|
||||||
* TODO: 重构 |
|
||||||
* |
|
||||||
* @param text 文本 |
|
||||||
* @param style 样式 |
|
||||||
* @param paintWidth 单元格宽度 |
|
||||||
* @return paintWidth 单位为PT |
|
||||||
*/ |
|
||||||
public static int getLineTextCount(String text, Style style, UNIT paintWidth) { |
|
||||||
if (style.getRotation() != 0) { |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
if (style.getTextStyle() != Style.TEXTSTYLE_WRAPTEXT) { |
|
||||||
return dealNotWrapTextCount(text.toCharArray()); |
|
||||||
} else {// 自动换行
|
|
||||||
return dealWrapTextCount(text, style, paintWidth); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static int dealNotWrapTextCount(char[] text_chars) { |
|
||||||
boolean remain_chars = false; |
|
||||||
int count = 0; |
|
||||||
for (int t = 0; t < text_chars.length; t++) { |
|
||||||
if (text_chars[t] == '\\') {// 判断是否是 "\n"
|
|
||||||
if (t + 1 < text_chars.length && text_chars[t + 1] == 'n') { |
|
||||||
// 是"\n"字符串,但不是换行符.
|
|
||||||
t++; |
|
||||||
count++; |
|
||||||
if (remain_chars) { |
|
||||||
remain_chars = false; |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (!remain_chars) { |
|
||||||
remain_chars = true; |
|
||||||
} |
|
||||||
} |
|
||||||
} else if (text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n')) { |
|
||||||
count++; |
|
||||||
if (remain_chars) { |
|
||||||
remain_chars = false; |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (!remain_chars) { |
|
||||||
remain_chars = true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// 最后一个
|
|
||||||
if (remain_chars) { |
|
||||||
count++; |
|
||||||
} |
|
||||||
|
|
||||||
return count; |
|
||||||
} |
|
||||||
|
|
||||||
// 自动换行
|
|
||||||
//neil:style里面, 默认值padding right = 2时, 默认不生效, 这边算行高时也不要计算入内
|
|
||||||
//临时处理, 去掉左边框线, 因为浏览器计算时需要考虑左边框线宽度, 但这边还是存在问题的
|
|
||||||
//同样需要考虑的是导出和web端展示, padding计算方式也不一致.
|
|
||||||
private static int dealWrapTextCount(String text, Style style, UNIT unitWidth) { |
|
||||||
AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess(); |
|
||||||
if (process != null) { |
|
||||||
return process.getAutoChangeLineCount(text, new ObjectHolder(style), unitWidth); |
|
||||||
} |
|
||||||
int count = 0; |
|
||||||
char[] text_chars = text.toCharArray(); |
|
||||||
FontMetrics fontMetrics = getFontMetrics(style); |
|
||||||
double paintWidth = unitWidth.toPixD(Constants.FR_PAINT_RESOLUTION); |
|
||||||
double width = paintWidth - style.getPaddingLeft() - (style.getPaddingRight() == Style.DEFAULT_PADDING ? 0 : style.getPaddingRight()) - style.getBorderLeftWidth(); |
|
||||||
boolean remain_lineText = false; |
|
||||||
int lineTextWidth = 0; |
|
||||||
int wordWidth = 0; |
|
||||||
for (int t = 0, len = text_chars.length; t < len; t++) { |
|
||||||
if (t != 0 && BaseUtils.isNumOrLetter(text_chars[t]) && BaseUtils.isNumOrLetter(text_chars[t - 1])) { |
|
||||||
if (wordWidth + fontMetrics.charWidth(text_chars[t]) > width) { |
|
||||||
if (lineTextWidth > 0) { |
|
||||||
count++; |
|
||||||
remain_lineText = false; |
|
||||||
lineTextWidth = 0; |
|
||||||
} |
|
||||||
count++; |
|
||||||
wordWidth = 0; |
|
||||||
} |
|
||||||
wordWidth += fontMetrics.charWidth(text_chars[t]); |
|
||||||
} else if (isSwitchLine(text_chars, t) || isLN(text_chars, t)) {// 判断是否是 "\n"
|
|
||||||
if (isLN(text_chars, t)) { |
|
||||||
t++;// 忽略'n'字符.// 是"\n"字符串,但不是换行符,依然需要换行.
|
|
||||||
} |
|
||||||
if (lineTextWidth + wordWidth > width && remain_lineText) { |
|
||||||
count += 2; |
|
||||||
} else { |
|
||||||
count++; |
|
||||||
} |
|
||||||
remain_lineText = false; |
|
||||||
lineTextWidth = 0; |
|
||||||
wordWidth = 0; |
|
||||||
} else { |
|
||||||
if (text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == '\\') {// 判断是否是转义字符'\'
|
|
||||||
t++;// _denny: 增加了转义字符'\\'用来表示\,使"\n"可以输入
|
|
||||||
} |
|
||||||
if (lineTextWidth + wordWidth > width && remain_lineText) { |
|
||||||
count++; |
|
||||||
lineTextWidth = isPunctuationAtLineHead(t, text_chars) ? dealLineWidthWithPunctuation(t, text_chars, fontMetrics) : 0; |
|
||||||
} |
|
||||||
remain_lineText = true; |
|
||||||
lineTextWidth += wordWidth; |
|
||||||
wordWidth = fontMetrics.charWidth(text_chars[t]); |
|
||||||
} |
|
||||||
} |
|
||||||
if (lineTextWidth + wordWidth > width && remain_lineText) { |
|
||||||
count += 2; |
|
||||||
} else { |
|
||||||
count++; |
|
||||||
} |
|
||||||
return count; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 标点符号是否在换行后的行首 |
|
||||||
*/ |
|
||||||
private static boolean isPunctuationAtLineHead(int t, char[] text_chars) { |
|
||||||
if (t > 1 && BaseUtils.isPunctuation(text_chars[t - 1])) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 防止有连续多个标点符号,要找一个非标点符号字符 |
|
||||||
* |
|
||||||
* @date 2014-4-17 |
|
||||||
*/ |
|
||||||
private static int dealLineWidthWithPunctuation(int t, char[] text_chars, FontMetrics fontMetrics) { |
|
||||||
if (t < 2) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
int lineWidth = 0; |
|
||||||
for (int index = t - 2; index >= 0; index--) { |
|
||||||
lineWidth += fontMetrics.charWidth(text_chars[index]); |
|
||||||
if (!BaseUtils.isPunctuation(text_chars[index])) { |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
return lineWidth; |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean isSwitchLine(char[] text_chars, int t) { |
|
||||||
return text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n'); |
|
||||||
} |
|
||||||
|
|
||||||
private static boolean isLN(char[] text_chars, int t) { |
|
||||||
return text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == 'n'; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Gets the preferred width. |
|
||||||
*/ |
|
||||||
public static UNIT getPreferredWidth(CellElement cell, UNIT height) { |
|
||||||
if (cell == null) { |
|
||||||
return UNIT.ZERO; |
|
||||||
} |
|
||||||
|
|
||||||
Object value = cell.getShowValue(); |
|
||||||
// 只接受Text,Number,和SeparatorPainter
|
|
||||||
// got the text
|
|
||||||
if (value instanceof BaseFormula) { |
|
||||||
if (((BaseFormula) value).getResult() != null) { |
|
||||||
value = ((BaseFormula) value).getResult(); |
|
||||||
} else { |
|
||||||
value = StringUtils.EMPTY; |
|
||||||
} |
|
||||||
} |
|
||||||
Style style = cell.getStyle(); |
|
||||||
if (style == null) { |
|
||||||
style = Style.DEFAULT_STYLE; |
|
||||||
} |
|
||||||
CellGUIAttr cg = cell.getCellGUIAttr() == null ? new CellGUIAttr() : cell.getCellGUIAttr(); |
|
||||||
value = Utils.resolveOtherValue(value, cg.isShowAsImage(), PresentationType.EXPORT); |
|
||||||
String text = Style.valueToText(value, style.getFormat()); |
|
||||||
|
|
||||||
FontMetrics cellFM = getFontMetrics(style); |
|
||||||
//bug 12151 有边框线的单元格 自动调整列宽 会多一行
|
|
||||||
UNIT padding = new PT(style.getPaddingLeft() + style.getPaddingRight()); |
|
||||||
|
|
||||||
if (cg.isShowAsHTML()) { |
|
||||||
return Html2ImageUtils.getHtmlWidth(text, height, style); |
|
||||||
} |
|
||||||
|
|
||||||
return FU.valueOfPix(cellFM.stringWidth(text) + UNIT_SIZE, Constants.FR_PAINT_RESOLUTION).add(padding); |
|
||||||
} |
|
||||||
|
|
||||||
private static FontMetrics getFontMetrics(Style style) { |
|
||||||
Font font = style.getFRFont().applyResolutionNP(Constants.FR_PAINT_RESOLUTION); |
|
||||||
FontProcessor processor = ExtraClassManager.getInstance().getSingle(FontProcessor.MARK_STRING); |
|
||||||
if (processor != null) { |
|
||||||
font = processor.readExtraFont(font); |
|
||||||
} |
|
||||||
return GraphHelper.getFontMetrics(font); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Preferred height. (Got the shrink preferred height of CellElement). |
|
||||||
* 单位格的预计算高度 |
|
||||||
* |
|
||||||
* @param cellElement 单元格内容 |
|
||||||
* @param paintWidth 画的宽度 |
|
||||||
* @return UNIT 单位 |
|
||||||
*/ |
|
||||||
public static UNIT analyzeCellElementPreferredHeight(CellElement cellElement, UNIT paintWidth) { |
|
||||||
// 计算高度用显示值
|
|
||||||
Object value = cellElement.getShowValue(); |
|
||||||
// 只接受Text,Number,和SeparatorPainter
|
|
||||||
Style style = cellElement.getStyle(); |
|
||||||
// got the text
|
|
||||||
if (value instanceof BaseFormula) { |
|
||||||
if (((BaseFormula) value).getResult() != null) { |
|
||||||
value = ((BaseFormula) value).getResult(); |
|
||||||
} else { |
|
||||||
value = StringUtils.EMPTY; |
|
||||||
} |
|
||||||
} |
|
||||||
CellGUIAttr cg = cellElement.getCellGUIAttr() == null ? new CellGUIAttr() : cellElement.getCellGUIAttr(); |
|
||||||
if (!(value instanceof String) && !(value instanceof Integer)) { |
|
||||||
value = DataUtils.resolveOtherValue(value, cg.isShowAsImage(), cg.isShowAsDownload(), null, true); |
|
||||||
} |
|
||||||
String text = Style.valueToText(value, style.getFormat()); |
|
||||||
|
|
||||||
if (cg.isShowAsHTML()) { |
|
||||||
return Html2ImageUtils.getHtmlHeight(text, paintWidth, style); |
|
||||||
} |
|
||||||
|
|
||||||
return PaintUtils.analyzeCellElementPreferredHeight(text, style, paintWidth, cg.isShowAsHTML()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 单位格的预计算高度 |
|
||||||
* 单位PT |
|
||||||
* |
|
||||||
* @param text 文本 |
|
||||||
* @param style 格式 |
|
||||||
* @param paintWidth 画的宽度 |
|
||||||
* @param isShowAsHtml 是否以html展示 |
|
||||||
* @return 返回 单位 |
|
||||||
*/ |
|
||||||
private static UNIT analyzeCellElementPreferredHeight(String text, Style style, UNIT paintWidth, boolean isShowAsHtml) { |
|
||||||
if (style == null) { |
|
||||||
//peter:获取默认的Style.
|
|
||||||
style = Style.DEFAULT_STYLE; |
|
||||||
} |
|
||||||
|
|
||||||
// got the text
|
|
||||||
if (text == null || text.length() <= 0) { |
|
||||||
return PT.valueOf(0); |
|
||||||
} |
|
||||||
|
|
||||||
// 变成Line Text List.
|
|
||||||
if (style.getRotation() != 0) { // more easy to paint.
|
|
||||||
// attribute map.
|
|
||||||
return PT.valueOf((float) GraphHelper.stringDimensionWithRotation(text, style.getFRFont(), -style.getRotation(), |
|
||||||
CoreConstants.DEFAULT_FRC).getHeight()); |
|
||||||
} |
|
||||||
// 先获得FontMetics.
|
|
||||||
int lineCount = getLineTextCount(text, style, paintWidth); |
|
||||||
AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess(); |
|
||||||
if (process != null) { |
|
||||||
//算了这两个接口分开做
|
|
||||||
return process.getLinedTextHeight(lineCount, new ObjectHolder(style)); |
|
||||||
} |
|
||||||
|
|
||||||
// carl:和paint那边一致,添上段前段后和行间距
|
|
||||||
PT lineSpacing = PT.valueOf(style.getSpacingAfter() + style.getSpacingBefore() + style.getLineSpacing() * lineCount); |
|
||||||
FontMetrics fontMetrics = getFontMetrics(style); |
|
||||||
int textHeight = fontMetrics.getHeight(); |
|
||||||
FU allTextHeight = FU.valueOfPix(textHeight * lineCount, Constants.FR_PAINT_RESOLUTION); |
|
||||||
return lineSpacing.add(allTextHeight);// 需要给底部添加Leading.
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 截取文字,只考虑了垂直方向,水平方向没意义且难度大. |
|
||||||
* |
|
||||||
* @param value 画的值 |
|
||||||
* @param style 字体样式格式. |
|
||||||
* @param blockArea 冻结的范围 |
|
||||||
* @param resolution 分辨率 |
|
||||||
* @return 返回的字符串 |
|
||||||
*/ |
|
||||||
public static String clipBlockValue(Object value, Style style, Rectangle primitiveArea, Rectangle blockArea, int resolution, boolean isShowAsHTML) { |
|
||||||
if (value == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
if (value instanceof BaseFormula) { |
|
||||||
value = ((BaseFormula) value).getResult(); |
|
||||||
} |
|
||||||
if (blockArea.y >= primitiveArea.height || blockArea.y + blockArea.height <= 0) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
//截取位置,相对于clipArea
|
|
||||||
int startY = blockArea.y > 0 ? blockArea.y : 0; |
|
||||||
int endY = blockArea.y + blockArea.height < primitiveArea.height ? blockArea.y + blockArea.height : primitiveArea.height; |
|
||||||
if (blockArea.x >= primitiveArea.width || blockArea.x + blockArea.width <= 0) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
if (isShowAsHTML) { |
|
||||||
return Html2ImageUtils.clipHtmlContent(value, style, primitiveArea, resolution, startY, endY); |
|
||||||
} |
|
||||||
List lineList = BaseUtils.getLineTextList((String) value, style, style.getFRFont().applyResolutionNP(resolution), primitiveArea.width, resolution); |
|
||||||
if (lineList.isEmpty()) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
double spacingBefore = PT.pt2pix(style.getSpacingBefore(), resolution); |
|
||||||
double spacingAfter = PT.pt2pix(style.getSpacingAfter(), resolution); |
|
||||||
double lineSpacing = PT.pt2pix(style.getLineSpacing(), resolution); |
|
||||||
double lineHeight = lineSpacing + GraphHelper.getFontMetrics(style.getFRFont().applyResolutionNP(resolution)).getHeight(); |
|
||||||
int textAllHeight = (int) (lineHeight * lineList.size() + spacingBefore + spacingAfter); |
|
||||||
//第一行文字距区域高度
|
|
||||||
int textStartY = (int) spacingBefore; |
|
||||||
|
|
||||||
if (style.getVerticalAlignment() == Constants.BOTTOM) { |
|
||||||
textStartY += (primitiveArea.height - textAllHeight); |
|
||||||
} |
|
||||||
if (endY <= textStartY || startY >= textStartY + lineHeight * lineList.size()) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
int lineStart = getLineStart(lineList, lineHeight, textStartY, startY);//截取区域起始行
|
|
||||||
int lineEnd = getLineEnd(lineList, lineHeight, endY, textStartY);//截取区域结束行
|
|
||||||
String text = ""; |
|
||||||
for (; lineStart <= lineEnd; lineStart++) { |
|
||||||
text += lineList.get(lineStart); |
|
||||||
} |
|
||||||
return text; |
|
||||||
} |
|
||||||
|
|
||||||
private static int getLineStart(List lineList, double lineHeight, int textStartY, int startY) { |
|
||||||
int lineStart = 0; |
|
||||||
for (int i = 0; i < lineList.size(); i++) { |
|
||||||
if (textStartY + lineHeight * (i) <= startY && textStartY + lineHeight * (i + 1) > startY) {//压线
|
|
||||||
if (startY - textStartY - lineHeight * (i) > lineHeight / 2) { |
|
||||||
lineStart = i + 1; |
|
||||||
} else { |
|
||||||
lineStart = i; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return lineStart; |
|
||||||
} |
|
||||||
|
|
||||||
private static int getLineEnd(List lineList, double lineHeight, int endY, int textStartY) { |
|
||||||
int lineEnd = lineList.size() - 1; |
|
||||||
for (int i = 0; i < lineList.size(); i++) { |
|
||||||
if (textStartY + lineHeight * (i) < endY && textStartY + lineHeight * (i + 1) >= endY) {//压线
|
|
||||||
//neil:仿宋,12号字, 行间距8为例, 转为px的行间距大小为10.666, 这边算出的应该有31.98行, 因此要进位
|
|
||||||
if (endY - textStartY - lineHeight * (i) >= lineHeight / 2) { |
|
||||||
lineEnd = i; |
|
||||||
} else { |
|
||||||
lineEnd = i - 1; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return lineEnd; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* paintBarcode |
|
||||||
*/ |
|
||||||
public static void paintBarcode(Graphics2D g2d, int width, int height, String text, Style style, BarcodeAttr barcodeAttr) { |
|
||||||
BarcodeImpl barcodeImpl; |
|
||||||
try { |
|
||||||
barcodeImpl = BarCodeUtils.getBarcodeImpl(barcodeAttr, text); |
|
||||||
} catch (BarcodeException exp) { |
|
||||||
try { |
|
||||||
//设置默认值.
|
|
||||||
barcodeImpl = BarCodeUtils.getBarcodeImpl(new BarcodeAttr(), null); |
|
||||||
} catch (BarcodeException e) { |
|
||||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//字体
|
|
||||||
if (style.getFRFont() != null) { |
|
||||||
barcodeImpl.setFont(style.getFRFont()); |
|
||||||
barcodeImpl.setForeground(style.getFRFont().getForeground()); |
|
||||||
} |
|
||||||
//背景
|
|
||||||
Background background = style.getBackground(); |
|
||||||
if (background != null && background instanceof ColorBackground) { |
|
||||||
barcodeImpl.setBackground(((ColorBackground) background).getColor()); |
|
||||||
} |
|
||||||
|
|
||||||
//根据宽度和高度来确定起始点
|
|
||||||
int pointX = (width - barcodeImpl.getWidth()) / 2; |
|
||||||
int pointY = (height - barcodeImpl.getHeight()) / 2; |
|
||||||
|
|
||||||
barcodeImpl.draw(g2d, pointX, pointY); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* create font attribute map, 创建属性map |
|
||||||
* |
|
||||||
* @param font 字体 |
|
||||||
* @return map 返回字体创建的Map |
|
||||||
*/ |
|
||||||
public static Map createFontAttributeMap(Font font) { |
|
||||||
Map returnFontAttributeMap = (Map) fontAttributeMapCache.get(font); |
|
||||||
if (returnFontAttributeMap == null) {// create
|
|
||||||
// returnFontAttributeMap.
|
|
||||||
returnFontAttributeMap = font.getAttributes(); |
|
||||||
fontAttributeMapCache.put(font, returnFontAttributeMap); |
|
||||||
} |
|
||||||
|
|
||||||
if (font instanceof FRFont) { |
|
||||||
FRFont frFont = (FRFont) font; |
|
||||||
|
|
||||||
// Strikethrough
|
|
||||||
if (frFont.isStrikethrough()) { |
|
||||||
returnFontAttributeMap.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return returnFontAttributeMap; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|