873 changed files with 52904 additions and 6158 deletions
@ -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,193 @@ |
|||||||
|
package com.fr.design; |
||||||
|
|
||||||
|
import com.fr.concurrent.NamedThreadFactory; |
||||||
|
import com.fr.general.CloudCenter; |
||||||
|
import com.fr.general.CloudCenterConfig; |
||||||
|
import com.fr.general.http.HttpToolbox; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.ProductConstants; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLReaderHelper; |
||||||
|
import com.fr.stable.xml.XMLTools; |
||||||
|
import com.fr.stable.xml.XMLable; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
import com.fr.third.javax.xml.stream.XMLStreamException; |
||||||
|
import com.fr.third.org.apache.commons.io.FileUtils; |
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ExecutorService; |
||||||
|
import java.util.concurrent.Executors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by kerry on 2021/10/22 |
||||||
|
*/ |
||||||
|
public class DesignerCloudURLManager implements XMLable { |
||||||
|
private static final String CLOUD_URL_INFO = "cloudUrl.info"; |
||||||
|
private static final String ROOT_XML_TAG = "CloudUrlInfoList"; |
||||||
|
private static final String CHILD_XML_TAG = "CloudUrlInfo"; |
||||||
|
private final Map<String, String> urlMap = new HashMap<>(); |
||||||
|
|
||||||
|
public static DesignerCloudURLManager getInstance() { |
||||||
|
return DesignerCloudURLManager.HOLDER.singleton; |
||||||
|
} |
||||||
|
|
||||||
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("TestCloudConnectThread")); |
||||||
|
|
||||||
|
private volatile boolean testResult; |
||||||
|
|
||||||
|
|
||||||
|
private static class HOLDER { |
||||||
|
private static final DesignerCloudURLManager singleton = new DesignerCloudURLManager(); |
||||||
|
} |
||||||
|
|
||||||
|
private DesignerCloudURLManager() { |
||||||
|
loadURLXMLFile(); |
||||||
|
} |
||||||
|
|
||||||
|
public String acquireUrlByKind(String key) { |
||||||
|
String url = urlMap.getOrDefault(key, StringUtils.EMPTY); |
||||||
|
if (StringUtils.isEmpty(url)) { |
||||||
|
//本地缓存中为空时,直接从云中心获取,获取完成后异步更新本地缓存文件
|
||||||
|
String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY); |
||||||
|
executorService.submit(() -> { |
||||||
|
updateURLXMLFile(key, latestUrl); |
||||||
|
}); |
||||||
|
return latestUrl; |
||||||
|
} |
||||||
|
//本地缓存不为空时,直接返回对应 url,同时异步更新
|
||||||
|
executorService.submit(() -> { |
||||||
|
String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY); |
||||||
|
updateURLXMLFile(key, latestUrl); |
||||||
|
}); |
||||||
|
return url; |
||||||
|
} |
||||||
|
|
||||||
|
private synchronized void updateURLXMLFile(String key, String url) { |
||||||
|
if (StringUtils.isNotEmpty(url) && (!urlMap.containsKey(key) || !url.equals(urlMap.get(key)))) { |
||||||
|
urlMap.put(key, url); |
||||||
|
saveURLXMLFile(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void testConnect() { |
||||||
|
executorService.submit(() -> { |
||||||
|
testResult = isOnline(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isConnected() { |
||||||
|
return testResult; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isOnline() { |
||||||
|
if (CloudCenterConfig.getInstance().isOnline()) { |
||||||
|
String ping = acquireUrlByKind("ping"); |
||||||
|
if (StringUtils.isNotEmpty(ping)) { |
||||||
|
try { |
||||||
|
return StringUtils.isEmpty(HttpToolbox.get(ping)); |
||||||
|
} catch (Exception ignore) { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 加载本地 url 管理文件 |
||||||
|
*/ |
||||||
|
private void loadURLXMLFile() { |
||||||
|
if (!getInfoFile().exists()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
XMLableReader reader = null; |
||||||
|
try (InputStream in = new FileInputStream(getInfoFile())) { |
||||||
|
// XMLableReader 还是应该考虑实现 Closable 接口的,这样就能使用 try-with 语句了
|
||||||
|
reader = XMLReaderHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER); |
||||||
|
if (reader == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
reader.readXMLObject(this); |
||||||
|
} catch (FileNotFoundException e) { |
||||||
|
// do nothing
|
||||||
|
} catch (XMLStreamException | IOException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} finally { |
||||||
|
try { |
||||||
|
if (reader != null) { |
||||||
|
reader.close(); |
||||||
|
} |
||||||
|
} catch (XMLStreamException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private File getInfoFile() { |
||||||
|
|
||||||
|
File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), CLOUD_URL_INFO)); |
||||||
|
try { |
||||||
|
if (!file.exists()) { |
||||||
|
file.createNewFile(); |
||||||
|
} |
||||||
|
} catch (Exception ex) { |
||||||
|
FineLoggerFactory.getLogger().error(ex.getMessage(), ex); |
||||||
|
} |
||||||
|
return file; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存到本地 URL 管理文件中,存放在 .Finereport110 中 |
||||||
|
*/ |
||||||
|
void saveURLXMLFile() { |
||||||
|
try { |
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||||
|
XMLTools.writeOutputStreamXML(this, out); |
||||||
|
out.flush(); |
||||||
|
out.close(); |
||||||
|
String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); |
||||||
|
FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8); |
||||||
|
} catch (Exception ex) { |
||||||
|
FineLoggerFactory.getLogger().error(ex.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void readXML(XMLableReader reader) { |
||||||
|
String tagName = reader.getTagName(); |
||||||
|
if (tagName.equals(CHILD_XML_TAG)) { |
||||||
|
String key = reader.getAttrAsString("key", StringUtils.EMPTY); |
||||||
|
String value = reader.getAttrAsString("url", StringUtils.EMPTY); |
||||||
|
this.urlMap.put(key, value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeXML(XMLPrintWriter xmlPrintWriter) { |
||||||
|
xmlPrintWriter.startTAG(ROOT_XML_TAG); |
||||||
|
Iterator<Map.Entry<String, String>> iterable = urlMap.entrySet().iterator(); |
||||||
|
while (iterable.hasNext()) { |
||||||
|
Map.Entry<String, String> entry = iterable.next(); |
||||||
|
xmlPrintWriter.startTAG(CHILD_XML_TAG).attr("key", entry.getKey()).attr("url", entry.getValue()).end(); |
||||||
|
} |
||||||
|
xmlPrintWriter.end(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() throws CloneNotSupportedException { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package com.fr.design.actions.file; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.design.actions.UpdateAction; |
||||||
|
import com.fr.design.menu.MenuKeySet; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.nx.app.designer.transform.ui.BatchTransformPane; |
||||||
|
|
||||||
|
import javax.swing.KeyStroke; |
||||||
|
import java.awt.Dialog; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by kerry on 2019-12-10 |
||||||
|
*/ |
||||||
|
public class BatchCompileAction extends UpdateAction { |
||||||
|
public BatchCompileAction() { |
||||||
|
this.setMenuKeySet(COMPILE); |
||||||
|
this.setName(getMenuKeySet().getMenuKeySetName() + "..."); |
||||||
|
this.setMnemonic(getMenuKeySet().getMnemonic()); |
||||||
|
this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/batch_transform.png")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
BatchTransformPane batchTransformPane = new BatchTransformPane(); |
||||||
|
Dialog dialog = batchTransformPane.showDialog(); |
||||||
|
dialog.setVisible(true); |
||||||
|
} |
||||||
|
|
||||||
|
private static final MenuKeySet COMPILE = new MenuKeySet() { |
||||||
|
@Override |
||||||
|
public char getMnemonic() { |
||||||
|
return 'C'; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getMenuName() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public KeyStroke getKeyStroke() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
package com.fr.design.actions.server; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.design.actions.UpdateAction; |
||||||
|
import com.fr.design.menu.MenuKeySet; |
||||||
|
import com.fr.design.utils.DesignUtils; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.nx.app.web.URLConstants; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
|
||||||
|
import javax.swing.KeyStroke; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Maksim |
||||||
|
* Created in 2020/11/5 11:44 上午 |
||||||
|
*/ |
||||||
|
public class LocalAnalyzerAction extends UpdateAction { |
||||||
|
|
||||||
|
public LocalAnalyzerAction() { |
||||||
|
this.setMenuKeySet(ANALYZER); |
||||||
|
this.setName(getMenuKeySet().getMenuKeySetName()); |
||||||
|
this.setMnemonic(getMenuKeySet().getMnemonic()); |
||||||
|
this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/analyzer.png")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
String path = StableUtils.pathJoin("/nx", URLConstants.ANALYZE_VIEW); |
||||||
|
DesignUtils.visitEnvServerByParameters(path, new String[]{}, new String[]{}); |
||||||
|
} |
||||||
|
|
||||||
|
private static final MenuKeySet ANALYZER = new MenuKeySet() { |
||||||
|
@Override |
||||||
|
public char getMnemonic() { |
||||||
|
return 'R'; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getMenuName() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Analyzer_Menu_Name"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public KeyStroke getKeyStroke() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package com.fr.design.border; |
||||||
|
|
||||||
|
import com.fr.design.constants.UIConstants; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.border.TitledBorder; |
||||||
|
import java.awt.Color; |
||||||
|
|
||||||
|
public class UITitledMatteBorder extends TitledBorder { |
||||||
|
public static UITitledMatteBorder createTitledTopBorder(String title, Color color) { |
||||||
|
return new UITitledMatteBorder(title, 1, 0, 0, 0, color); |
||||||
|
} |
||||||
|
|
||||||
|
public static UITitledMatteBorder createTitledBorder(String title, Color color) { |
||||||
|
return new UITitledMatteBorder(title, 1, 1, 1, 1, color); |
||||||
|
} |
||||||
|
|
||||||
|
public static UITitledMatteBorder createTitledBorder(String title, int top, int left, int bottom, int right, Color color) { |
||||||
|
return new UITitledMatteBorder(title, top, left, bottom, right, color); |
||||||
|
} |
||||||
|
|
||||||
|
private UITitledMatteBorder(String title, int top, int left, int bottom, int right, Color color) { |
||||||
|
super( |
||||||
|
BorderFactory.createMatteBorder(top, left, bottom, right, UIConstants.TITLED_BORDER_COLOR), |
||||||
|
title, |
||||||
|
TitledBorder.LEADING, |
||||||
|
TitledBorder.TOP, |
||||||
|
null, |
||||||
|
color |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,180 @@ |
|||||||
|
package com.fr.design.cell; |
||||||
|
|
||||||
|
import com.fr.base.CellBorderSourceFlag; |
||||||
|
import com.fr.base.CellBorderStyle; |
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.report.cell.TemplateCellElement; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.AlphaComposite; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Composite; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.Graphics; |
||||||
|
import java.awt.Graphics2D; |
||||||
|
import java.awt.GridLayout; |
||||||
|
import java.awt.Rectangle; |
||||||
|
import java.awt.RenderingHints; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/3 |
||||||
|
*/ |
||||||
|
public class CellRectangleStylePreviewPane extends JPanel { |
||||||
|
|
||||||
|
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); |
||||||
|
private final float transparentBackgroundWidth; |
||||||
|
private final float transparentBackgroundHeight; |
||||||
|
|
||||||
|
private static final int ROW_COUNT = 2; |
||||||
|
private static final int COLUMN_COUNT = 2; |
||||||
|
|
||||||
|
private final TemplateCellElement[][] cellElementGrid = new TemplateCellElement[ROW_COUNT][COLUMN_COUNT]; |
||||||
|
private final int[][] borderSourceFlags = new int[ROW_COUNT][COLUMN_COUNT]; |
||||||
|
private final CellStylePreviewPane[][] cellStylePreviewPaneGrid = new CellStylePreviewPane[ROW_COUNT][COLUMN_COUNT]; |
||||||
|
|
||||||
|
public CellRectangleStylePreviewPane(boolean supportInnerBorder) { |
||||||
|
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); |
||||||
|
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); |
||||||
|
|
||||||
|
setLayout(new GridLayout(2, 2)); |
||||||
|
setOpaque(false); |
||||||
|
setBackground(null); |
||||||
|
|
||||||
|
for (int r = 0; r < ROW_COUNT; r++) { |
||||||
|
for (int c = 0; c < COLUMN_COUNT; c++) { |
||||||
|
CellStylePreviewPane pane = new CellStylePreviewPane(c, r, COLUMN_COUNT, ROW_COUNT, false, false); |
||||||
|
TemplateCellElement cellElement = DefaultThemedTemplateCellElementCase.createInstance(c, r); |
||||||
|
int flags = CellBorderSourceFlag.INVALID_BORDER_SOURCE; |
||||||
|
if (supportInnerBorder) { |
||||||
|
flags = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; |
||||||
|
if (r != 0) { |
||||||
|
flags |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; |
||||||
|
} |
||||||
|
if (r != ROW_COUNT - 1) { |
||||||
|
flags |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; |
||||||
|
} |
||||||
|
if (c != 0) { |
||||||
|
flags |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; |
||||||
|
} |
||||||
|
if (c != COLUMN_COUNT - 1) { |
||||||
|
flags |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
pane.setStyle(cellElement.getStyle()); |
||||||
|
add(pane); |
||||||
|
|
||||||
|
cellElementGrid[r][c] = cellElement; |
||||||
|
borderSourceFlags[r][c] = flags; |
||||||
|
cellStylePreviewPaneGrid[r][c] = pane; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setPlainText(String text) { |
||||||
|
cellStylePreviewPaneGrid[0][1].setPaintText(text); |
||||||
|
cellStylePreviewPaneGrid[1][1].setPaintText(text); |
||||||
|
repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setStyle(Style style, CellBorderStyle borderStyle) { |
||||||
|
for (int i = 0; i < ROW_COUNT; i++) { |
||||||
|
for (int j = 0; j < COLUMN_COUNT; j++) { |
||||||
|
CellStylePreviewPane pane = cellStylePreviewPaneGrid[i][j]; |
||||||
|
TemplateCellElement cellElement = cellElementGrid[i][j]; |
||||||
|
int flag = borderSourceFlags[i][j]; |
||||||
|
cellElement.setStyle(CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, flag)); |
||||||
|
|
||||||
|
pane.setStyle(cellElement.getStyle()); |
||||||
|
} |
||||||
|
} |
||||||
|
repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setPreferredSize(Dimension preferredSize) { |
||||||
|
super.setPreferredSize(preferredSize); |
||||||
|
int hw = preferredSize.width / 2; |
||||||
|
int hh = preferredSize.height / 2; |
||||||
|
cellStylePreviewPaneGrid[0][0].setPreferredSize(new Dimension(hw, hh)); |
||||||
|
cellStylePreviewPaneGrid[0][1].setPreferredSize(new Dimension(hw, hh)); |
||||||
|
cellStylePreviewPaneGrid[1][0].setPreferredSize(new Dimension(hw, hh)); |
||||||
|
cellStylePreviewPaneGrid[1][1].setPreferredSize(new Dimension(hw, hh)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Dimension getPreferredSize() { |
||||||
|
Dimension d00 = cellStylePreviewPaneGrid[0][0].getPreferredSize(); |
||||||
|
Dimension d01 = cellStylePreviewPaneGrid[0][1].getPreferredSize(); |
||||||
|
Dimension d10 = cellStylePreviewPaneGrid[1][0].getPreferredSize(); |
||||||
|
Dimension d11 = cellStylePreviewPaneGrid[1][1].getPreferredSize(); |
||||||
|
|
||||||
|
int width = Math.max(d00.width + d01.width, d10.width + d11.width); |
||||||
|
int height = Math.max(d00.height + d10.height, d01.height + d11.height); |
||||||
|
|
||||||
|
return new Dimension(width, height); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
Graphics2D g2d = (Graphics2D) g; |
||||||
|
g2d.clearRect(0, 0, getWidth(), getHeight()); |
||||||
|
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); |
||||||
|
|
||||||
|
paintTransparentBackground((Graphics2D) g, cellElementGrid[0][0].getStyle()); |
||||||
|
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); |
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); |
||||||
|
|
||||||
|
super.paint(g); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Rectangle getBounds() { |
||||||
|
return super.getBounds(); |
||||||
|
} |
||||||
|
|
||||||
|
private void paintTransparentBackground(Graphics2D g2d, Style style) { |
||||||
|
float alpha = computeTransparentBackgroundAlpha(style); |
||||||
|
|
||||||
|
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; |
||||||
|
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; |
||||||
|
float maxScale = Math.max(scaleWidth, scaleHeight); |
||||||
|
|
||||||
|
if (maxScale <= 1) { |
||||||
|
scaleWidth = scaleHeight = 1; |
||||||
|
} else { |
||||||
|
scaleHeight = scaleWidth = maxScale; |
||||||
|
} |
||||||
|
|
||||||
|
Composite oldComposite = g2d.getComposite(); |
||||||
|
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); |
||||||
|
g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); |
||||||
|
g2d.setComposite(oldComposite); |
||||||
|
} |
||||||
|
|
||||||
|
private float computeTextColorBrightness(Style style) { |
||||||
|
Color fontColor = style.getFRFont().getForeground(); |
||||||
|
return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F; |
||||||
|
} |
||||||
|
|
||||||
|
private float computeTransparentBackgroundAlpha(Style style) { |
||||||
|
float textBrightness = computeTextColorBrightness(style); |
||||||
|
|
||||||
|
float alpha = 1.0F; |
||||||
|
if (textBrightness < 50) { |
||||||
|
alpha = 0.2F; |
||||||
|
} else if (textBrightness < 160){ |
||||||
|
alpha = 0.5F; |
||||||
|
} |
||||||
|
return alpha; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,220 @@ |
|||||||
|
package com.fr.design.cell; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.base.GraphHelper; |
||||||
|
import com.fr.base.NameStyle; |
||||||
|
import com.fr.base.ScreenResolution; |
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.general.FRFont; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.stable.Constants; |
||||||
|
import com.fr.stable.unit.PT; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.AlphaComposite; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Composite; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.Font; |
||||||
|
import java.awt.FontMetrics; |
||||||
|
import java.awt.Graphics; |
||||||
|
import java.awt.Graphics2D; |
||||||
|
import java.awt.RenderingHints; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/3 |
||||||
|
*/ |
||||||
|
public class CellStylePreviewPane extends JPanel { |
||||||
|
|
||||||
|
public static final int MINIMUM_HEIGHT = 40; |
||||||
|
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); |
||||||
|
private final float transparentBackgroundWidth; |
||||||
|
private final float transparentBackgroundHeight; |
||||||
|
private String paintText = "Report"; |
||||||
|
private Style style = Style.DEFAULT_STYLE; |
||||||
|
|
||||||
|
private final int column; |
||||||
|
private final int row; |
||||||
|
private final int columnSpan; |
||||||
|
private final int rowSpan; |
||||||
|
|
||||||
|
private final boolean autoClearCanvas; |
||||||
|
private final boolean paintingMosaic; |
||||||
|
|
||||||
|
public CellStylePreviewPane(int column, int row, int columnSpan, int rowSpan, boolean autoClearCanvas, boolean paintingMosaic) { |
||||||
|
this.column = column; |
||||||
|
this.row = row; |
||||||
|
this.columnSpan = columnSpan; |
||||||
|
this.rowSpan = rowSpan; |
||||||
|
this.autoClearCanvas = autoClearCanvas; |
||||||
|
this.paintingMosaic = paintingMosaic; |
||||||
|
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); |
||||||
|
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); |
||||||
|
setPreferredSize(new Dimension(0, 0)); |
||||||
|
} |
||||||
|
|
||||||
|
public void setPaintText(String paintText) { |
||||||
|
this.paintText = paintText; |
||||||
|
repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setStyle(Style style) { |
||||||
|
this.style = style; |
||||||
|
repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setStyle(NameStyle style) { |
||||||
|
paintText = style.getName(); |
||||||
|
setStyle(style.getRealStyle()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
Graphics2D g2d = (Graphics2D) g; |
||||||
|
if (autoClearCanvas) { |
||||||
|
g2d.clearRect(0, 0, getWidth(), getHeight()); |
||||||
|
} |
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); |
||||||
|
|
||||||
|
if (paintingMosaic) { |
||||||
|
paintTransparentBackground(g2d, style); |
||||||
|
} |
||||||
|
|
||||||
|
paintCellStyle(g2d, style); |
||||||
|
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); |
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); |
||||||
|
} |
||||||
|
|
||||||
|
private void paintTransparentBackground(Graphics2D g2d, Style style) { |
||||||
|
float alpha = computeTransparentBackgroundAlpha(style); |
||||||
|
|
||||||
|
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; |
||||||
|
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; |
||||||
|
float maxScale = Math.max(scaleWidth, scaleHeight); |
||||||
|
|
||||||
|
if (maxScale <= 1) { |
||||||
|
scaleWidth = scaleHeight = 1; |
||||||
|
} else { |
||||||
|
scaleHeight = scaleWidth = maxScale; |
||||||
|
} |
||||||
|
|
||||||
|
Composite oldComposite = g2d.getComposite(); |
||||||
|
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); |
||||||
|
g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); |
||||||
|
g2d.setComposite(oldComposite); |
||||||
|
} |
||||||
|
|
||||||
|
private float computeTextColorBrightness(Style style) { |
||||||
|
Color fontColor = style.getFRFont().getForeground(); |
||||||
|
return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F; |
||||||
|
} |
||||||
|
|
||||||
|
private float computeTransparentBackgroundAlpha(Style style) { |
||||||
|
float textBrightness = computeTextColorBrightness(style); |
||||||
|
|
||||||
|
float alpha = 1.0F; |
||||||
|
if (textBrightness < 50) { |
||||||
|
alpha = 0.2F; |
||||||
|
} else if (textBrightness < 160){ |
||||||
|
alpha = 0.5F; |
||||||
|
} |
||||||
|
return alpha; |
||||||
|
} |
||||||
|
|
||||||
|
private void paintCellStyle(Graphics2D g2d, Style style) { |
||||||
|
int resolution = ScreenResolution.getScreenResolution(); |
||||||
|
|
||||||
|
int width = getWidth(); |
||||||
|
int height = getHeight(); |
||||||
|
|
||||||
|
if (style == Style.DEFAULT_STYLE) { |
||||||
|
// 如果是默认的style,就只写"Report"上去
|
||||||
|
Style.paintContent(g2d, paintText, style, width, height, resolution); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Style.paintBackground(g2d, style, width, height); |
||||||
|
|
||||||
|
Style.paintContent(g2d, paintText, style, width, height, resolution); |
||||||
|
|
||||||
|
paintCellBorder(g2d, style); |
||||||
|
} |
||||||
|
|
||||||
|
protected void paintCellBorder(Graphics2D g2d, Style style) { |
||||||
|
float adjustLeft = 0; |
||||||
|
float adjustTop = 0; |
||||||
|
float adjustRight = 0; |
||||||
|
float adjustBottom = 0; |
||||||
|
if (column == 0) { |
||||||
|
adjustLeft = computeHalfSize4StyledBorder(style.getBorderLeft()); |
||||||
|
} |
||||||
|
if (row == 0) { |
||||||
|
adjustTop = computeHalfSize4StyledBorder(style.getBorderTop()); |
||||||
|
} |
||||||
|
if (column == columnSpan - 1) { |
||||||
|
adjustRight = -computeHalfSize4StyledBorder(style.getBorderRight()); |
||||||
|
} |
||||||
|
if (row == rowSpan - 1) { |
||||||
|
adjustBottom = -computeHalfSize4StyledBorder(style.getBorderBottom()); |
||||||
|
} |
||||||
|
|
||||||
|
g2d.translate(adjustLeft, adjustTop); |
||||||
|
Style.paintBorder(g2d, style, getWidth() - adjustLeft + adjustRight, getHeight() - adjustTop + adjustBottom); |
||||||
|
g2d.translate(-adjustLeft, -adjustTop); |
||||||
|
} |
||||||
|
|
||||||
|
private float computeHalfSize4StyledBorder(int border) { |
||||||
|
float size = GraphHelper.getLineStyleSize(border) / 2.0F; |
||||||
|
|
||||||
|
if (border == Constants.LINE_DOUBLE) { |
||||||
|
size += GraphHelper.getLineStyleSize(Constants.LINE_THIN) / 2.0F; |
||||||
|
} else if (border == Constants.LINE_DOUBLE_DOT) { |
||||||
|
size += GraphHelper.getLineStyleSize(Constants.LINE_DOT) / 2.0F; |
||||||
|
} |
||||||
|
|
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Dimension getPreferredSize() { |
||||||
|
Dimension size = super.getPreferredSize(); |
||||||
|
int width = size.width; |
||||||
|
int height = size.height; |
||||||
|
|
||||||
|
if (height != 0) { |
||||||
|
// 使用者设置了一个高度
|
||||||
|
return size; |
||||||
|
} else if (width == 0) { |
||||||
|
// 使用者未设置任何尺寸
|
||||||
|
return new Dimension(width, MINIMUM_HEIGHT); |
||||||
|
} else { |
||||||
|
// 使用者设置了宽度,但未设置高度
|
||||||
|
return getAutoWrapContentPreferredSize(width, height); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Dimension getAutoWrapContentPreferredSize(int width, int height) { |
||||||
|
int resolution = ScreenResolution.getScreenResolution(); |
||||||
|
|
||||||
|
// 计算文本区域高度
|
||||||
|
final FRFont frFont = style.getFRFont(); |
||||||
|
final Font rfont = frFont.applyResolutionNP(resolution); |
||||||
|
final FontMetrics metrics = GraphHelper.getFontMetrics(rfont); |
||||||
|
final int textLineHeight = metrics.getHeight(); |
||||||
|
final double textLineSpacing = PT.pt2pix(style.getLineSpacing(), resolution); |
||||||
|
|
||||||
|
List<?> textLineList = BaseUtils.getLineTextList(paintText, style, rfont, height, width, resolution); |
||||||
|
|
||||||
|
double textLinesHeight = textLineList.size() * textLineHeight + Math.max(0, textLineList.size() - 1) * textLineSpacing; |
||||||
|
|
||||||
|
height = (int) Math.max(MINIMUM_HEIGHT, textLinesHeight); |
||||||
|
|
||||||
|
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,27 @@ |
|||||||
|
package com.fr.design.data; |
||||||
|
|
||||||
|
public class NameChangeBean { |
||||||
|
private String oldName; |
||||||
|
private String changedName; |
||||||
|
|
||||||
|
public NameChangeBean(String oldName, String changedName) { |
||||||
|
this.oldName = oldName; |
||||||
|
this.changedName = changedName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getOldName() { |
||||||
|
return oldName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOldName(String oldName) { |
||||||
|
this.oldName = oldName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getChangedName() { |
||||||
|
return changedName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setChangedName(String changedName) { |
||||||
|
this.changedName = changedName; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
package com.fr.design.data; |
||||||
|
|
||||||
|
import com.fr.base.io.IOFile; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.esd.core.strategy.config.StrategyConfig; |
||||||
|
import com.fr.esd.core.strategy.config.StrategyConfigHelper; |
||||||
|
import com.fr.esd.core.strategy.config.service.StrategyConfigService; |
||||||
|
import com.fr.esd.core.strategy.persistence.StrategyConfigsAttr; |
||||||
|
import com.fr.esd.event.DSMapping; |
||||||
|
import com.fr.esd.event.DsNameTarget; |
||||||
|
import com.fr.esd.event.StrategyEventsNotifier; |
||||||
|
import com.fr.esd.event.xml.XMLSavedHook; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author rinoux |
||||||
|
* @version 10.0 |
||||||
|
* Created by rinoux on 2020/10/28 |
||||||
|
*/ |
||||||
|
public class StrategyConfigAttrUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前编辑模版的数据集缓存配置属性 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private static StrategyConfigsAttr getStrategyConfigsAttr() { |
||||||
|
StrategyConfigsAttr attr; |
||||||
|
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
if (jTemplate != null) { |
||||||
|
IOFile ioFile = (IOFile) jTemplate.getTarget(); |
||||||
|
|
||||||
|
attr = ioFile.getAttrMark(StrategyConfigsAttr.ATTR_MARK); |
||||||
|
if (attr == null) { |
||||||
|
attr = new StrategyConfigsAttr(); |
||||||
|
ioFile.addAttrMark(attr); |
||||||
|
} |
||||||
|
|
||||||
|
//新建模版此时不存在,不需要注册钩子
|
||||||
|
if (attr.getXmlSavedHook() == null && WorkContext.getWorkResource().exist(jTemplate.getPath())) { |
||||||
|
attr.setXmlSavedHook(new StrategyConfigsAttrSavedHook(jTemplate.getPath(), attr)); |
||||||
|
} |
||||||
|
return attr; |
||||||
|
} else { |
||||||
|
throw new IllegalStateException("[ESD]No editing template found."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 获取模版数据集配置 |
||||||
|
* |
||||||
|
* @param dsName |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static StrategyConfig getStrategyConfig(String dsName) { |
||||||
|
|
||||||
|
return getStrategyConfigsAttr().getStrategyConfig(dsName); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 移除模版数据集配置 |
||||||
|
* |
||||||
|
* @param dsName |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static StrategyConfig removeStrategyConfig(String dsName) { |
||||||
|
|
||||||
|
return getStrategyConfigsAttr().removeStrategyConfig(dsName); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加模版数据集配置 |
||||||
|
* |
||||||
|
* @param strategyConfig |
||||||
|
*/ |
||||||
|
public static void addStrategyConfig(StrategyConfig strategyConfig) { |
||||||
|
|
||||||
|
getStrategyConfigsAttr().addStrategyConfig(strategyConfig); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class StrategyConfigsAttrSavedHook implements XMLSavedHook<StrategyConfigsAttr> { |
||||||
|
|
||||||
|
private static final long serialVersionUID = -8843201977112289321L; |
||||||
|
|
||||||
|
private final String tplPath; |
||||||
|
private final Map<String, StrategyConfig> origStrategyConfigs; |
||||||
|
|
||||||
|
public StrategyConfigsAttrSavedHook(String tplPath, StrategyConfigsAttr raw) { |
||||||
|
this.tplPath = tplPath; |
||||||
|
this.origStrategyConfigs = new HashMap<>(); |
||||||
|
this.initOrigStrategyConfigs(raw); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void initOrigStrategyConfigs(StrategyConfigsAttr raw) { |
||||||
|
origStrategyConfigs.clear(); |
||||||
|
raw.getStrategyConfigs().forEach((k, v) -> { |
||||||
|
try { |
||||||
|
origStrategyConfigs.put(k, v.clone()); |
||||||
|
} catch (CloneNotSupportedException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doAfterSaved(StrategyConfigsAttr saved) { |
||||||
|
|
||||||
|
FineLoggerFactory.getLogger().info("[ESD]Write StrategyConfigsAttr done, now check change."); |
||||||
|
Set<String> dsNames = new HashSet<>(); |
||||||
|
dsNames.addAll(origStrategyConfigs.keySet()); |
||||||
|
dsNames.addAll(saved.getStrategyConfigs().keySet()); |
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(tplPath)) { |
||||||
|
dsNames.forEach(dsName -> { |
||||||
|
if (StringUtils.isNotEmpty(dsName)) { |
||||||
|
StrategyEventsNotifier.compareAndFireConfigEvents(origStrategyConfigs.get(dsName), saved.getStrategyConfig(dsName), new DSMapping(tplPath, new DsNameTarget(dsName))); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
initOrigStrategyConfigs(saved); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,226 @@ |
|||||||
|
package com.fr.design.data.datapane; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.gui.ibutton.UIRadioButton; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.ilable.ActionLabel; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.utils.gui.GUICoreUtils; |
||||||
|
import com.fr.esd.common.CacheConstants; |
||||||
|
import com.fr.esd.core.strategy.config.StrategyConfig; |
||||||
|
import com.fr.esd.core.strategy.config.StrategyConfigHelper; |
||||||
|
import com.fr.esd.util.ESDUtils; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.AbstractAction; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Desktop; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.net.URI; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author rinoux |
||||||
|
* @version 10.0 |
||||||
|
* Created by rinoux on 2020/7/22 |
||||||
|
*/ |
||||||
|
public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> { |
||||||
|
private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html"; |
||||||
|
|
||||||
|
private UIRadioButton selectAutoUpdate; |
||||||
|
private UIRadioButton selectBySchema; |
||||||
|
private UICheckBox shouldEvolve; |
||||||
|
private UILabel updateIntervalCheckTips; |
||||||
|
private UITextField updateInterval; |
||||||
|
private UITextField schemaTime; |
||||||
|
private ActionLabel actionLabel; |
||||||
|
private UILabel schemaTimeCheckTips; |
||||||
|
private final boolean global; |
||||||
|
private StrategyConfig strategyConfig; |
||||||
|
|
||||||
|
|
||||||
|
public ESDStrategyConfigPane(boolean global) { |
||||||
|
this.global = global; |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
private void init() { |
||||||
|
setLayout(FRGUIPaneFactory.createM_BorderLayout()); |
||||||
|
|
||||||
|
this.selectAutoUpdate = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Every_Interval")); |
||||||
|
|
||||||
|
this.updateInterval = new UITextField(4); |
||||||
|
this.shouldEvolve = new UICheckBox(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Auto_Evolved_Strategy"), false); |
||||||
|
this.shouldEvolve.setEnabled(false); |
||||||
|
this.updateIntervalCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Interval_Format")); |
||||||
|
this.updateIntervalCheckTips.setForeground(Color.RED); |
||||||
|
this.updateIntervalCheckTips.setVisible(false); |
||||||
|
|
||||||
|
this.selectBySchema = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron")); |
||||||
|
this.schemaTime = new UITextField(10); |
||||||
|
this.schemaTimeCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format")); |
||||||
|
this.schemaTimeCheckTips.setVisible(false); |
||||||
|
this.schemaTimeCheckTips.setForeground(Color.RED); |
||||||
|
|
||||||
|
|
||||||
|
this.selectAutoUpdate.addActionListener(new AbstractAction() { |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
ESDStrategyConfigPane.this.selectBySchema.setSelected(!ESDStrategyConfigPane.this.selectAutoUpdate.isSelected()); |
||||||
|
ESDStrategyConfigPane.this.schemaTime.setEnabled(false); |
||||||
|
ESDStrategyConfigPane.this.updateInterval.setEnabled(true); |
||||||
|
ESDStrategyConfigPane.this.shouldEvolve.setEnabled(true); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
this.selectBySchema.addActionListener(new AbstractAction() { |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
ESDStrategyConfigPane.this.selectAutoUpdate.setSelected(!ESDStrategyConfigPane.this.selectBySchema.isSelected()); |
||||||
|
ESDStrategyConfigPane.this.schemaTime.setEnabled(true); |
||||||
|
ESDStrategyConfigPane.this.updateInterval.setEnabled(false); |
||||||
|
ESDStrategyConfigPane.this.shouldEvolve.setEnabled(false); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
JPanel pane = FRGUIPaneFactory.createVerticalTitledBorderPane(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Update_Strategy")); |
||||||
|
add(pane, BorderLayout.NORTH); |
||||||
|
|
||||||
|
JPanel row1 = GUICoreUtils.createFlowPane(new Component[]{ |
||||||
|
this.selectAutoUpdate, |
||||||
|
this.updateInterval, |
||||||
|
new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Minute_Update_Cache")), |
||||||
|
this.shouldEvolve, |
||||||
|
this.updateIntervalCheckTips |
||||||
|
}, 0, 5); |
||||||
|
pane.add(row1); |
||||||
|
|
||||||
|
ActionLabel actionLabel = new ActionLabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron_Help")); |
||||||
|
actionLabel.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
try { |
||||||
|
Desktop.getDesktop().browse(new URI(CRON_HELP_URL)); |
||||||
|
} catch (Exception exp) { |
||||||
|
FineLoggerFactory.getLogger().error(exp.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
JPanel row2 = GUICoreUtils.createFlowPane(new Component[]{ |
||||||
|
this.selectBySchema, |
||||||
|
this.schemaTime, |
||||||
|
actionLabel, |
||||||
|
this.schemaTimeCheckTips |
||||||
|
}, 0, 5); |
||||||
|
pane.add(row2); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void populateBean(StrategyConfig ob) { |
||||||
|
|
||||||
|
if (ob == null && !global) { |
||||||
|
ob = StrategyConfigHelper.createStrategyConfig(true, false, true); |
||||||
|
} |
||||||
|
this.strategyConfig = ob; |
||||||
|
|
||||||
|
this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.valueOf(ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE)); |
||||||
|
this.schemaTime.setText(StringUtils.join(",", ob.getUpdateSchema().toArray(new String[0]))); |
||||||
|
this.shouldEvolve.setSelected(ob.shouldEvolve()); |
||||||
|
this.selectBySchema.setSelected(ob.isScheduleBySchema()); |
||||||
|
this.selectAutoUpdate.setSelected(!ob.isScheduleBySchema()); |
||||||
|
|
||||||
|
if (global) { |
||||||
|
//使用全局配置,禁用面板编辑
|
||||||
|
disablePane(); |
||||||
|
} else { |
||||||
|
setSchemaEnable(!this.selectAutoUpdate.isSelected()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void disablePane() { |
||||||
|
this.selectAutoUpdate.setEnabled(false); |
||||||
|
this.updateInterval.setEnabled(false); |
||||||
|
this.shouldEvolve.setEnabled(false); |
||||||
|
|
||||||
|
this.selectBySchema.setEnabled(false); |
||||||
|
this.schemaTime.setEnabled(false); |
||||||
|
} |
||||||
|
|
||||||
|
private void setSchemaEnable(boolean enable) { |
||||||
|
this.updateInterval.setEnabled(!enable); |
||||||
|
this.shouldEvolve.setEnabled(!enable); |
||||||
|
|
||||||
|
this.schemaTime.setEnabled(enable); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public StrategyConfig updateBean() { |
||||||
|
StrategyConfig config = null; |
||||||
|
if (!this.global) { |
||||||
|
try { |
||||||
|
//这里是new的config
|
||||||
|
config = this.strategyConfig.clone(); |
||||||
|
|
||||||
|
if (this.selectBySchema.isSelected()) { |
||||||
|
List<String> schemaTimes = new ArrayList<>(); |
||||||
|
String text = this.schemaTime.getText(); |
||||||
|
|
||||||
|
if (ESDUtils.checkUpdateTimeSchema(text)) { |
||||||
|
if (ESDUtils.isCronExpression(text)) { |
||||||
|
schemaTimes.add(text); |
||||||
|
} else { |
||||||
|
Collections.addAll(schemaTimes, text.split(",")); |
||||||
|
} |
||||||
|
} else { |
||||||
|
this.schemaTimeCheckTips.setVisible(true); |
||||||
|
throw new IllegalArgumentException("[ESD]Update schema time format error."); |
||||||
|
} |
||||||
|
config.setScheduleBySchema(true); |
||||||
|
config.setUpdateSchema(schemaTimes); |
||||||
|
} else { |
||||||
|
String interval = this.updateInterval.getText(); |
||||||
|
if (checkUpdateInterval(interval)) { |
||||||
|
long intervalMillis = StringUtils.isEmpty(interval) ? 0 : (long) (Double.parseDouble(interval) * CacheConstants.MILLIS_OF_MINUTE); |
||||||
|
config.setUpdateInterval(intervalMillis); |
||||||
|
} else { |
||||||
|
this.updateIntervalCheckTips.setVisible(true); |
||||||
|
throw new IllegalArgumentException("[ESD]Error update interval format."); |
||||||
|
} |
||||||
|
|
||||||
|
config.setShouldEvolve(this.shouldEvolve.isSelected()); |
||||||
|
config.setScheduleBySchema(false); |
||||||
|
} |
||||||
|
} catch (CloneNotSupportedException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return config; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private boolean checkUpdateInterval(String intervalValue) { |
||||||
|
try { |
||||||
|
return !StringUtils.isEmpty(intervalValue) && !(Double.parseDouble(intervalValue) <= 0); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected String title4PopupWindow() { |
||||||
|
return InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Strategy_Config_Title"); |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -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,48 @@ |
|||||||
|
package com.fr.design.data.datapane.connect; |
||||||
|
|
||||||
|
import com.fr.design.dialog.BasicDialog; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
import com.fr.design.editlock.EditLockUtils; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.file.ConnectionConfig; |
||||||
|
import com.fr.report.LockItem; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2021/9/8 |
||||||
|
*/ |
||||||
|
public class ConnectionListDialogActionAdapter extends DialogActionAdapter { |
||||||
|
|
||||||
|
private final ConnectionManagerPane connectionManagerPane; |
||||||
|
private final BasicDialog connectionListDialog; |
||||||
|
private final ConnectionConfig connectionConfig; |
||||||
|
|
||||||
|
public ConnectionListDialogActionAdapter(ConnectionManagerPane connectionManagerPane, |
||||||
|
BasicDialog connectionListDialog, |
||||||
|
ConnectionConfig connectionConfig) { |
||||||
|
this.connectionManagerPane = connectionManagerPane; |
||||||
|
this.connectionListDialog = connectionListDialog; |
||||||
|
this.connectionConfig = connectionConfig; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
if (!connectionManagerPane.isNamePermitted()) { |
||||||
|
connectionListDialog.setDoOKSucceed(false); |
||||||
|
return; |
||||||
|
} |
||||||
|
connectionManagerPane.update(connectionConfig); |
||||||
|
DesignerContext.getDesignerBean("databasename").refreshBeanElement(); |
||||||
|
// 关闭定义数据连接页面,为其解锁
|
||||||
|
EditLockUtils.unlock(LockItem.CONNECTION); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doCancel() { |
||||||
|
// 关闭定义数据连接页面,为其解锁
|
||||||
|
super.doCancel(); |
||||||
|
EditLockUtils.unlock(LockItem.CONNECTION); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package com.fr.design.data.tabledata.strategy; |
||||||
|
|
||||||
|
import com.fr.esd.core.strategy.config.StrategyConfig; |
||||||
|
import com.fr.esd.query.StrategicTableData; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author rinoux |
||||||
|
* @version 10.0 |
||||||
|
* Created by rinoux on 2021/3/19 |
||||||
|
*/ |
||||||
|
public abstract class StrategyConfigHandler<T extends StrategicTableData> { |
||||||
|
|
||||||
|
private final T tableData; |
||||||
|
|
||||||
|
public StrategyConfigHandler(T tableData) { |
||||||
|
this.tableData = tableData; |
||||||
|
} |
||||||
|
|
||||||
|
protected T getTableData() { |
||||||
|
return tableData; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 查找配置 |
||||||
|
* |
||||||
|
* @return 缓存配置 |
||||||
|
*/ |
||||||
|
public abstract StrategyConfig find(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 保存配置 |
||||||
|
* |
||||||
|
* @param config 缓存配置 |
||||||
|
*/ |
||||||
|
public abstract void save(T saved, StrategyConfig config); |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package com.fr.design.data.tabledata.tabledatapane.db; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
public enum StrategyConfigFrom { |
||||||
|
GLOBAL(0, Toolkit.i18nText("Fine-Design_ESD_Use_Global_Settings")), |
||||||
|
|
||||||
|
INDIVIDUAL(1, Toolkit.i18nText("Fine-Design_ESD_Use_Individual_Settings")); |
||||||
|
|
||||||
|
int index; |
||||||
|
|
||||||
|
String displayText; |
||||||
|
|
||||||
|
StrategyConfigFrom(int index, String displayText) { |
||||||
|
this.index = index; |
||||||
|
this.displayText = displayText; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public int getIndex() { |
||||||
|
return this.index; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String getDisplayText() { |
||||||
|
return this.displayText; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String toString() { |
||||||
|
return getDisplayText(); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@ |
|||||||
|
package com.fr.design.formula; |
||||||
|
|
||||||
|
import com.fr.design.formula.exception.FormulaExceptionTipsProcessor; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.parser.FRParser; |
||||||
|
import com.fr.script.checker.FunctionCheckerDispatcher; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.script.Expression; |
||||||
|
import com.fr.stable.script.Node; |
||||||
|
import com.fr.third.antlr.TokenStreamRecognitionException; |
||||||
|
|
||||||
|
import java.io.StringReader; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/9/28 |
||||||
|
*/ |
||||||
|
public class FormulaChecker { |
||||||
|
public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula"); |
||||||
|
public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"); |
||||||
|
private static FormulaExceptionTipsProcessor processor = FormulaExceptionTipsProcessor.getProcessor(); |
||||||
|
|
||||||
|
public static FormulaCheckResult check(String formulaText) { |
||||||
|
if (StringUtils.isEmpty(formulaText) || formulaText.equals(Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Tips"))) { |
||||||
|
return new FormulaCheckResult(true, VALID_FORMULA, FormulaCoordinates.INVALID, true); |
||||||
|
} |
||||||
|
//过滤一些空格等符号
|
||||||
|
StringReader in = new StringReader(formulaText); |
||||||
|
//此lexer为公式校验定制
|
||||||
|
FRFormulaLexer lexer = new FRFormulaLexer(in); |
||||||
|
FRParser parser = new FRParser(lexer); |
||||||
|
|
||||||
|
try { |
||||||
|
Expression expression = parser.parse(); |
||||||
|
Node node = expression.getConditionalExpression(); |
||||||
|
boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(formulaText, node); |
||||||
|
return new FormulaCheckResult(valid, valid ? Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula") : |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"), FormulaCoordinates.INVALID, true); |
||||||
|
} catch (Exception e) { |
||||||
|
if (e instanceof TokenStreamRecognitionException) { |
||||||
|
return processor.getExceptionTips(((TokenStreamRecognitionException) e).recog); |
||||||
|
} |
||||||
|
return processor.getExceptionTips(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package com.fr.design.formula; |
||||||
|
|
||||||
|
public class FormulaCheckerException extends Exception { |
||||||
|
public FormulaCheckerException() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public FormulaCheckerException(String message) { |
||||||
|
super(message); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.fr.design.formula; |
||||||
|
|
||||||
|
import com.fr.parser.BinaryExpression; |
||||||
|
import com.fr.parser.DatasetFunctionCall; |
||||||
|
import com.fr.parser.FunctionCall; |
||||||
|
import com.fr.stable.script.Node; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/8/30 |
||||||
|
*/ |
||||||
|
public class UnsupportedFormulaScanner { |
||||||
|
public final static String[] UNSUPPORTED_FORMULAS = new String[]{"PROPORTION", "TOIMAGE", |
||||||
|
"WEBIMAGE", "SORT", "CROSSLAYERTOTAL", "CIRCULAR", "LAYERTOTAL", "MOM", "HIERARCHY", |
||||||
|
"FILENAME", "FILESIZE", "FILETYPE", "TREELAYER", "GETUSERDEPARTMENTS", "GETUSERJOBTITLES"}; |
||||||
|
|
||||||
|
private String unSupportFormula = ""; |
||||||
|
|
||||||
|
public boolean travelFormula(Node node) { |
||||||
|
if (node instanceof FunctionCall) { |
||||||
|
if (isUnsupportedFomula(((FunctionCall) node).getName())) { |
||||||
|
unSupportFormula = ((FunctionCall) node).getName(); |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
for (Node argument : ((FunctionCall) node).getArguments()) { |
||||||
|
if (!travelFormula(argument)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (node instanceof BinaryExpression) { |
||||||
|
for (Node array : ((BinaryExpression) node).getNodes()) { |
||||||
|
if (!travelFormula(array)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (node instanceof DatasetFunctionCall) { |
||||||
|
DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) node; |
||||||
|
unSupportFormula = datasetFunctionCall.getSourceName() + "." + datasetFunctionCall.getFnName() + "()"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public String getUnSupportFormula() { |
||||||
|
return unSupportFormula; |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean isUnsupportedFomula(String formula) { |
||||||
|
return Arrays.asList(UNSUPPORTED_FORMULAS).contains(formula.toUpperCase()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
package com.fr.design.formula.exception; |
||||||
|
|
||||||
|
import com.fr.design.formula.FormulaChecker; |
||||||
|
import com.fr.design.formula.exception.function.FormulaCheckWrongFunction; |
||||||
|
import com.fr.design.formula.exception.function.MismatchedCharFunction; |
||||||
|
import com.fr.design.formula.exception.function.MismatchedTokenFunction; |
||||||
|
import com.fr.design.formula.exception.function.NoViableAltForCharFunction; |
||||||
|
import com.fr.design.formula.exception.function.NoViableAltFunction; |
||||||
|
import com.fr.script.checker.exception.FunctionCheckWrongException; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.third.antlr.MismatchedCharException; |
||||||
|
import com.fr.third.antlr.MismatchedTokenException; |
||||||
|
import com.fr.third.antlr.NoViableAltException; |
||||||
|
import com.fr.third.antlr.NoViableAltForCharException; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/26 |
||||||
|
*/ |
||||||
|
public class FormulaExceptionTipsProcessor { |
||||||
|
private static final Map<Class, Function<Exception, FormulaCheckResult>> EXCEPTION_TIPS = new ConcurrentHashMap<>(); |
||||||
|
|
||||||
|
private static final FormulaExceptionTipsProcessor PROCESSOR = new FormulaExceptionTipsProcessor(); |
||||||
|
|
||||||
|
static { |
||||||
|
EXCEPTION_TIPS.put(FunctionCheckWrongException.class, FormulaCheckWrongFunction.getFunction()); |
||||||
|
EXCEPTION_TIPS.put(MismatchedCharException.class, MismatchedCharFunction.getFunction()); |
||||||
|
EXCEPTION_TIPS.put(MismatchedTokenException.class, MismatchedTokenFunction.getFunction()); |
||||||
|
EXCEPTION_TIPS.put(NoViableAltException.class, NoViableAltFunction.getFunction()); |
||||||
|
EXCEPTION_TIPS.put(NoViableAltForCharException.class, NoViableAltForCharFunction.getFunction()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public FormulaCheckResult getExceptionTips(Exception e) { |
||||||
|
return EXCEPTION_TIPS.getOrDefault(e.getClass(), |
||||||
|
e1 -> new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false)) |
||||||
|
.apply(e); |
||||||
|
} |
||||||
|
|
||||||
|
public static FormulaExceptionTipsProcessor getProcessor() { |
||||||
|
return PROCESSOR; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/28 |
||||||
|
*/ |
||||||
|
public class FormulaCheckConstants { |
||||||
|
public static final String COLON = ":"; |
||||||
|
public static final String LEFT = "("; |
||||||
|
public static final String COMMON = ","; |
||||||
|
public static final String RIGHT = ")"; |
||||||
|
public static final String BLANK = " "; |
||||||
|
public static final String SINGLE_QUOTES = "'"; |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.script.checker.exception.FunctionCheckWrongException; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.script.rules.FunctionParameterType; |
||||||
|
import com.fr.script.rules.FunctionRule; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/26 |
||||||
|
*/ |
||||||
|
public class FormulaCheckWrongFunction implements Function<Exception, FormulaCheckResult> { |
||||||
|
private final static FormulaCheckWrongFunction FUNCTION = new FormulaCheckWrongFunction(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public FormulaCheckResult apply(Exception e) { |
||||||
|
if (e instanceof FunctionCheckWrongException) { |
||||||
|
FunctionCheckWrongException ce = (FunctionCheckWrongException) e; |
||||||
|
List<FunctionRule> rules = ce.getRules(); |
||||||
|
String functionName = ce.getFunctionName(); |
||||||
|
StringBuilder errorMsg = new StringBuilder(functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + FormulaCheckConstants.COLON); |
||||||
|
for (int i = 0; i < rules.size(); i++) { |
||||||
|
errorMsg.append(FormulaCheckConstants.LEFT); |
||||||
|
if (rules.get(i).getParameterList().isEmpty()) { |
||||||
|
errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param")); |
||||||
|
} |
||||||
|
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) { |
||||||
|
errorMsg.append(getTypeString(functionParameterType)).append(FormulaCheckConstants.COMMON); |
||||||
|
} |
||||||
|
if (FormulaCheckConstants.COMMON.equals(errorMsg.charAt(errorMsg.length() - 1) + StringUtils.EMPTY)) { |
||||||
|
errorMsg.deleteCharAt(errorMsg.length() - 1); |
||||||
|
} |
||||||
|
errorMsg.append(FormulaCheckConstants.RIGHT); |
||||||
|
if (i != rules.size() - 1) { |
||||||
|
errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or")); |
||||||
|
} |
||||||
|
} |
||||||
|
return new FormulaCheckResult(false, errorMsg.toString(), new FormulaCoordinates(1, indexPosition(ce.getFormulaText(), ce.getNode().toString())), true); |
||||||
|
} |
||||||
|
return new FormulaCheckResult(false, StringUtils.EMPTY, new FormulaCoordinates(-1, -1), true); |
||||||
|
} |
||||||
|
|
||||||
|
private static String getTypeString(FunctionParameterType type) { |
||||||
|
switch (type) { |
||||||
|
case NUMBER: |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number"); |
||||||
|
case STRING: |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String"); |
||||||
|
case ANY: |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any"); |
||||||
|
case DATE: |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date"); |
||||||
|
case BOOLEAN: |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean"); |
||||||
|
case ARRAY: |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array"); |
||||||
|
} |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
public static Function<Exception, FormulaCheckResult> getFunction() { |
||||||
|
return FUNCTION; |
||||||
|
} |
||||||
|
|
||||||
|
private int indexPosition(String formulaText, String invalidFormula) { |
||||||
|
//处理一下自己FunctionCall自己拼的逗号逻辑
|
||||||
|
if (invalidFormula.contains(",")) { |
||||||
|
invalidFormula = invalidFormula.substring(0, invalidFormula.indexOf(",")); |
||||||
|
} |
||||||
|
int index = formulaText.indexOf(invalidFormula); |
||||||
|
return index; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
import com.fr.design.formula.FormulaChecker; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.third.antlr.MismatchedCharException; |
||||||
|
|
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/28 |
||||||
|
*/ |
||||||
|
public class MismatchedCharFunction implements Function<Exception, FormulaCheckResult> { |
||||||
|
private final static MismatchedCharFunction FUNCTION = new MismatchedCharFunction(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public FormulaCheckResult apply(Exception e) { |
||||||
|
if (e instanceof MismatchedCharException) { |
||||||
|
MismatchedCharException charException = (MismatchedCharException) e; |
||||||
|
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1); |
||||||
|
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false); |
||||||
|
} |
||||||
|
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static Function<Exception, FormulaCheckResult> getFunction() { |
||||||
|
return FUNCTION; |
||||||
|
} |
||||||
|
|
||||||
|
private String getMessage(MismatchedCharException charException) { |
||||||
|
StringBuffer sb = new StringBuffer(); |
||||||
|
switch (charException.mismatchType) { |
||||||
|
case 1: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": "); |
||||||
|
appendCharName(sb, charException.expecting); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ") |
||||||
|
.append(FormulaCheckConstants.BLANK) |
||||||
|
.append(FormulaCheckConstants.SINGLE_QUOTES); |
||||||
|
appendCharName(sb, charException.expecting); |
||||||
|
sb.append("';").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway")); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
case 4: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token")); |
||||||
|
if (charException.mismatchType == 4) { |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not")); |
||||||
|
} |
||||||
|
|
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")).append(": "); |
||||||
|
appendCharName(sb, charException.expecting); |
||||||
|
sb.append(".."); |
||||||
|
appendCharName(sb, charException.upper); |
||||||
|
break; |
||||||
|
case 5: |
||||||
|
case 6: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") |
||||||
|
.append(charException.mismatchType == 6 ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not") : FormulaCheckConstants.BLANK) |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF")).append(" ("); |
||||||
|
int[] elems = charException.set.toArray(); |
||||||
|
|
||||||
|
for (int i = 0; i < elems.length; ++i) { |
||||||
|
appendCharName(sb, elems[i]); |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Char")); |
||||||
|
} |
||||||
|
|
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private void appendCharName(StringBuffer sb, int c) { |
||||||
|
switch (c) { |
||||||
|
case 9: |
||||||
|
sb.append("'\\t'"); |
||||||
|
break; |
||||||
|
case 10: |
||||||
|
sb.append("'\\n'"); |
||||||
|
break; |
||||||
|
case 13: |
||||||
|
sb.append("'\\r'"); |
||||||
|
break; |
||||||
|
case 65535: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF")); |
||||||
|
break; |
||||||
|
default: |
||||||
|
sb.append((char) c); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,110 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
import com.fr.design.formula.FormulaChecker; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.third.antlr.MismatchedTokenException; |
||||||
|
|
||||||
|
import java.lang.reflect.Field; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/28 |
||||||
|
*/ |
||||||
|
public class MismatchedTokenFunction implements Function<Exception, FormulaCheckResult> { |
||||||
|
private final static MismatchedTokenFunction FUNCTION = new MismatchedTokenFunction(); |
||||||
|
public static final String NULL_STRING = "null"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public FormulaCheckResult apply(Exception e) { |
||||||
|
if (e instanceof MismatchedTokenException) { |
||||||
|
MismatchedTokenException charException = (MismatchedTokenException) e; |
||||||
|
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1); |
||||||
|
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false); |
||||||
|
} |
||||||
|
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static Function<Exception, FormulaCheckResult> getFunction() { |
||||||
|
return FUNCTION; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage(MismatchedTokenException exception) { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
Object fieldValue = getFieldValue(exception, "tokenText"); |
||||||
|
String tokenText = fieldValue == null ? NULL_STRING : fieldValue.toString(); |
||||||
|
switch (exception.mismatchType) { |
||||||
|
case 1: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") |
||||||
|
.append(tokenName(exception.expecting, exception)); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ") |
||||||
|
.append(tokenName(exception.expecting, exception)) |
||||||
|
.append("; ") |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway")); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token")) |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")) |
||||||
|
.append(": ") |
||||||
|
.append(tokenName(exception.expecting, exception)) |
||||||
|
.append("..") |
||||||
|
.append(tokenName(exception.upper, exception)); |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token")) |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not")) |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")) |
||||||
|
.append(": ") |
||||||
|
.append(tokenName(exception.expecting, exception)) |
||||||
|
.append("..") |
||||||
|
.append(tokenName(exception.upper, exception)); |
||||||
|
break; |
||||||
|
case 5: |
||||||
|
case 6: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ") |
||||||
|
.append(exception.mismatchType == 6 ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not") : FormulaCheckConstants.BLANK) |
||||||
|
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF")).append("("); |
||||||
|
int[] elms = exception.set.toArray(); |
||||||
|
|
||||||
|
for (int i = 0; i < elms.length; ++i) { |
||||||
|
sb.append(' '); |
||||||
|
sb.append(tokenName(elms[i], exception)); |
||||||
|
} |
||||||
|
|
||||||
|
break; |
||||||
|
default: |
||||||
|
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Token")); |
||||||
|
} |
||||||
|
|
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private String tokenName(int tokenType, MismatchedTokenException exception) { |
||||||
|
if (tokenType == 0) { |
||||||
|
return "<Set of tokens>"; |
||||||
|
} else { |
||||||
|
String[] tokenNames = (String[]) getFieldValue(exception, "tokenNames"); |
||||||
|
return tokenType >= 0 && tokenType < tokenNames.length ? TranslateTokenUtils.translateToken(tokenNames[tokenType]) : "<" + tokenType + ">"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private Object getFieldValue(Object object, String fieldName) { |
||||||
|
try { |
||||||
|
Field field = object.getClass().getDeclaredField(fieldName); |
||||||
|
field.setAccessible(true); |
||||||
|
return field.get(object); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().warn(e.getMessage(), e); |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
import com.fr.design.formula.FormulaChecker; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.third.antlr.NoViableAltForCharException; |
||||||
|
|
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/28 |
||||||
|
*/ |
||||||
|
public class NoViableAltForCharFunction implements Function<Exception, FormulaCheckResult> { |
||||||
|
private final static NoViableAltForCharFunction FUNCTION = new NoViableAltForCharFunction(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public FormulaCheckResult apply(Exception e) { |
||||||
|
if (e instanceof NoViableAltForCharException) { |
||||||
|
NoViableAltForCharException charException = (NoViableAltForCharException) e; |
||||||
|
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1); |
||||||
|
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false); |
||||||
|
} |
||||||
|
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static Function<Exception, FormulaCheckResult> getFunction() { |
||||||
|
return FUNCTION; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage(NoViableAltForCharException exception) { |
||||||
|
String mesg = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Char") + ": "; |
||||||
|
if (exception.foundChar >= ' ' && exception.foundChar <= '~') { |
||||||
|
mesg = mesg + '\''; |
||||||
|
mesg = mesg + exception.foundChar; |
||||||
|
mesg = mesg + '\''; |
||||||
|
} else { |
||||||
|
mesg = mesg + exception.foundChar; |
||||||
|
} |
||||||
|
|
||||||
|
return mesg; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
import com.fr.design.formula.FormulaChecker; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.script.checker.result.FormulaCheckResult; |
||||||
|
import com.fr.script.checker.result.FormulaCoordinates; |
||||||
|
import com.fr.third.antlr.NoViableAltException; |
||||||
|
import com.fr.third.antlr.TreeParser; |
||||||
|
|
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/10/28 |
||||||
|
*/ |
||||||
|
public class NoViableAltFunction implements Function<Exception, FormulaCheckResult> { |
||||||
|
private final static NoViableAltFunction FUNCTION = new NoViableAltFunction(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public FormulaCheckResult apply(Exception e) { |
||||||
|
if (e instanceof NoViableAltException) { |
||||||
|
NoViableAltException altException = (NoViableAltException) e; |
||||||
|
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(altException.line, altException.column - 1); |
||||||
|
return new FormulaCheckResult(false, getMessage(altException), formulaCoordinates, false); |
||||||
|
} |
||||||
|
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static Function<Exception, FormulaCheckResult> getFunction() { |
||||||
|
return FUNCTION; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage(NoViableAltException exception) { |
||||||
|
if (exception.token != null) { |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Token") + ": " + exception.token.getText(); |
||||||
|
} else { |
||||||
|
return exception.node == TreeParser.ASTNULL ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_End_Of_Subtree") : |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_AST_Node") + ": " + exception.node.toString(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
package com.fr.design.formula.exception.function; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/11/30 |
||||||
|
*/ |
||||||
|
public class TranslateTokenUtils { |
||||||
|
public static String translateToken(String token) { |
||||||
|
switch (token) { |
||||||
|
case ("RPAREN"): |
||||||
|
return ")"; |
||||||
|
case ("LPAREN"): |
||||||
|
return "("; |
||||||
|
case ("COMMA"): |
||||||
|
return ","; |
||||||
|
case ("COLON"): |
||||||
|
return ":"; |
||||||
|
case ("EOF"): |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF"); |
||||||
|
case ("DOT"): |
||||||
|
return "."; |
||||||
|
case ("FLOT_NUM"): |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Float_Number"); |
||||||
|
case ("LOR"): |
||||||
|
return "||"; |
||||||
|
case ("LAND"): |
||||||
|
return "&&"; |
||||||
|
case ("EQUAL"): |
||||||
|
return "="; |
||||||
|
case ("EQUAL2"): |
||||||
|
return "="; |
||||||
|
case ("NOT_EQUAL"): |
||||||
|
return "!="; |
||||||
|
case ("NOT_EQUAL2"): |
||||||
|
return "!="; |
||||||
|
case ("GE"): |
||||||
|
return ">="; |
||||||
|
case ("LE"): |
||||||
|
return "<="; |
||||||
|
case ("LT"): |
||||||
|
return "<"; |
||||||
|
case ("PLUS"): |
||||||
|
return "+"; |
||||||
|
case ("MINUS"): |
||||||
|
return "-"; |
||||||
|
case ("STAR"): |
||||||
|
return "*"; |
||||||
|
case ("DIV"): |
||||||
|
return "/"; |
||||||
|
case ("MOD"): |
||||||
|
return "%"; |
||||||
|
case ("POWER"): |
||||||
|
return "^"; |
||||||
|
case ("LNOT"): |
||||||
|
return "!"; |
||||||
|
case ("WAVE"): |
||||||
|
return "~"; |
||||||
|
case ("LBRACK"): |
||||||
|
return "["; |
||||||
|
case ("SEMI"): |
||||||
|
return ";"; |
||||||
|
case ("RBRACK"): |
||||||
|
return "]"; |
||||||
|
case ("LCURLY"): |
||||||
|
return "{"; |
||||||
|
case ("RCURLY"): |
||||||
|
return "}"; |
||||||
|
case ("DCOLON"): |
||||||
|
return ";"; |
||||||
|
case ("INT_NUM"): |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Integer"); |
||||||
|
case ("CR_ADRESS"): |
||||||
|
return "\n"; |
||||||
|
case ("SHARP"): |
||||||
|
return "#"; |
||||||
|
case ("AT"): |
||||||
|
return "@"; |
||||||
|
case ("QUESTION"): |
||||||
|
return "?"; |
||||||
|
case ("BOR"): |
||||||
|
return "||"; |
||||||
|
case ("BAND"): |
||||||
|
return "&&"; |
||||||
|
case ("Char"): |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Character"); |
||||||
|
case ("DIGIT"): |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Digital"); |
||||||
|
case ("XDIGIT"): |
||||||
|
return Toolkit.i18nText("Fine-Design_Basic_Formula_Hexadecimal_Digital"); |
||||||
|
default: |
||||||
|
return token; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.stable.fun.mark.Mutable; |
||||||
|
|
||||||
|
|
||||||
|
public interface PcFitProvider extends Mutable { |
||||||
|
String XML_TAG = "PcFitProvider"; |
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
//设计器上看到的选项
|
||||||
|
String getContentDisplayValue(); |
||||||
|
|
||||||
|
//返回给前端的值
|
||||||
|
int getContentDisplayKey(); |
||||||
|
|
||||||
|
//设计器上的提示信息
|
||||||
|
String getContentDisplayTip(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.PcFitProvider; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
|
||||||
|
@API(level = PcFitProvider.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractPcFitProvider implements PcFitProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String mark4Provider() { |
||||||
|
return getClass().getName(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.intelli.record.Focus; |
||||||
|
import com.fr.intelli.record.Original; |
||||||
|
import com.fr.record.analyzer.EnableMetrics; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by rinoux on 2016/12/16. |
||||||
|
*/ |
||||||
|
@EnableMetrics |
||||||
|
public class DesignerStartWithEmptyFile extends AbstractDesignerStartOpenFileProcessor { |
||||||
|
|
||||||
|
private static final DesignerStartWithEmptyFile INSTANCE = new DesignerStartWithEmptyFile(); |
||||||
|
|
||||||
|
private DesignerStartWithEmptyFile() { |
||||||
|
} |
||||||
|
|
||||||
|
public static DesignerStartWithEmptyFile getInstance() { |
||||||
|
return INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@Focus(id = "com.fr.dzstartemptyfile", text = "Fine_Design_Start_Empty_File", source = Original.REPORT) |
||||||
|
public FILE fileToShow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@ |
|||||||
|
package com.fr.design.gui.autocomplete; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Hoky |
||||||
|
* @date 2021/11/5 |
||||||
|
*/ |
||||||
|
public class FormulaCompletion extends BasicCompletion { |
||||||
|
private Icon icon; |
||||||
|
|
||||||
|
public FormulaCompletion(CompletionProvider provider, String replacementText, Icon icon) { |
||||||
|
super(provider, replacementText); |
||||||
|
this.icon = icon; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Icon getIcon() { |
||||||
|
return icon; |
||||||
|
} |
||||||
|
|
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,47 @@ |
|||||||
|
package com.fr.design.gui.frpane; |
||||||
|
|
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Container; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/17 |
||||||
|
*/ |
||||||
|
public class AttributeChangeUtils { |
||||||
|
private static AbstractAttrNoScrollPane findNearestAttrNoScrollPaneAncestor(Component c) { |
||||||
|
for(Container p = c.getParent(); p != null; p = p.getParent()) { |
||||||
|
if (p instanceof AbstractAttrNoScrollPane) { |
||||||
|
return (AbstractAttrNoScrollPane) p; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public static void changeComposedUI(Component composedComponent, boolean fireMiddleStateChanged, UIChangeAction action) { |
||||||
|
AbstractAttrNoScrollPane attrPane = findNearestAttrNoScrollPaneAncestor(composedComponent); |
||||||
|
boolean oldAutoFire = true; |
||||||
|
|
||||||
|
if (!fireMiddleStateChanged) { |
||||||
|
// 禁止属性面板自动处理属性更新
|
||||||
|
if (attrPane != null) { |
||||||
|
oldAutoFire = attrPane.isAutoFireAttributesChanged(); |
||||||
|
attrPane.setAutoFireAttributesChanged(false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 更新UI
|
||||||
|
action.changeComposedUI(); |
||||||
|
|
||||||
|
if (!fireMiddleStateChanged) { |
||||||
|
// 恢复属性面板自动处理属性更新
|
||||||
|
if (attrPane != null) { |
||||||
|
attrPane.setAutoFireAttributesChanged(oldAutoFire); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public interface UIChangeAction { |
||||||
|
void changeComposedUI(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package com.fr.design.gui.ibutton; |
||||||
|
|
||||||
|
import com.fr.design.gui.ipoppane.PopupHider; |
||||||
|
import com.fr.design.style.color.ColorControlWindow; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
|
||||||
|
|
||||||
|
public class UINoThemeColorButton extends UIColorButton{ |
||||||
|
|
||||||
|
public UINoThemeColorButton(Icon icon) { |
||||||
|
super(icon); |
||||||
|
} |
||||||
|
|
||||||
|
protected ColorControlWindow initColorControlWindow(){ |
||||||
|
return new NoThemeColorControlWindow(this); |
||||||
|
} |
||||||
|
|
||||||
|
private class NoThemeColorControlWindow extends ColorControlWindow{ |
||||||
|
|
||||||
|
|
||||||
|
public NoThemeColorControlWindow(PopupHider popupHider) { |
||||||
|
super(popupHider); |
||||||
|
} |
||||||
|
|
||||||
|
protected boolean supportThemeColor(){ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void colorChanged() { |
||||||
|
UINoThemeColorButton.this.setColor(this.getColor()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue