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.
188 lines
7.0 KiB
188 lines
7.0 KiB
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; |
|
} |
|
|
|
}
|
|
|