forked from fanruan/design
Browse Source
* commit '53f04b81acf630c64cfec637d2e3c25cdf0ae0c5': (55 commits) REPORT-80276 填报-填报属性设置-数据表搜索时概率出现多个重复的搜索结果 REPORT-79999 填报-填报属性设置-对表的模糊搜索匹配不精确 REPORT-79909 设计器启动失败,有模板名称叫WorkBook88888888888888.cpt导致 REPORT-79440 找不到驱动的话可以保存数据连接 REPORT-64340 删除无效日志 REPORT-77217 ConnectionProvider-修改之后数据连接信息无法保存 同步10.0 【问题原因】产生假保存的原因是,在保存的时候会判断现有的Connection与以前存储的Connection是否有不同,如果不同就代表需要更新。实际上插件中的Connection相关类没有写equals方法,然后新旧Connection被认为是相同了,就没有走后面的更新配置的逻辑 【改动方案】拉rinoux、vito、hugh一起沟通了下方案,暂时主代码里做个兼容,让主代码内置的两种Connection去判断是否要更新,其余的Connection(插件Connection)都必须更新 【review建议】同步10.0 单独写一个 DefaultLoginKeys REPORT-72595 FR源码中存在加密密钥硬编码,建议放到配置文件中 REPORT-75991 插件完整性校验,弹窗链接帮助文档说明 【问题原因】安全类需求,将原来仅对官方插件开启的 插件完整性校验,扩大到了 第三方插件。但弹窗不明确,对于用户侧没有闭环,需要添加帮助文档链接,帮助用户清楚前因后果与解决方案。 【改动方案】1.提示文案内容修改;2.提示中存在超链接,将插件这边因为"插件完整性校验"而失败的弹窗单独处理了下,由原本的JOptionPane修改为JEditorPane 【review建议】其它的弹窗暂时没有变动的需求,跟产品沟通过了,如果以后有必要统一的时候再来统一处理 REPORT-72635 - 数据连接面板为空的问题(含控制权限) 有些新类,没提交进去 REPORT-72635 - 数据连接面板为空的问题(含控制权限) 【问题原因】同步到10.0 【改动思路】同步到10.0 【review建议】无 REPORT-76370 提供一个数据连接前置检查接口&提交10.0 REPORT-76370 提供一个数据连接前置检查接口&提交10.0 REPORT-38555 fix:数字控件中内容可以输入空格和减号 REPORT-38555 fix:数字控件中内容可以输入空格和减号 REPORT-38523 fix: 右侧单元格属性表鼠标事件有误,修改了mouseReleased事件 REPORT-74887 新建决策报表,拖入第三方插件图表无法编辑 无JIRA任务 合final REPORT-74118 单元格数据源老模板切换到数据集数据并添加多分类,多分类不可修改 REPORT-74118 单元格数据源老模板切换到数据集数据并添加多分类,多分类不可修改 ...
Link.Zhao-赵展
2 years ago
132 changed files with 5747 additions and 469 deletions
@ -0,0 +1,44 @@
|
||||
package com.fr.design.actions.help.alphafine; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/26 |
||||
*/ |
||||
public class AlphaFineShortCutUtil { |
||||
|
||||
private static final String TYPE = "pressed"; |
||||
private static final String DISPLAY_TYPE = "+"; |
||||
private static final String BACK_SLASH = "BACK_SLASH"; |
||||
private static final String DISPLAY_BACK_SLASH = "\\"; |
||||
private static final String SLASH = "SLASH"; |
||||
private static final String DISPLAY_SLASH = "/"; |
||||
private static final String CONTROL = "CONTROL"; |
||||
private static final String DISPLAY_CONTROL = "ctrl"; |
||||
private static final String OPEN_BRACKET = "OPEN_BRACKET"; |
||||
private static final String DISPLAY_OPEN_BRACKET = "{"; |
||||
private static final String CLOSE_BRACKET = "CLOSE_BRACKET"; |
||||
private static final String DISPLAY_CLOSE_BRACKET = "}"; |
||||
private static final String COMMA = "COMMA"; |
||||
private static final String DISPLAY_COMMA = ","; |
||||
private static final String PERIOD = "PERIOD"; |
||||
private static final String DISPLAY_PERIOD = "."; |
||||
private static final String SEMICOLON = "SEMICOLON"; |
||||
private static final String DISPLAY_SEMICOLON = ";"; |
||||
private static final String QUOTE = "QUOTE"; |
||||
private static final String DISPLAY_QUOTE = "'"; |
||||
private static final String EQUALS = "EQUALS"; |
||||
private static final String DISPLAY_EQUALS = "+"; |
||||
private static final String MINUS = "MINUS"; |
||||
private static final String DISPLAY_MINUS = "-"; |
||||
private static final String COMMAND = "META"; |
||||
private static final String SMALL_COMMAND = "meta"; |
||||
private static final String DISPLAY_COMMAND = "\u2318"; |
||||
|
||||
public static String getDisplayShortCut(String shortCut) { |
||||
return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH) |
||||
.replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET) |
||||
.replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE) |
||||
.replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
|
||||
package com.fr.design.actions.help.alphafine; |
||||
|
||||
import java.util.Stack; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/23 |
||||
*/ |
||||
public class SizedStack<T> extends Stack<T> { |
||||
|
||||
private final int maxSize; |
||||
|
||||
public SizedStack(int size) { |
||||
super(); |
||||
this.maxSize = size; |
||||
} |
||||
|
||||
@Override |
||||
public T push(T object) { |
||||
while (this.size() >= maxSize) { |
||||
this.remove(0); |
||||
} |
||||
// 不重复
|
||||
if (this.contains(object)) { |
||||
return object; |
||||
} |
||||
return super.push(object); |
||||
} |
||||
} |
@ -0,0 +1,57 @@
|
||||
package com.fr.design.data.datapane.auth; |
||||
|
||||
import com.fr.base.TableData; |
||||
import com.fr.data.impl.Connection; |
||||
import com.fr.data.impl.DBTableData; |
||||
import com.fr.data.impl.NameDatabaseConnection; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.workspace.WorkContext; |
||||
import com.fr.workspace.server.connection.DBConnectAuth; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
|
||||
/** |
||||
* 数据连接权限相关的工具类 |
||||
* @author Yvan |
||||
*/ |
||||
public class TableDataAuthHelper { |
||||
|
||||
/** |
||||
* 编辑数据集时是否需要检查权限 |
||||
* @param tableData |
||||
* @return |
||||
*/ |
||||
public static boolean needCheckAuthWhenEdit(TableData tableData) { |
||||
// 远程设计下,编辑DBTableData时需要判断权限
|
||||
return !WorkContext.getCurrent().isLocal() && tableData instanceof DBTableData; |
||||
} |
||||
|
||||
/** |
||||
* 获取无权限数据连接集合 |
||||
* 远程下需要调用RPC,为耗时操作,谨慎使用 |
||||
* @return |
||||
*/ |
||||
public static Collection<String> getNoAuthConnections() { |
||||
// 获取无权限连接集合
|
||||
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections(); |
||||
return noAuthConnections == null ? Collections.emptyList() : noAuthConnections; |
||||
} |
||||
|
||||
/** |
||||
* 通过数据集获取其数据连接的名称 |
||||
* |
||||
* 注意: |
||||
* 1. Connection接口本身是不提供名称的,只有我们内部为了使用方便,将其包装成了NameDataBaseConnection |
||||
* 如果不是NameDataBaseConnection类型,则无名称,因此这里只能用判断类型的方式获取名称 |
||||
* 2. 仅支持DBTableData获取连接名 |
||||
* @return |
||||
*/ |
||||
public static String getConnectionNameByDBTableData(DBTableData tableData) { |
||||
Connection database = tableData.getDatabase(); |
||||
if (database instanceof NameDatabaseConnection) { |
||||
return ((NameDatabaseConnection) database).getName(); |
||||
} |
||||
return StringUtils.EMPTY; |
||||
} |
||||
} |
@ -0,0 +1,23 @@
|
||||
package com.fr.design.data.tabledata.tabledatapane.loading; |
||||
|
||||
|
||||
|
||||
/** |
||||
* 可切换的DBTableData对应的数据集面板,需要使用CardLayout布局 |
||||
* 主要是给插件适配用的 |
||||
* @author Yvan |
||||
*/ |
||||
public interface SwitchableTableDataPane { |
||||
|
||||
/** Loading面板 */ |
||||
String LOADING_PANE_NAME = "Loading"; |
||||
/** 内容面板 */ |
||||
String CONTENT_PANE_NAME = "Content"; |
||||
|
||||
/** |
||||
* 根据面板名称切换面板 |
||||
* @param paneName 面板名称 |
||||
*/ |
||||
void switchTo(String paneName); |
||||
|
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.fr.design.data.tabledata.tabledatapane.loading; |
||||
|
||||
import com.fr.design.dialog.BasicPane; |
||||
import com.fr.design.i18n.Toolkit; |
||||
|
||||
import javax.swing.JPanel; |
||||
import java.awt.CardLayout; |
||||
|
||||
/** |
||||
* @author Yvan |
||||
*/ |
||||
public class TableDataLoadingPane extends BasicPane { |
||||
|
||||
/** Loading面板 */ |
||||
public static final String LOADING_PANE_NAME = "Loading"; |
||||
/** 无权限提示面板 */ |
||||
public static final String NO_AUTH_PANE_NAME = "NoAuthority"; |
||||
/** 错误提示面板 */ |
||||
public static final String ERROR_NAME = "Error"; |
||||
|
||||
private CardLayout card; |
||||
|
||||
/** 加载中面板 */ |
||||
private JPanel loadingPane; |
||||
/** 错误提示面板 */ |
||||
private JPanel errorPane; |
||||
/** 数据连接无权限面板 */ |
||||
private JPanel noAuthorityPane; |
||||
|
||||
public TableDataLoadingPane() { |
||||
initPanes(); |
||||
} |
||||
|
||||
private void initPanes() { |
||||
card = new CardLayout(); |
||||
this.setLayout(card); |
||||
loadingPane = new TipsPane(true); |
||||
errorPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Error")); |
||||
noAuthorityPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_No_Auth")); |
||||
add(LOADING_PANE_NAME, loadingPane); |
||||
add(NO_AUTH_PANE_NAME, noAuthorityPane); |
||||
add(ERROR_NAME, errorPane); |
||||
switchTo(LOADING_PANE_NAME); |
||||
} |
||||
|
||||
public void switchTo(String panelName) { |
||||
card.show(this, panelName); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
package com.fr.design.data.tabledata.tabledatapane.loading; |
||||
|
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
|
||||
import javax.swing.JPanel; |
||||
import javax.swing.JProgressBar; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
|
||||
/** |
||||
* 提示面板,支持自定义提示,支持进度条配置可选 |
||||
* @author Yvan |
||||
*/ |
||||
public class TipsPane extends JPanel { |
||||
|
||||
/** |
||||
* 默认提示 |
||||
*/ |
||||
private static final String LOADING = Toolkit.i18nText("Fine-Design_Basic_Loading_And_Waiting"); |
||||
|
||||
public TipsPane () { |
||||
this(LOADING, false); |
||||
} |
||||
|
||||
public TipsPane (String tip) { |
||||
this(tip, false); |
||||
} |
||||
|
||||
public TipsPane (boolean needProgressBar) { |
||||
this(LOADING, needProgressBar); |
||||
} |
||||
|
||||
public TipsPane (String tips, boolean needProgressBar) { |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
UILabel tipsLabel = new UILabel(tips, SwingConstants.CENTER); |
||||
this.add(tipsLabel, BorderLayout.CENTER); |
||||
if (needProgressBar) { |
||||
JProgressBar progressBar = new JProgressBar(); |
||||
progressBar.setIndeterminate(true); |
||||
this.add(progressBar, BorderLayout.SOUTH); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,70 @@
|
||||
package com.fr.design.extra.exe.callback.handle; |
||||
|
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.dialog.link.MessageWithLink; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.plugin.error.PluginErrorCode; |
||||
import com.fr.plugin.manage.control.PluginTaskResult; |
||||
|
||||
/** |
||||
* 帮助处理插件操作(安装、更新等)的弹窗 |
||||
* @author Yvan |
||||
*/ |
||||
public class PluginCallBackHelper { |
||||
|
||||
private static final String NEW_LINE_TAG = "<br/>"; |
||||
private static final String REFERENCE = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_Reference"); |
||||
private static final String HELP_DOCUMENT_NAME = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_NAME"); |
||||
private static final String CONNECTOR = "-"; |
||||
private static final String HELP_DOCUMENT_LINK = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK"); |
||||
|
||||
|
||||
/** |
||||
* 展示插件操作失败后的提示弹窗 |
||||
* @param result |
||||
* @param pluginInfo |
||||
*/ |
||||
public static void showErrorMessage(PluginTaskResult result, String pluginInfo) { |
||||
// 单独处理下插件完整性校验失败的提示
|
||||
if (PluginCallBackHelper.needHandleInvalidatePackage(result)) { |
||||
MessageWithLink messageWithLink = PluginCallBackHelper.generate4InvalidatePackage(pluginInfo); |
||||
PluginTaskResultErrorDialog resultDialog = new PluginTaskResultErrorDialog(null, messageWithLink); |
||||
resultDialog.showResult(); |
||||
} else { |
||||
FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 判断是否需要处理 插件安装包校验失败 导致的安装失败任务 |
||||
* @param result |
||||
* @return |
||||
*/ |
||||
private static boolean needHandleInvalidatePackage(PluginTaskResult result) { |
||||
return !result.isSuccess() && result.getCode() == PluginErrorCode.InstallPackageValidateFailed; |
||||
} |
||||
|
||||
/** |
||||
* 根据插件原始报错信息,构建MessageWithLink |
||||
* @param originInfo |
||||
* @return |
||||
*/ |
||||
private static MessageWithLink generate4InvalidatePackage(String originInfo) { |
||||
|
||||
return new MessageWithLink(getSupplementaryMessage(originInfo), HELP_DOCUMENT_NAME, HELP_DOCUMENT_LINK); |
||||
} |
||||
|
||||
/** |
||||
* 根据插件原始报错信息,获取增加了补充说明后的信息 |
||||
* @param originInfo |
||||
* @return |
||||
*/ |
||||
private static String getSupplementaryMessage(String originInfo) { |
||||
return new StringBuilder() |
||||
.append(originInfo) |
||||
.append(NEW_LINE_TAG) |
||||
.append(REFERENCE) |
||||
.append(CONNECTOR) |
||||
.toString(); |
||||
} |
||||
} |
@ -0,0 +1,86 @@
|
||||
package com.fr.design.extra.exe.callback.handle; |
||||
|
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.design.dialog.link.MessageWithLink; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.VerticalFlowLayout; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JPanel; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Dimension; |
||||
import java.awt.Frame; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
/** |
||||
* 当前仅处理Error提示,之后有需要再扩展 |
||||
* @author Yvan |
||||
*/ |
||||
public class PluginTaskResultErrorDialog extends JDialog { |
||||
|
||||
private static final Dimension LABEL = new Dimension(60, 90); |
||||
|
||||
private JPanel contentPane; |
||||
|
||||
private UILabel errorLabel; |
||||
|
||||
private UIButton confirmButton; |
||||
|
||||
private MessageWithLink messageWithLink; |
||||
|
||||
public PluginTaskResultErrorDialog(Frame parent, MessageWithLink messageWithLink) { |
||||
super(parent, true); |
||||
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning")); |
||||
this.messageWithLink = messageWithLink; |
||||
|
||||
initContentPane(); |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
this.setResizable(false); |
||||
this.add(contentPane, BorderLayout.CENTER); |
||||
this.setSize(new Dimension( 380, 160)); |
||||
GUICoreUtils.centerWindow(this); |
||||
} |
||||
|
||||
/** |
||||
* 初始化内容面板 |
||||
*/ |
||||
private void initContentPane() { |
||||
this.contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
// error图标
|
||||
errorLabel = new UILabel(IconUtils.readIcon("/com/fr/design/standard/system/error_tips.svg")); |
||||
errorLabel.setPreferredSize(LABEL); |
||||
errorLabel.setBorder(BorderFactory.createEmptyBorder(10, 20, 40, 20)); |
||||
// 提示内容
|
||||
JPanel messagePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
messagePane.add(errorLabel, BorderLayout.WEST); |
||||
messagePane.add(messageWithLink, BorderLayout.CENTER); |
||||
messagePane.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10)); |
||||
this.contentPane.add(messagePane, BorderLayout.CENTER); |
||||
// 确定按钮
|
||||
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Button_OK")); |
||||
confirmButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
hideResult(); |
||||
} |
||||
}); |
||||
JPanel confirmPane = new JPanel(new VerticalFlowLayout()); |
||||
confirmPane.add(confirmButton); |
||||
confirmPane.setBorder(BorderFactory.createEmptyBorder(0, 160, 10, 0)); |
||||
this.contentPane.add(confirmPane, BorderLayout.SOUTH); |
||||
} |
||||
|
||||
public void showResult() { |
||||
this.setVisible(true); |
||||
} |
||||
|
||||
public void hideResult() { |
||||
this.setVisible(false); |
||||
} |
||||
} |
@ -1,77 +0,0 @@
|
||||
package com.fr.design.gui.icombobox; |
||||
|
||||
import com.fr.log.FineLoggerFactory; |
||||
|
||||
import javax.swing.JTree; |
||||
import javax.swing.SwingWorker; |
||||
import javax.swing.tree.TreeCellRenderer; |
||||
import java.util.concurrent.FutureTask; |
||||
|
||||
/** |
||||
* 模糊搜索前需执行完前置任务的TreeComboBox |
||||
* @author Lucian.Chen |
||||
* @version 10.0 |
||||
* Created by Lucian.Chen on 2021/4/14 |
||||
*/ |
||||
public class SearchPreTaskTreeComboBox extends FRTreeComboBox { |
||||
|
||||
/** |
||||
* 模糊搜索前任务 |
||||
*/ |
||||
private FutureTask<Void> preSearchTask; |
||||
|
||||
public SearchPreTaskTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) { |
||||
super(tree, renderer, editable); |
||||
} |
||||
|
||||
public FutureTask<Void> getPreSearchTask() { |
||||
return preSearchTask; |
||||
} |
||||
|
||||
public void setPreSearchTask(FutureTask<Void> preSearchTask) { |
||||
this.preSearchTask = preSearchTask; |
||||
} |
||||
|
||||
protected UIComboBoxEditor createEditor() { |
||||
return new SearchPreTaskComboBoxEditor(this); |
||||
} |
||||
|
||||
private class SearchPreTaskComboBoxEditor extends FrTreeSearchComboBoxEditor { |
||||
|
||||
public SearchPreTaskComboBoxEditor(FRTreeComboBox comboBox) { |
||||
super(comboBox); |
||||
} |
||||
|
||||
protected void changeHandler() { |
||||
if (isSetting()) { |
||||
return; |
||||
} |
||||
setPopupVisible(true); |
||||
new SwingWorker<Void, Void>() { |
||||
@Override |
||||
protected Void doInBackground() { |
||||
FutureTask<Void> task = getPreSearchTask(); |
||||
try { |
||||
// 确保模糊搜索前任务执行完成后,再进行模糊搜索
|
||||
if (task != null) { |
||||
task.get(); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
if (task != null) { |
||||
// 任务执行后置空,否则会被别的操作重复触发
|
||||
setPreSearchTask(null); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
// 模糊搜索
|
||||
search(); |
||||
} |
||||
}.execute(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,236 @@
|
||||
package com.fr.design.gui.icombobox; |
||||
|
||||
import com.fr.concurrent.NamedThreadFactory; |
||||
import com.fr.data.core.DataCoreUtils; |
||||
import com.fr.data.core.db.TableProcedure; |
||||
import com.fr.data.impl.Connection; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.data.datapane.ChoosePane; |
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.module.ModuleContext; |
||||
import com.fr.stable.ArrayUtils; |
||||
import com.fr.stable.Filter; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.JTree; |
||||
import javax.swing.SwingWorker; |
||||
import javax.swing.event.PopupMenuEvent; |
||||
import javax.swing.event.PopupMenuListener; |
||||
import javax.swing.tree.DefaultMutableTreeNode; |
||||
import javax.swing.tree.DefaultTreeModel; |
||||
import javax.swing.tree.TreeCellRenderer; |
||||
import javax.swing.tree.TreeNode; |
||||
import javax.swing.tree.TreePath; |
||||
import java.util.Enumeration; |
||||
import java.util.concurrent.ExecutorService; |
||||
|
||||
/** |
||||
* 实现模糊搜索表名的FRTreeComboBox |
||||
* FRTreeComboBox:搜索后滚动到首个匹配节点 |
||||
* SearchFRTreeComboBox:显示所有匹配的节点 |
||||
* |
||||
* @author Lucian.Chen |
||||
* @version 10.0 |
||||
* Created by Lucian.Chen on 2021/4/14 |
||||
*/ |
||||
public class TableSearchTreeComboBox extends FRTreeComboBox { |
||||
// 持有父容器,需要实时获取其他组件值
|
||||
private final ChoosePane parent; |
||||
/** |
||||
* 保证模糊搜索的原子性操作 |
||||
*/ |
||||
private final ExecutorService singleExecutor = ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory("TableSearchTreeComboBox")); |
||||
|
||||
public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) { |
||||
super(tree, renderer); |
||||
this.parent = parent; |
||||
initPopupListener(); |
||||
} |
||||
|
||||
protected UIComboBoxEditor createEditor() { |
||||
return new TableSearchComboBoxEditor(this); |
||||
} |
||||
|
||||
@Override |
||||
protected String pathToString(TreePath path) { |
||||
Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); |
||||
if (obj instanceof TableProcedure) { |
||||
return ((TableProcedure) obj).getName(); |
||||
} |
||||
return super.pathToString(path); |
||||
} |
||||
|
||||
@Override |
||||
public void setSelectedItemString(String _name) { |
||||
super.setSelectedItemString(_name); |
||||
// 会因为连续两次选中的值一致,导致未触发编辑框联动
|
||||
this.getEditor().setItem(_name); |
||||
} |
||||
|
||||
/** |
||||
* 执行模糊搜索 |
||||
*/ |
||||
private void searchExecute() { |
||||
UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor(); |
||||
String searchText = (String) searchEditor.getItem(); |
||||
singleExecutor.execute(new SwingWorker<Void, Void>() { |
||||
@Override |
||||
protected Void doInBackground() { |
||||
processTableDataNames( |
||||
parent.getDSName(), |
||||
parent.getConnection(), |
||||
parent.getSchema(), |
||||
createFilter(searchText)); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
expandTree(); |
||||
// 输入框获取焦点
|
||||
searchEditor.getEditorComponent().requestFocus(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private TableNameFilter createFilter(String text) { |
||||
return StringUtils.isEmpty(text) ? EMPTY_FILTER : new TableNameFilter(text); |
||||
} |
||||
|
||||
/** |
||||
* 查询数据库表,并构建节点目录 |
||||
* |
||||
* @param databaseName 数据库名 |
||||
* @param connection 数据连接 |
||||
* @param schema 模式 |
||||
* @param filter 模糊搜索过滤器 |
||||
*/ |
||||
private void processTableDataNames(String databaseName, Connection connection, String schema, TableNameFilter filter) { |
||||
if (tree == null) { |
||||
return; |
||||
} |
||||
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); |
||||
rootTreeNode.removeAllChildren(); |
||||
|
||||
if (connection == null) { |
||||
return; |
||||
} |
||||
try { |
||||
schema = StringUtils.isEmpty(schema) ? null : schema; |
||||
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(connection, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); |
||||
if (ArrayUtils.isNotEmpty(sqlTableArray)) { |
||||
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); |
||||
rootTreeNode.add(tableTreeNode); |
||||
addArrayNode(tableTreeNode, sqlTableArray, filter); |
||||
} |
||||
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(connection, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); |
||||
if (ArrayUtils.isNotEmpty(sqlViewArray)) { |
||||
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); |
||||
rootTreeNode.add(viewTreeNode); |
||||
addArrayNode(viewTreeNode, sqlViewArray, filter); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), |
||||
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); |
||||
} |
||||
} |
||||
|
||||
private void addArrayNode(ExpandMutableTreeNode rootNode, TableProcedure[] sqlArray, TableNameFilter filter) { |
||||
if (sqlArray != null) { |
||||
for (TableProcedure procedure : sqlArray) { |
||||
if (filter.accept(procedure)) { |
||||
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(procedure); |
||||
rootNode.add(viewChildTreeNode); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 展开节点 |
||||
*/ |
||||
private void expandTree() { |
||||
((DefaultTreeModel) tree.getModel()).reload(); |
||||
// daniel 展开所有tree
|
||||
TreeNode root = (TreeNode) tree.getModel().getRoot(); |
||||
TreePath parent = new TreePath(root); |
||||
TreeNode node = (TreeNode) parent.getLastPathComponent(); |
||||
for (Enumeration e = node.children(); e.hasMoreElements(); ) { |
||||
TreeNode n = (TreeNode) e.nextElement(); |
||||
TreePath path = parent.pathByAddingChild(n); |
||||
tree.expandPath(path); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 表名模糊搜索实现 |
||||
*/ |
||||
private static class TableNameFilter implements Filter<TableProcedure> { |
||||
private String searchFilter; |
||||
|
||||
public TableNameFilter() { |
||||
} |
||||
|
||||
public TableNameFilter(String searchFilter) { |
||||
this.searchFilter = searchFilter.toLowerCase().trim(); |
||||
} |
||||
|
||||
// 表名匹配
|
||||
@Override |
||||
public boolean accept(TableProcedure procedure) { |
||||
return procedure.getName().toLowerCase().contains(searchFilter); |
||||
} |
||||
} |
||||
|
||||
private static final TableNameFilter EMPTY_FILTER = new TableNameFilter() { |
||||
public boolean accept(TableProcedure procedure) { |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
private void initPopupListener() { |
||||
// 点击下拉时触发模糊搜索
|
||||
this.addPopupMenuListener(new PopupMenuListener() { |
||||
|
||||
@Override |
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { |
||||
searchExecute(); |
||||
} |
||||
|
||||
@Override |
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void popupMenuCanceled(PopupMenuEvent e) { |
||||
|
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 重写输入框编辑器,实现输入框模糊搜索逻辑 |
||||
*/ |
||||
private class TableSearchComboBoxEditor extends FrTreeSearchComboBoxEditor { |
||||
|
||||
public TableSearchComboBoxEditor(FRTreeComboBox comboBox) { |
||||
super(comboBox); |
||||
} |
||||
|
||||
@Override |
||||
protected void changeHandler() { |
||||
if (isSetting()) { |
||||
return; |
||||
} |
||||
setPopupVisible(true); |
||||
this.item = textField.getText(); |
||||
searchExecute(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@
|
||||
package com.fr.design.login.config; |
||||
|
||||
import com.fr.log.FineLoggerFactory; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Properties; |
||||
|
||||
/** |
||||
* @author Lanlan |
||||
* @version 10.0 |
||||
* Created by Lanlan on 2022/6/20 |
||||
*/ |
||||
public class DefaultLoginKeys { |
||||
|
||||
private static final String FILENAME = "com/fr/design/config/default"; |
||||
|
||||
private static final DefaultLoginKeys INSTANCE = new DefaultLoginKeys(); |
||||
|
||||
public static DefaultLoginKeys getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private final Map<String, String> keys = new HashMap<>(); |
||||
|
||||
private DefaultLoginKeys() { |
||||
Properties properties = load(); |
||||
for (Map.Entry<Object, Object> entry : properties.entrySet()) { |
||||
String name = entry.getKey().toString(); |
||||
keys.put(name, entry.getValue().toString()); |
||||
} |
||||
} |
||||
|
||||
public String getKey(String name) { |
||||
return keys.get(name); |
||||
} |
||||
|
||||
private Properties load() { |
||||
Properties properties = new Properties(); |
||||
try (InputStream inputStream = DefaultLoginKeys.class.getClassLoader().getResourceAsStream(FILENAME)) { |
||||
properties.load(inputStream); |
||||
} catch (IOException e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return properties; |
||||
} |
||||
} |
@ -0,0 +1,28 @@
|
||||
package com.fr.design.utils; |
||||
|
||||
import com.fr.base.svg.SVGIcon; |
||||
import com.fr.base.svg.SystemScaleUtils; |
||||
import java.awt.Graphics2D; |
||||
|
||||
/** |
||||
* 用于绘制svg图片缩放(高分屏下) |
||||
* |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/5/6 |
||||
*/ |
||||
public class SvgPaintUtils { |
||||
|
||||
public static void beforePaint(Graphics2D g2) { |
||||
if (SystemScaleUtils.isJreHiDPIEnabled()) { |
||||
g2.scale(1 / SVGIcon.SYSTEM_SCALE, 1 / SVGIcon.SYSTEM_SCALE); |
||||
} |
||||
} |
||||
|
||||
public static void afterPaint(Graphics2D g2) { |
||||
if (SystemScaleUtils.isJreHiDPIEnabled()) { |
||||
g2.scale(SVGIcon.SYSTEM_SCALE, SVGIcon.SYSTEM_SCALE); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1 @@
|
||||
Fine-Designer_Login=i7hP48WAcuTrmxfN |
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,44 @@
|
||||
package com.fr.design.gui.itextfield; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
|
||||
/** |
||||
* @author Destiny.Lin |
||||
* @version 10.0 |
||||
* created by Destiny.Lin on 2022-07-11 |
||||
*/ |
||||
public class UINumberFieldTest { |
||||
|
||||
@Test |
||||
public void testUINumberFieldTest(){ |
||||
UINumberField uiNumberField = new UINumberField(); |
||||
uiNumberField.setFieldDocument(); |
||||
//异常输入测试
|
||||
uiNumberField.setText("-.1"); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
uiNumberField.setText(".-1"); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
uiNumberField.setText("1-"); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
uiNumberField.setText("1-1"); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
uiNumberField.setText("1 "); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
uiNumberField.setText(".1"); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
uiNumberField.setText("1 -"); |
||||
Assert.assertEquals("",uiNumberField.getText()); |
||||
|
||||
//正常输入测试
|
||||
uiNumberField.setText("0.1"); |
||||
Assert.assertEquals("0.1",uiNumberField.getText()); |
||||
uiNumberField.setText("1"); |
||||
Assert.assertEquals("1",uiNumberField.getText()); |
||||
uiNumberField.setText("-1.5"); |
||||
Assert.assertEquals("-1.5",uiNumberField.getText()); |
||||
uiNumberField.setText("-123.123"); |
||||
Assert.assertEquals("-123.123",uiNumberField.getText()); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
package com.fr.design.form.util; |
||||
|
||||
import com.fr.base.Style; |
||||
import com.fr.general.FRFont; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
/** |
||||
* 富文本导出工具栏 |
||||
* |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/5/19 |
||||
*/ |
||||
public class HtmlPaintUtils { |
||||
|
||||
|
||||
private static final Pattern FONT_SIZE_PATTERN = Pattern.compile(Pattern.quote("font-size:") + "(.*?)" + Pattern.quote("px")); |
||||
|
||||
/** |
||||
* 设置单元格字体为富文本中的最大字体 |
||||
* |
||||
* @param style |
||||
*/ |
||||
public static Style deriveMaxFontFromRichChar(Style style, String html) { |
||||
int maxSize = style.getFRFont().getSize(); |
||||
Matcher matcher = FONT_SIZE_PATTERN.matcher(html); |
||||
while (matcher.find()) { |
||||
String value = matcher.group(1); |
||||
try { |
||||
double pxSize = Double.parseDouble(value); |
||||
int ptSize = FontTransformUtil.roundUp(FontTransformUtil.px2pt(pxSize)); |
||||
maxSize = Math.max(maxSize, ptSize); |
||||
} catch (Throwable e) { |
||||
FineLoggerFactory.getLogger().debug(e.getMessage(), e); |
||||
} |
||||
} |
||||
FRFont cellFont = style.getFRFont(); |
||||
return style.deriveFRFont(cellFont.applySize(maxSize)); |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
package com.fr.design.form.util; |
||||
|
||||
import com.fr.base.Style; |
||||
import junit.framework.TestCase; |
||||
import org.junit.Assert; |
||||
|
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/5/25 |
||||
*/ |
||||
public class HtmlPaintUtilsTest extends TestCase { |
||||
|
||||
public void testDeriveMaxFontFromRichChar() { |
||||
// 富文本字体size更大
|
||||
String testHtml0 = "<span style=\"font-size:21px;font-family:'宋体';\">这是一条测试数据</span>"; |
||||
Style style0 = Style.DEFAULT_STYLE; |
||||
Assert.assertEquals(16, HtmlPaintUtils.deriveMaxFontFromRichChar(style0, testHtml0).getFRFont().getSize()); |
||||
|
||||
// 单元格字体size更大
|
||||
String testHtml1 = "<span style=\"font-size:7px;font-family:'宋体';\">这是一条测试数据</span>"; |
||||
Style style1 = Style.DEFAULT_STYLE; |
||||
int oldFontSize = style1.getFRFont().getSize(); |
||||
Assert.assertEquals(oldFontSize, HtmlPaintUtils.deriveMaxFontFromRichChar(style1, testHtml1).getFRFont().getSize()); |
||||
|
||||
// 富文本字体size更大 不同文本 有不同size
|
||||
String testHtml2 = "<span style=\"font-size:21px;font-family:'宋体';\">这是一条测</span><span style=\"font-size:31px;font-family:'宋体';\">试数</span><span style=\"font-size:21px;font-family:'宋体';\">据</span>"; |
||||
Style style2 = Style.DEFAULT_STYLE; |
||||
Assert.assertEquals(23, HtmlPaintUtils.deriveMaxFontFromRichChar(style2, testHtml2).getFRFont().getSize()); |
||||
|
||||
|
||||
// 异常场景1
|
||||
String testHtml3 = "xxxx奇怪的格式xxxx"; |
||||
Style style3 = Style.DEFAULT_STYLE; |
||||
oldFontSize = style1.getFRFont().getSize(); |
||||
Assert.assertEquals(oldFontSize, HtmlPaintUtils.deriveMaxFontFromRichChar(style3, testHtml3).getFRFont().getSize()); |
||||
|
||||
// 异常场景2
|
||||
String testHtml4 = "<span style=\"font-size:xxxxpx;font-family:'宋体';\">这是一条测试数据</span>"; |
||||
Style style4 = Style.DEFAULT_STYLE; |
||||
oldFontSize = style1.getFRFont().getSize(); |
||||
Assert.assertEquals(oldFontSize, HtmlPaintUtils.deriveMaxFontFromRichChar(style4, testHtml4).getFRFont().getSize()); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,83 @@
|
||||
package com.fr.design.mainframe.alphafine; |
||||
|
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; |
||||
import com.fr.stable.ArrayUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/20 |
||||
*/ |
||||
public class AlphaFineUtil { |
||||
|
||||
public static String highLightModelName(String modelName, String[] strings) { |
||||
if (strings == null || ArrayUtils.isEmpty(strings)) { |
||||
return modelName; |
||||
} |
||||
for (String string : strings) { |
||||
// 高亮分词 跳过高亮颜色本身的字符
|
||||
boolean skipHighLight = modelName.contains(AlphaFineConstants.HIGH_LIGHT_COLOR) && AlphaFineConstants.HIGH_LIGHT_COLOR.contains(string); |
||||
if (skipHighLight) { |
||||
continue; |
||||
} |
||||
String primaryStr = getReplacedString(modelName, string); |
||||
if (StringUtils.isNotEmpty(primaryStr)) { |
||||
modelName = modelName.replaceAll("(?i)" + primaryStr, "|<font color=" + AlphaFineConstants.HIGH_LIGHT_COLOR + ">" + primaryStr + "</font>|"); |
||||
} |
||||
} |
||||
modelName = "<html><head><style> .style{" + |
||||
"overflow: hidden;" + |
||||
"text-overflow: ellipsis;" + |
||||
"white-space: nowrap;}" + |
||||
"</style></head><body class=\"style\">" + modelName.replaceAll("\\|", StringUtils.EMPTY) + "</body></HTML>"; |
||||
return modelName; |
||||
} |
||||
|
||||
|
||||
private static String getReplacedString(String modelName, String string) { |
||||
// 如果是直接包含了高亮字符 返回
|
||||
if (StringUtils.contains(modelName, string)) { |
||||
return string; |
||||
} |
||||
//需要考虑modelName有空格的情况
|
||||
//比如现在是work boo k 搜索词是workb,应该要替换的部分是work b
|
||||
//先去掉已经匹配替换过的部分,因为考虑到分词的情况,可能会进行多次替换
|
||||
final String regex = "\\|<font.*?</font>\\|"; |
||||
modelName = modelName.replaceAll(regex, StringUtils.EMPTY); |
||||
//再去掉空格进行匹配
|
||||
String noBlackName = modelName.replaceAll(StringUtils.BLANK, StringUtils.EMPTY).toLowerCase(); |
||||
int index = noBlackName.indexOf(string.toLowerCase()); |
||||
if (index == -1) { |
||||
return StringUtils.EMPTY; |
||||
} |
||||
StringBuilder result = new StringBuilder(); |
||||
int count = 0; |
||||
while (count < string.length()) { |
||||
char pos = modelName.charAt(index++); |
||||
result.append(pos); |
||||
count += pos == ' ' ? 0 : 1; |
||||
} |
||||
return result.toString(); |
||||
} |
||||
|
||||
public static String escapeExprSpecialWord(String keyword) { |
||||
if (StringUtils.isNotBlank(keyword)) { |
||||
String[] fbsArr = { "\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|" }; |
||||
for (String key : fbsArr) { |
||||
if (keyword.contains(key)) { |
||||
keyword = keyword.replace(key, "\\" + key); |
||||
} |
||||
} |
||||
} |
||||
return keyword; |
||||
} |
||||
|
||||
public static boolean unread() { |
||||
Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); |
||||
Set<Long> idSet = ProductNewsSearchManager.getInstance().getIdSet(); |
||||
return !idSet.isEmpty() && !readSet.containsAll(idSet); |
||||
} |
||||
} |
@ -0,0 +1,910 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.base.svg.SVGLoader; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.actions.help.alphafine.AlphaFineConfigManager; |
||||
import com.fr.design.actions.help.alphafine.AlphaFineShortCutUtil; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.borders.UITextFieldBorder; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.design.mainframe.alphafine.CellType; |
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import com.fr.design.mainframe.alphafine.model.ProductNews; |
||||
import com.fr.design.mainframe.alphafine.preview.DefaultProductNewsPane; |
||||
import com.fr.design.mainframe.alphafine.preview.HelpDocumentNoResultPane; |
||||
import com.fr.design.mainframe.alphafine.preview.LoadingRightSearchResultPane; |
||||
import com.fr.design.mainframe.alphafine.preview.NetWorkFailedPane; |
||||
import com.fr.design.mainframe.alphafine.preview.NoResultPane; |
||||
import com.fr.design.mainframe.alphafine.preview.NoResultWithLinkPane; |
||||
import com.fr.design.mainframe.alphafine.preview.SearchLoadingPane; |
||||
import com.fr.design.mainframe.alphafine.preview.SimpleRightSearchResultPane; |
||||
import com.fr.design.mainframe.alphafine.question.QuestionWindow; |
||||
import com.fr.design.mainframe.alphafine.search.ProductNewsSearchWorkerManager; |
||||
import com.fr.design.mainframe.alphafine.search.SearchTextBean; |
||||
import com.fr.design.mainframe.alphafine.search.SearchWorkerManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.ActionSearchManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.DocumentSearchManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.FileSearchManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.PluginSearchManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.SegmentationManager; |
||||
import com.fr.design.utils.DesignUtils; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.CardLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.Font; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.Image; |
||||
import java.awt.Insets; |
||||
import java.awt.RenderingHints; |
||||
import java.awt.Toolkit; |
||||
import java.awt.Window; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.FocusEvent; |
||||
import java.awt.event.FocusListener; |
||||
import java.awt.event.KeyAdapter; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JButton; |
||||
import javax.swing.JFrame; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPopupMenu; |
||||
import javax.swing.SwingConstants; |
||||
import javax.swing.Timer; |
||||
import javax.swing.event.PopupMenuEvent; |
||||
import javax.swing.event.PopupMenuListener; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/04/06 |
||||
*/ |
||||
public class AlphaFineFrame extends JFrame { |
||||
|
||||
private static final String ADVANCED_SEARCH_MARK = "k:"; |
||||
private static final String ACTION_MARK_SHORT = "k:1 "; |
||||
private static final String ACTION_MARK = "k:setting "; |
||||
private static final String DOCUMENT_MARK_SHORT = "k:2 "; |
||||
private static final String DOCUMENT_MARK = "k:help "; |
||||
private static final String FILE_MARK_SHORT = "k:3 "; |
||||
private static final String FILE_MARK = "k:reportlets "; |
||||
private static final String CPT_MARK = "k:cpt "; |
||||
private static final String FRM_MARK = "k:frm "; |
||||
private static final String DS_MARK = "k:ds "; |
||||
private static final String DS_NAME = "dsname=\""; |
||||
private static final String PLUGIN_MARK_SHORT = "k:4 "; |
||||
private static final String PLUGIN_MARK = "k:shop "; |
||||
|
||||
private static final int TIMER_DELAY = 300; |
||||
|
||||
private static final String PLACE_HOLDER = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine"); |
||||
|
||||
private static final String SETTING = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set"); |
||||
|
||||
private static final String NO_RESULT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_No_Result"); |
||||
|
||||
private static final String SKILLS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Skills"); |
||||
|
||||
private static final String SEARCH_TERM = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Search_Term"); |
||||
|
||||
private static final String SEARCH = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Search"); |
||||
|
||||
private static final String GO_FORUM = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Go_Forum"); |
||||
|
||||
private static final String TEMPLATES = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Templates"); |
||||
|
||||
public static final String PRODUCT_NEWS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News"); |
||||
|
||||
private static final String HELP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help"); |
||||
|
||||
private static final String PLUGIN = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon"); |
||||
|
||||
private static final String ONE_CLICK_READ = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_One_Click_Read"); |
||||
|
||||
private static final String NO_SEARCH_RESULT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_NO_Result"); |
||||
|
||||
private static final String PRODUCT_DYNAMICS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_Dynamics"); |
||||
|
||||
private static final Image SEARCH_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/search.svg"); |
||||
|
||||
private static final Color BORDER_COLOR = new Color(232, 232, 233); |
||||
|
||||
private final CardLayout cardLayout = new CardLayout(); |
||||
|
||||
private final JPanel resultPane = new JPanel(cardLayout); |
||||
|
||||
private String storeText; |
||||
|
||||
private String[] segmentationResult; |
||||
|
||||
private UILabel useTipLabel; |
||||
|
||||
private UILabel tipIconLabel; |
||||
|
||||
private AlphaFineTextField searchTextField; |
||||
|
||||
private AlphaFineList searchResultList; |
||||
|
||||
private SearchLoadingPane searchLoadingPane; |
||||
|
||||
private JPanel searchTextFieldWrapperPane; |
||||
|
||||
private UILabel clearLabel; |
||||
|
||||
private JPanel tabPane; |
||||
|
||||
private CellType selectedType; |
||||
|
||||
private String beforeSearchStr = StringUtils.EMPTY; |
||||
|
||||
private SearchWorkerManager settingSearchWorkerManager; |
||||
|
||||
private SearchWorkerManager fileSearchWorkerManager; |
||||
|
||||
private SearchWorkerManager documentWorkerManager; |
||||
|
||||
private SearchWorkerManager pluginSearchWorkerManager; |
||||
|
||||
private SearchWorkerManager currentSearchWorkerManager; |
||||
|
||||
private ProductNewsSearchWorkerManager productNewsSearchWorkerManager; |
||||
|
||||
public AlphaFineFrame() { |
||||
this.setTitle(AlphaFineConstants.TITLE); |
||||
setUndecorated(true); |
||||
setSize(AlphaFineConstants.FIELD_SIZE); |
||||
initComponents(); |
||||
centerWindow(this); |
||||
initSearchManager(); |
||||
} |
||||
|
||||
private void initSearchManager() { |
||||
|
||||
this.productNewsSearchWorkerManager = new ProductNewsSearchWorkerManager( |
||||
CellType.PRODUCT_NEWS, |
||||
searchTextBean -> { |
||||
return ProductNewsSearchManager.getInstance().getSearchResult(searchTextBean.getSegmentation()); |
||||
}, |
||||
this |
||||
); |
||||
|
||||
this.settingSearchWorkerManager = new SearchWorkerManager( |
||||
CellType.ACTION, |
||||
searchTextBean -> ActionSearchManager.getInstance().getSearchResult(searchTextBean), |
||||
this, |
||||
new SimpleRightSearchResultPane(new NoResultPane(NO_RESULT, AlphaFineConstants.NO_RESULT_ICON)) |
||||
); |
||||
fileSearchWorkerManager = new SearchWorkerManager( |
||||
CellType.FILE, |
||||
searchTextBean -> FileSearchManager.getInstance().getSearchResult(searchTextBean), |
||||
this, |
||||
new LoadingRightSearchResultPane() |
||||
); |
||||
documentWorkerManager = new SearchWorkerManager( |
||||
CellType.DOCUMENT, |
||||
searchTextBean -> DocumentSearchManager.getInstance().getSearchResult(searchTextBean), |
||||
this, |
||||
new SimpleRightSearchResultPane(new JPanel()) |
||||
); |
||||
|
||||
pluginSearchWorkerManager = new SearchWorkerManager( |
||||
CellType.PLUGIN, |
||||
searchTextBean -> PluginSearchManager.getInstance().getSearchResult(searchTextBean), |
||||
this, |
||||
new LoadingRightSearchResultPane() |
||||
); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 初始化全部组件 |
||||
*/ |
||||
private void initComponents() { |
||||
|
||||
add(createTopPane(), BorderLayout.NORTH); |
||||
initSearchTextField(); |
||||
add(createSearchPane(), BorderLayout.CENTER); |
||||
add(createShowPane(), BorderLayout.SOUTH); |
||||
this.getContentPane().setBackground(Color.WHITE); |
||||
this.setIconImage(SEARCH_IMAGE); |
||||
this.setSize(AlphaFineConstants.FULL_SIZE); |
||||
} |
||||
|
||||
private JPanel createTopPane() { |
||||
JPanel topPane = new JPanel(new BorderLayout()); |
||||
topPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
||||
topPane.setBackground(Color.WHITE); |
||||
JPanel topLeftPane = new JPanel(new FlowLayout(FlowLayout.LEFT)); |
||||
topLeftPane.setBackground(Color.WHITE); |
||||
UILabel alphaFineLabel = new UILabel(AlphaFineConstants.TITLE); |
||||
alphaFineLabel.setFont(new Font("Arial Black", Font.PLAIN, 20)); |
||||
alphaFineLabel.setForeground(UIConstants.FLESH_BLUE); |
||||
topLeftPane.add(alphaFineLabel); |
||||
topPane.add(topLeftPane, BorderLayout.WEST); |
||||
|
||||
JPanel topRightPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 10)); |
||||
topRightPane.setBackground(Color.WHITE); |
||||
JPanel tipPane = new JPanel(new BorderLayout()); |
||||
tipPane.setBackground(Color.WHITE); |
||||
tipIconLabel = new UILabel(AlphaFineConstants.BULB_ICON); |
||||
tipIconLabel.addMouseListener(tipMouseListener); |
||||
useTipLabel = new UILabel(SKILLS); |
||||
useTipLabel.addMouseListener(tipMouseListener); |
||||
useTipLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); |
||||
tipPane.add(tipIconLabel, BorderLayout.WEST); |
||||
tipPane.add(useTipLabel, BorderLayout.CENTER); |
||||
topRightPane.add(tipPane); |
||||
UIButton minimizeButton = createButton(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/minimize.svg")); |
||||
minimizeButton.addActionListener(e -> AlphaFineFrame.this.setExtendedState(JFrame.ICONIFIED)); |
||||
topRightPane.add(minimizeButton); |
||||
UIButton closeButton = createButton(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/close.svg")); |
||||
closeButton.addActionListener(e -> AlphaFineFrame.this.dispose()); |
||||
topRightPane.add(closeButton); |
||||
topPane.add(topRightPane, BorderLayout.EAST); |
||||
return topPane; |
||||
} |
||||
|
||||
private MouseAdapter tipMouseListener = new MouseAdapter() { |
||||
|
||||
private JPopupMenu popupMenu; |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
tipIconLabel.setIcon(AlphaFineConstants.YELLOW_BULB_ICON); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
if (popupMenu == null || !popupMenu.isShowing()) { |
||||
useTipLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); |
||||
tipIconLabel.setIcon(AlphaFineConstants.BULB_ICON); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
useTipLabel.setForeground(UIConstants.FLESH_BLUE); |
||||
tipIconLabel.setIcon(AlphaFineConstants.LIGHT_YELLOW_BULB_ICON); |
||||
popupMenu = createTipPop(); |
||||
GUICoreUtils.showPopupMenu(popupMenu, e.getComponent(), e.getComponent().getX() - 60, e.getComponent().getY() + 20); |
||||
} |
||||
}; |
||||
|
||||
|
||||
private JPopupMenu createTipPop() { |
||||
JPanel panel = new JPanel(new BorderLayout()); |
||||
String toolTip = AlphaFineShortCutUtil.getDisplayShortCut(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Short_Cut", DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getShortcuts())); |
||||
UILabel label = new UILabel(toolTip); |
||||
label.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); |
||||
label.setBackground(Color.WHITE); |
||||
panel.add(label); |
||||
panel.setBackground(Color.WHITE); |
||||
JPopupMenu popupMenu = new JPopupMenu(); |
||||
popupMenu.setBorder(BorderFactory.createEmptyBorder(20, 5, 10, 5)); |
||||
popupMenu.add(panel); |
||||
popupMenu.setBackground(Color.WHITE); |
||||
popupMenu.addPopupMenuListener(new PopupMenuListener() { |
||||
@Override |
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { |
||||
// do nothing
|
||||
} |
||||
|
||||
@Override |
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { |
||||
useTipLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); |
||||
tipIconLabel.setIcon(AlphaFineConstants.BULB_ICON); |
||||
} |
||||
|
||||
@Override |
||||
public void popupMenuCanceled(PopupMenuEvent e) { |
||||
// do nothing
|
||||
} |
||||
}); |
||||
return popupMenu; |
||||
} |
||||
|
||||
private JPanel createSearchPane() { |
||||
JPanel searchPane = new JPanel(new BorderLayout()); |
||||
searchPane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20)); |
||||
searchTextFieldWrapperPane = new JPanel(new BorderLayout()) { |
||||
@Override |
||||
protected void paintBorder(Graphics g) { |
||||
g.setColor(BORDER_COLOR); |
||||
g.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 5, 5); |
||||
} |
||||
}; |
||||
searchTextFieldWrapperPane.setBorder(new UITextFieldBorder(new Insets(2, 3, 2, 3))); |
||||
searchTextFieldWrapperPane.setBackground(Color.WHITE); |
||||
searchTextFieldWrapperPane.add(searchTextField, BorderLayout.CENTER); |
||||
clearLabel = new UILabel(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/clear.svg")); |
||||
clearLabel.setVisible(false); |
||||
clearLabel.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
searchTextField.setText(StringUtils.EMPTY); |
||||
beforeSearchStr = StringUtils.EMPTY; |
||||
clearLabel.setVisible(false); |
||||
} |
||||
}); |
||||
searchTextFieldWrapperPane.add(clearLabel, BorderLayout.EAST); |
||||
searchPane.add(searchTextFieldWrapperPane, BorderLayout.CENTER); |
||||
JButton searchButton = new JButton(SEARCH) { |
||||
@Override |
||||
public void paintComponent(Graphics g) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||
g2d.setColor(UIConstants.FLESH_BLUE); |
||||
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 4, 4); |
||||
super.paintComponent(g2d); |
||||
} |
||||
}; |
||||
searchButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
fireSearch(); |
||||
} |
||||
}); |
||||
searchButton.setPreferredSize(new Dimension(70, 60)); |
||||
searchButton.setForeground(Color.WHITE); |
||||
searchButton.setBorderPainted(false); |
||||
searchButton.setContentAreaFilled(false); |
||||
searchPane.add(searchButton, BorderLayout.EAST); |
||||
searchPane.setBackground(Color.WHITE); |
||||
return searchPane; |
||||
} |
||||
|
||||
private JPanel createShowPane() { |
||||
JPanel showPane = new JPanel(new BorderLayout()); |
||||
resultPane.add(new DefaultProductNewsPane(), CellType.PRODUCT_NEWS.getFlagStr4None()); |
||||
resultPane.add(new NoResultWithLinkPane(GO_FORUM, AlphaFineConstants.NO_RESULT_ICON), CellType.NO_RESULT.getFlagStr4None()); |
||||
resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.ACTION.getFlagStr4None()); |
||||
resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.FILE.getFlagStr4None()); |
||||
resultPane.add(new NoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.PLUGIN.getFlagStr4None()); |
||||
resultPane.add(new HelpDocumentNoResultPane(SEARCH_TERM, AlphaFineConstants.NO_RESULT_ICON), CellType.DOCUMENT.getFlagStr4None()); |
||||
resultPane.add(new NetWorkFailedPane(this::reSearch), AlphaFineConstants.NETWORK_ERROR); |
||||
|
||||
JPanel labelPane = new JPanel(new BorderLayout()); |
||||
labelPane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 20)); |
||||
labelPane.setBackground(Color.WHITE); |
||||
JPanel labelContentPane = new JPanel(new BorderLayout()); |
||||
UILabel tabLabel = new UILabel(PRODUCT_DYNAMICS); |
||||
tabLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); |
||||
tabLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); |
||||
tabLabel.setPreferredSize(new Dimension(100, 30)); |
||||
JPanel westPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); |
||||
westPane.add(tabLabel); |
||||
labelContentPane.add(westPane, BorderLayout.WEST); |
||||
JPanel eastPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0)); |
||||
UILabel readLabel = new UILabel(ONE_CLICK_READ); |
||||
readLabel.setHorizontalAlignment(SwingConstants.RIGHT); |
||||
readLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));; |
||||
readLabel.setPreferredSize(new Dimension(100, 30)); |
||||
readLabel.setForeground(UIConstants.FLESH_BLUE); |
||||
readLabel.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
fireOneClickRead(); |
||||
showPane.repaint(); |
||||
} |
||||
}); |
||||
eastPane.add(readLabel); |
||||
labelContentPane.add(eastPane, BorderLayout.EAST); |
||||
labelContentPane.setBackground(new Color(245, 245, 247)); |
||||
labelPane.add(labelContentPane); |
||||
labelPane.setPreferredSize(new Dimension(AlphaFineConstants.FULL_SIZE.width, 30)); |
||||
|
||||
tabPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 10)); |
||||
tabPane.setBackground(Color.WHITE); |
||||
List<SelectedLabel> selectedLabelList = createSelectedLabelList(); |
||||
selectedType = selectedLabelList.get(0).getCellType(); |
||||
// 第一个tab 非产品动态
|
||||
if (selectedType != CellType.PRODUCT_NEWS) { |
||||
tabLabel.setText(selectedLabelList.get(0).getText()); |
||||
readLabel.setVisible(false); |
||||
} |
||||
for (SelectedLabel selectedLabel : selectedLabelList) { |
||||
selectedLabel.addMouseListener(createMouseListener(selectedLabelList, selectedLabel, tabPane, tabLabel, readLabel)); |
||||
tabPane.add(selectedLabel); |
||||
} |
||||
showPane.add(tabPane, BorderLayout.NORTH); |
||||
showPane.add(labelPane, BorderLayout.CENTER); |
||||
showPane.add(resultPane, BorderLayout.SOUTH); |
||||
return showPane; |
||||
} |
||||
|
||||
private MouseAdapter createMouseListener(List<SelectedLabel> selectedLabelList, SelectedLabel selectedLabel, |
||||
JPanel tabPane, UILabel tabLabel, UILabel readLabel) { |
||||
return new MouseAdapter() { |
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
for (SelectedLabel label : selectedLabelList) { |
||||
label.setSelected(false); |
||||
label.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); |
||||
} |
||||
selectedLabel.setSelected(true); |
||||
// 处理产品动态 tab与下方文字展示不一致
|
||||
if (ComparatorUtils.equals(selectedLabel.getText().trim(), PRODUCT_NEWS)) { |
||||
tabLabel.setText(PRODUCT_DYNAMICS); |
||||
} else { |
||||
tabLabel.setText(selectedLabel.getText()); |
||||
} |
||||
readLabel.setVisible(false); |
||||
tabPane.repaint(); |
||||
switch (selectedLabel.getCellType()) { |
||||
case PRODUCT_NEWS: |
||||
readLabel.setVisible(true); |
||||
switchType(CellType.PRODUCT_NEWS); |
||||
break; |
||||
case ACTION: |
||||
currentSearchWorkerManager = settingSearchWorkerManager; |
||||
switchType(CellType.ACTION); |
||||
break; |
||||
case FILE: |
||||
currentSearchWorkerManager = fileSearchWorkerManager; |
||||
switchType(CellType.FILE); |
||||
break; |
||||
case DOCUMENT: |
||||
currentSearchWorkerManager = documentWorkerManager; |
||||
switchType(CellType.DOCUMENT); |
||||
break; |
||||
case PLUGIN: |
||||
currentSearchWorkerManager = pluginSearchWorkerManager; |
||||
switchType(CellType.PLUGIN); |
||||
break; |
||||
} |
||||
if (currentSearchWorkerManager != null) { |
||||
AlphaFineList alphaFineList = currentSearchWorkerManager.getSearchResultList(); |
||||
if (alphaFineList != null) { |
||||
alphaFineList.setSelectedIndex(0); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private Color defaultColor; |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
defaultColor = selectedLabel.getForeground(); |
||||
selectedLabel.setForeground(AlphaFineConstants.SUSPENDED_COLOR); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
selectedLabel.setForeground(defaultColor); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
private List<SelectedLabel> createSelectedLabelList() { |
||||
List<SelectedLabel> selectedLabelList = new ArrayList<>(); |
||||
AlphaFineConfigManager alphaFineConfigManager = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager(); |
||||
if (alphaFineConfigManager.isProductDynamics()) { |
||||
selectedLabelList.add(new SelectedLabel(PRODUCT_NEWS, CellType.PRODUCT_NEWS, true)); |
||||
} |
||||
if (alphaFineConfigManager.isContainAction()) { |
||||
selectedLabelList.add(new SelectedLabel(SETTING, CellType.ACTION)); |
||||
} |
||||
if (alphaFineConfigManager.isContainFileContent() || alphaFineConfigManager.isContainTemplate()) { |
||||
selectedLabelList.add(new SelectedLabel(TEMPLATES, CellType.FILE)); |
||||
} |
||||
if (alphaFineConfigManager.isContainDocument()) { |
||||
selectedLabelList.add(new SelectedLabel(HELP, CellType.DOCUMENT)); |
||||
} |
||||
if (alphaFineConfigManager.isContainPlugin()) { |
||||
selectedLabelList.add(new SelectedLabel(PLUGIN, CellType.PLUGIN)); |
||||
} |
||||
return selectedLabelList; |
||||
} |
||||
|
||||
private void fireOneClickRead() { |
||||
List<ProductNews> productNewsList = ProductNewsSearchManager.getInstance().getCachedProductNewsList(); |
||||
Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); |
||||
for (ProductNews productNews : productNewsList) { |
||||
readSet.add(productNews.getId()); |
||||
} |
||||
} |
||||
|
||||
private void switchType(CellType cellType) { |
||||
this.selectedType = cellType; |
||||
if (StringUtils.isEmpty(searchTextField.getText())) { |
||||
cardLayout.show(resultPane, cellType.getFlagStr4None()); |
||||
} else { |
||||
// 当前搜索未结束 不切换loading
|
||||
if (!checkSearchLoading()) { |
||||
return; |
||||
} |
||||
// 所有都搜索都结束 移除loading
|
||||
if (isAllSearchOver()) { |
||||
resultPane.remove(searchLoadingPane); |
||||
} |
||||
|
||||
// 网络异常
|
||||
if (checkNetworkError()) { |
||||
return; |
||||
} |
||||
|
||||
cardLayout.show(resultPane, cellType.getFlagStr4Result()); |
||||
checkSearchResult(); |
||||
} |
||||
|
||||
} |
||||
|
||||
private boolean checkNetworkError() { |
||||
boolean networkError; |
||||
if (selectedType == CellType.PRODUCT_NEWS) { |
||||
networkError = productNewsSearchWorkerManager.isNetWorkError(); |
||||
} else { |
||||
networkError = currentSearchWorkerManager.isNetWorkError(); |
||||
} |
||||
cardLayout.show(resultPane, AlphaFineConstants.NETWORK_ERROR); |
||||
return networkError; |
||||
} |
||||
|
||||
private boolean checkSearchLoading() { |
||||
boolean searchOver; |
||||
if (selectedType == CellType.PRODUCT_NEWS) { |
||||
searchOver = productNewsSearchWorkerManager.isSearchOver(); |
||||
} else { |
||||
searchOver = currentSearchWorkerManager.isSearchOver(); |
||||
} |
||||
cardLayout.show(resultPane, AlphaFineConstants.LOADING); |
||||
return searchOver; |
||||
} |
||||
|
||||
private boolean isAllSearchOver() { |
||||
return productNewsSearchWorkerManager.isSearchOver() |
||||
&& pluginSearchWorkerManager.isSearchOver() |
||||
&& fileSearchWorkerManager.isSearchOver() |
||||
&& settingSearchWorkerManager.isSearchOver() |
||||
&& documentWorkerManager.isSearchOver(); |
||||
} |
||||
|
||||
private void checkSearchResult() { |
||||
if (currentSearchWorkerManager == null) { |
||||
return; |
||||
} |
||||
searchResultList = currentSearchWorkerManager.getSearchResultList(); |
||||
if (searchResultList != null) { |
||||
searchResultList.requestFocus(); |
||||
} |
||||
boolean hasSearchResult = true; |
||||
if (selectedType == CellType.PRODUCT_NEWS) { |
||||
hasSearchResult = productNewsSearchWorkerManager.hasSearchResult(); |
||||
} else { |
||||
hasSearchResult = currentSearchWorkerManager.hasSearchResult(); |
||||
} |
||||
|
||||
if (!hasSearchResult) { |
||||
cardLayout.show(resultPane, CellType.NO_RESULT.getFlagStr4None()); |
||||
} |
||||
|
||||
} |
||||
|
||||
private void initSearchTextField() { |
||||
searchTextField = new AlphaFineTextField(PLACE_HOLDER); |
||||
initTextFieldListener(); |
||||
searchTextField.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); |
||||
searchTextField.setBackground(Color.WHITE); |
||||
searchTextField.setPreferredSize(new Dimension(300, 60)); |
||||
searchTextField.setBorder(null); |
||||
} |
||||
|
||||
|
||||
private void initTextFieldListener() { |
||||
searchTextField.addKeyListener(new KeyAdapter() { |
||||
@Override |
||||
public void keyPressed(KeyEvent e) { |
||||
// 搜索提示框
|
||||
if (StringUtils.isNotEmpty(searchTextField.getText())) { |
||||
clearLabel.setVisible(true); |
||||
SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); |
||||
} else { |
||||
beforeSearchStr = StringUtils.EMPTY; |
||||
} |
||||
AlphaFineToolTipList alphaFineToolTipList = SearchTooltipPopup.getInstance().getAlphaFineToolTipList(); |
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) { |
||||
if (!alphaFineToolTipList.isSelectionEmpty()) { |
||||
fireSearch(alphaFineToolTipList.getSelectedValue()); |
||||
return; |
||||
} |
||||
fireSearch(); |
||||
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) { |
||||
if (alphaFineToolTipList.getSelectedIndex() == alphaFineToolTipList.getModel().getSize() - 1) { |
||||
alphaFineToolTipList.setSelectedIndex(0); |
||||
} |
||||
alphaFineToolTipList.setSelectedIndex(alphaFineToolTipList.getSelectedIndex() + 1); |
||||
} else if (e.getKeyCode() == KeyEvent.VK_UP) { |
||||
alphaFineToolTipList.setSelectedIndex(alphaFineToolTipList.getSelectedIndex() - 1); |
||||
} |
||||
|
||||
} |
||||
}); |
||||
|
||||
searchTextField.addFocusListener(new FocusListener() { |
||||
@Override |
||||
public void focusGained(FocusEvent e) { |
||||
if (StringUtils.isNotEmpty(searchTextField.getText())) { |
||||
SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void focusLost(FocusEvent e) { |
||||
if (e.getOppositeComponent() != SearchTooltipPopup.getInstance().getAlphaFineToolTipList()) { |
||||
SearchTooltipPopup.getInstance().hide(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
startSearchTextFieldTimer(); |
||||
|
||||
} |
||||
|
||||
private void startSearchTextFieldTimer() { |
||||
Timer timer = new Timer(TIMER_DELAY, e -> { |
||||
// 坑 isShowing返回false 即使textField有内容 getText返回的也是空
|
||||
if (searchTextField.isShowing() && StringUtils.isEmpty(searchTextField.getText())) { |
||||
SearchTooltipPopup.getInstance().hide(); |
||||
clearLabel.setVisible(false); |
||||
switchType(selectedType); |
||||
beforeSearchStr = StringUtils.EMPTY; |
||||
} else if (searchTextField.hasFocus()) { |
||||
clearLabel.setVisible(true); |
||||
SearchTooltipPopup.getInstance().show(searchTextFieldWrapperPane); |
||||
} |
||||
tabPane.repaint(); |
||||
|
||||
}); |
||||
timer.start(); |
||||
} |
||||
|
||||
public void fireSearch(String text) { |
||||
searchTextField.setText(text); |
||||
fireSearch(); |
||||
} |
||||
|
||||
private void fireSearch() { |
||||
// 焦点转移
|
||||
AlphaFineFrame.this.requestFocus(); |
||||
if (ComparatorUtils.equals(beforeSearchStr, searchTextField.getText())) { |
||||
return; |
||||
} |
||||
if (StringUtils.isEmpty(searchTextField.getText())) { |
||||
beforeSearchStr = StringUtils.EMPTY; |
||||
return; |
||||
} |
||||
String lowerCaseSearchText = preProcessSearchText(searchTextField.getText().toLowerCase()); |
||||
if (DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isNeedSegmentationCheckbox()) { |
||||
dealSegmentationSearch(lowerCaseSearchText); |
||||
} else { |
||||
dealNormalSearch(); |
||||
} |
||||
DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getHistorySearch().push(searchTextField.getText()); |
||||
doSearch(lowerCaseSearchText); |
||||
beforeSearchStr = searchTextField.getText(); |
||||
SearchTooltipPopup.getInstance().hide(); |
||||
} |
||||
|
||||
/** |
||||
* 普通搜索 |
||||
*/ |
||||
private void dealNormalSearch() { |
||||
String searchText = preProcessSearchText(searchTextField.getText()); |
||||
if (StringUtils.isEmpty(getRealSearchText(searchText))) { |
||||
segmentationResult = null; |
||||
} else { |
||||
segmentationResult = new String[]{getRealSearchText(searchText)}; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 分词搜索 |
||||
*/ |
||||
private void dealSegmentationSearch(String lowerCaseSearchText) { |
||||
//是高级搜索
|
||||
if (searchTextField.getText().toLowerCase().startsWith(ADVANCED_SEARCH_MARK)) { |
||||
segmentationResult = SegmentationManager.getInstance().startSegmentation(getStoreText(lowerCaseSearchText)); |
||||
} |
||||
//是普通搜索
|
||||
else { |
||||
segmentationResult = SegmentationManager.getInstance().startSegmentation(lowerCaseSearchText); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 文本预处理 限制长度 |
||||
* |
||||
* @param text |
||||
* @return |
||||
*/ |
||||
private String preProcessSearchText(String text) { |
||||
if (text.length() > AlphaFineConstants.LEN_LIMIT) { |
||||
return text.substring(0, AlphaFineConstants.LEN_LIMIT); |
||||
} else { |
||||
return text; |
||||
} |
||||
} |
||||
|
||||
private void dealWithSearchResult() { |
||||
final AlphaCellModel model = searchResultList.getSelectedValue(); |
||||
if (model != null) { |
||||
model.doAction(); |
||||
} |
||||
} |
||||
|
||||
public void showResult(String flag) { |
||||
cardLayout.show(resultPane, flag); |
||||
} |
||||
|
||||
public void addResult(JPanel panel, String flag) { |
||||
resultPane.add(panel, flag); |
||||
} |
||||
|
||||
public void removeSearchResultPane(JPanel panel) { |
||||
resultPane.remove(panel); |
||||
} |
||||
|
||||
|
||||
|
||||
private void doSearch(String text) { |
||||
initSearchLoadingPane(); |
||||
SearchTextBean searchTextBean = generateSearchTextBean(text); |
||||
this.productNewsSearchWorkerManager.doSearch(searchTextBean); |
||||
this.settingSearchWorkerManager.doSearch(searchTextBean); |
||||
this.fileSearchWorkerManager.doSearch(searchTextBean); |
||||
this.documentWorkerManager.doSearch(searchTextBean); |
||||
this.pluginSearchWorkerManager.doSearch(searchTextBean); |
||||
} |
||||
|
||||
private SearchTextBean generateSearchTextBean(String searchText) { |
||||
if (searchText.startsWith(ACTION_MARK_SHORT) || searchText.startsWith(ACTION_MARK) |
||||
|| searchText.startsWith(DOCUMENT_MARK_SHORT) || searchText.startsWith(DOCUMENT_MARK)) { |
||||
return new SearchTextBean(StringUtils.EMPTY, new String[]{getStoreText(searchText)}); |
||||
} else if (searchText.startsWith(FILE_MARK_SHORT) || searchText.startsWith(FILE_MARK) |
||||
|| searchText.startsWith(CPT_MARK) || searchText.startsWith(FRM_MARK) |
||||
|| searchText.startsWith(PLUGIN_MARK_SHORT) || searchText.startsWith(PLUGIN_MARK)) { |
||||
return new SearchTextBean(getStoreText(searchText), new String[]{getStoreText(searchText)}); |
||||
} else if (searchText.startsWith(DS_MARK)) { |
||||
return new SearchTextBean(getStoreText(searchText), new String[]{DS_NAME + getStoreText(searchText)}); |
||||
} else { |
||||
return new SearchTextBean(searchText, segmentationResult == null ? new String[]{} : segmentationResult); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 仅搜索依赖网络的搜索项 |
||||
* |
||||
*/ |
||||
private void reSearch() { |
||||
String text = preProcessSearchText(this.searchTextField.getText().toLowerCase()); |
||||
if (StringUtils.isEmpty(text)) { |
||||
return; |
||||
} |
||||
searchLoadingPane = new SearchLoadingPane(); |
||||
SearchTextBean searchTextBean = new SearchTextBean(text, segmentationResult); |
||||
this.productNewsSearchWorkerManager.doSearch(searchTextBean); |
||||
this.documentWorkerManager.doSearch(searchTextBean); |
||||
this.pluginSearchWorkerManager.doSearch(searchTextBean); |
||||
} |
||||
|
||||
private void initSearchLoadingPane() { |
||||
if (searchLoadingPane == null) { |
||||
searchLoadingPane = new SearchLoadingPane(); |
||||
} |
||||
resultPane.add(searchLoadingPane, AlphaFineConstants.LOADING); |
||||
cardLayout.show(resultPane, AlphaFineConstants.LOADING); |
||||
} |
||||
|
||||
public String getSearchText() { |
||||
return searchTextField.getText(); |
||||
} |
||||
|
||||
|
||||
public CellType getSelectedType() { |
||||
return selectedType; |
||||
} |
||||
|
||||
public void setStoreText(String storeText) { |
||||
this.storeText = storeText; |
||||
} |
||||
|
||||
/** |
||||
* 截取字符串中关键词 |
||||
* |
||||
* @param searchText |
||||
* @return |
||||
*/ |
||||
private String getStoreText(String searchText) { |
||||
//这里也需要先做一个去除不需要空格的处理
|
||||
setStoreText((searchText.substring(searchText.indexOf(StringUtils.BLANK) + 1)).replaceAll(StringUtils.BLANK, StringUtils.EMPTY)); |
||||
return storeText; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 去除特殊字符,空格等 |
||||
*/ |
||||
private String getRealSearchText(String searchText) { |
||||
searchText = searchText.toLowerCase(); |
||||
Pattern p = Pattern.compile(AlphaFineConstants.SPECIAL_CHARACTER_REGEX); |
||||
Matcher m = p.matcher(searchText); |
||||
searchText = m.replaceAll(StringUtils.EMPTY).trim().replaceAll(StringUtils.BLANK, StringUtils.EMPTY); |
||||
if (searchText.length() == 0) { |
||||
return null; |
||||
} |
||||
return searchText; |
||||
} |
||||
|
||||
private UIButton createButton(Icon icon) { |
||||
UIButton button = new UIButton() { |
||||
@Override |
||||
public void paintComponent(Graphics g) { |
||||
g.setColor(Color.WHITE); |
||||
g.fillRect(0, 0, getSize().width, getSize().height); |
||||
super.paintComponent(g); |
||||
} |
||||
}; |
||||
button.setPreferredSize(new Dimension(20, 20)); |
||||
button.setIcon(icon); |
||||
button.set4ToolbarButton(); |
||||
button.setBorderPainted(false); |
||||
button.setRolloverEnabled(false); |
||||
return button; |
||||
} |
||||
|
||||
/** |
||||
* 设置面板位置 |
||||
* |
||||
* @param win |
||||
*/ |
||||
private void centerWindow(Window win) { |
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); |
||||
|
||||
Dimension winSize = win.getSize(); |
||||
|
||||
if (winSize.height > screenSize.height) { |
||||
winSize.height = screenSize.height; |
||||
} |
||||
if (winSize.width > screenSize.width) { |
||||
winSize.width = screenSize.width; |
||||
} |
||||
//这里设置位置:水平居中,竖直偏上
|
||||
win.setLocation((screenSize.width - winSize.width) / 2, (screenSize.height - winSize.height) / AlphaFineConstants.SHOW_SIZE); |
||||
} |
||||
|
||||
@Override |
||||
public void setVisible(boolean b) { |
||||
super.setVisible(b); |
||||
QuestionWindow.getInstance().setVisible(!b); |
||||
if (!b) { |
||||
AlphaFineHelper.resetAlphaFineDialog(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void dispose() { |
||||
super.dispose(); |
||||
AlphaFineHelper.resetAlphaFineDialog(); |
||||
QuestionWindow.getInstance().setVisible(true); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,84 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import com.fr.design.mainframe.alphafine.cell.model.DocumentModel; |
||||
import com.fr.design.mainframe.alphafine.preview.ResultShowPane; |
||||
import java.awt.event.KeyAdapter; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import javax.swing.JList; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/18 |
||||
*/ |
||||
public class AlphaFineList extends JList<AlphaCellModel> { |
||||
|
||||
private ResultShowPane resultShowPane; |
||||
|
||||
public AlphaFineList() { |
||||
addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
AlphaCellModel selectedValue = getSelectedValue(); |
||||
if (e.getClickCount() == AlphaFineConstants.DEFAULT_CLICK_COUNT && selectedValue.hasAction()) { |
||||
// 点击搜索结果 主页面移动到后面
|
||||
if (!(selectedValue instanceof DocumentModel)) { |
||||
// 帮助文档不跳转
|
||||
AlphaFineHelper.getAlphaFineDialog().toBack(); |
||||
} |
||||
dealWithSearchResult(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
addListSelectionListener(e -> { |
||||
if (!e.getValueIsAdjusting() && getSelectedValue() != null) { |
||||
if (resultShowPane != null) { |
||||
resultShowPane.showResult(getSelectedValue()); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
|
||||
addKeyListener(new KeyAdapter() { |
||||
@Override |
||||
public void keyPressed(KeyEvent e) { |
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) { |
||||
AlphaCellModel selectedValue = getSelectedValue(); |
||||
if (selectedValue.hasAction() && !(selectedValue instanceof DocumentModel)) { |
||||
AlphaFineHelper.getAlphaFineDialog().toBack(); |
||||
} |
||||
dealWithSearchResult(); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void setResultShowPane(ResultShowPane resultShowPane) { |
||||
this.resultShowPane = resultShowPane; |
||||
} |
||||
|
||||
@Override |
||||
public void setSelectedIndex(int index) { |
||||
super.setSelectedIndex(index); |
||||
AlphaCellModel alphaCellModel = getSelectedValue(); |
||||
if (resultShowPane != null && alphaCellModel != null) { |
||||
resultShowPane.showResult(getSelectedValue()); |
||||
} |
||||
ensureIndexIsVisible(getSelectedIndex()); |
||||
} |
||||
|
||||
private void dealWithSearchResult() { |
||||
final AlphaCellModel model = this.getSelectedValue(); |
||||
if (model != null) { |
||||
model.doAction(); |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,68 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineUtil; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JList; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.ListCellRenderer; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public class AlphaFineToolTipContentCellRender implements ListCellRenderer<String> { |
||||
|
||||
private static final Color SELECTED_COLOR = new Color(65, 155, 249, 26); |
||||
|
||||
private static final Icon HOT_SEARCH_ICON = IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/hot_search.svg"); |
||||
|
||||
private static final Icon SEARCH_ICON = IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/search.svg"); |
||||
|
||||
private static final Icon HISTORY_SEARCH_ICON = IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/history_search.svg"); |
||||
|
||||
|
||||
@Override |
||||
public Component getListCellRendererComponent(JList<? extends String> list, String value, int index, |
||||
boolean isSelected, boolean cellHasFocus) { |
||||
|
||||
if (StringUtils.isEmpty(value)) { |
||||
return new LineCellRender().getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); |
||||
} |
||||
|
||||
JPanel panel = new JPanel(new BorderLayout()); |
||||
panel.setBackground(null); |
||||
|
||||
UILabel iconLabel = new UILabel(); |
||||
iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 5, 0)); |
||||
iconLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); |
||||
iconLabel.setText(value); |
||||
if (ComparatorUtils.equals(value, AlphaFineConstants.HOT_SEARCH)) { |
||||
iconLabel.setIcon(HOT_SEARCH_ICON); |
||||
} else if (AlphaFineConstants.HOT_SEARCH_SET.contains(value)) { |
||||
iconLabel.setIcon(SEARCH_ICON); |
||||
} else { |
||||
iconLabel.setIcon(HISTORY_SEARCH_ICON); |
||||
} |
||||
|
||||
if (isSelected && !ComparatorUtils.equals(value, AlphaFineConstants.HOT_SEARCH)) { |
||||
iconLabel.setText(AlphaFineUtil.highLightModelName(value, new String[]{value})); |
||||
panel.setBackground(SELECTED_COLOR); |
||||
} |
||||
panel.add(iconLabel, BorderLayout.WEST); |
||||
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); |
||||
panel.setPreferredSize(new Dimension(640, 32)); |
||||
|
||||
return panel; |
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.general.ComparatorUtils; |
||||
import java.awt.event.KeyAdapter; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import javax.swing.JList; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public class AlphaFineToolTipList extends JList<String> { |
||||
|
||||
public AlphaFineToolTipList() { |
||||
addKeyListener(new KeyAdapter() { |
||||
@Override |
||||
public void keyPressed(KeyEvent e) { |
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) { |
||||
AlphaFineHelper.getAlphaFineDialog().fireSearch(getSelectedValue()); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
if (e.getClickCount() == 2) { |
||||
if (ComparatorUtils.equals(getSelectedValue(), AlphaFineConstants.HOT_SEARCH)) { |
||||
return; |
||||
} |
||||
AlphaFineHelper.getAlphaFineDialog().fireSearch(getSelectedValue()); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,62 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.util.Stack; |
||||
import javax.swing.DefaultListModel; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public class AlphaSearchTooltipPane extends JPanel { |
||||
|
||||
private AlphaFineToolTipList alphaFineToolTipList; |
||||
|
||||
public AlphaSearchTooltipPane() { |
||||
alphaFineToolTipList = new AlphaFineToolTipList(); |
||||
alphaFineToolTipList.setCellRenderer(new AlphaFineToolTipContentCellRender()); |
||||
alphaFineToolTipList.setModel(getDefaultListModel()); |
||||
UIScrollPane scrollPane = new UIScrollPane(alphaFineToolTipList); |
||||
scrollPane.setBorder(null); |
||||
scrollPane.setBackground(Color.WHITE); |
||||
this.add(scrollPane); |
||||
this.setPreferredSize(new Dimension(640, 250)); |
||||
this.setBackground(Color.WHITE); |
||||
} |
||||
|
||||
public AlphaFineToolTipList getAlphaFineToolTipList() { |
||||
return alphaFineToolTipList; |
||||
} |
||||
|
||||
private DefaultListModel<String> getDefaultListModel() { |
||||
DefaultListModel<String> defaultListModel = new DefaultListModel<>(); |
||||
defaultListModel.addElement(AlphaFineConstants.HOT_SEARCH); |
||||
for (String content : AlphaFineConstants.HOT_SEARCH_SET) { |
||||
defaultListModel.addElement(content); |
||||
} |
||||
return defaultListModel; |
||||
} |
||||
|
||||
public void refreshHistory() { |
||||
Stack<String> stack = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getHistorySearch(); |
||||
if (stack.isEmpty()) { |
||||
return; |
||||
} |
||||
DefaultListModel<String> defaultListModel = new DefaultListModel<>(); |
||||
for (int i = stack.size() - 1; i >= 0; i--) { |
||||
defaultListModel.addElement(stack.get(i)); |
||||
} |
||||
// defaultListModel.addElement(StringUtils.EMPTY);
|
||||
defaultListModel.addElement(AlphaFineConstants.HOT_SEARCH); |
||||
for (String content : AlphaFineConstants.HOT_SEARCH_SET) { |
||||
defaultListModel.addElement(content); |
||||
} |
||||
alphaFineToolTipList.setModel(defaultListModel); |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JList; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.ListCellRenderer; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public class LineCellRender implements ListCellRenderer<String> { |
||||
|
||||
@Override |
||||
public Component getListCellRendererComponent(JList<? extends String> list, String value, int index, |
||||
boolean isSelected, boolean cellHasFocus) { |
||||
JPanel panel = new JPanel(new BorderLayout()); |
||||
UILabel splitLabel = new UILabel(); |
||||
panel.setBackground(null); |
||||
splitLabel.setBackground(UIConstants.BARNOMAL); |
||||
splitLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 5,0)); |
||||
panel.setPreferredSize(new Dimension(640, 1)); |
||||
panel.add(splitLabel); |
||||
return panel; |
||||
} |
||||
} |
@ -0,0 +1,100 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineUtil; |
||||
import com.fr.design.mainframe.alphafine.model.ProductNews; |
||||
import com.fr.design.utils.DesignUtils; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.text.SimpleDateFormat; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JList; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.ListCellRenderer; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/19 |
||||
*/ |
||||
public class ProductNewsContentCellRender implements ListCellRenderer<Object> { |
||||
|
||||
private static final String FINE_REPORT = "FineReport"; |
||||
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd"); |
||||
|
||||
/** |
||||
* 透明灰色背景 Y方向偏移 |
||||
*/ |
||||
private static final int GRAY_BACKGROUND_Y_GAP = 39; |
||||
|
||||
/** |
||||
* 透明灰色背景 高度 |
||||
*/ |
||||
private static final int GRAY_BACKGROUND_HEIGHT = 23; |
||||
|
||||
/** |
||||
* 单行产品动态的高度与宽度尺寸 |
||||
*/ |
||||
private static final Dimension DEFAULT_DIMENSION = new Dimension(500, 100); |
||||
|
||||
private String[] segmentationResult; |
||||
|
||||
private ProductNewsList productNewsList; |
||||
|
||||
public ProductNewsContentCellRender(String[] segmentationResult, ProductNewsList productNewsList) { |
||||
this.segmentationResult = segmentationResult; |
||||
this.productNewsList = productNewsList; |
||||
} |
||||
|
||||
public ProductNewsContentCellRender(ProductNewsList productNewsList) { |
||||
this(null, productNewsList); |
||||
} |
||||
|
||||
@Override |
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, |
||||
boolean cellHasFocus) { |
||||
ProductNews productNews = (ProductNews) value; |
||||
JPanel panel = new JPanel(new BorderLayout()); |
||||
panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); |
||||
panel.setBackground(Color.WHITE); |
||||
|
||||
panel.add(new ProductNewsImagePanel(productNews), BorderLayout.WEST); |
||||
JPanel textPane = new JPanel(new BorderLayout()); |
||||
textPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 0)); |
||||
UILabel titleLabel = new UILabel(AlphaFineUtil.highLightModelName(productNews.getTitle(), segmentationResult)); |
||||
titleLabel.setFont(DesignUtils.getDefaultGUIFont().applySize(20)); |
||||
if (productNewsList.getHoverIndex() == index) { |
||||
titleLabel.setForeground(UIConstants.FLESH_BLUE); |
||||
} |
||||
|
||||
textPane.add(titleLabel, BorderLayout.NORTH); |
||||
JPanel infoPane = new JPanel(new BorderLayout()); |
||||
UILabel productLabel = new UILabel(FINE_REPORT) { |
||||
@Override |
||||
protected void paintComponent(Graphics g) { |
||||
g.setColor(AlphaFineConstants.BACKGROUND_COLOR); |
||||
g.fillRect(0, getHeight() - GRAY_BACKGROUND_Y_GAP, getWidth(), GRAY_BACKGROUND_HEIGHT); |
||||
super.paintComponent(g); |
||||
} |
||||
}; |
||||
productLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); |
||||
infoPane.add(productLabel, BorderLayout.WEST); |
||||
|
||||
UILabel dateLabel = new UILabel(DATE_FORMAT.format(productNews.getPushDate())); |
||||
dateLabel.setForeground(AlphaFineConstants.FOREGROUND_COLOR_6); |
||||
dateLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); |
||||
infoPane.setBackground(Color.WHITE); |
||||
infoPane.add(dateLabel, BorderLayout.CENTER); |
||||
textPane.setBackground(Color.WHITE); |
||||
textPane.add(infoPane, BorderLayout.CENTER); |
||||
panel.add(textPane, BorderLayout.CENTER); |
||||
panel.setPreferredSize(DEFAULT_DIMENSION); |
||||
return panel; |
||||
} |
||||
} |
@ -0,0 +1,79 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.base.GraphHelper; |
||||
import com.fr.base.svg.SVGLoader; |
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.mainframe.alphafine.model.ProductNews; |
||||
import com.fr.design.utils.SvgPaintUtils; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.Image; |
||||
|
||||
import java.awt.RenderingHints; |
||||
import java.util.Set; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/15 |
||||
*/ |
||||
public class ProductNewsImagePanel extends JPanel { |
||||
|
||||
private static final Image NEW_TIP_IMAGE = SVGLoader.load("/com/fr/design/mainframe/alphafine/images/new_tip.svg"); |
||||
|
||||
private static final int BACKGROUND_HEIGHT = 20; |
||||
|
||||
private static final Color BACKGROUND_COLOR = new Color(116, 181, 249); |
||||
|
||||
private static final Color COVER_COLOR = new Color(116, 181, 249, 26); |
||||
|
||||
private ProductNews productNews; |
||||
|
||||
private int width = 200; |
||||
private int height = 150; |
||||
|
||||
public ProductNewsImagePanel(ProductNews productNews) { |
||||
this.productNews = productNews; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
Graphics2D g2 = (Graphics2D) g; |
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); |
||||
Color defaultColor = g2.getColor(); |
||||
|
||||
Image image = productNews.getImage(); |
||||
if (image != null) { |
||||
g2.drawImage(productNews.getImage(), 0, 0, getWidth(), getHeight(), this); |
||||
} else { |
||||
g2.setColor(COVER_COLOR); |
||||
g2.fillRect(0, 0, getWidth(), getHeight()); |
||||
} |
||||
Set<Long> readSet = DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet(); |
||||
if (!readSet.contains(productNews.getId())) { |
||||
SvgPaintUtils.beforePaint(g2); |
||||
g2.drawImage(NEW_TIP_IMAGE, 0, 0, this); |
||||
SvgPaintUtils.afterPaint(g2); |
||||
} |
||||
|
||||
g2.setColor(BACKGROUND_COLOR); |
||||
g2.fillRect(0, getHeight() - BACKGROUND_HEIGHT, getWidth(), BACKGROUND_HEIGHT); |
||||
g2.setColor(Color.WHITE); |
||||
int x = (getWidth() - GraphHelper.getWidth(productNews.getTag().getDesc(), g2.getFont())) / 2; |
||||
g2.drawString(productNews.getTag().getDesc(), x, getHeight() - 5); |
||||
g2.setColor(defaultColor); |
||||
} |
||||
|
||||
@Override |
||||
public Dimension getPreferredSize() { |
||||
return new Dimension(width, height); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,78 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.DesignerEnvManager; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.design.mainframe.alphafine.model.ProductNews; |
||||
import com.fr.log.FineLoggerFactory; |
||||
|
||||
import java.awt.Cursor; |
||||
import java.awt.Desktop; |
||||
import java.awt.Point; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseMotionAdapter; |
||||
import java.net.URI; |
||||
import javax.swing.DefaultListModel; |
||||
import javax.swing.JList; |
||||
import javax.swing.ListModel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/21 |
||||
*/ |
||||
public class ProductNewsList extends JList<ProductNews> { |
||||
|
||||
private int hoverIndex = -1; |
||||
|
||||
public ProductNewsList(ListModel<ProductNews> dataModel) { |
||||
super(dataModel); |
||||
addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
if (e.getClickCount() == AlphaFineConstants.DEFAULT_CLICK_COUNT) { |
||||
dealWithClick(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
hoverIndex = -1; |
||||
ProductNewsList.this.repaint(); |
||||
} |
||||
}); |
||||
|
||||
addMouseMotionListener(new MouseMotionAdapter() { |
||||
@Override |
||||
public void mouseMoved(MouseEvent e) { |
||||
Point p = new Point(e.getX(), e.getY()); |
||||
int index = ProductNewsList.this.locationToIndex(p); |
||||
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
||||
if (index != hoverIndex) { |
||||
hoverIndex = index; |
||||
ProductNewsList.this.repaint(); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public ProductNewsList() { |
||||
this(new DefaultListModel<>()); |
||||
} |
||||
|
||||
private void dealWithClick() { |
||||
ProductNews productNews = getSelectedValue(); |
||||
try { |
||||
Desktop.getDesktop().browse(new URI(productNews.getUrl())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().getReadSet().add(productNews.getId()); |
||||
AlphaFineHelper.getAlphaFineDialog().repaint(); |
||||
} |
||||
|
||||
public int getHoverIndex() { |
||||
return hoverIndex; |
||||
} |
||||
} |
@ -0,0 +1,36 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
|
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/21 |
||||
*/ |
||||
public class ProductNewsSearchResultPane extends JPanel { |
||||
|
||||
private ProductNewsList productNewsList; |
||||
|
||||
public ProductNewsSearchResultPane(String[] segmentationResult) { |
||||
|
||||
productNewsList = new ProductNewsList(); |
||||
UIScrollPane scrollPane = new UIScrollPane(productNewsList); |
||||
scrollPane.setBackground(Color.WHITE); |
||||
scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 20)); |
||||
productNewsList.setCellRenderer(new ProductNewsContentCellRender(segmentationResult, productNewsList)); |
||||
this.setLayout(new BorderLayout()); |
||||
this.setBackground(Color.WHITE); |
||||
this.add(scrollPane); |
||||
this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); |
||||
} |
||||
|
||||
public ProductNewsList getProductNewsList() { |
||||
return productNewsList; |
||||
} |
||||
} |
@ -0,0 +1,126 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import com.fr.design.mainframe.alphafine.model.SearchResult; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.DefaultListModel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/18 |
||||
*/ |
||||
public class SearchListModel extends DefaultListModel<AlphaCellModel> { |
||||
|
||||
private static final int MAX_SHOW_SIZE = 12; |
||||
private static final long serialVersionUID = 7230585307439551228L; |
||||
|
||||
|
||||
private SearchResult myDelegate; |
||||
|
||||
/** |
||||
* 第一有效的项是否被选中 |
||||
*/ |
||||
private boolean isValidSelected; |
||||
|
||||
private UIScrollPane leftSearchResultPane; |
||||
|
||||
private AlphaFineList searchResultList; |
||||
|
||||
public SearchListModel(SearchResult searchResult, AlphaFineList searchResultList, UIScrollPane leftSearchResultPane) { |
||||
this.myDelegate = searchResult; |
||||
this.searchResultList = searchResultList; |
||||
this.leftSearchResultPane = leftSearchResultPane; |
||||
} |
||||
|
||||
@Override |
||||
public void addElement(AlphaCellModel element) { |
||||
AlphaFineHelper.checkCancel(); |
||||
int index = myDelegate.size(); |
||||
myDelegate.add(element); |
||||
fireContentsChanged(this, index, index); |
||||
fireSelectedStateChanged(element, index); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
protected void fireContentsChanged(Object source, int index0, int index1) { |
||||
if (myDelegate.size() > MAX_SHOW_SIZE) { |
||||
leftSearchResultPane.getVerticalScrollBar().setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0)); |
||||
leftSearchResultPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 2)); |
||||
} else { |
||||
leftSearchResultPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
||||
} |
||||
super.fireContentsChanged(source, index0, index1); |
||||
} |
||||
|
||||
/** |
||||
* 触发选中第一有效的项 |
||||
* |
||||
* @param element |
||||
* @param index |
||||
*/ |
||||
private void fireSelectedStateChanged(AlphaCellModel element, int index) { |
||||
if (element.hasAction() && !isValidSelected()) { |
||||
searchResultList.setSelectedIndex(index); |
||||
setValidSelected(true); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public AlphaCellModel getElementAt(int index) { |
||||
return myDelegate.get(index); |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, AlphaCellModel element) { |
||||
myDelegate.add(index, element); |
||||
fireIntervalAdded(this, index, index); |
||||
} |
||||
|
||||
@Override |
||||
public AlphaCellModel remove(int index) { |
||||
AlphaCellModel object = myDelegate.get(index); |
||||
myDelegate.remove(object); |
||||
fireContentsChanged(this, index, index); |
||||
return object; |
||||
} |
||||
|
||||
@Override |
||||
public int getSize() { |
||||
return this.myDelegate.size(); |
||||
} |
||||
|
||||
@Override |
||||
public void removeAllElements() { |
||||
this.myDelegate.clear(); |
||||
} |
||||
|
||||
/** |
||||
* 重置选中状态 |
||||
*/ |
||||
public void resetSelectedState() { |
||||
setValidSelected(false); |
||||
} |
||||
|
||||
private boolean isValidSelected() { |
||||
return isValidSelected; |
||||
} |
||||
|
||||
private void setValidSelected(boolean selected) { |
||||
isValidSelected = selected; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isEmpty() { |
||||
return myDelegate.isEmpty(); |
||||
} |
||||
|
||||
public void resetState() { |
||||
for (int i = 0; i < getSize(); i++) { |
||||
getElementAt(i).resetState(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,83 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineUtil; |
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JList; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.ListCellRenderer; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/19 |
||||
*/ |
||||
public class SearchResultContentCellRender implements ListCellRenderer<Object> { |
||||
|
||||
private static final int OFFSET = 45; |
||||
private static final String SELECTED_PATH = AlphaFineConstants.IMAGE_URL + "selected"; |
||||
private static final String CELL_PATH = AlphaFineConstants.IMAGE_URL + "alphafine"; |
||||
private static final String SUFFIX = ".png"; |
||||
|
||||
private String[] segmentationResult; |
||||
|
||||
public SearchResultContentCellRender(String[] segmentationResult) { |
||||
this.segmentationResult = segmentationResult; |
||||
} |
||||
|
||||
@Override |
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, |
||||
boolean cellHasFocus) { |
||||
|
||||
|
||||
AlphaCellModel model = (AlphaCellModel) value; |
||||
JPanel panel = new JPanel(new BorderLayout()); |
||||
panel.setBackground(null); |
||||
panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); |
||||
// 图标icon 样式
|
||||
UILabel iconLabel = new UILabel(); |
||||
if (isSelected) { |
||||
iconLabel.setText(StringUtils.BLANK + model.getName()); |
||||
String iconUrl = SELECTED_PATH + model.getType().getTypeValue() + SUFFIX; |
||||
panel.setBackground(AlphaFineConstants.BLUE); |
||||
iconLabel.setForeground(Color.WHITE); |
||||
iconLabel.setIcon(IOUtils.readIcon(iconUrl)); |
||||
} else { |
||||
iconLabel.setText(AlphaFineUtil.highLightModelName(model.getName(), segmentationResult)); |
||||
String iconUrl = CELL_PATH + model.getType().getTypeValue() + SUFFIX; |
||||
iconLabel.setIcon(IOUtils.readIcon(iconUrl)); |
||||
} |
||||
iconLabel.setFont(AlphaFineConstants.MEDIUM_FONT); |
||||
|
||||
|
||||
// 内容详情label 样式
|
||||
UILabel detailLabel = new UILabel(); |
||||
String description = model.getDescription(); |
||||
if (StringUtils.isNotBlank(description)) { |
||||
detailLabel.setText("-" + description); |
||||
detailLabel.setForeground(AlphaFineConstants.LIGHT_GRAY); |
||||
panel.add(detailLabel, BorderLayout.CENTER); |
||||
int width = (int) (iconLabel.getPreferredSize().getWidth() + detailLabel.getPreferredSize().getWidth()); |
||||
if (width > AlphaFineConstants.LEFT_WIDTH - OFFSET) { |
||||
int nameWidth = (int) (AlphaFineConstants.LEFT_WIDTH - detailLabel.getPreferredSize().getWidth() - OFFSET); |
||||
iconLabel.setPreferredSize(new Dimension(nameWidth, AlphaFineConstants.CELL_HEIGHT)); |
||||
} |
||||
} else { |
||||
iconLabel.setPreferredSize(new Dimension(AlphaFineConstants.LEFT_WIDTH - OFFSET, AlphaFineConstants.CELL_HEIGHT)); |
||||
} |
||||
|
||||
panel.add(iconLabel, BorderLayout.WEST); |
||||
panel.setPreferredSize(new Dimension(list.getFixedCellWidth(), AlphaFineConstants.CELL_HEIGHT)); |
||||
return panel; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,51 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.model.SearchResult; |
||||
import com.fr.design.mainframe.alphafine.preview.ResultShowPane; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public class SearchResultPane extends JPanel { |
||||
|
||||
private AlphaFineList searchResultList; |
||||
|
||||
private SearchListModel searchListModel; |
||||
|
||||
private UIScrollPane leftSearchResultPane; |
||||
|
||||
|
||||
public SearchResultPane(String[] segmentationResult, ResultShowPane rightSearchResultPane) { |
||||
searchResultList = new AlphaFineList(); |
||||
searchResultList.setFixedCellHeight(AlphaFineConstants.CELL_HEIGHT); |
||||
leftSearchResultPane = new UIScrollPane(searchResultList); |
||||
leftSearchResultPane.setBorder(null); |
||||
leftSearchResultPane.setBackground(Color.WHITE); |
||||
leftSearchResultPane.setPreferredSize(new Dimension(AlphaFineConstants.LEFT_WIDTH, AlphaFineConstants.CONTENT_HEIGHT)); |
||||
searchListModel = new SearchListModel(new SearchResult(), searchResultList, leftSearchResultPane); |
||||
searchResultList.setModel(searchListModel); |
||||
searchResultList.setCellRenderer(new SearchResultContentCellRender(segmentationResult)); |
||||
searchResultList.setResultShowPane(rightSearchResultPane); |
||||
this.setPreferredSize(AlphaFineConstants.CONTENT_SIZE); |
||||
this.setLayout(new BorderLayout()); |
||||
this.add(leftSearchResultPane, BorderLayout.WEST); |
||||
this.add(rightSearchResultPane, BorderLayout.EAST); |
||||
this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); |
||||
} |
||||
|
||||
public AlphaFineList getSearchResultList() { |
||||
return searchResultList; |
||||
} |
||||
|
||||
public UIScrollPane getLeftSearchResultPane() { |
||||
return leftSearchResultPane; |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import java.awt.Component; |
||||
import java.awt.Point; |
||||
import javax.swing.Popup; |
||||
import javax.swing.PopupFactory; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public class SearchTooltipPopup { |
||||
|
||||
private static final SearchTooltipPopup INSTANCE = new SearchTooltipPopup(); |
||||
|
||||
public static SearchTooltipPopup getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private AlphaSearchTooltipPane alphaSearchTooltipPane; |
||||
|
||||
private SearchTooltipPopup() { |
||||
alphaSearchTooltipPane = new AlphaSearchTooltipPane(); |
||||
} |
||||
|
||||
private boolean showPopup; |
||||
|
||||
private Popup popup; |
||||
|
||||
public void show(Component owner) { |
||||
if (popup == null || !showPopup) { |
||||
PopupFactory pf = PopupFactory.getSharedInstance(); |
||||
Point point = owner.getLocationOnScreen(); |
||||
alphaSearchTooltipPane.refreshHistory(); |
||||
popup = pf.getPopup(owner, alphaSearchTooltipPane, point.x, point.y + owner.getHeight()); |
||||
} |
||||
if (!showPopup) { |
||||
alphaSearchTooltipPane.repaint(); |
||||
popup.show(); |
||||
getAlphaFineToolTipList().clearSelection(); |
||||
showPopup = true; |
||||
} |
||||
} |
||||
|
||||
public AlphaFineToolTipList getAlphaFineToolTipList() { |
||||
return alphaSearchTooltipPane.getAlphaFineToolTipList(); |
||||
} |
||||
|
||||
public void hide() { |
||||
if (popup != null) { |
||||
popup.hide(); |
||||
} |
||||
showPopup = false; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,81 @@
|
||||
package com.fr.design.mainframe.alphafine.component; |
||||
|
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineUtil; |
||||
import com.fr.design.mainframe.alphafine.CellType; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.RenderingHints; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/07 |
||||
*/ |
||||
public class SelectedLabel extends UILabel { |
||||
|
||||
private static final int WIDTH = 4; |
||||
private static final int HEIGHT = 4; |
||||
private static final int GAP = 0; |
||||
private static final int BORDER_RIGHT = 5; |
||||
private static final int BORDER_TOP = 2; |
||||
|
||||
private boolean selected; |
||||
private CellType cellType; |
||||
|
||||
public SelectedLabel(String text, CellType cellType, boolean selected) { |
||||
super(text); |
||||
this.setForeground(AlphaFineConstants.FOREGROUND_COLOR_8); |
||||
this.setBorder(BorderFactory.createEmptyBorder(BORDER_TOP, 0, 0, BORDER_RIGHT)); |
||||
this.selected = selected; |
||||
this.cellType = cellType; |
||||
} |
||||
|
||||
public SelectedLabel(String text, CellType cellType) { |
||||
this(text, cellType, false); |
||||
} |
||||
|
||||
@Override |
||||
public void paintComponent(Graphics g) { |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, |
||||
RenderingHints.VALUE_ANTIALIAS_ON); |
||||
if (selected) { |
||||
g2d.setColor(UIConstants.FLESH_BLUE); |
||||
setForeground(UIConstants.FLESH_BLUE); |
||||
g2d.drawLine(0, this.getHeight() - 1, this.getWidth() - BORDER_RIGHT, this.getHeight() - 1); |
||||
} |
||||
super.paintComponent(g); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void paintBorder(Graphics g) { |
||||
super.paintBorder(g); |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
||||
if (cellType == CellType.PRODUCT_NEWS && AlphaFineUtil.unread()) { |
||||
Color oldColor = g.getColor(); |
||||
g2d.setColor(Color.RED); |
||||
g2d.fillOval(getWidth() - WIDTH, GAP, WIDTH, HEIGHT); |
||||
g2d.setColor(oldColor); |
||||
} |
||||
} |
||||
|
||||
public boolean isSelected() { |
||||
return selected; |
||||
} |
||||
|
||||
public void setSelected(boolean selected) { |
||||
this.selected = selected; |
||||
} |
||||
|
||||
public CellType getCellType() { |
||||
return cellType; |
||||
} |
||||
} |
@ -0,0 +1,14 @@
|
||||
package com.fr.design.mainframe.alphafine.exception; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/27 |
||||
*/ |
||||
public class AlphaFineNetworkException extends RuntimeException { |
||||
|
||||
public AlphaFineNetworkException() { |
||||
super("NetWork Error"); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,200 @@
|
||||
package com.fr.design.mainframe.alphafine.model; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import java.awt.Image; |
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 产品动态 |
||||
* |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/05 |
||||
*/ |
||||
public class ProductNews { |
||||
|
||||
private long id; |
||||
private String title; |
||||
|
||||
private Tag tag; |
||||
private Target target; |
||||
|
||||
private Status status; |
||||
private String url; |
||||
private Image image; |
||||
|
||||
|
||||
private Date pushDate; |
||||
|
||||
/** |
||||
* 创建cid的用户 |
||||
*/ |
||||
private int creator; |
||||
|
||||
public long getId() { |
||||
return id; |
||||
} |
||||
|
||||
public ProductNews setId(long id) { |
||||
this.id = id; |
||||
return this; |
||||
} |
||||
|
||||
public String getTitle() { |
||||
return title; |
||||
} |
||||
|
||||
public ProductNews setTitle(String title) { |
||||
this.title = title; |
||||
return this; |
||||
} |
||||
|
||||
public Tag getTag() { |
||||
return tag; |
||||
} |
||||
|
||||
public ProductNews setTag(Tag tag) { |
||||
this.tag = tag; |
||||
return this; |
||||
} |
||||
|
||||
public Target getTarget() { |
||||
return target; |
||||
} |
||||
|
||||
public ProductNews setTarget(Target target) { |
||||
this.target = target; |
||||
return this; |
||||
} |
||||
|
||||
public Status getStatus() { |
||||
return status; |
||||
} |
||||
|
||||
public ProductNews setStatus(Status status) { |
||||
this.status = status; |
||||
return this; |
||||
} |
||||
|
||||
public String getUrl() { |
||||
return url; |
||||
} |
||||
|
||||
public ProductNews setUrl(String url) { |
||||
this.url = url; |
||||
return this; |
||||
} |
||||
|
||||
public Image getImage() { |
||||
return image; |
||||
} |
||||
|
||||
public ProductNews setImage(Image image) { |
||||
this.image = image; |
||||
return this; |
||||
} |
||||
|
||||
public Date getPushDate() { |
||||
return pushDate; |
||||
} |
||||
|
||||
public ProductNews setPushDate(Date pushDate) { |
||||
this.pushDate = pushDate; |
||||
return this; |
||||
} |
||||
|
||||
public int getCreator() { |
||||
return creator; |
||||
} |
||||
|
||||
public ProductNews setCreator(int creator) { |
||||
this.creator = creator; |
||||
return this; |
||||
} |
||||
|
||||
interface CodeParser { |
||||
int getCode(); |
||||
} |
||||
|
||||
public enum Status implements CodeParser { |
||||
STOP(0), START(1); |
||||
|
||||
private final int code; |
||||
|
||||
Status(int code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
@Override |
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public static Status parseCode(int code) { |
||||
for (Status status : values()) { |
||||
if (code == status.code) { |
||||
return status; |
||||
} |
||||
} |
||||
throw new IllegalArgumentException(); |
||||
} |
||||
} |
||||
|
||||
public enum Tag { |
||||
SOLUTION(1, Toolkit.i18nText("Fine-Design_Report_AlphaFine_Solution")), |
||||
MATERIAL(2, Toolkit.i18nText("Fine-Design_Report_AlphaFine_Material")), |
||||
NEW_PRODUCT(3, Toolkit.i18nText("Fine-Design_Report_AlphaFine_New_Product")); |
||||
|
||||
private final int code; |
||||
|
||||
private final String desc; |
||||
|
||||
Tag(int code, String desc) { |
||||
this.code = code; |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public static Tag parseCode(int code) { |
||||
for (Tag tag :values()) { |
||||
if (tag.code == code) { |
||||
return tag; |
||||
} |
||||
} |
||||
throw new IllegalArgumentException(); |
||||
} |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return desc; |
||||
} |
||||
} |
||||
|
||||
public enum Target { |
||||
ALL_USER(0); |
||||
|
||||
private final int code; |
||||
|
||||
Target(int code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public static Target parseCode(int code) { |
||||
for (Target target : values()) { |
||||
if (target.code == code) { |
||||
return target; |
||||
} |
||||
} |
||||
throw new IllegalArgumentException(); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,121 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.design.mainframe.alphafine.component.ProductNewsContentCellRender; |
||||
import com.fr.design.mainframe.alphafine.component.ProductNewsList; |
||||
import com.fr.design.mainframe.alphafine.exception.AlphaFineNetworkException; |
||||
import com.fr.design.mainframe.alphafine.model.ProductNews; |
||||
import com.fr.design.mainframe.alphafine.search.manager.impl.ProductNewsSearchManager; |
||||
import com.fr.design.utils.DesignUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.util.List; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.DefaultListModel; |
||||
import javax.swing.ImageIcon; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingWorker; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/14 |
||||
*/ |
||||
public class DefaultProductNewsPane extends JPanel { |
||||
|
||||
|
||||
private static final String LOADING = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Loading"); |
||||
private static final ImageIcon LOADING_ICON = new ImageIcon(DefaultProductNewsPane.class.getResource("/com/fr/web/images/loading-local.gif")); |
||||
|
||||
private SwingWorker<List<ProductNews>, Void> worker; |
||||
|
||||
public DefaultProductNewsPane() { |
||||
|
||||
setLayout(new BorderLayout()); |
||||
this.add(createLoadingPane()); |
||||
this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); |
||||
this.worker = createWorker(); |
||||
this.worker.execute(); |
||||
} |
||||
|
||||
|
||||
private JPanel createLoadingPane() { |
||||
JPanel loadingPane = new JPanel(new BorderLayout()); |
||||
UILabel loadingLabel = new UILabel(LOADING); |
||||
loadingLabel.setForeground(AlphaFineConstants.MEDIUM_GRAY); |
||||
loadingLabel.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); |
||||
loadingLabel.setBorder(BorderFactory.createEmptyBorder(0, 280, 0, 0)); |
||||
UILabel loadingIconLabel = new UILabel(LOADING_ICON); |
||||
loadingIconLabel.setBorder(BorderFactory.createEmptyBorder(100, 0, 0, 0)); |
||||
loadingPane.add(loadingIconLabel, BorderLayout.NORTH); |
||||
loadingPane.add(loadingLabel, BorderLayout.CENTER); |
||||
loadingPane.setBackground(Color.WHITE); |
||||
return loadingPane; |
||||
} |
||||
|
||||
private SwingWorker<List<ProductNews>, Void> createWorker() { |
||||
if (this.worker != null && !this.worker.isDone()) { |
||||
this.worker.cancel(true); |
||||
this.worker = null; |
||||
} |
||||
return new SwingWorker<List<ProductNews>, Void>() { |
||||
|
||||
@Override |
||||
protected List<ProductNews> doInBackground() throws Exception { |
||||
if (!AlphaFineHelper.isNetworkOk()) { |
||||
throw new AlphaFineNetworkException(); |
||||
} |
||||
return ProductNewsSearchManager.getInstance().getProductNewsList(); |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
DefaultProductNewsPane.this.removeAll(); |
||||
try { |
||||
DefaultProductNewsPane.this.add(createContentPane(get())); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
if (e.getCause() instanceof AlphaFineNetworkException) { |
||||
DefaultProductNewsPane.this.add(new NetWorkFailedPane(() -> { |
||||
DefaultProductNewsPane.this.removeAll(); |
||||
add(createLoadingPane()); |
||||
refresh(); |
||||
worker = createWorker(); |
||||
worker.execute(); |
||||
})); |
||||
} |
||||
} |
||||
refresh(); |
||||
} |
||||
}; |
||||
|
||||
} |
||||
|
||||
private void refresh() { |
||||
this.validate(); |
||||
this.repaint(); |
||||
if (AlphaFineHelper.getAlphaFineDialog() != null) { |
||||
AlphaFineHelper.getAlphaFineDialog().repaint(); |
||||
} |
||||
} |
||||
|
||||
private UIScrollPane createContentPane(List<ProductNews> productNewsList) { |
||||
DefaultListModel<ProductNews> productNewsDefaultListModel = new DefaultListModel<>(); |
||||
for (ProductNews productNews : productNewsList) { |
||||
productNewsDefaultListModel.addElement(productNews); |
||||
} |
||||
ProductNewsList productNewsJList = new ProductNewsList(productNewsDefaultListModel); |
||||
productNewsJList.setBackground(Color.WHITE); |
||||
productNewsJList.setCellRenderer(new ProductNewsContentCellRender(productNewsJList)); |
||||
UIScrollPane scrollPane = new UIScrollPane(productNewsJList); |
||||
scrollPane.setBackground(Color.WHITE); |
||||
scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 20)); |
||||
return scrollPane; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,167 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||
import com.fr.design.utils.BrowseUtils; |
||||
import com.fr.design.utils.DesignUtils; |
||||
import com.fr.json.JSON; |
||||
import com.fr.json.JSONArray; |
||||
import com.fr.json.JSONFactory; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
|
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Cursor; |
||||
import java.awt.Dimension; |
||||
import java.awt.GridLayout; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JSeparator; |
||||
import javax.swing.SwingConstants; |
||||
import javax.swing.SwingWorker; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/13 |
||||
*/ |
||||
public class HelpDocumentNoResultPane extends JPanel { |
||||
|
||||
private static final String RECOMMEND = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Recommend_For_You"); |
||||
|
||||
private static final Color DOT_COLOR = new Color(200, 201, 205); |
||||
|
||||
private SwingWorker<Boolean, Void> worker; |
||||
|
||||
private String title; |
||||
|
||||
private Icon icon; |
||||
|
||||
private Map<String, String> linkMap; |
||||
|
||||
public HelpDocumentNoResultPane(String title, Icon icon) { |
||||
this.title = title; |
||||
this.icon = icon; |
||||
this.linkMap = generateMap(); |
||||
setLayout(new BorderLayout()); |
||||
worker = createWorker(); |
||||
worker.execute(); |
||||
} |
||||
|
||||
private SwingWorker<Boolean, Void> createWorker() { |
||||
if (this.worker != null && !this.worker.isDone()) { |
||||
this.worker.cancel(true); |
||||
this.worker = null; |
||||
} |
||||
return new SwingWorker<Boolean, Void>() { |
||||
|
||||
@Override |
||||
protected Boolean doInBackground() throws Exception { |
||||
return AlphaFineHelper.isNetworkOk(); |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
HelpDocumentNoResultPane.this.removeAll(); |
||||
try { |
||||
if (get()) { |
||||
add(new NoResultPane(title, icon, 150), BorderLayout.CENTER); |
||||
add(createRecommendPane(linkMap), BorderLayout.EAST); |
||||
} else { |
||||
add(new NetWorkFailedPane(() -> { |
||||
worker = createWorker(); |
||||
worker.execute(); |
||||
})); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
refresh(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
|
||||
private void refresh() { |
||||
this.validate(); |
||||
this.repaint(); |
||||
} |
||||
|
||||
|
||||
private Map<String, String> generateMap() { |
||||
JSONArray jsonArray = JSONFactory.createJSON(JSON.ARRAY, AlphaFineConstants.ALPHA_HELP_RECOMMEND); |
||||
Map<String, String> linkMap = new LinkedHashMap<>(); |
||||
for (int i = 0, len = jsonArray.size(); i < len; i++) { |
||||
JSONObject json = jsonArray.getJSONObject(i); |
||||
linkMap.put(json.getString("name"), json.getString("link")); |
||||
} |
||||
return linkMap; |
||||
} |
||||
|
||||
private JPanel createRecommendPane(Map<String, String> linkMap) { |
||||
JPanel wrapRecommendPane = new JPanel(new BorderLayout()); |
||||
wrapRecommendPane.setPreferredSize(new Dimension(200, 305)); |
||||
JPanel recommendPane = new JPanel(); |
||||
recommendPane.setLayout(new GridLayout(0, 1)); |
||||
recommendPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 130, 0)); |
||||
recommendPane.setBackground(Color.WHITE); |
||||
recommendPane.add(new UILabel(RECOMMEND)); |
||||
for (Map.Entry<String, String> entry : linkMap.entrySet()) { |
||||
recommendPane.add(createListLabel(entry.getKey(), entry.getValue())); |
||||
} |
||||
// 分割线
|
||||
JSeparator sep = new JSeparator(); |
||||
sep.setOrientation(JSeparator.VERTICAL); |
||||
sep.setLayout(new GridLayout(0, 1)); |
||||
sep.setPreferredSize(new Dimension(1, 285)); |
||||
sep.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); |
||||
sep.add(new UILabel()); |
||||
wrapRecommendPane.add(sep, BorderLayout.WEST); |
||||
wrapRecommendPane.add(recommendPane, BorderLayout.CENTER); |
||||
return wrapRecommendPane; |
||||
} |
||||
|
||||
private JPanel createListLabel(String text, String link) { |
||||
UILabel listLabel = new UILabel(String.format("%s", text)); |
||||
listLabel.setForeground(UIConstants.FLESH_BLUE); |
||||
listLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); |
||||
listLabel.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
responseClick(link); |
||||
} |
||||
}); |
||||
listLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
||||
|
||||
JPanel listPane = new JPanel(new BorderLayout()); |
||||
listPane.setBackground(Color.WHITE); |
||||
UILabel dotLabel = new UILabel("·"); |
||||
dotLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); |
||||
dotLabel.setFont(DesignUtils.getDefaultGUIFont().applySize(14)); |
||||
dotLabel.setHorizontalAlignment(SwingConstants.LEADING); |
||||
dotLabel.setForeground(DOT_COLOR); |
||||
listPane.add(dotLabel, BorderLayout.WEST); |
||||
listPane.add(listLabel, BorderLayout.CENTER); |
||||
listPane.setPreferredSize(new Dimension(100, 20)); |
||||
return listPane; |
||||
} |
||||
|
||||
/** |
||||
* 方便记录埋点 |
||||
* |
||||
* @param link |
||||
*/ |
||||
private void responseClick(String link) { |
||||
BrowseUtils.browser(link); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,167 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.CellType; |
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import com.fr.design.mainframe.alphafine.cell.model.FileModel; |
||||
import com.fr.design.mainframe.alphafine.cell.model.PluginModel; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.project.ProjectConstants; |
||||
import com.fr.workspace.WorkContext; |
||||
import com.fr.workspace.server.exporter.LocalExportOperator; |
||||
import com.fr.workspace.server.exporter.TemplateExportOperator; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.IOException; |
||||
import java.net.URL; |
||||
import java.util.concurrent.ExecutionException; |
||||
import javax.imageio.ImageIO; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.ImageIcon; |
||||
import javax.swing.SwingWorker; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/20 |
||||
*/ |
||||
public class LoadingRightSearchResultPane extends ResultShowPane { |
||||
|
||||
private SwingWorker<BufferedImage, Void> showWorker; |
||||
|
||||
public LoadingRightSearchResultPane() { |
||||
|
||||
this.setBackground(Color.WHITE); |
||||
this.setPreferredSize(new Dimension(AlphaFineConstants.RIGHT_WIDTH - 1, AlphaFineConstants.CONTENT_HEIGHT)); |
||||
initLoadingLabel(); |
||||
|
||||
} |
||||
|
||||
private void initLoadingLabel() { |
||||
UILabel label = new UILabel(new ImageIcon(getClass().getResource("/com/fr/design/mainframe/alphafine/images/opening.gif"))); |
||||
label.setBorder(BorderFactory.createEmptyBorder(120, 0, 0, 0)); |
||||
this.add(label, BorderLayout.CENTER); |
||||
} |
||||
|
||||
private void showDefaultPreviewPane() { |
||||
this.removeAll(); |
||||
initLoadingLabel(); |
||||
validate(); |
||||
repaint(); |
||||
revalidate(); |
||||
} |
||||
|
||||
@Override |
||||
public void showResult(AlphaCellModel selectedValue) { |
||||
showDefaultPreviewPane(); |
||||
checkWorker(); |
||||
if (selectedValue.getType() == CellType.FILE) { |
||||
fileShowWorker(selectedValue); |
||||
} |
||||
|
||||
if (selectedValue.getType() == CellType.PLUGIN) { |
||||
pluginShowWorker(selectedValue); |
||||
} |
||||
this.showWorker.execute(); |
||||
} |
||||
|
||||
private void fileShowWorker(AlphaCellModel selectedValue) { |
||||
this.showWorker = new SwingWorker<BufferedImage, Void>() { |
||||
@Override |
||||
protected BufferedImage doInBackground() throws Exception { |
||||
final String fileName = ((FileModel) selectedValue).getFilePath().substring(ProjectConstants.REPORTLETS_NAME.length() + 1); |
||||
if (fileName.endsWith(ProjectConstants.FRM_SUFFIX)) { |
||||
return frmToImage(fileName); |
||||
} else if (fileName.endsWith(ProjectConstants.CPT_SUFFIX)) { |
||||
return cptToImage(fileName); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
if (!isCancelled()) { |
||||
LoadingRightSearchResultPane.this.removeAll(); |
||||
try { |
||||
LoadingRightSearchResultPane.this.add(new FilePreviewPane(get())); |
||||
} catch (InterruptedException | ExecutionException e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
validate(); |
||||
repaint(); |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
|
||||
private void pluginShowWorker(AlphaCellModel selectedValue) { |
||||
this.showWorker = new SwingWorker<BufferedImage, Void>() { |
||||
@Override |
||||
protected BufferedImage doInBackground() { |
||||
BufferedImage bufferedImage = null; |
||||
try { |
||||
bufferedImage = ImageIO.read(new URL(((PluginModel) selectedValue).getImageUrl())); |
||||
} catch (IOException e) { |
||||
try { |
||||
bufferedImage = ImageIO.read(getClass().getResource("/com/fr/design/mainframe/alphafine/images/default_product.png")); |
||||
} catch (IOException e1) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
return bufferedImage; |
||||
} |
||||
|
||||
@Override |
||||
protected void done() { |
||||
try { |
||||
if (!isCancelled()) { |
||||
LoadingRightSearchResultPane.this.removeAll(); |
||||
LoadingRightSearchResultPane.this.add(new PluginPreviewPane((selectedValue).getName(), get(), ((PluginModel) selectedValue).getVersion(), ((PluginModel) selectedValue).getJartime(), ((PluginModel) selectedValue).getType(), ((PluginModel) selectedValue).getPrice())); |
||||
validate(); |
||||
repaint(); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
|
||||
|
||||
private BufferedImage frmToImage(String fileName) throws Exception { |
||||
byte[] bytes = null; |
||||
try { |
||||
bytes = WorkContext.getCurrent().get(TemplateExportOperator.class).exportFormAsImageData(fileName); |
||||
} catch (Exception ignored) { |
||||
// 兼容下老版本
|
||||
bytes = new LocalExportOperator().exportFormAsImageData(fileName); |
||||
} |
||||
return TemplateExportOperator.byteDataToImage(bytes); |
||||
} |
||||
|
||||
|
||||
private BufferedImage cptToImage(String fileName) throws Exception { |
||||
byte[] bytes = null; |
||||
try { |
||||
bytes = WorkContext.getCurrent().get(TemplateExportOperator.class).exportWorkBookAsImageData(fileName); |
||||
} catch (Exception ignored) { |
||||
// 兼容下老版本
|
||||
bytes = new LocalExportOperator().exportWorkBookAsImageData(fileName); |
||||
} |
||||
return TemplateExportOperator.byteDataToImage(bytes); |
||||
} |
||||
|
||||
|
||||
private void checkWorker() { |
||||
if (this.showWorker != null && !this.showWorker.isDone()) { |
||||
this.showWorker.cancel(true); |
||||
this.showWorker = null; |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,69 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.share.ui.base.MouseClickListener; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Cursor; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/28 |
||||
*/ |
||||
public class NetWorkFailedPane extends JPanel { |
||||
|
||||
private Runnable reload; |
||||
|
||||
public NetWorkFailedPane() { |
||||
this(() -> {}); |
||||
} |
||||
|
||||
public NetWorkFailedPane(Runnable reload) { |
||||
this.reload = reload; |
||||
this.setLayout(new BorderLayout()); |
||||
this.add(createInternetErrorPane()); |
||||
this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); |
||||
this.setBackground(Color.WHITE); |
||||
} |
||||
|
||||
private JPanel createInternetErrorPane() { |
||||
JPanel panel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5); |
||||
panel.setBackground(Color.WHITE); |
||||
UILabel imagePanel = new UILabel(IOUtils.readIcon("/com/fr/base/images/share/internet_error.png")); |
||||
imagePanel.setBorder(BorderFactory.createEmptyBorder(50, 280, 0, 0)); |
||||
panel.add(imagePanel); |
||||
UILabel uiLabel = tipLabel(Toolkit.i18nText("Fine-Design_Share_Internet_Connect_Failed")); |
||||
uiLabel.setBorder(BorderFactory.createEmptyBorder(0, 300, 0, 0)); |
||||
uiLabel.setForeground(Color.decode("#8F8F92")); |
||||
UILabel reloadLabel = tipLabel(Toolkit.i18nText("Fine-Design_Share_Online_Reload")); |
||||
reloadLabel.setBorder(BorderFactory.createEmptyBorder(0, 310, 0, 0)); |
||||
reloadLabel.setForeground(Color.decode("#419BF9")); |
||||
reloadLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
||||
reloadLabel.addMouseListener(new MouseClickListener() { |
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
reload.run(); |
||||
} |
||||
}); |
||||
panel.add(uiLabel); |
||||
panel.add(reloadLabel); |
||||
return panel; |
||||
} |
||||
|
||||
private UILabel tipLabel(String text) { |
||||
UILabel tipLabel = new UILabel(text); |
||||
tipLabel.setHorizontalAlignment(SwingConstants.CENTER); |
||||
return tipLabel; |
||||
} |
||||
} |
@ -0,0 +1,63 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.dialog.link.MessageWithLink; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.utils.BrowseUtils; |
||||
import com.fr.design.utils.DesignUtils; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.event.HyperlinkEvent; |
||||
import javax.swing.event.HyperlinkListener; |
||||
|
||||
/** |
||||
* 带跳转链接的无结果面板 |
||||
* |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/12 |
||||
*/ |
||||
public class NoResultWithLinkPane extends NoResultPane { |
||||
|
||||
private static final String TAG_A_START = "<a>"; |
||||
private static final String TAG_A_END = "</a>"; |
||||
|
||||
public NoResultWithLinkPane(String title, Icon icon) { |
||||
super(title, icon); |
||||
} |
||||
|
||||
@Override |
||||
protected Component generateDescription(String title) { |
||||
String[] para1 = title.split(TAG_A_START); |
||||
String[] para2 = para1[1].split(TAG_A_END); |
||||
|
||||
MessageWithLink messageWithLink = new MessageWithLink(para1[0], para2[0], AlphaFineConstants.ALPHA_GO_TO_FORUM, para2[1], Color.WHITE, DesignUtils.getDefaultGUIFont().applySize(14), AlphaFineConstants.MEDIUM_GRAY) { |
||||
@Override |
||||
protected void initListener(String link) { |
||||
|
||||
addHyperlinkListener(new HyperlinkListener() { |
||||
@Override |
||||
public void hyperlinkUpdate(HyperlinkEvent e) { |
||||
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { |
||||
jumpToForum(link); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
}; |
||||
messageWithLink.setBorder(BorderFactory.createEmptyBorder(0, AlphaFineConstants.LEFT_WIDTH - 30, 135, 0)); |
||||
return messageWithLink; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 方便记录埋点 |
||||
* |
||||
* @param link |
||||
*/ |
||||
private void jumpToForum(String link) { |
||||
BrowseUtils.browser(link); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,14 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/22 |
||||
*/ |
||||
public abstract class ResultShowPane extends JPanel { |
||||
|
||||
public abstract void showResult(AlphaCellModel selectedValue); |
||||
} |
@ -0,0 +1,27 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
|
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import javax.swing.ImageIcon; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/21 |
||||
*/ |
||||
public class SearchLoadingPane extends JPanel { |
||||
|
||||
private static final ImageIcon LOADING_ICON = new ImageIcon(SearchLoadingPane.class.getResource("/com/fr/design/mainframe/alphafine/images/opening.gif")); |
||||
|
||||
public SearchLoadingPane() { |
||||
setLayout(new BorderLayout()); |
||||
this.add(new UILabel(LOADING_ICON)); |
||||
this.setPreferredSize(AlphaFineConstants.PREVIEW_SIZE); |
||||
this.setBackground(Color.WHITE); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,32 @@
|
||||
package com.fr.design.mainframe.alphafine.preview; |
||||
|
||||
import com.fr.design.mainframe.alphafine.AlphaFineConstants; |
||||
import com.fr.design.mainframe.alphafine.CellType; |
||||
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import javax.swing.JPanel; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 11.0 |
||||
* Created by hades on 2022/4/20 |
||||
*/ |
||||
public class SimpleRightSearchResultPane extends ResultShowPane { |
||||
|
||||
public SimpleRightSearchResultPane(JPanel contentPane) { |
||||
this.add(contentPane); |
||||
this.setBackground(Color.WHITE); |
||||
this.setPreferredSize(new Dimension(AlphaFineConstants.RIGHT_WIDTH - 1, AlphaFineConstants.CONTENT_HEIGHT)); |
||||
} |
||||
|
||||
@Override |
||||
public void showResult(AlphaCellModel selectedValue) { |
||||
if (selectedValue.getType() == CellType.DOCUMENT) { |
||||
this.removeAll(); |
||||
this.add(new DocumentPreviewPane((selectedValue).getName(), (selectedValue).getContent())); |
||||
validate(); |
||||
repaint(); |
||||
} |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue