You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
7.0 KiB
189 lines
7.0 KiB
6 years ago
|
package com.fanruan.api.design.work;
|
||
|
|
||
|
import com.fanruan.api.design.DesignKit;
|
||
|
import com.fanruan.api.design.ui.component.pane.UITextPane;
|
||
|
import com.fanruan.api.log.LogKit;
|
||
|
import com.fanruan.api.util.AssistKit;
|
||
|
import com.fr.base.BaseFormula;
|
||
|
import com.fr.design.dialog.DialogActionAdapter;
|
||
|
import com.fr.design.formula.FormulaFactory;
|
||
|
import com.fr.design.formula.UIFormula;
|
||
|
import com.fr.report.cell.cellattr.core.RichText;
|
||
|
import com.fr.report.cell.cellattr.core.RichTextConverter;
|
||
|
|
||
|
import javax.swing.text.AttributeSet;
|
||
|
import javax.swing.text.BadLocationException;
|
||
|
import javax.swing.text.Element;
|
||
|
import javax.swing.text.StyledDocument;
|
||
|
import java.awt.event.MouseAdapter;
|
||
|
import java.awt.event.MouseEvent;
|
||
|
import java.awt.event.MouseListener;
|
||
|
|
||
|
/**
|
||
|
* @author richie
|
||
|
* @version 10.0
|
||
|
* Created by richie on 2019/10/25
|
||
|
* 富文本编辑器容器
|
||
|
*/
|
||
|
public class RichTextEditingPane extends UITextPane {
|
||
|
|
||
|
private static final int WRAPPER_LEN = 3;
|
||
|
|
||
|
private static final int PREFIX_LEN = 2;
|
||
|
|
||
|
private boolean updating = false;
|
||
|
|
||
|
/**
|
||
|
* 构造函数
|
||
|
*/
|
||
|
public RichTextEditingPane() {
|
||
|
//双击选取公式监听器
|
||
|
//往前回溯, 寻找${, 如果发现先找到了}, 说明不在公式内部, 直接return.
|
||
|
//有可能当前字符刚好处于{后面, 所以要-1
|
||
|
//发现大括号了, 再找$
|
||
|
//再往后找"}"
|
||
|
//发现左大括号了, 肯定异常
|
||
|
//要把后缀包进去, 所以+1
|
||
|
// 取得选择文本的起始位置和结束位置
|
||
|
//公式起点
|
||
|
//公式终点
|
||
|
//找到公式的起点与终点了, 下面就是选中, 并弹出编辑窗口
|
||
|
//缓存第一个字符的样式, 用于给新公式设置样式
|
||
|
//弹出公式编辑窗口
|
||
|
MouseListener doubleClickFormulaListener = new MouseAdapter() {
|
||
|
|
||
|
private int findFormulaStart(int start, StyledDocument doc) throws BadLocationException {
|
||
|
//往前回溯, 寻找${, 如果发现先找到了}, 说明不在公式内部, 直接return.
|
||
|
//有可能当前字符刚好处于{后面, 所以要-1
|
||
|
for (int i = start - 1; i >= 0; i--) {
|
||
|
String text = doc.getText(i, 1);
|
||
|
if (AssistKit.equals(text, RichText.SUFFIX)) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//发现大括号了, 再找$
|
||
|
if (AssistKit.equals(text, RichText.PREFIX)) {
|
||
|
if (i - 1 >= 0 && AssistKit.equals(doc.getText(i - 1, 1), RichText.FLAG)) {
|
||
|
return i - 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
private int findFormulaEnd(int start, StyledDocument doc) throws BadLocationException {
|
||
|
//再往后找"}"
|
||
|
int total = doc.getLength();
|
||
|
for (int j = start; j < total; j++) {
|
||
|
String text = doc.getText(j, 1);
|
||
|
//发现左大括号了, 肯定异常
|
||
|
if (AssistKit.equals(text, RichText.PREFIX)) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (AssistKit.equals(text, RichText.SUFFIX)) {
|
||
|
//要把后缀包进去, 所以+1
|
||
|
return j + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
private void popUpFormulaEditPane(final String formulaContent, final int formulaStart,
|
||
|
final AttributeSet attrs) {
|
||
|
final UIFormula formulaPane = FormulaFactory.createFormulaPane();
|
||
|
formulaPane.populate(BaseFormula.createFormulaBuilder().build(formulaContent));
|
||
|
formulaPane.showLargeWindow(DesignKit.getDesignerFrame(), new DialogActionAdapter() {
|
||
|
@Override
|
||
|
public void doOk() {
|
||
|
StyledDocument doc = (StyledDocument) RichTextEditingPane.this.getDocument();
|
||
|
BaseFormula fm = formulaPane.update();
|
||
|
String content = RichTextConverter.asFormula(fm.getContent());
|
||
|
try {
|
||
|
doc.remove(formulaStart, formulaContent.length() + WRAPPER_LEN);
|
||
|
doc.insertString(formulaStart, content, attrs);
|
||
|
} catch (BadLocationException e) {
|
||
|
LogKit.error(e.getMessage(), e);
|
||
|
}
|
||
|
}
|
||
|
}).setVisible(true);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void mouseReleased(MouseEvent e) {
|
||
|
if (e.getClickCount() == 2) {
|
||
|
// 取得选择文本的起始位置和结束位置
|
||
|
int start = RichTextEditingPane.this.getSelectionStart();
|
||
|
|
||
|
if (start <= 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
StyledDocument doc = (StyledDocument) RichTextEditingPane.this.getDocument();
|
||
|
try {
|
||
|
//公式起点
|
||
|
final int formulaStart = findFormulaStart(start, doc);
|
||
|
if (formulaStart == -1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//公式终点
|
||
|
int formulaEnd = findFormulaEnd(start, doc);
|
||
|
if (formulaEnd == -1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//找到公式的起点与终点了, 下面就是选中, 并弹出编辑窗口
|
||
|
RichTextEditingPane.this.select(formulaStart, formulaEnd);
|
||
|
//缓存第一个字符的样式, 用于给新公式设置样式
|
||
|
Element ele = doc.getCharacterElement(formulaStart);
|
||
|
final AttributeSet attrs = ele.getAttributes();
|
||
|
|
||
|
final String formulaContent = doc.getText(formulaStart + PREFIX_LEN, formulaEnd - formulaStart - WRAPPER_LEN);
|
||
|
//弹出公式编辑窗口
|
||
|
popUpFormulaEditPane(formulaContent, formulaStart, attrs);
|
||
|
} catch (BadLocationException e1) {
|
||
|
LogKit.error(e1.getMessage());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
this.addMouseListener(doubleClickFormulaListener);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 是否有其他进程正在更新编辑区域
|
||
|
*
|
||
|
* @return 是否有其他进程正在更新编辑区域
|
||
|
*/
|
||
|
public boolean isUpdating() {
|
||
|
return updating;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 设置更新状态
|
||
|
*
|
||
|
* @param updating 是否正在更新
|
||
|
*/
|
||
|
public void setUpdating(boolean updating) {
|
||
|
this.updating = updating;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 开始更新
|
||
|
*/
|
||
|
public void startUpdating() {
|
||
|
this.updating = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 结束更新
|
||
|
*/
|
||
|
public void finishUpdating() {
|
||
|
this.updating = false;
|
||
|
}
|
||
|
|
||
|
}
|