diff --git a/README.md b/README.md
index 48a2510..14c6eb6 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
# demo-cell-property-provider
-单元格扩展属性接口实例
\ No newline at end of file
+单元格扩展属性接口实例\
+demo生效后,设计器打开模板,单元格属性(选中单元格,设计器右边纵向展示的图标的最后一个)最后有一个key值属性可编译保存
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..3d3e2c4
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,124 @@
+
+apply plugin: 'java'
+
+[compileJava,compileTestJava]*.options*.encoding = 'UTF-8'
+
+ext {
+ /**
+ * 项目中依赖的jar的路径
+ * 1.如果依赖的jar需要打包到zip中,放置在lib根目录下
+ * 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可
+ */
+ libPath = "$projectDir/../webroot/WEB-INF/lib"
+
+ /**
+ * 是否对插件的class进行加密保护,防止反编译
+ */
+ guard = false
+
+ def pluginInfo = getPluginInfo()
+ pluginPre = "fine-plugin"
+ pluginName = pluginInfo.id
+ pluginVersion = pluginInfo.version
+
+ outputPath = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes"
+}
+
+group = 'com.fr.plugin'
+version = '10.0'
+sourceCompatibility = '8'
+
+sourceSets {
+ main {
+ java.outputDir = file(outputPath)
+ output.resourcesDir = file(outputPath)
+ }
+}
+
+ant.importBuild("encrypt.xml")
+//定义ant变量
+ant.projectDir = projectDir
+ant.references["compile.classpath"] = ant.path {
+ fileset(dir: libPath, includes: '**/*.jar')
+ fileset(dir: ".",includes:"**/*.jar" )
+}
+
+classes.dependsOn('clean')
+
+task copyFiles(type: Copy,dependsOn: 'classes'){
+ from outputPath
+ into "$projectDir/classes"
+}
+
+task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){
+ from "$projectDir/classes"
+ into "$projectDir/transform-classes"
+ include "**/*.*"
+}
+jar.dependsOn("preJar")
+
+task makeJar(type: Jar,dependsOn: preJar){
+ from fileTree(dir: "$projectDir/transform-classes")
+ baseName pluginPre
+ appendix pluginName
+ version pluginVersion
+ destinationDir = file("$buildDir/libs")
+
+ doLast(){
+ delete file("$projectDir/classes")
+ delete file("$projectDir/transform-classes")
+ }
+}
+
+task copyFile(type: Copy,dependsOn: ["makeJar"]){
+ from "$buildDir/libs"
+ from("$projectDir/lib") {
+ include "*.jar"
+ }
+ from "$projectDir/plugin.xml"
+ into file("$buildDir/temp/plugin")
+}
+
+task zip(type:Zip,dependsOn:["copyFile"]){
+ from "$buildDir/temp/plugin"
+ destinationDir file("$buildDir/install")
+ baseName pluginPre
+ appendix pluginName
+ version pluginVersion
+}
+
+//控制build时包含哪些文件,排除哪些文件
+processResources {
+// exclude everything
+// 用*.css没效果
+// exclude '**/*.css'
+// except this file
+// include 'xx.xml'
+}
+
+/*读取plugin.xml中的version*/
+def getPluginInfo(){
+ def xmlFile = file("plugin.xml")
+ if (!xmlFile.exists()) {
+ return ["id":"none", "version":"1.0.0"]
+ }
+ def plugin = new XmlParser().parse(xmlFile)
+ def version = plugin.version[0].text()
+ def id = plugin.id[0].text()
+ return ["id":id,"version":version]
+}
+
+repositories {
+ mavenLocal()
+ maven {
+ url = uri('http://mvn.finedevelop.com/repository/maven-public/')
+ }
+}
+
+dependencies {
+ //使用本地jar
+ implementation fileTree(dir: 'lib', include: ['**/*.jar'])
+ implementation fileTree(dir: libPath, include: ['**/*.jar'])
+}
+
+
diff --git a/encrypt.xml b/encrypt.xml
new file mode 100644
index 0000000..1401cd1
--- /dev/null
+++ b/encrypt.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugin.xml b/plugin.xml
new file mode 100644
index 0000000..379a778
--- /dev/null
+++ b/plugin.xml
@@ -0,0 +1,19 @@
+
+ com.tptj.demo.hg.cell.property.provider.v10
+
+ yes
+ 1.0
+ 10.0
+ tptj
+ 2019-07-18
+
+
+ com.tptj.demo.hg.cell.property.provider
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/tptj/demo/hg/cell/property/provider/Demo.java b/src/main/java/com/tptj/demo/hg/cell/property/provider/Demo.java
new file mode 100644
index 0000000..403872d
--- /dev/null
+++ b/src/main/java/com/tptj/demo/hg/cell/property/provider/Demo.java
@@ -0,0 +1,61 @@
+package com.tptj.demo.hg.cell.property.provider;
+
+import com.fr.intelli.record.Focus;
+import com.fr.json.JSONException;
+import com.fr.json.JSONObject;
+import com.fr.record.analyzer.EnableMetrics;
+import com.fr.report.cell.CellElement;
+import com.fr.report.fun.CellPropertyProvider;
+import com.fr.report.fun.impl.AbstractCellPropertyProvider;
+import com.fr.stable.StringUtils;
+import com.fr.stable.web.Repository;
+import com.fr.stable.xml.XMLPrintWriter;
+import com.fr.stable.xml.XMLableReader;
+
+/**
+ * @author 秃破天际
+ * @version 10.0
+ * Created by 秃破天际 on 2021-06-03
+ **/
+@EnableMetrics
+public class Demo extends AbstractCellPropertyProvider {
+
+ public static final String XML_TAG = "DemoProperty";
+ private String key;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ @Override
+ public String xmlTag() {
+ return XML_TAG;
+ }
+
+ @Override
+ public void readXML(XMLableReader reader) {
+ key = reader.getAttrAsString("key", StringUtils.EMPTY);
+ }
+
+ @Override
+ public void writeXML(XMLPrintWriter writer) {
+ writer.startTAG(XML_TAG).attr("key",key).end();
+ }
+
+ @Override
+ public CellPropertyProvider clone() {
+ Demo obj = (Demo) super.clone();
+ obj.key = key;
+ return obj;
+ }
+
+ @Override
+ @Focus(id="com.tptj.demo.hg.cell.property.provider.v10",text = "cell property provider")
+ public void mixinCellJson(JSONObject cellJson, Repository repository, CellElement cellElement) throws JSONException {
+ cellJson.put("key", key);
+ }
+}
diff --git a/src/main/java/com/tptj/demo/hg/cell/property/provider/DemoComponent.java b/src/main/java/com/tptj/demo/hg/cell/property/provider/DemoComponent.java
new file mode 100644
index 0000000..eb1d920
--- /dev/null
+++ b/src/main/java/com/tptj/demo/hg/cell/property/provider/DemoComponent.java
@@ -0,0 +1,36 @@
+package com.tptj.demo.hg.cell.property.provider;
+
+import com.fr.design.cell.AbstractCellElementPropertyPane;
+import com.fr.design.designer.TargetComponent;
+import com.fr.design.mainframe.ElementCasePane;
+
+import java.awt.*;
+
+/**
+ * @author 秃破天际
+ * @version 10.0
+ * Created by 秃破天际 on 2021-06-03
+ **/
+public class DemoComponent extends AbstractCellElementPropertyPane {
+ private KeyEditor editor;
+ public DemoComponent(){
+ this.setLayout(new BorderLayout());
+ editor = new KeyEditor();
+ add(editor, BorderLayout.CENTER);
+ }
+
+ @Override
+ public void populate(TargetComponent component) {
+ if(component instanceof ElementCasePane){
+ editor.populate((ElementCasePane)component);
+ }
+ validate();
+ repaint();
+ }
+
+ @Override
+ protected String title4PopupWindow() {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/tptj/demo/hg/cell/property/provider/DemoPane.java b/src/main/java/com/tptj/demo/hg/cell/property/provider/DemoPane.java
new file mode 100644
index 0000000..a9a5d8d
--- /dev/null
+++ b/src/main/java/com/tptj/demo/hg/cell/property/provider/DemoPane.java
@@ -0,0 +1,72 @@
+package com.tptj.demo.hg.cell.property.provider;
+
+import com.fr.design.cell.CellElementPropertyComponent;
+import com.fr.design.fun.impl.AbstractCellPropertyPaneProvider;
+import com.fr.design.mainframe.EastRegionContainerPane;
+import com.fr.design.mainframe.JWorkBook;
+import com.fr.design.mainframe.PaneHolder;
+import com.fr.design.mainframe.PropertyItemBean;
+
+import javax.swing.*;
+
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+import static com.fr.design.mainframe.EastRegionContainerPane.PropertyMode.FORM_REPORT;
+import static com.fr.design.mainframe.EastRegionContainerPane.PropertyMode.POLY_REPORT;
+
+/**
+ * @author 秃破天际
+ * @version 10.0
+ * Created by 秃破天际 on 2021-06-03
+ **/
+public class DemoPane extends AbstractCellPropertyPaneProvider {
+ private DemoComponent component = new DemoComponent();
+ @Override
+ public CellElementPropertyComponent getSingletonCelPropertyPane() {
+ return component;
+ }
+
+ @Override
+ protected PaneHolder getPathHolder0() {
+ return new PaneHolder() {
+ @Override
+ public JPanel getInstance(Object arg) {
+ return getSingletonCelPropertyPane().toPanel();
+ }
+ };
+ }
+
+ @Override
+ protected Class sign() {
+ return JWorkBook.class;
+ }
+
+ @Override
+ public String key() {
+ return "key";
+ }
+
+ @Override
+ public PropertyItemBean getItem() {
+ PropertyItemBean bean = new PropertyItemBean();
+ bean.setName("key");
+ bean.setTitle("KEY");
+ bean.setBtnIconName("cellelement");
+ bean.setVisibleModes(new EastRegionContainerPane.PropertyMode[]{
+ EastRegionContainerPane.PropertyMode.REPORT,
+ FORM_REPORT,
+ POLY_REPORT});
+ bean.setButtonListeners(new ArrayList(0));
+ bean.setEnableModes(new EastRegionContainerPane.PropertyMode[]{
+ EastRegionContainerPane.PropertyMode.REPORT,
+ FORM_REPORT,
+ POLY_REPORT});
+ return bean;
+ }
+
+ @Override
+ public String replaceKey() {
+ return null;
+ }
+}
diff --git a/src/main/java/com/tptj/demo/hg/cell/property/provider/KeyEditor.java b/src/main/java/com/tptj/demo/hg/cell/property/provider/KeyEditor.java
new file mode 100644
index 0000000..a658ef3
--- /dev/null
+++ b/src/main/java/com/tptj/demo/hg/cell/property/provider/KeyEditor.java
@@ -0,0 +1,132 @@
+package com.tptj.demo.hg.cell.property.provider;
+
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.grid.GridKeyListener;
+import com.fr.grid.selection.CellSelection;
+import com.fr.quickeditor.CellQuickEditor;
+import com.fr.report.cell.DefaultTemplateCellElement;
+import com.fr.stable.ColumnRow;
+import com.fr.stable.StringUtils;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import java.awt.*;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+/**
+ * @author 秃破天际
+ * @version 10.0
+ * Created by 秃破天际 on 2021-06-03
+ **/
+public class KeyEditor extends CellQuickEditor {
+ private UITextField w_key;
+ private boolean isEditing = false;
+
+ private DocumentListener documentListener = new DocumentListener() {
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ changeReportPaneCell(w_key.getText().trim());
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ changeReportPaneCell(w_key.getText().trim());
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ changeReportPaneCell(w_key.getText().trim());
+ }
+
+ };
+
+ public void showText(String str) {
+ // 正在编辑时不处理
+ if (isEditing) {
+ return;
+ }
+ w_key.getDocument().removeDocumentListener(documentListener);
+ w_key.setText(str);
+ w_key.getDocument().addDocumentListener(documentListener);
+ }
+
+ private void changeReportPaneCell(String tmpText) {
+ isEditing = true;
+ CellSelection cs1 = (CellSelection) tc.getSelection();
+ ColumnRow columnRow = ColumnRow.valueOf(cs1.getColumn(), cs1.getRow());
+ columnRowTextField.setText(columnRow.toString());
+ cellElement = tc.getEditingElementCase().getTemplateCellElement(cs1.getColumn(), cs1.getRow());
+ if (cellElement == null) {
+ CellSelection cs = (CellSelection) tc.getSelection();
+ cellElement = new DefaultTemplateCellElement(cs.getColumn(), cs.getRow());
+ tc.getEditingElementCase().addCellElement(cellElement, false);
+ }
+ if (tmpText != null ) {
+ Demo property = new Demo();
+ property.setKey(tmpText);
+ cellElement.addCellAttr(property);
+ }
+ fireTargetModified();
+ w_key.requestFocus();
+ isEditing = false;
+ }
+
+ @Override
+ public JComponent createCenterBody() {
+ JPanel panel = new JPanel( new BorderLayout() );
+ w_key = new UITextField();
+ w_key.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (tc == null) {
+ return;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ GridKeyListener dispatchListener = new GridKeyListener(tc.getGrid());
+ dispatchListener.keyPressed(e);
+ dispatchListener.keyTyped(e);
+ }
+ }
+ @Override
+ public void keyReleased(KeyEvent e) {
+ if (tc != null) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ return;
+ }
+ tc.getGrid().dispatchEvent(e);
+ }
+ }
+ });
+ panel.add(w_key, BorderLayout.CENTER);
+ return panel;
+ }
+
+ @Override
+ public boolean isScrollAll() {
+ return false;
+ }
+
+ @Override
+ public Object getComboBoxSelected() {
+ return null;
+ }
+
+ @Override
+ protected void refreshDetails() {
+ String str;
+ if ( null == cellElement ) {
+ str = StringUtils.EMPTY;
+ } else {
+ Demo attr = cellElement.getCellAttr( Demo.XML_TAG );
+ if ( null == attr ) {
+ str = StringUtils.EMPTY;
+ } else{
+ str = attr.getKey();
+ }
+ }
+ showText(str);
+ w_key.setEditable(tc.isSelectedOneCell());
+ }
+}