804 changed files with 54535 additions and 4994 deletions
@ -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,117 @@ |
|||||||
|
package com.fr.design.cell; |
||||||
|
|
||||||
|
import com.fr.base.NameStyle; |
||||||
|
import com.fr.base.ScreenResolution; |
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
|
||||||
|
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.RenderingHints; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/3 |
||||||
|
*/ |
||||||
|
public class CellStylePreviewPane 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 String paintText = "Report"; |
||||||
|
private Style style = Style.DEFAULT_STYLE; |
||||||
|
|
||||||
|
public CellStylePreviewPane() { |
||||||
|
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); |
||||||
|
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); |
||||||
|
} |
||||||
|
|
||||||
|
public void setStyle(Style style) { |
||||||
|
this.style = style; |
||||||
|
if (style instanceof NameStyle) { |
||||||
|
paintText = ((NameStyle) style).getName(); |
||||||
|
} |
||||||
|
repaint(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
Graphics2D g2d = (Graphics2D) g; |
||||||
|
g.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(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); |
||||||
|
|
||||||
|
Style.paintBorder(g2d, style, width, height); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Dimension getMinimumSize() { |
||||||
|
return getPreferredSize(); |
||||||
|
} |
||||||
|
} |
@ -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,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(); |
||||||
|
} |
||||||
|
} |
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,78 @@ |
|||||||
|
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(",")); |
||||||
|
} |
||||||
|
return formulaText.indexOf(invalidFormula); |
||||||
|
} |
||||||
|
} |
@ -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()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.general.act.BorderPacker; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/11 |
||||||
|
*/ |
||||||
|
public abstract class AbstractBorderPackerPane extends BasicPane { |
||||||
|
|
||||||
|
public abstract void populateBean(BorderPacker style); |
||||||
|
public abstract void updateBean(BorderPacker style); |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.design.designer.IntervalConstants; |
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.gui.frpane.UIPercentDragPane; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; |
||||||
|
import com.fr.design.widget.FRWidgetFactory; |
||||||
|
import com.fr.general.Background; |
||||||
|
import com.fr.general.act.BackgroundPacker; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.event.ChangeEvent; |
||||||
|
import javax.swing.event.ChangeListener; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/11 |
||||||
|
*/ |
||||||
|
public abstract class AbstractTranslucentBackgroundSpecialPane<T extends BackgroundPacker> extends BasicPane { |
||||||
|
|
||||||
|
private final int uiLabelWidth; |
||||||
|
private final int uiSettingWidth; |
||||||
|
// 背景名称:如主题背景 或 标题背景
|
||||||
|
private final String backgroundName; |
||||||
|
// 背景
|
||||||
|
protected BackgroundSpecialPane backgroundPane = new LayoutBackgroundSpecialPane(); |
||||||
|
// 背景透明度
|
||||||
|
protected UIPercentDragPane opacityPane = new UIPercentDragPane(); |
||||||
|
|
||||||
|
public AbstractTranslucentBackgroundSpecialPane(int uiLabelWidth, int uiSettingWidth, String backgroundName) { |
||||||
|
this.uiLabelWidth = uiLabelWidth; |
||||||
|
this.uiSettingWidth = uiSettingWidth; |
||||||
|
this.backgroundName = backgroundName; |
||||||
|
this.initializePane(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initializePane() { |
||||||
|
setLayout(new BorderLayout(0, 0)); |
||||||
|
|
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; |
||||||
|
|
||||||
|
// 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐
|
||||||
|
JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(7, 0, 0, 0)); |
||||||
|
backgroundLabelPane.add(FRWidgetFactory.createLineWrapLabel(backgroundName), BorderLayout.NORTH); |
||||||
|
|
||||||
|
JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( |
||||||
|
new JComponent[][]{ |
||||||
|
{backgroundLabelPane, backgroundPane} |
||||||
|
}, |
||||||
|
new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||||
|
|
||||||
|
JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( |
||||||
|
new JComponent[][]{ |
||||||
|
{new UILabel(""), FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, |
||||||
|
{new UILabel(""), opacityPane} |
||||||
|
}, |
||||||
|
new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||||
|
opacityComposedPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); |
||||||
|
opacityComposedPane.setVisible(false); |
||||||
|
|
||||||
|
backgroundPane.addChangeListener(new ChangeListener() { |
||||||
|
@Override |
||||||
|
public void stateChanged(ChangeEvent e) { |
||||||
|
Background background = backgroundPane.update(); |
||||||
|
opacityComposedPane.setVisible(background != null); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
add(backgroundComposedPane, BorderLayout.NORTH, 0); |
||||||
|
add(opacityComposedPane, BorderLayout.CENTER, 1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public abstract void populateBean(T style); |
||||||
|
|
||||||
|
public abstract void updateBean(T style); |
||||||
|
|
||||||
|
protected static class LayoutBackgroundSpecialPane extends BackgroundSpecialPane { |
||||||
|
@Override |
||||||
|
protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { |
||||||
|
return new GradientBackgroundQuickPane(140); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.general.act.BorderPacker; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/11 |
||||||
|
*/ |
||||||
|
public class ComponentBodyStylePane extends AbstractTranslucentBackgroundSpecialPane<BorderPacker> { |
||||||
|
|
||||||
|
public ComponentBodyStylePane(int uiLabelWidth) { |
||||||
|
this(uiLabelWidth, -1); |
||||||
|
} |
||||||
|
|
||||||
|
public ComponentBodyStylePane(int uiLabelWidth, int uiSettingWidth) { |
||||||
|
super(uiLabelWidth, uiSettingWidth, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(BorderPacker style) { |
||||||
|
this.backgroundPane.populateBean(style.getBackground()); |
||||||
|
if (this.opacityPane != null) { |
||||||
|
this.opacityPane.populateBean(style.getAlpha()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateBean(BorderPacker style) { |
||||||
|
style.setBackground(backgroundPane.update()); |
||||||
|
style.setAlpha((float)opacityPane.updateBean()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.design.designer.IntervalConstants; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBox; |
||||||
|
import com.fr.design.gui.ispinner.UISpinner; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.design.widget.FRWidgetFactory; |
||||||
|
import com.fr.general.act.BorderPacker; |
||||||
|
|
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/11 |
||||||
|
*/ |
||||||
|
public class ComponentIntegralStylePane extends AbstractBorderPackerPane { |
||||||
|
public static final String[] BORDER_STYLE = new String[]{ |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow") |
||||||
|
}; |
||||||
|
|
||||||
|
//渲染风格:有无阴影
|
||||||
|
protected UIComboBox borderStyleCombo; |
||||||
|
// 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色)
|
||||||
|
protected TranslucentBorderSpecialPane borderPane; |
||||||
|
//边框圆角或圆角裁剪
|
||||||
|
protected UISpinner cornerSpinner; |
||||||
|
|
||||||
|
private final int uiLabelWidth; |
||||||
|
private final int uiSettingWidth; |
||||||
|
private final boolean supportBorderImage; |
||||||
|
private final boolean supportCornerRadius; |
||||||
|
|
||||||
|
public ComponentIntegralStylePane(int uiLabelWidth, |
||||||
|
boolean supportBorderImage, boolean supportCornerRadius) { |
||||||
|
this(uiLabelWidth, -1, supportBorderImage, supportCornerRadius); |
||||||
|
} |
||||||
|
|
||||||
|
public ComponentIntegralStylePane(int uiLabelWidth, int uiSettingWidth) { |
||||||
|
this(uiLabelWidth, uiSettingWidth, true, true); |
||||||
|
} |
||||||
|
|
||||||
|
public ComponentIntegralStylePane( |
||||||
|
int uiLabelWidth, int uiSettingWidth, |
||||||
|
boolean supportBorderImage, boolean supportCornerRadius) { |
||||||
|
this.uiLabelWidth = uiLabelWidth; |
||||||
|
this.uiSettingWidth = uiSettingWidth; |
||||||
|
this.supportBorderImage = supportBorderImage; |
||||||
|
this.supportCornerRadius = supportCornerRadius; |
||||||
|
|
||||||
|
this.initializePane(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initializeComponents() { |
||||||
|
borderStyleCombo = new UIComboBox(BORDER_STYLE); |
||||||
|
borderPane = new TranslucentBorderSpecialPane(this.supportBorderImage); |
||||||
|
cornerSpinner = new UISpinner(0,1000,1,0); |
||||||
|
} |
||||||
|
|
||||||
|
protected void initializePane() { |
||||||
|
setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.initializeComponents(); |
||||||
|
|
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double[] rowSize = supportCornerRadius ? new double[] {p, p, p} : new double[]{p, p}; |
||||||
|
double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; |
||||||
|
|
||||||
|
JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ |
||||||
|
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), FRGUIPaneFactory.createBorderLayoutNorthPaneWithComponent(borderStyleCombo)}, |
||||||
|
{this.borderPane, null}, |
||||||
|
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, |
||||||
|
}, |
||||||
|
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); |
||||||
|
|
||||||
|
this.add(content, BorderLayout.NORTH); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(BorderPacker style) { |
||||||
|
if (this.borderStyleCombo != null) { |
||||||
|
this.borderStyleCombo.setSelectedIndex(style.getBorderStyle()); |
||||||
|
} |
||||||
|
if (cornerSpinner != null) { |
||||||
|
this.cornerSpinner.setValue(style.getBorderRadius()); |
||||||
|
} |
||||||
|
if (this.borderPane != null) { |
||||||
|
this.borderPane.populateBean(style); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateBean(BorderPacker style) { |
||||||
|
if (borderStyleCombo != null) { |
||||||
|
style.setBorderStyle(borderStyleCombo.getSelectedIndex()); |
||||||
|
} |
||||||
|
if (cornerSpinner != null) { |
||||||
|
style.setBorderRadius((int) cornerSpinner.getValue()); |
||||||
|
} |
||||||
|
if (borderPane != null) { |
||||||
|
borderPane.updateBean(style); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,351 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.base.Utils; |
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.design.designer.IntervalConstants; |
||||||
|
import com.fr.design.formula.TinyFormulaPane; |
||||||
|
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||||
|
import com.fr.design.gui.ibutton.UIColorButton; |
||||||
|
import com.fr.design.gui.ibutton.UIToggleButton; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBox; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.design.widget.FRWidgetFactory; |
||||||
|
import com.fr.form.ui.LayoutBorderStyle; |
||||||
|
import com.fr.form.ui.WidgetTitle; |
||||||
|
import com.fr.general.FRFont; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.general.act.BorderPacker; |
||||||
|
import com.fr.general.act.TitlePacker; |
||||||
|
import com.fr.stable.Constants; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.event.ChangeEvent; |
||||||
|
import javax.swing.event.ChangeListener; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.Font; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/11 |
||||||
|
*/ |
||||||
|
public class ComponentTitleStylePane extends AbstractBorderPackerPane { |
||||||
|
private static final Dimension BUTTON_SIZE = new Dimension(20, 20); |
||||||
|
public static final TitlePacker DEFAULT_TITLE_PACKER = new WidgetTitle(); |
||||||
|
|
||||||
|
// 标题可见
|
||||||
|
protected UICheckBox visibleCheckbox; |
||||||
|
//标题文字内容
|
||||||
|
protected TinyFormulaPane textContentPane; |
||||||
|
//标题字体格式
|
||||||
|
protected UIComboBox fontFamilyComboBox; |
||||||
|
//标题字体大小
|
||||||
|
protected UIComboBox fontSizeComboBox; |
||||||
|
//标题字体颜色
|
||||||
|
protected UIColorButton fontColorSelectPane; |
||||||
|
//标题字体特殊效果:粗体、斜体、下划线
|
||||||
|
private UIToggleButton fontBoldButton; |
||||||
|
private UIToggleButton fontItalicButton; |
||||||
|
private UIToggleButton fontUnderlineButton; |
||||||
|
// 标题图文混排
|
||||||
|
protected TextInsetImageBackgroundSpecialPane insetImagePane; |
||||||
|
//对齐方式
|
||||||
|
protected UIButtonGroup alignPane; |
||||||
|
//标题整体背景
|
||||||
|
protected TitleTranslucentBackgroundSpecialPane backgroundPane; |
||||||
|
|
||||||
|
// 是否支持用户编辑这些属性(不支持时: 设置面板总是不可见)
|
||||||
|
private boolean isSupportTitleVisible = true; |
||||||
|
private boolean isSupportTitleContent = true; |
||||||
|
private boolean isSupportTitleOtherSetting = true; |
||||||
|
|
||||||
|
// 用于控制各部分设置的可见性
|
||||||
|
private JPanel titleVisiblePane; |
||||||
|
private JPanel titleContentPane; |
||||||
|
private JPanel titleOtherSettingPane; |
||||||
|
|
||||||
|
private final int uiLabelWidth; |
||||||
|
private final int uiSettingWidth; |
||||||
|
|
||||||
|
public ComponentTitleStylePane(int uiLabelWidth) { |
||||||
|
this(uiLabelWidth, -1); |
||||||
|
} |
||||||
|
|
||||||
|
public ComponentTitleStylePane( |
||||||
|
int uiLabelWidth, int uiSettingWidth) { |
||||||
|
this.uiLabelWidth = uiLabelWidth; |
||||||
|
this.uiSettingWidth = uiSettingWidth; |
||||||
|
this.initializePane(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initializeComponents() { |
||||||
|
visibleCheckbox = new UICheckBox(); |
||||||
|
|
||||||
|
textContentPane = new TinyFormulaPane(); |
||||||
|
|
||||||
|
fontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); |
||||||
|
FRFont frFont = DEFAULT_TITLE_PACKER.getFrFont(); |
||||||
|
if (frFont != null) { |
||||||
|
String fontFamily = frFont.getFamily(); |
||||||
|
// 使用style中默认的字体初始化titleFontFamilyComboBox,保证UI和数据的一致性
|
||||||
|
this.fontFamilyComboBox.setSelectedItem(fontFamily); |
||||||
|
} |
||||||
|
fontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); |
||||||
|
|
||||||
|
fontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); |
||||||
|
fontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); |
||||||
|
|
||||||
|
fontColorSelectPane = new UIColorButton(); |
||||||
|
fontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); |
||||||
|
fontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); |
||||||
|
|
||||||
|
fontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); |
||||||
|
fontBoldButton.setPreferredSize(BUTTON_SIZE); |
||||||
|
fontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); |
||||||
|
fontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); |
||||||
|
|
||||||
|
fontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); |
||||||
|
fontItalicButton.setPreferredSize(BUTTON_SIZE); |
||||||
|
fontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); |
||||||
|
fontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); |
||||||
|
|
||||||
|
fontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); |
||||||
|
fontUnderlineButton.setPreferredSize(BUTTON_SIZE); |
||||||
|
fontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); |
||||||
|
fontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); |
||||||
|
|
||||||
|
insetImagePane = new TextInsetImageBackgroundSpecialPane(); |
||||||
|
|
||||||
|
alignPane = new UIButtonGroup<>( |
||||||
|
new Icon[]{ |
||||||
|
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), |
||||||
|
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), |
||||||
|
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png") |
||||||
|
}, |
||||||
|
new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}); |
||||||
|
alignPane.setAllToolTips( |
||||||
|
new String[] { |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right") |
||||||
|
}); |
||||||
|
alignPane.setSelectedItem(DEFAULT_TITLE_PACKER.getPosition()); |
||||||
|
|
||||||
|
backgroundPane = new TitleTranslucentBackgroundSpecialPane(this.uiLabelWidth, this.uiSettingWidth); |
||||||
|
} |
||||||
|
|
||||||
|
private void initializePane() { |
||||||
|
this.setLayout(new BorderLayout(0, 0)); |
||||||
|
this.initializeComponents(); |
||||||
|
|
||||||
|
titleVisiblePane = this.createTitleVisiblePane(); |
||||||
|
titleContentPane = this.createTitleContentPane(); |
||||||
|
titleOtherSettingPane = this.createTitleOtherSettingPane(); |
||||||
|
|
||||||
|
if (isSupportTitleVisible) { |
||||||
|
titleVisiblePane.setVisible(true); |
||||||
|
} |
||||||
|
if (isSupportTitleVisible) { |
||||||
|
titleContentPane.setVisible(false); |
||||||
|
} |
||||||
|
if (isSupportTitleVisible) { |
||||||
|
titleOtherSettingPane.setVisible(false); |
||||||
|
} |
||||||
|
|
||||||
|
addComponents(titleVisiblePane, titleContentPane, titleOtherSettingPane); |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createTitleVisiblePane() { |
||||||
|
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
|
||||||
|
visibleCheckbox.setSelected(false); |
||||||
|
|
||||||
|
container.add(visibleCheckbox, BorderLayout.WEST); |
||||||
|
container.add(FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER); |
||||||
|
|
||||||
|
visibleCheckbox.addChangeListener(new ChangeListener() { |
||||||
|
@Override |
||||||
|
public void stateChanged(ChangeEvent e) { |
||||||
|
boolean visible = visibleCheckbox.isSelected(); |
||||||
|
if (titleContentPane != null) { |
||||||
|
titleContentPane.setVisible(visible && isSupportTitleContent); |
||||||
|
} |
||||||
|
if (titleOtherSettingPane != null) { |
||||||
|
titleOtherSettingPane.setVisible(visible && isSupportTitleOtherSetting); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
return container; |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createTitleContentPane() { |
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double[] rowSize = {p}; |
||||||
|
double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; |
||||||
|
|
||||||
|
return TableLayoutHelper.createCommonTableLayoutPane( |
||||||
|
new JComponent[][]{{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), textContentPane}}, |
||||||
|
rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createTitleOtherSettingPane() { |
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double[] rowSize = {p, p, p, p, p}; |
||||||
|
double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; |
||||||
|
|
||||||
|
JComponent[][] components = new JComponent[][]{ |
||||||
|
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), FRGUIPaneFactory.createBorderLayoutNorthPaneWithComponent(fontFamilyComboBox)}, |
||||||
|
{null, createTitleFontButtonPane()}, |
||||||
|
{insetImagePane, null}, |
||||||
|
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), alignPane}, |
||||||
|
{backgroundPane, null} |
||||||
|
}; |
||||||
|
|
||||||
|
return TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, IntervalConstants.INTERVAL_L1); |
||||||
|
} |
||||||
|
|
||||||
|
protected JPanel createTitleFontButtonPane(){ |
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double[] rowSize = {p}; |
||||||
|
double[] columnSize = {f, p, p, p, p}; |
||||||
|
|
||||||
|
JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { |
||||||
|
{fontSizeComboBox, fontColorSelectPane, fontItalicButton, fontBoldButton, fontUnderlineButton}, |
||||||
|
}, rowSize, columnSize, IntervalConstants.INTERVAL_W0); |
||||||
|
|
||||||
|
JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
containerPane.add(buttonPane, BorderLayout.NORTH); |
||||||
|
|
||||||
|
return containerPane; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(BorderPacker style) { |
||||||
|
TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle(); |
||||||
|
widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; |
||||||
|
boolean titleVisible = style != null && style.getType() != LayoutBorderStyle.STANDARD; |
||||||
|
visibleCheckbox.setSelected(isSupportTitleVisible && titleVisible); |
||||||
|
titleContentPane.setVisible(isSupportTitleContent && titleVisible); |
||||||
|
titleOtherSettingPane.setVisible(isSupportTitleOtherSetting && titleVisible); |
||||||
|
|
||||||
|
this.textContentPane.populateBean(widgetTitle.getTextObject().toString()); |
||||||
|
|
||||||
|
FRFont frFont = widgetTitle.getFrFont(); |
||||||
|
this.fontSizeComboBox.setSelectedItem(frFont.getSize()); |
||||||
|
this.fontFamilyComboBox.setSelectedItem(frFont.getFamily()); |
||||||
|
this.fontColorSelectPane.setColor(frFont.getForeground()); |
||||||
|
this.fontColorSelectPane.repaint(); |
||||||
|
fontBoldButton.setSelected(frFont.isBold()); |
||||||
|
fontItalicButton.setSelected(frFont.isItalic()); |
||||||
|
|
||||||
|
int line = frFont.getUnderline(); |
||||||
|
if (line == Constants.LINE_NONE) { |
||||||
|
fontUnderlineButton.setSelected(false); |
||||||
|
} else { |
||||||
|
fontUnderlineButton.setSelected(true); |
||||||
|
} |
||||||
|
|
||||||
|
alignPane.setSelectedItem(widgetTitle.getPosition()); |
||||||
|
insetImagePane.populateBean(widgetTitle); |
||||||
|
backgroundPane.populateBean(widgetTitle); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateBean(BorderPacker style) { |
||||||
|
style.setType(visibleCheckbox != null && visibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD); |
||||||
|
TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); |
||||||
|
title.setTextObject(textContentPane.updateBean()); |
||||||
|
FRFont frFont = title.getFrFont(); |
||||||
|
frFont = frFont.applySize((Integer) fontSizeComboBox.getSelectedItem()); |
||||||
|
frFont = frFont.applyName(fontFamilyComboBox.getSelectedItem().toString()); |
||||||
|
frFont = frFont.applyForeground(fontColorSelectPane.getColor()); |
||||||
|
frFont = updateTitleFontItalicBold(frFont); |
||||||
|
int line = fontUnderlineButton.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE; |
||||||
|
frFont = frFont.applyUnderline(line); |
||||||
|
title.setFrFont(frFont); |
||||||
|
title.setPosition((Integer) alignPane.getSelectedItem()); |
||||||
|
insetImagePane.updateBean(title); |
||||||
|
backgroundPane.updateBean(title); |
||||||
|
style.setTitle(title); |
||||||
|
} |
||||||
|
|
||||||
|
private FRFont updateTitleFontItalicBold(FRFont frFont) { |
||||||
|
int italic_bold = frFont.getStyle(); |
||||||
|
boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC); |
||||||
|
boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC); |
||||||
|
if (fontItalicButton.isSelected() && !isItalic) { |
||||||
|
italic_bold += Font.ITALIC; |
||||||
|
} else if (!fontItalicButton.isSelected() && isItalic) { |
||||||
|
italic_bold -= Font.ITALIC; |
||||||
|
} |
||||||
|
frFont = frFont.applyStyle(italic_bold); |
||||||
|
if (fontBoldButton.isSelected() && !isBold) { |
||||||
|
italic_bold += Font.BOLD; |
||||||
|
} else if (!fontBoldButton.isSelected() && isBold) { |
||||||
|
italic_bold -= Font.BOLD; |
||||||
|
} |
||||||
|
frFont = frFont.applyStyle(italic_bold); |
||||||
|
return frFont; |
||||||
|
} |
||||||
|
|
||||||
|
private void addComponents(JComponent... components) { |
||||||
|
if (components == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
JPanel container = this; |
||||||
|
for (int i = 0; i < components.length; i++) { |
||||||
|
JComponent component = components[i]; |
||||||
|
if (component != null) { |
||||||
|
container.add(component, BorderLayout.NORTH); |
||||||
|
component.setBorder(BorderFactory.createEmptyBorder(i == 0 ? 0 : IntervalConstants.INTERVAL_L1, 0, 0, 0)); |
||||||
|
if (i < components.length - 1) { |
||||||
|
JPanel nextContainer = new JPanel(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
container.add(nextContainer, BorderLayout.CENTER); |
||||||
|
container = nextContainer; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void setSupportTitleVisible(boolean supporting) { |
||||||
|
isSupportTitleVisible = supporting; |
||||||
|
if (titleVisiblePane != null) { |
||||||
|
titleVisiblePane.setVisible(supporting); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setSupportTitleContent(boolean supporting) { |
||||||
|
isSupportTitleContent = supporting; |
||||||
|
if (titleContentPane != null) { |
||||||
|
boolean titleVisible = visibleCheckbox.isSelected(); |
||||||
|
if (isSupportTitleContent) { |
||||||
|
titleContentPane.setVisible(titleVisible); |
||||||
|
} else { |
||||||
|
titleContentPane.setVisible(false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setSupportOtherSetting(boolean supporting) { |
||||||
|
isSupportTitleOtherSetting = supporting; |
||||||
|
if (titleOtherSettingPane != null) { |
||||||
|
boolean titleVisible = visibleCheckbox.isSelected(); |
||||||
|
if (isSupportTitleOtherSetting) { |
||||||
|
titleOtherSettingPane.setVisible(titleVisible); |
||||||
|
} else { |
||||||
|
titleOtherSettingPane.setVisible(false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,140 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.base.theme.TemplateTheme; |
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.event.UIObserver; |
||||||
|
import com.fr.design.event.UIObserverListener; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.gui.frpane.AttributeChangeUtils; |
||||||
|
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
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.design.mainframe.JTemplate; |
||||||
|
import com.fr.design.widget.FRWidgetFactory; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/19 |
||||||
|
*/ |
||||||
|
public class FollowingThemePane extends BasicPane implements UIObserver { |
||||||
|
public static final int SETTING_LABEL_WIDTH = 60; |
||||||
|
|
||||||
|
public static final String[] FOLLOWING_THEME_STRING_ARRAYS = new String[]{ |
||||||
|
Toolkit.i18nText("Fine-Design_Style_Follow_Theme"), |
||||||
|
Toolkit.i18nText("Fine-Design_Style_Not_Follow_Theme"), |
||||||
|
}; |
||||||
|
|
||||||
|
private final UIButtonGroup<String> followingThemeButtonGroup; |
||||||
|
private final List<FollowingThemeActionChangeListener> changeListeners = new ArrayList<>(); |
||||||
|
private UIObserverListener uiObserverListener; |
||||||
|
|
||||||
|
private JPanel container; |
||||||
|
|
||||||
|
public FollowingThemePane(String name) { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
||||||
|
|
||||||
|
followingThemeButtonGroup = new UIButtonGroup<>(FOLLOWING_THEME_STRING_ARRAYS); |
||||||
|
followingThemeButtonGroup.setAutoFireStateChanged(false); |
||||||
|
followingThemeButtonGroup.setSelectedIndex(1); |
||||||
|
followingThemeButtonGroup.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
AttributeChangeUtils.changeComposedUI(FollowingThemePane.this, false, new AttributeChangeUtils.UIChangeAction() { |
||||||
|
@Override |
||||||
|
public void changeComposedUI() { |
||||||
|
for (FollowingThemeActionChangeListener changeListener : changeListeners) { |
||||||
|
changeListener.onFollowingTheme(isFollowingTheme()); |
||||||
|
} |
||||||
|
invalidate(); |
||||||
|
} |
||||||
|
}); |
||||||
|
if (uiObserverListener != null) { |
||||||
|
uiObserverListener.doChange(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
UILabel followingThemeLabel = FRWidgetFactory.createLineWrapLabel(name); |
||||||
|
|
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
JPanel followingThemePane = |
||||||
|
TableLayoutHelper.createGapTableLayoutPane( new Component[][]{new Component[] { followingThemeLabel, FRGUIPaneFactory.createBorderLayoutNorthPaneWithComponent(followingThemeButtonGroup)}}, |
||||||
|
new double[] { p }, new double[] { SETTING_LABEL_WIDTH, f }, 10, 0); |
||||||
|
followingThemePane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); |
||||||
|
followingThemePane.setVisible(false); |
||||||
|
|
||||||
|
add(followingThemePane, BorderLayout.NORTH); |
||||||
|
container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
add(container, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
public void addFollowThemePane(JPanel content, FollowingThemeActionChangeListener changeListener) { |
||||||
|
if (content != null) { |
||||||
|
container.add(content, BorderLayout.NORTH); |
||||||
|
changeListeners.add(changeListener); |
||||||
|
|
||||||
|
JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
container.add(nextContainer, BorderLayout.CENTER); |
||||||
|
container = nextContainer; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void registerChangeListener(UIObserverListener uiObserverListener) { |
||||||
|
this.uiObserverListener = uiObserverListener; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean shouldResponseChangeListener() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public interface FollowingThemeActionChangeListener { |
||||||
|
void onFollowingTheme(boolean following); |
||||||
|
} |
||||||
|
|
||||||
|
public TemplateTheme getUsingTheme() { |
||||||
|
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
if (template != null) { |
||||||
|
return template.getTemplateTheme(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void supportFollowingTheme(boolean supporting) { |
||||||
|
getComponent(0).setVisible(supporting); |
||||||
|
if (!supporting) { |
||||||
|
setFollowingTheme(false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setFollowingTheme(boolean following) { |
||||||
|
followingThemeButtonGroup.setSelectedIndex(following ? 0 : 1); |
||||||
|
for (FollowingThemeActionChangeListener changeListener : changeListeners) { |
||||||
|
changeListener.onFollowingTheme(isFollowingTheme()); |
||||||
|
} |
||||||
|
} |
||||||
|
public boolean isFollowingTheme() { |
||||||
|
return followingThemeButtonGroup.getSelectedIndex() == 0; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,102 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.design.ExtraDesignClassManager; |
||||||
|
import com.fr.design.event.UIObserverListener; |
||||||
|
import com.fr.design.fun.BackgroundQuickUIProvider; |
||||||
|
import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; |
||||||
|
import com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; |
||||||
|
import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; |
||||||
|
import com.fr.design.mainframe.backgroundpane.ImageBackgroundQuickPane; |
||||||
|
import com.fr.design.mainframe.backgroundpane.NullBackgroundQuickPane; |
||||||
|
import com.fr.design.mainframe.backgroundpane.PatternBackgroundQuickPane; |
||||||
|
import com.fr.design.mainframe.backgroundpane.TextureBackgroundQuickPane; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/19 |
||||||
|
*/ |
||||||
|
public class ReportBackgroundSpecialPane extends BackgroundPane { |
||||||
|
public ReportBackgroundSpecialPane(){ |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { |
||||||
|
NullBackgroundQuickPane nullBackgroundPane = new NullBackgroundQuickPane(); |
||||||
|
|
||||||
|
ColorBackgroundQuickPane colorBackgroundPane = new ColorBackgroundQuickPane(); |
||||||
|
colorBackgroundPane.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
fireStateChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
ImageBackgroundQuickPane imageBackgroundPane = new ImageBackgroundQuickPane(); |
||||||
|
imageBackgroundPane.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
fireStateChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
GradientBackgroundQuickPane gradientBackgroundPane = createGradientBackgroundQuickPane(); |
||||||
|
gradientBackgroundPane.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
fireStateChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
TextureBackgroundQuickPane textureBackgroundPane = new TextureBackgroundQuickPane(); |
||||||
|
textureBackgroundPane.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
fireStateChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
PatternBackgroundQuickPane patternBackgroundPane = new PatternBackgroundQuickPane(); |
||||||
|
patternBackgroundPane.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
fireStateChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
List<BackgroundQuickPane> kinds = new ArrayList<BackgroundQuickPane>(); |
||||||
|
|
||||||
|
kinds.add(nullBackgroundPane); |
||||||
|
kinds.add(colorBackgroundPane); |
||||||
|
kinds.add(imageBackgroundPane); |
||||||
|
kinds.add(gradientBackgroundPane); |
||||||
|
kinds.add(textureBackgroundPane); |
||||||
|
kinds.add(patternBackgroundPane); |
||||||
|
|
||||||
|
Set<BackgroundQuickUIProvider> providers = ExtraDesignClassManager.getInstance().getArray(BackgroundQuickUIProvider.MARK_STRING); |
||||||
|
for (BackgroundQuickUIProvider provider : providers) { |
||||||
|
BackgroundQuickPane newTypePane = provider.appearanceForBackground(); |
||||||
|
newTypePane.registerChangeListener(new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
fireStateChanged(); |
||||||
|
} |
||||||
|
}); |
||||||
|
kinds.add(newTypePane); |
||||||
|
} |
||||||
|
|
||||||
|
return kinds.toArray(new BackgroundQuickPane[kinds.size()]); |
||||||
|
} |
||||||
|
|
||||||
|
protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { |
||||||
|
// 使用默认的150宽度构建渐变条
|
||||||
|
return new GradientBackgroundQuickPane(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.design.constants.LayoutConstants; |
||||||
|
import com.fr.design.designer.IntervalConstants; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
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.design.mainframe.theme.edit.ui.LabelUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.JTextArea; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Component; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/29 |
||||||
|
*/ |
||||||
|
public class TextFontTippedPane extends AbstractBasicStylePane { |
||||||
|
|
||||||
|
private FRFontPane fontPane; |
||||||
|
|
||||||
|
public TextFontTippedPane(boolean showFormatTip) { |
||||||
|
this.initializePane(showFormatTip); |
||||||
|
} |
||||||
|
|
||||||
|
private void initializePane(boolean showFormatTip) { |
||||||
|
setLayout(new BorderLayout()); |
||||||
|
setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); |
||||||
|
|
||||||
|
fontPane = new FRFontPane(); |
||||||
|
this.add(createLabeledPane(Toolkit.i18nText("Fine-Design_Form_FR_Font"), fontPane), BorderLayout.NORTH); |
||||||
|
|
||||||
|
if (showFormatTip) { |
||||||
|
JPanel formatTipPane = createFormatTipPane(); |
||||||
|
this.add(formatTipPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createLabeledPane(String text, JPanel panel) { |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double[] rowSize = { p }; |
||||||
|
double[] columnSize = {p, f}; |
||||||
|
|
||||||
|
UILabel uiLabel = new UILabel(text); |
||||||
|
JPanel uiLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
uiLabelPane.add(uiLabel, BorderLayout.NORTH); |
||||||
|
|
||||||
|
return TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ |
||||||
|
new Component[] { uiLabelPane, panel }, |
||||||
|
}, rowSize, columnSize, LayoutConstants.VGAP_LARGE, LayoutConstants.VGAP_MEDIUM); |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createFormatTipPane() { |
||||||
|
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
container.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); |
||||||
|
JTextArea formatMigratedTip = LabelUtils.createAutoWrapLabel(Toolkit.i18nText("Fine-Design_Report_Format_Style_Migrated_Tip"), new Color(153, 153, 153)); |
||||||
|
|
||||||
|
container.add(formatMigratedTip, BorderLayout.NORTH); |
||||||
|
return container; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Text"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(Style style) { |
||||||
|
this.fontPane.populateBean(style); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Style update(Style style) { |
||||||
|
return this.fontPane.update(style); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,485 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.base.CoreDecimalFormat; |
||||||
|
import com.fr.base.GraphHelper; |
||||||
|
import com.fr.base.Style; |
||||||
|
import com.fr.base.TextFormat; |
||||||
|
import com.fr.data.core.FormatField; |
||||||
|
import com.fr.data.core.FormatField.FormatContents; |
||||||
|
import com.fr.design.border.UIRoundedBorder; |
||||||
|
import com.fr.design.constants.LayoutConstants; |
||||||
|
import com.fr.design.constants.UIConstants; |
||||||
|
import com.fr.design.event.GlobalNameListener; |
||||||
|
import com.fr.design.event.GlobalNameObserver; |
||||||
|
import com.fr.design.event.UIObserverListener; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.icombobox.TextFontComboBox; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBox; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBoxRenderer; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JLabel; |
||||||
|
import javax.swing.JList; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.SwingConstants; |
||||||
|
import javax.swing.UIManager; |
||||||
|
import javax.swing.border.Border; |
||||||
|
import javax.swing.border.TitledBorder; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.CardLayout; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.FontMetrics; |
||||||
|
import java.awt.Graphics; |
||||||
|
import java.awt.event.ItemEvent; |
||||||
|
import java.awt.event.ItemListener; |
||||||
|
import java.math.RoundingMode; |
||||||
|
import java.text.Format; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.Arrays; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/9/29 |
||||||
|
* 包含格式相关的设置 |
||||||
|
*/ |
||||||
|
public class TextFormatPane extends AbstractBasicStylePane implements GlobalNameObserver { |
||||||
|
private static final long serialVersionUID = 724330854437726751L; |
||||||
|
|
||||||
|
private static final int LABEL_X = 4; |
||||||
|
private static final int LABEL_Y = 18; |
||||||
|
private static final int LABEL_DELTA_WIDTH = 8; |
||||||
|
private static final int LABEL_HEIGHT = 15; //标签背景的范围
|
||||||
|
private static final int CURRENCY_FLAG_POINT = 6; |
||||||
|
|
||||||
|
private static final Integer[] TYPES = new Integer[]{ |
||||||
|
FormatContents.NULL, FormatContents.NUMBER, |
||||||
|
FormatContents.CURRENCY, FormatContents.PERCENT, |
||||||
|
FormatContents.SCIENTIFIC, FormatContents.DATE, |
||||||
|
FormatContents.TIME, FormatContents.TEXT}; |
||||||
|
|
||||||
|
private static final Integer[] DATE_TYPES = new Integer[]{FormatContents.NULL, FormatContents.DATE, FormatContents.TIME}; |
||||||
|
|
||||||
|
private Format format; |
||||||
|
|
||||||
|
private UIComboBox typeComboBox; |
||||||
|
private TextFontComboBox textField; |
||||||
|
private UILabel sampleLabel; |
||||||
|
private JPanel contentPane; |
||||||
|
private JPanel txtCenterPane; |
||||||
|
private JPanel centerPane; |
||||||
|
private JPanel optionPane; |
||||||
|
private UICheckBox roundingBox; |
||||||
|
private JPanel formatFontPane; |
||||||
|
private boolean isRightFormat; |
||||||
|
private boolean isDate = false; |
||||||
|
private GlobalNameListener globalNameListener = null; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor. |
||||||
|
*/ |
||||||
|
public TextFormatPane() { |
||||||
|
this.initComponents(TYPES); |
||||||
|
} |
||||||
|
|
||||||
|
protected UIComboBox getTypeComboBox() { |
||||||
|
return typeComboBox; |
||||||
|
} |
||||||
|
|
||||||
|
protected void initComponents(Integer[] types) { |
||||||
|
this.setLayout(new BorderLayout(0, 4)); |
||||||
|
initSampleLabel(); |
||||||
|
contentPane = new JPanel(new BorderLayout(0, 4)) { |
||||||
|
@Override |
||||||
|
public Dimension getPreferredSize() { |
||||||
|
return new Dimension(super.getPreferredSize().width, 65); |
||||||
|
} |
||||||
|
}; |
||||||
|
typeComboBox = new UIComboBox(types); |
||||||
|
UIComboBoxRenderer render = createComBoxRender(); |
||||||
|
typeComboBox.setRenderer(render); |
||||||
|
typeComboBox.addItemListener(itemListener); |
||||||
|
typeComboBox.setGlobalName("typeComboBox"); |
||||||
|
contentPane.add(sampleLabel, BorderLayout.NORTH); |
||||||
|
|
||||||
|
txtCenterPane = new JPanel(new BorderLayout()); |
||||||
|
textField = new TextFontComboBox(); |
||||||
|
textField.addItemListener(textFieldItemListener); |
||||||
|
textField.setEditable(true); |
||||||
|
textField.setGlobalName("textField"); |
||||||
|
txtCenterPane.add(textField, BorderLayout.NORTH); |
||||||
|
|
||||||
|
contentPane.add(txtCenterPane, BorderLayout.CENTER); |
||||||
|
|
||||||
|
centerPane = new JPanel(new CardLayout()); |
||||||
|
centerPane.add(new JPanel(), "hide"); |
||||||
|
centerPane.setPreferredSize(new Dimension(0, 0)); |
||||||
|
centerPane.add(contentPane, "show"); |
||||||
|
|
||||||
|
typeComboBox.setPreferredSize(new Dimension(155,20)); |
||||||
|
JPanel typePane = new JPanel(new BorderLayout()); |
||||||
|
typePane.add(typeComboBox, BorderLayout.CENTER); |
||||||
|
typePane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0)); |
||||||
|
|
||||||
|
JPanel option = new JPanel(new BorderLayout()); |
||||||
|
option.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Option"), SwingConstants.LEFT), BorderLayout.WEST); |
||||||
|
roundingBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Base_Option_Half_Up")); |
||||||
|
roundingBox.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); |
||||||
|
roundingBox.addItemListener(new ItemListener() { |
||||||
|
@Override |
||||||
|
public void itemStateChanged(ItemEvent e) { |
||||||
|
} |
||||||
|
}); |
||||||
|
roundingBox.setGlobalName("roundingBox"); |
||||||
|
option.add(roundingBox, BorderLayout.CENTER); |
||||||
|
optionPane = new JPanel(new CardLayout()); |
||||||
|
optionPane.add(new JPanel(), "hide"); |
||||||
|
optionPane.setPreferredSize(new Dimension(0, 0)); |
||||||
|
optionPane.add(option, "show"); |
||||||
|
|
||||||
|
Component[][] components = getComponent(centerPane, typePane); |
||||||
|
this.add(createContentPane(components), BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
protected JPanel createContentPane (Component[][] components) { |
||||||
|
double f = TableLayout.FILL; |
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double[] rowSize = new double[components.length]; |
||||||
|
Arrays.fill(rowSize, p); |
||||||
|
double[] columnSize = {p, f}; |
||||||
|
int[][] rowCount = new int[components.length][2]; |
||||||
|
Arrays.fill(rowCount, new int[] {1, 1}); |
||||||
|
return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_LARGE, LayoutConstants.VGAP_MEDIUM); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected Component[][] getComponent (JPanel centerPane, JPanel typePane) { |
||||||
|
return new Component[][]{ |
||||||
|
new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Format"), SwingConstants.LEFT), typePane}, |
||||||
|
new Component[]{centerPane, null}, |
||||||
|
new Component[]{optionPane, null}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
protected UIComboBoxRenderer createComBoxRender() { |
||||||
|
return new UIComboBoxRenderer() { |
||||||
|
@Override |
||||||
|
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
||||||
|
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); |
||||||
|
if (value instanceof Integer) { |
||||||
|
label.setText(" " + FormatField.getInstance().getName((Integer) value)); |
||||||
|
} |
||||||
|
return label; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
private void initSampleLabel() { |
||||||
|
Border interBorder = new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 4); |
||||||
|
String title = Toolkit.i18nText("Fine-Design_Report_Base_StyleFormat_Sample"); |
||||||
|
Border border = BorderFactory.createTitledBorder(interBorder, title, TitledBorder.LEFT, 0, null, UIConstants.LINE_COLOR); |
||||||
|
sampleLabel = new UILabel(FormatField.getInstance().getFormatValue()) { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
super.paint(g); |
||||||
|
int width = getWidth(); |
||||||
|
Color original = g.getColor(); |
||||||
|
g.setColor(getBackground()); |
||||||
|
g.fillRect(LABEL_X, LABEL_Y, width - LABEL_DELTA_WIDTH, LABEL_HEIGHT); |
||||||
|
g.setColor(UIConstants.LINE_COLOR); |
||||||
|
FontMetrics cellFM = g.getFontMetrics(); |
||||||
|
int textWidth = cellFM.stringWidth(getText()); |
||||||
|
GraphHelper.drawString(g, getText(), (width - textWidth) / 2, 26); |
||||||
|
g.setColor(original); |
||||||
|
} |
||||||
|
}; |
||||||
|
sampleLabel.setHorizontalAlignment(UILabel.CENTER); |
||||||
|
sampleLabel.setBorder(border); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
/** |
||||||
|
* 得到合适的大小 |
||||||
|
*/ |
||||||
|
public Dimension getPreferredSize() { |
||||||
|
if (this.typeComboBox.getSelectedIndex() == FormatContents.NULL) { |
||||||
|
return typeComboBox.getPreferredSize(); |
||||||
|
} |
||||||
|
return super.getPreferredSize(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 弹出框标题 |
||||||
|
* |
||||||
|
* @return 标题 |
||||||
|
*/ |
||||||
|
public String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Fine-Design_Report_Text"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Populate |
||||||
|
*/ |
||||||
|
public void populateBean(Format format) { |
||||||
|
this.format = format; |
||||||
|
|
||||||
|
if (format == null) { |
||||||
|
this.typeComboBox.setSelectedIndex(FormatContents.NULL); |
||||||
|
} else { |
||||||
|
if (format instanceof CoreDecimalFormat) { |
||||||
|
// check all value
|
||||||
|
String pattern = ((CoreDecimalFormat) format).toPattern(); |
||||||
|
if (isCurrencyFormatStyle(pattern)) { |
||||||
|
setPatternComboBoxAndList(FormatContents.CURRENCY, pattern); |
||||||
|
} else if (pattern.indexOf("%") > 0) { |
||||||
|
setPatternComboBoxAndList(FormatContents.PERCENT, pattern); |
||||||
|
this.roundingBox.setSelected(((CoreDecimalFormat) format).getRoundingMode().equals(RoundingMode.HALF_UP)); |
||||||
|
} else if (pattern.indexOf("E") > 0) { |
||||||
|
setPatternComboBoxAndList(FormatContents.SCIENTIFIC, pattern); |
||||||
|
} else { |
||||||
|
setPatternComboBoxAndList(FormatContents.NUMBER, pattern); |
||||||
|
} |
||||||
|
} else if (format instanceof SimpleDateFormat) { // date and time
|
||||||
|
String pattern = ((SimpleDateFormat) format).toPattern(); |
||||||
|
if (!isTimeType(pattern)) { |
||||||
|
setPatternComboBoxAndList(FormatContents.DATE, pattern); |
||||||
|
} else { |
||||||
|
setPatternComboBoxAndList(FormatContents.TIME, pattern); |
||||||
|
} |
||||||
|
} else if (format instanceof TextFormat) { // Text
|
||||||
|
this.typeComboBox.setSelectedItem(FormatContents.TEXT); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isCurrencyFormatStyle(String pattern) { |
||||||
|
if (pattern.length() == 0) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
if (pattern.charAt(0) == '¤' || pattern.charAt(0) == '$') { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return pattern.length() > CURRENCY_FLAG_POINT && pattern.startsWith("#,##0;"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断是否是数组有模式 |
||||||
|
* |
||||||
|
* @param stringArray 字符串数组 |
||||||
|
* @param pattern 格式 |
||||||
|
* @return 是否是数组有模式 |
||||||
|
*/ |
||||||
|
public static int isArrayContainPattern(String[] stringArray, String pattern) { |
||||||
|
for (int i = 0; i < stringArray.length; i++) { |
||||||
|
if (ComparatorUtils.equals(stringArray[i], pattern)) { |
||||||
|
return i; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPatternComboBoxAndList(int formatStyle, String pattern) { |
||||||
|
this.typeComboBox.setSelectedItem(formatStyle); |
||||||
|
this.textField.setSelectedItem(pattern); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isTimeType(String pattern) { |
||||||
|
return pattern.matches(".*[Hhmsa].*"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* update |
||||||
|
*/ |
||||||
|
public Format update() { |
||||||
|
String patternString = String.valueOf(textField.getSelectedItem()); |
||||||
|
if (getFormatContents() == FormatContents.TEXT) { |
||||||
|
return FormatField.getInstance().getFormat(getFormatContents(), patternString); |
||||||
|
} |
||||||
|
if (isRightFormat) { |
||||||
|
if (StringUtils.isNotEmpty(patternString)) { |
||||||
|
RoundingMode roundingMode = roundingBox.isSelected() ? RoundingMode.HALF_UP : RoundingMode.HALF_EVEN; |
||||||
|
return FormatField.getInstance().getFormat(getFormatContents(), patternString, roundingMode); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private int getFormatContents() { |
||||||
|
return (Integer) typeComboBox.getSelectedItem(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Refresh preview label. |
||||||
|
*/ |
||||||
|
private void refreshPreviewLabel() { |
||||||
|
this.sampleLabel.setText(FormatField.getInstance().getFormatValue()); |
||||||
|
this.sampleLabel.setForeground(UIManager.getColor("Label.foreground")); |
||||||
|
try { |
||||||
|
isRightFormat = true; |
||||||
|
if (StringUtils.isEmpty(String.valueOf(textField.getSelectedItem()))) { |
||||||
|
return; |
||||||
|
} |
||||||
|
this.sampleLabel.setText(FormatField.getInstance().getFormatValue(getFormatContents(), String.valueOf(textField.getSelectedItem()))); |
||||||
|
} catch (Exception e) { |
||||||
|
this.sampleLabel.setForeground(Color.red); |
||||||
|
this.sampleLabel.setText(e.getMessage()); |
||||||
|
isRightFormat = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isTextOrNull() { |
||||||
|
int contents = getFormatContents(); |
||||||
|
return contents == FormatContents.TEXT || contents == FormatContents.NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Radio selection listener. |
||||||
|
*/ |
||||||
|
ItemListener itemListener = new ItemListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void itemStateChanged(ItemEvent e) { |
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) { |
||||||
|
int contents = getFormatContents(); |
||||||
|
String[] items = FormatField.getInstance().getFormatArray(contents, false); |
||||||
|
CardLayout cardLayout = (CardLayout) centerPane.getLayout(); |
||||||
|
|
||||||
|
if (isTextOrNull()) { |
||||||
|
centerPane.setPreferredSize(new Dimension(0, 0)); |
||||||
|
cardLayout.show(centerPane, "hide"); |
||||||
|
} else { |
||||||
|
textField.removeAllItems(); |
||||||
|
textField.setItemArray(items); |
||||||
|
textField.setSelectedIndex(0); |
||||||
|
centerPane.setPreferredSize(new Dimension(270, 65)); |
||||||
|
cardLayout.show(centerPane, "show"); |
||||||
|
} |
||||||
|
CardLayout optionLayout = ((CardLayout) optionPane.getLayout()); |
||||||
|
if (getFormatContents() == FormatContents.PERCENT) { |
||||||
|
optionPane.setPreferredSize(new Dimension(100, 20)); |
||||||
|
optionLayout.show(optionPane, "show"); |
||||||
|
} else { |
||||||
|
optionPane.setPreferredSize(new Dimension(0, 0)); |
||||||
|
optionLayout.show(optionPane, "hide"); |
||||||
|
roundingBox.setSelected(false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
ItemListener textFieldItemListener = new ItemListener() { |
||||||
|
@Override |
||||||
|
public void itemStateChanged(ItemEvent e) { |
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) { |
||||||
|
refreshPreviewLabel(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
@Override |
||||||
|
/** |
||||||
|
* populate |
||||||
|
*/ |
||||||
|
public void populateBean(Style style) { |
||||||
|
this.populateBean(style.getFormat()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
/** |
||||||
|
* update |
||||||
|
*/ |
||||||
|
public Style update(Style style) { |
||||||
|
if (ComparatorUtils.equals(globalNameListener.getGlobalName(), "textField") |
||||||
|
|| ComparatorUtils.equals(globalNameListener.getGlobalName(), "typeComboBox") |
||||||
|
|| ComparatorUtils.equals(globalNameListener.getGlobalName(), "roundingBox")) { |
||||||
|
return style.deriveFormat(this.update()); |
||||||
|
} |
||||||
|
return style; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 默认只显示百分比的编辑下拉. |
||||||
|
*/ |
||||||
|
public void justUsePercentFormat() { |
||||||
|
typeComboBox.setEnabled(false); |
||||||
|
this.typeComboBox.setSelectedItem(FormatContents.PERCENT); |
||||||
|
} |
||||||
|
|
||||||
|
public void setForDataSheet() { |
||||||
|
Integer[] otherTypes = new Integer[]{FormatContents.NULL, FormatContents.NUMBER, FormatContents.CURRENCY, FormatContents.PERCENT, FormatContents.SCIENTIFIC,}; |
||||||
|
this.typeComboBox = new UIComboBox(otherTypes); |
||||||
|
UIComboBoxRenderer render = new UIComboBoxRenderer() { |
||||||
|
@Override |
||||||
|
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
||||||
|
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); |
||||||
|
if (value instanceof Integer) { |
||||||
|
label.setText(" " + FormatField.getInstance().getName((Integer) value)); |
||||||
|
} |
||||||
|
return label; |
||||||
|
} |
||||||
|
}; |
||||||
|
typeComboBox.setRenderer(render); |
||||||
|
typeComboBox.addItemListener(itemListener); |
||||||
|
setTypeComboBoxPane(typeComboBox); |
||||||
|
} |
||||||
|
|
||||||
|
protected void setTypeComboBoxPane (UIComboBox typeComboBox) { |
||||||
|
this.add(typeComboBox, BorderLayout.NORTH); |
||||||
|
} |
||||||
|
|
||||||
|
public void setComboBoxModel(boolean isDate) { |
||||||
|
if (this.isDate != isDate) { |
||||||
|
this.isDate = isDate; |
||||||
|
this.typeComboBox.setSelectedIndex(0); |
||||||
|
if (isDate) { |
||||||
|
for (int i = 0; i < DATE_TYPES.length; i++) { |
||||||
|
this.typeComboBox.addItem(DATE_TYPES[i]); |
||||||
|
} |
||||||
|
for (int i = 0; i < TYPES.length; i++) { |
||||||
|
this.typeComboBox.removeItemAt(1); |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (int i = 0; i < TYPES.length; i++) { |
||||||
|
this.typeComboBox.addItem(TYPES[i]); |
||||||
|
} |
||||||
|
for (int i = 0; i < DATE_TYPES.length; i++) { |
||||||
|
this.typeComboBox.removeItemAt(1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void registerNameListener(GlobalNameListener listener) { |
||||||
|
globalNameListener = listener; |
||||||
|
} |
||||||
|
|
||||||
|
public void registerChangeListener(UIObserverListener listener) { |
||||||
|
typeComboBox.registerChangeListener(listener); |
||||||
|
textField.registerChangeListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean shouldResponseNameListener() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setGlobalName(String name) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package com.fr.design.gui.style; |
||||||
|
|
||||||
|
import com.fr.general.act.TitlePacker; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Starryi |
||||||
|
* @version 1.0 |
||||||
|
* Created by Starryi on 2021/8/11 |
||||||
|
*/ |
||||||
|
public class TitleTranslucentBackgroundSpecialPane extends AbstractTranslucentBackgroundSpecialPane<TitlePacker> { |
||||||
|
|
||||||
|
public TitleTranslucentBackgroundSpecialPane(int uiLabelWidth, int uiSettingWidth) { |
||||||
|
super(uiLabelWidth, uiSettingWidth, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(TitlePacker style) { |
||||||
|
backgroundPane.populateBean(style.getBackground()); |
||||||
|
opacityPane.populateBean(style.getBackgroundOpacity()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateBean(TitlePacker style) { |
||||||
|
style.setBackground(backgroundPane.update()); |
||||||
|
style.setBackgroundOpacity((float)opacityPane.updateBean()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,328 @@ |
|||||||
|
package com.fr.design.hyperlink.popup; |
||||||
|
|
||||||
|
import com.fr.base.BaseFormula; |
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.base.Parameter; |
||||||
|
import com.fr.design.dialog.BasicDialog; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
import com.fr.design.formula.TinyFormulaPane; |
||||||
|
import com.fr.design.gui.frpane.ReportletParameterViewPane; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.ibutton.UIRadioButton; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditAction; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.gui.itree.filetree.ReportletPane; |
||||||
|
import com.fr.design.hyperlink.AbstractHyperLinkPane; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.module.DesignModuleFactory; |
||||||
|
import com.fr.design.parameter.ParameterReader; |
||||||
|
import com.fr.design.utils.gui.GUICoreUtils; |
||||||
|
import com.fr.js.MobilePopupHyperlink; |
||||||
|
import com.fr.stable.CommonUtils; |
||||||
|
import com.fr.stable.FormulaProvider; |
||||||
|
import com.fr.stable.ParameterProvider; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class ContentSettingPane extends AbstractHyperLinkPane<MobilePopupHyperlink> { |
||||||
|
private JPanel popupTargetPane; |
||||||
|
private UIRadioButton templatePopupButton; |
||||||
|
private UIRadioButton textPopupButton; |
||||||
|
private ButtonGroup popupTargetButtons; |
||||||
|
|
||||||
|
private JPanel templateContentPane; |
||||||
|
private UITextField templatePathTextField; |
||||||
|
private UICheckBox extendParametersCheckBox; |
||||||
|
|
||||||
|
private JPanel textSettingPanel; |
||||||
|
private TinyFormulaPane textContentPane; |
||||||
|
private CustomFontPane fontPane; |
||||||
|
|
||||||
|
public ContentSettingPane() { |
||||||
|
super(); |
||||||
|
this.initCompoennt(); |
||||||
|
} |
||||||
|
|
||||||
|
public void addTargetRadioActionListener(ActionListener listener) { |
||||||
|
templatePopupButton.addActionListener(listener); |
||||||
|
textPopupButton.addActionListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTargetType() { |
||||||
|
if (templatePopupButton.isSelected()) { |
||||||
|
return MobilePopupConstants.Target_Template; |
||||||
|
} else { |
||||||
|
return MobilePopupConstants.Target_Text; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void initCompoennt() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); |
||||||
|
this.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Content"))); |
||||||
|
|
||||||
|
popupTargetPane = this.createPopupTargetPane(); |
||||||
|
this.add(popupTargetPane, BorderLayout.NORTH); |
||||||
|
|
||||||
|
templateContentPane= this.createTemplateContentPane(); |
||||||
|
textSettingPanel = this.createTextSettingPane(); |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createPopupTargetPane() { |
||||||
|
templatePopupButton = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Template")); |
||||||
|
templatePopupButton.addActionListener(radioActionListener); |
||||||
|
|
||||||
|
textPopupButton = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Text")); |
||||||
|
textPopupButton.addActionListener(radioActionListener); |
||||||
|
|
||||||
|
popupTargetButtons = new ButtonGroup(); |
||||||
|
popupTargetButtons.add(templatePopupButton); |
||||||
|
popupTargetButtons.add(textPopupButton); |
||||||
|
|
||||||
|
JPanel popupButtonsPanel = new JPanel(); |
||||||
|
popupButtonsPanel.setLayout( new FlowLayout(FlowLayout.LEFT, 10, 0)); |
||||||
|
popupButtonsPanel.add(templatePopupButton); |
||||||
|
popupButtonsPanel.add(textPopupButton); |
||||||
|
return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Target"), popupButtonsPanel); |
||||||
|
} |
||||||
|
|
||||||
|
private ActionListener radioActionListener = new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
if(templatePopupButton.isSelected()) { |
||||||
|
ContentSettingPane.this.add(templateContentPane); |
||||||
|
ContentSettingPane.this.remove(textSettingPanel); |
||||||
|
} else if (textPopupButton.isSelected()) { |
||||||
|
ContentSettingPane.this.add(textSettingPanel); |
||||||
|
ContentSettingPane.this.remove(templateContentPane); |
||||||
|
} |
||||||
|
ContentSettingPane.this.revalidate(); |
||||||
|
ContentSettingPane.this.repaint(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private JPanel createTemplateContentPane() { |
||||||
|
JPanel templateContentPane = new JPanel(); |
||||||
|
templateContentPane.setLayout(new BorderLayout(0,8)); |
||||||
|
|
||||||
|
templateContentPane.add(this.createTemplateSelectPanel(), BorderLayout.NORTH); |
||||||
|
|
||||||
|
parameterViewPane = this.createReportletParameterViewPane(); |
||||||
|
templateContentPane.add(parameterViewPane, BorderLayout.CENTER); |
||||||
|
|
||||||
|
extendParametersCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Extends_Report_Parameters")); |
||||||
|
templateContentPane.add(GUICoreUtils.createFlowPane(extendParametersCheckBox, FlowLayout.LEFT), BorderLayout.SOUTH); |
||||||
|
|
||||||
|
return templateContentPane; |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createTemplateSelectPanel() { |
||||||
|
JPanel templatePanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
// 路径输入框
|
||||||
|
templatePathTextField = new UITextField(20); |
||||||
|
templatePanel.add(templatePathTextField, BorderLayout.CENTER); |
||||||
|
|
||||||
|
// 选择路径按钮
|
||||||
|
UIButton templateSelectButton = new UIButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Select")); |
||||||
|
templateSelectButton.setPreferredSize(new Dimension(templateSelectButton.getPreferredSize().width, 20)); |
||||||
|
templatePanel.add(templateSelectButton, BorderLayout.EAST); |
||||||
|
templateSelectButton.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent evt) { |
||||||
|
final ReportletPane reportletPane = new ReportletPane(); |
||||||
|
reportletPane.setSelectedReportletPath(templatePathTextField.getText()); |
||||||
|
BasicDialog reportletDialog = reportletPane.showWindow(SwingUtilities.getWindowAncestor(ContentSettingPane.this)); |
||||||
|
|
||||||
|
reportletDialog.addDialogActionListener(new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
templatePathTextField.setText(reportletPane.getSelectedReportletPath()); |
||||||
|
} |
||||||
|
}); |
||||||
|
reportletDialog.setVisible(true); |
||||||
|
} |
||||||
|
}); |
||||||
|
return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Template"), templatePanel); |
||||||
|
} |
||||||
|
|
||||||
|
private ReportletParameterViewPane createReportletParameterViewPane() { |
||||||
|
ReportletParameterViewPane templateParameterViewPane = new ReportletParameterViewPane( |
||||||
|
new UITableEditAction[]{ |
||||||
|
new HyperlinkParametersAction() |
||||||
|
}, |
||||||
|
getChartParaType(), |
||||||
|
getValueEditorPane(), |
||||||
|
getValueEditorPane() |
||||||
|
); |
||||||
|
templateParameterViewPane.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Parameter"), null)); |
||||||
|
templateParameterViewPane.setPreferredSize(new Dimension(this.getWidth(), 200)); |
||||||
|
return templateParameterViewPane; |
||||||
|
} |
||||||
|
|
||||||
|
private JPanel createTextSettingPane() { |
||||||
|
JPanel textSettingPanel = new JPanel(); |
||||||
|
textSettingPanel.setLayout(new BorderLayout(0,8)); |
||||||
|
|
||||||
|
textContentPane = new TinyFormulaPane(); |
||||||
|
textContentPane.getUITextField().setColumns(20); |
||||||
|
textSettingPanel.add( |
||||||
|
MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Text"), textContentPane), |
||||||
|
BorderLayout.CENTER); |
||||||
|
|
||||||
|
fontPane = new CustomFontPane(); |
||||||
|
textSettingPanel.add( |
||||||
|
MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Style"), fontPane), |
||||||
|
BorderLayout.SOUTH); |
||||||
|
return MobilePopupUIUtils.createTitleSplitLineContentPane("", textSettingPanel); |
||||||
|
} |
||||||
|
|
||||||
|
private String getReportletName() { |
||||||
|
String text = this.templatePathTextField.getText(); |
||||||
|
return StringUtils.isBlank(text) ? StringUtils.EMPTY : text.substring(1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(MobilePopupHyperlink link) { |
||||||
|
this.populatePopupTargetBean(link.getPopupTarget()); |
||||||
|
this.populateTemplateContentBean(link); |
||||||
|
this.populateTextContentBean(link); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MobilePopupHyperlink updateBean() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateBean(MobilePopupHyperlink link) { |
||||||
|
this.updatePopupTargetBean(link); |
||||||
|
this.updateTemplateContentBean(link); |
||||||
|
this.updateTextContentBean(link); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String title4PopupWindow() { |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 自动添加模板参数的按钮操作 |
||||||
|
*/ |
||||||
|
private class HyperlinkParametersAction extends UITableEditAction { |
||||||
|
public HyperlinkParametersAction() { |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Template_Parameter")); |
||||||
|
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/p.gif")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
String tpl = getReportletName(); |
||||||
|
if (StringUtils.isBlank(tpl)) { |
||||||
|
JOptionPane.showMessageDialog( |
||||||
|
ContentSettingPane.this, |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Please_Select_Reportlet") + ".", |
||||||
|
Toolkit.i18nText("Fine-Design_Basic_Message"), |
||||||
|
JOptionPane.WARNING_MESSAGE); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
//根据模板路径返回参数
|
||||||
|
//与当前模块、当前文件无关
|
||||||
|
Parameter[] parameters = new Parameter[0]; |
||||||
|
|
||||||
|
ParameterReader[] readers = DesignModuleFactory.getParameterReaders(); |
||||||
|
for (ParameterReader reader : readers) { |
||||||
|
Parameter[] ps = reader.readParameterFromPath(tpl); |
||||||
|
if (ps != null) { |
||||||
|
parameters = ps; |
||||||
|
} |
||||||
|
} |
||||||
|
parameterViewPane.populate(parameters); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkEnabled() { |
||||||
|
//do nothing
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void populatePopupTargetBean(String target) { |
||||||
|
if (StringUtils.equals(target, MobilePopupConstants.Target_Text)) { |
||||||
|
popupTargetButtons.setSelected(textPopupButton.getModel(), true); |
||||||
|
this.remove(templateContentPane); |
||||||
|
this.add(textSettingPanel, BorderLayout.CENTER); |
||||||
|
} else { |
||||||
|
popupTargetButtons.setSelected(templatePopupButton.getModel(), true); |
||||||
|
this.remove(textSettingPanel); |
||||||
|
this.add(templateContentPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void updatePopupTargetBean(MobilePopupHyperlink mobilePopupHyperlink) { |
||||||
|
if (templatePopupButton.isSelected()) { |
||||||
|
mobilePopupHyperlink.setPopupTarget(MobilePopupConstants.Target_Template); |
||||||
|
} else if (textPopupButton.isSelected()) { |
||||||
|
mobilePopupHyperlink.setPopupTarget(MobilePopupConstants.Target_Text); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void populateTemplateContentBean(MobilePopupHyperlink link) { |
||||||
|
// 模板路径
|
||||||
|
templatePathTextField.setText(link.getReportletPath()); |
||||||
|
|
||||||
|
// 参数面板
|
||||||
|
List<ParameterProvider> parameterList = this.parameterViewPane.update(); |
||||||
|
parameterList.clear(); |
||||||
|
ParameterProvider[] parameters =link.getParameters(); |
||||||
|
parameterViewPane.populate(parameters); |
||||||
|
|
||||||
|
// 继承参数
|
||||||
|
extendParametersCheckBox.setSelected(link.isExtendParameters()); |
||||||
|
} |
||||||
|
|
||||||
|
private void updateTemplateContentBean(MobilePopupHyperlink link) { |
||||||
|
link.setReportletPath(templatePathTextField.getText()); |
||||||
|
|
||||||
|
List<ParameterProvider> parameterList = this.parameterViewPane.update(); |
||||||
|
if (!parameterList.isEmpty()) { |
||||||
|
Parameter[] parameters = new Parameter[parameterList.size()]; |
||||||
|
parameterList.toArray(parameters); |
||||||
|
link.setParameters(parameters); |
||||||
|
} else { |
||||||
|
link.setParameters(null); |
||||||
|
} |
||||||
|
|
||||||
|
link.setExtendParameters(extendParametersCheckBox.isSelected()); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void populateTextContentBean(MobilePopupHyperlink link) { |
||||||
|
Object text = link.getPopupText(); |
||||||
|
if (text instanceof FormulaProvider) { |
||||||
|
textContentPane.populateBean(((FormulaProvider) text).getContent()); |
||||||
|
} else { |
||||||
|
textContentPane.populateBean(text == null ? StringUtils.EMPTY : text.toString()); |
||||||
|
} |
||||||
|
fontPane.populateBean(link.getFRFont()); |
||||||
|
} |
||||||
|
private void updateTextContentBean(MobilePopupHyperlink link) { |
||||||
|
link.setPopupText(textContentPane.getUITextField().getText()); |
||||||
|
String text = textContentPane.updateBean(); |
||||||
|
if (CommonUtils.maybeFormula(text)) { |
||||||
|
link.setPopupText(BaseFormula.createFormulaBuilder().build(textContentPane.updateBean())); |
||||||
|
} else { |
||||||
|
link.setPopupText(text); |
||||||
|
} |
||||||
|
|
||||||
|
link.setFRFont(fontPane.updateBean()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
package com.fr.design.hyperlink.popup; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.design.constants.LayoutConstants; |
||||||
|
import com.fr.design.gui.ibutton.UIColorButton; |
||||||
|
import com.fr.design.gui.ibutton.UIToggleButton; |
||||||
|
import com.fr.design.gui.icombobox.UIComboBox; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.utils.gui.GUICoreUtils; |
||||||
|
import com.fr.general.FRFont; |
||||||
|
import com.fr.stable.Constants; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
public class CustomFontPane extends JPanel { |
||||||
|
private static final int MAX_FONT_SIZE = 100; |
||||||
|
private static final Dimension BUTTON_SIZE = new Dimension(20, 18); |
||||||
|
|
||||||
|
public static Vector<Integer> getFontSizes() { |
||||||
|
Vector<Integer> FONT_SIZES = new Vector<Integer>(); |
||||||
|
for (int i = 1; i < MAX_FONT_SIZE; i++) { |
||||||
|
FONT_SIZES.add(i); |
||||||
|
} |
||||||
|
return FONT_SIZES; |
||||||
|
} |
||||||
|
|
||||||
|
private UIComboBox fontSizeComboBox; |
||||||
|
private UIToggleButton bold; |
||||||
|
private UIToggleButton italic; |
||||||
|
private UIToggleButton underline; |
||||||
|
private UIColorButton colorSelectPane; |
||||||
|
|
||||||
|
public CustomFontPane() { |
||||||
|
this.initComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponent() { |
||||||
|
|
||||||
|
fontSizeComboBox = new UIComboBox(getFontSizes()); |
||||||
|
fontSizeComboBox.setPreferredSize(new Dimension(60, 20)); |
||||||
|
fontSizeComboBox.setEditable(true); |
||||||
|
|
||||||
|
colorSelectPane = new UIColorButton(); |
||||||
|
bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); |
||||||
|
italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); |
||||||
|
underline = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); |
||||||
|
|
||||||
|
this.setButtonsTips(); |
||||||
|
this.setButtonsSize(BUTTON_SIZE); |
||||||
|
|
||||||
|
Component[] components_font = new Component[]{ |
||||||
|
fontSizeComboBox, colorSelectPane, bold, underline, italic |
||||||
|
}; |
||||||
|
|
||||||
|
JPanel buttonPane = new JPanel(new BorderLayout()); |
||||||
|
buttonPane.add(GUICoreUtils.createFlowPane(components_font, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL)); |
||||||
|
|
||||||
|
this.setLayout(new BorderLayout(0,0)); |
||||||
|
this.add(buttonPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
private void setButtonsTips() { |
||||||
|
colorSelectPane.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Foreground")); |
||||||
|
italic.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Italic")); |
||||||
|
bold.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Bold")); |
||||||
|
underline.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Underline")); |
||||||
|
} |
||||||
|
|
||||||
|
private void setButtonsSize(Dimension size) { |
||||||
|
colorSelectPane.setPreferredSize(size); |
||||||
|
bold.setPreferredSize(size); |
||||||
|
italic.setPreferredSize(size); |
||||||
|
underline.setPreferredSize(size); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void populateBean(FRFont frFont) { |
||||||
|
fontSizeComboBox.setSelectedItem(frFont.getSize()); |
||||||
|
colorSelectPane.setColor(frFont.getForeground()); |
||||||
|
bold.setSelected(frFont.isBold()); |
||||||
|
italic.setSelected(frFont.isItalic()); |
||||||
|
underline.setSelected(frFont.getUnderline() != Constants.LINE_NONE); |
||||||
|
} |
||||||
|
|
||||||
|
public FRFont updateBean() { |
||||||
|
int style = Font.PLAIN; |
||||||
|
style += this.bold.isSelected() ? Font.BOLD : Font.PLAIN; |
||||||
|
style += this.italic.isSelected() ? Font.ITALIC : Font.PLAIN; |
||||||
|
return FRFont.getInstance( |
||||||
|
FRFont.DEFAULT_FONTNAME, |
||||||
|
style, |
||||||
|
Float.parseFloat(fontSizeComboBox.getSelectedItem().toString()), |
||||||
|
colorSelectPane.getColor(), |
||||||
|
underline.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.fr.design.hyperlink.popup; |
||||||
|
|
||||||
|
import com.fr.stable.Constants; |
||||||
|
|
||||||
|
public interface MobilePopupConstants { |
||||||
|
int[] BORDER_LINE_STYLE_ARRAY = new int[]{ |
||||||
|
Constants.LINE_NONE, |
||||||
|
Constants.LINE_THIN, |
||||||
|
Constants.LINE_MEDIUM, |
||||||
|
Constants.LINE_THICK, |
||||||
|
}; |
||||||
|
|
||||||
|
String Target_Template= "template"; |
||||||
|
String Target_Text = "text"; |
||||||
|
String Regular_Custom = "custom"; |
||||||
|
String Regular_Auto_Height = "auto_height"; |
||||||
|
|
||||||
|
double Popup_Center_Default_Width = 95; |
||||||
|
double Popup_Center_Default_Height = 95; |
||||||
|
double Popup_Follow_Default_Width = 40; |
||||||
|
double Popup_Follow_Default_Height = 10; |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue