xiqiu
1 year ago
412 changed files with 14830 additions and 1794 deletions
@ -0,0 +1,12 @@ |
|||||||
|
package com.fr.common.exception; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/12/27 |
||||||
|
*/ |
||||||
|
public interface ThrowableHandler { |
||||||
|
|
||||||
|
boolean process(Throwable e); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
package com.fr.common.listener; |
||||||
|
|
||||||
|
import com.fr.design.data.DesignTableDataManager; |
||||||
|
import javax.swing.event.AncestorEvent; |
||||||
|
import javax.swing.event.AncestorListener; |
||||||
|
import javax.swing.event.ChangeListener; |
||||||
|
|
||||||
|
/** |
||||||
|
* 管理数据集相关监听的注册 |
||||||
|
* |
||||||
|
* 原本的监听生命周期注册与销毁: |
||||||
|
* |
||||||
|
* 创建时组件时进行注册,在模板关闭时进行销毁 |
||||||
|
* 但是在模板未关闭的这段时间,如果不断的打开和关闭某些弹窗,次数达到一定程度,会导致出现大量内存占用,除非此时关闭模板 |
||||||
|
* |
||||||
|
* 改成以下模式: |
||||||
|
* |
||||||
|
* 当组件可见或者被添加到某个大组件 注册相关监听 |
||||||
|
* 当组件不可见或者被移除时 立即移除相关监听 |
||||||
|
* 及时清理无效监听,减少实时内存占用 |
||||||
|
* |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 11.0 |
||||||
|
* Created by hades on 2022/2/14 |
||||||
|
*/ |
||||||
|
public class ManageDsListenerRegisterListener implements AncestorListener { |
||||||
|
|
||||||
|
private ChangeListener changeListener; |
||||||
|
|
||||||
|
public ManageDsListenerRegisterListener(ChangeListener changeListener) { |
||||||
|
this.changeListener = changeListener; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void ancestorAdded(AncestorEvent event) { |
||||||
|
DesignTableDataManager.addDsChangeListener(changeListener); |
||||||
|
// 添加后 fire一下 更新数据
|
||||||
|
changeListener.stateChanged(null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void ancestorRemoved(AncestorEvent event) { |
||||||
|
DesignTableDataManager.removeDsChangeLister(changeListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void ancestorMoved(AncestorEvent event) { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package com.fr.design.actions.community; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.login.AbstractDesignerSSO; |
||||||
|
import com.fr.general.CloudCenter; |
||||||
|
|
||||||
|
public class StudyPlanAction extends AbstractDesignerSSO { |
||||||
|
public StudyPlanAction() { |
||||||
|
this.setName(Toolkit.i18nText("Fine-Design_Study_Plan")); |
||||||
|
this.setSmallIcon("/com/fr/design/images/bbs/studyPlan"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getJumpUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,200 @@ |
|||||||
|
package com.fr.design.actions.help.alphafine; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.general.CloudCenter; |
||||||
|
import com.fr.json.JSONArray; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 云端变量统一管理 |
||||||
|
* |
||||||
|
* @author Link |
||||||
|
* @version 11.0 |
||||||
|
* Created by Link on 2022/9/28 |
||||||
|
*/ |
||||||
|
public class AlphaFineCloudConstants { |
||||||
|
|
||||||
|
private static final String PLUGIN_SEARCH_API = "plugin.searchAPI"; |
||||||
|
private static final String PLUGIN_ALL_SEARCH_API = "plugin.all.searchAPI"; |
||||||
|
private static final String AF_PLUGIN_INFO = "af.pluginInfo"; |
||||||
|
private static final String AF_REUSE_INFO = "af.reuseInfo"; |
||||||
|
private static final String AF_DOC_VIEW = "af.doc_view"; |
||||||
|
private static final String AF_DOC_SEARCH = "af.doc_search"; |
||||||
|
private static final String AF_DOC_INFO = "af.doc_info"; |
||||||
|
private static final String AF_PLUGIN_IMAGE = "af.plugin_image"; |
||||||
|
private static final String AF_RECORD = "af.record"; |
||||||
|
private static final String AF_CLOUD_SEARCH = "af.cloud_search"; |
||||||
|
private static final String AF_SIMILAR_SEARCH = "af.similar_search"; |
||||||
|
private static final String AF_ADVICE_SEARCH = "af.advice_search"; |
||||||
|
private static final String AF_HOT_SEARCH = "af.hot_search"; |
||||||
|
private static final String AF_GO_FORUM = "af.go_fourm"; |
||||||
|
private static final String AF_GO_WEB = "af.go_web"; |
||||||
|
private static final String AF_PREVIEW = "af.preview"; |
||||||
|
private static final String AF_CID_NEW = "af.cid.new"; |
||||||
|
private static final String AF_CID_USER_GROUP_INFO = "af.cid.user.group.info"; |
||||||
|
private static final String AF_HELP_QUICK_START = "af.help.quick.start"; |
||||||
|
private static final String AF_HELP_REPORT_LEARNING_PATH = "af.help.report.learning.path"; |
||||||
|
private static final String AF_HELP_PARAM_LEARNING_PATH = "af.help.param.learning.path"; |
||||||
|
private static final String AF_HELP_FILL_LEARNING_PATH = "af.help.fill.learning.path"; |
||||||
|
private static final String AF_HELP_API_SUMMARY = "af.help.api.summary"; |
||||||
|
private static final String AF_HELP_MONTHLY_DOCUMENT = "af.help.monthly.document"; |
||||||
|
private static final String AF_RECOMMEND = "af.recommend"; |
||||||
|
|
||||||
|
private static final String LINK_NAME = "name"; |
||||||
|
private static final String LINK_URL = "link"; |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取插件搜索api |
||||||
|
*/ |
||||||
|
public static String getPluginSearchUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(PLUGIN_SEARCH_API); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 帆软市场里全部插件api |
||||||
|
*/ |
||||||
|
public static String getSearchAllPluginUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(PLUGIN_ALL_SEARCH_API); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取插件信息api |
||||||
|
*/ |
||||||
|
public static String getPluginUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_PLUGIN_INFO); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取组件信息api |
||||||
|
*/ |
||||||
|
public static String getReuseUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_REUSE_INFO); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取帮助文档url |
||||||
|
*/ |
||||||
|
public static String getDocumentDocUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_VIEW); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 帮助文档搜索api |
||||||
|
*/ |
||||||
|
public static String getDocumentSearchUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_SEARCH); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 帮助文档信息api |
||||||
|
*/ |
||||||
|
public static String getDocumentInformationUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_INFO); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 插件图片api |
||||||
|
*/ |
||||||
|
public static String getPluginImageUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_PLUGIN_IMAGE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取云端接口,用于上传alphafine搜索记录 |
||||||
|
*/ |
||||||
|
public static String getCloudServerUrl() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_RECORD); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取搜索api,输入搜索词,返回fr的相关功能 |
||||||
|
*/ |
||||||
|
public static String getSearchApi() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_CLOUD_SEARCH); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取模糊搜索api前缀,输入搜索词,返回alphaFine相关内容,插件,文档,功能等 |
||||||
|
*/ |
||||||
|
public static String getSimilarSearchUrlPrefix() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_SIMILAR_SEARCH); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 补全建议搜索结果 api,与AF_SIMILAR_SEARCH接口类似,但是返回的信息更全 |
||||||
|
*/ |
||||||
|
public static String getComplementAdviceSearchUrlPrefix() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_ADVICE_SEARCH); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取热门问题 |
||||||
|
*/ |
||||||
|
public static String getAlphaHotSearch() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_HOT_SEARCH); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 跳转论坛url |
||||||
|
*/ |
||||||
|
public static String getAlphaGoToForum() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_GO_FORUM); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 推荐搜索api,输入搜索词,返回猜你想搜的内容(html格式) |
||||||
|
*/ |
||||||
|
public static String getAlphaGoToWeb() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_GO_WEB); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 帆软智能客服页面url |
||||||
|
*/ |
||||||
|
public static String getAlphaPreview() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_PREVIEW); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* cid系统的产品动态api |
||||||
|
*/ |
||||||
|
public static String getAlphaCid() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_CID_NEW); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* cid系统的 用户组信息api |
||||||
|
*/ |
||||||
|
public static String getAlphaCidUserGroupInfo() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_CID_USER_GROUP_INFO); |
||||||
|
} |
||||||
|
|
||||||
|
private static String getDefaultRecommend() { |
||||||
|
String[][] links = new String[][]{ |
||||||
|
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Quick_Start"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_QUICK_START)}, |
||||||
|
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Report_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_REPORT_LEARNING_PATH)}, |
||||||
|
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Parameter_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_PARAM_LEARNING_PATH)}, |
||||||
|
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Fill_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_FILL_LEARNING_PATH)}, |
||||||
|
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Api_Summary"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_API_SUMMARY)}, |
||||||
|
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Monthly_Document"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_MONTHLY_DOCUMENT)} |
||||||
|
}; |
||||||
|
JSONArray jsonArray = new JSONArray(); |
||||||
|
for (String[] link : links) { |
||||||
|
Map<String, String> map = new HashMap<>(); |
||||||
|
map.put(LINK_NAME, link[0]); |
||||||
|
map.put(LINK_URL, link[1]); |
||||||
|
jsonArray.put(map); |
||||||
|
} |
||||||
|
|
||||||
|
return jsonArray.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取默认推荐帮助文档url |
||||||
|
*/ |
||||||
|
public static String getAlphaHelpRecommend() { |
||||||
|
return CloudCenter.getInstance().acquireUrlByKind(AF_RECOMMEND, getDefaultRecommend()); |
||||||
|
} |
||||||
|
} |
@ -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,229 @@ |
|||||||
|
package com.fr.design.actions.help.alphafine.component; |
||||||
|
|
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.design.actions.help.alphafine.AlphaFineConfigPane; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.SwingUtilities; |
||||||
|
import javax.swing.plaf.PanelUI; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.FlowLayout; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Comparator; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* alphafine设置 - 搜索范围 - 自定义排序 - 弹出面板 |
||||||
|
* |
||||||
|
* @author Link |
||||||
|
* @version 11.0 |
||||||
|
* Created by Link on 2022/9/18 |
||||||
|
*/ |
||||||
|
public class CustomSortPane extends JPanel { |
||||||
|
|
||||||
|
|
||||||
|
private static final int WIDTH = 147; |
||||||
|
private static final int ITEM_HEIGHT = 23; |
||||||
|
private static final int GAP = 1; |
||||||
|
private static final Color BACKGROUND_COLOR = new Color(0xdadadd); |
||||||
|
|
||||||
|
private UIButton top; |
||||||
|
private UIButton bottom; |
||||||
|
private UIButton up; |
||||||
|
private UIButton down; |
||||||
|
private JPanel toolbarPane; |
||||||
|
private MenuLabelPane sortItemPane; |
||||||
|
private List<UICheckBox> sortItems; |
||||||
|
private MenuLabel selectedLabel; |
||||||
|
private AlphaFineConfigPane parentPane; |
||||||
|
|
||||||
|
public CustomSortPane(List<UICheckBox> items, AlphaFineConfigPane parentPane) { |
||||||
|
this.sortItems = items; |
||||||
|
this.parentPane = parentPane; |
||||||
|
setLayout(new BorderLayout(GAP, GAP)); |
||||||
|
int height = (sortItems.size() + 1) * (ITEM_HEIGHT + GAP) + GAP; |
||||||
|
setPreferredSize(new Dimension(WIDTH, height)); |
||||||
|
initComponent(); |
||||||
|
add(toolbarPane, BorderLayout.NORTH); |
||||||
|
add(sortItemPane, BorderLayout.CENTER); |
||||||
|
revalidate(); |
||||||
|
this.setVisible(true); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setUI(PanelUI ui) { |
||||||
|
super.setUI(ui); |
||||||
|
setBackground(BACKGROUND_COLOR); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void initComponent() { |
||||||
|
createToolbarPane(); |
||||||
|
createSortItemPane(); |
||||||
|
} |
||||||
|
|
||||||
|
private void createToolbarPane() { |
||||||
|
top = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/top.svg"), false); |
||||||
|
bottom = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bottom.svg"), false); |
||||||
|
up = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/up.svg"), false); |
||||||
|
down = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/down.svg"), false); |
||||||
|
top.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/top_disable.svg")); |
||||||
|
bottom.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bottom_disable.svg")); |
||||||
|
up.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/up_disable.svg")); |
||||||
|
down.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/down_disable.svg")); |
||||||
|
top.addActionListener(e -> { |
||||||
|
SwingUtilities.invokeLater(() -> { |
||||||
|
sortItemPane.setComponentZOrder(selectedLabel, 0); |
||||||
|
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); |
||||||
|
CustomSortPane.this.revalidate(); |
||||||
|
CustomSortPane.this.repaint(); |
||||||
|
refreshCurrentOrder(); |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
bottom.addActionListener(e -> { |
||||||
|
SwingUtilities.invokeLater(() -> { |
||||||
|
sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentCount() - 1); |
||||||
|
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); |
||||||
|
CustomSortPane.this.revalidate(); |
||||||
|
CustomSortPane.this.repaint(); |
||||||
|
refreshCurrentOrder(); |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
up.addActionListener(e -> { |
||||||
|
SwingUtilities.invokeLater(() -> { |
||||||
|
sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentZOrder(selectedLabel) - 1); |
||||||
|
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); |
||||||
|
CustomSortPane.this.revalidate(); |
||||||
|
CustomSortPane.this.repaint(); |
||||||
|
refreshCurrentOrder(); |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
down.addActionListener(e -> { |
||||||
|
SwingUtilities.invokeLater(() -> { |
||||||
|
sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentZOrder(selectedLabel) + 1); |
||||||
|
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); |
||||||
|
CustomSortPane.this.revalidate(); |
||||||
|
CustomSortPane.this.repaint(); |
||||||
|
refreshCurrentOrder(); |
||||||
|
}); |
||||||
|
|
||||||
|
}); |
||||||
|
toolbarPane = new JPanel(new FlowLayout(FlowLayout.TRAILING, GAP, GAP)); |
||||||
|
toolbarPane.setBorder(BorderFactory.createEmptyBorder()); |
||||||
|
toolbarPane.add(top); |
||||||
|
toolbarPane.add(bottom); |
||||||
|
toolbarPane.add(up); |
||||||
|
toolbarPane.add(down); |
||||||
|
} |
||||||
|
|
||||||
|
private void createSortItemPane() { |
||||||
|
String[] currentTabOrder = parentPane.getCurrentOrder(); |
||||||
|
Map<String, Integer> sortMap = new HashMap<>(); |
||||||
|
for (int i = 0; i < currentTabOrder.length; i++) { |
||||||
|
sortMap.put(currentTabOrder[i], i); |
||||||
|
} |
||||||
|
List<MenuLabel> sortLabels = new ArrayList<>(); |
||||||
|
for (UICheckBox item : sortItems) { |
||||||
|
MenuLabel label = new MenuLabel(item.getText(), (Function<MenuLabel, Object>) o -> { |
||||||
|
selectedLabel = o; |
||||||
|
disableButton(); |
||||||
|
return null; |
||||||
|
}); |
||||||
|
sortLabels.add(label); |
||||||
|
} |
||||||
|
sortLabels.sort(Comparator.comparingInt(tab -> sortMap.get(tab.getText()))); |
||||||
|
sortItemPane = new MenuLabelPane(sortLabels); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 如果选中第一个和最后一个,则置灰向上和向下的按钮 |
||||||
|
*/ |
||||||
|
private void disableButton() { |
||||||
|
int order = sortItemPane.getComponentZOrder(selectedLabel); |
||||||
|
if (order == 0) { |
||||||
|
setToolbarEnable(false, false, true, true); |
||||||
|
} else if (order == sortItemPane.getComponentCount() - 1) { |
||||||
|
setToolbarEnable(true, true, false, false); |
||||||
|
} else { |
||||||
|
setToolbarEnable(true, true, true, true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置 置顶,上移,下移,置底 按钮的状态 |
||||||
|
* true:启用 |
||||||
|
* false:关闭 |
||||||
|
*/ |
||||||
|
private void setToolbarEnable(boolean top, boolean up, boolean down, boolean bottom) { |
||||||
|
this.top.setEnabled(top); |
||||||
|
this.up.setEnabled(up); |
||||||
|
this.down.setEnabled(down); |
||||||
|
this.bottom.setEnabled(bottom); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据选项当前位置以及菜单大小设置 置顶,上移,下移,置底 按钮的状态 |
||||||
|
*/ |
||||||
|
private void setToolbarEnable(int order, int maxOrder) { |
||||||
|
this.top.setEnabled(true); |
||||||
|
this.up.setEnabled(true); |
||||||
|
this.down.setEnabled(true); |
||||||
|
this.bottom.setEnabled(true); |
||||||
|
// 选项处于顶端,则置灰上移和置顶按钮
|
||||||
|
if (order == 0) { |
||||||
|
this.top.setEnabled(false); |
||||||
|
this.up.setEnabled(false); |
||||||
|
} |
||||||
|
// 选项处于底端,则置灰下移和置底按钮
|
||||||
|
if (order == maxOrder - 1) { |
||||||
|
this.down.setEnabled(false); |
||||||
|
this.bottom.setEnabled(false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void refreshCurrentOrder() { |
||||||
|
String[] currentTabOrder = parentPane.getCurrentOrder(); |
||||||
|
HashSet<String> selectedTab = new HashSet<>(); |
||||||
|
for (UICheckBox item : sortItems) { |
||||||
|
selectedTab.add(item.getText()); |
||||||
|
} |
||||||
|
|
||||||
|
// 未选中的tab,保持原排序不变
|
||||||
|
Map<String, Integer> exTab = new HashMap<>(); |
||||||
|
for (int i = 0; i < currentTabOrder.length; i++) { |
||||||
|
if (!selectedTab.contains(currentTabOrder[i])) { |
||||||
|
exTab.put(currentTabOrder[i], i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 计算当前排序
|
||||||
|
String[] newOrder = new String[currentTabOrder.length]; |
||||||
|
Component[] components = sortItemPane.getComponents(); |
||||||
|
for (String s : exTab.keySet()) { |
||||||
|
newOrder[exTab.get(s)] = s; |
||||||
|
} |
||||||
|
|
||||||
|
int t = 0; |
||||||
|
for (int i = 0; i < newOrder.length; i++) { |
||||||
|
if (StringUtils.isEmpty(newOrder[i])) { |
||||||
|
newOrder[i] = ((MenuLabel) components[t++]).getText(); |
||||||
|
} |
||||||
|
} |
||||||
|
parentPane.setCurrentOrder(newOrder); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
package com.fr.design.actions.help.alphafine.component; |
||||||
|
|
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.utils.DesignUtils; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.plaf.LabelUI; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.event.MouseAdapter; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.awt.event.MouseListener; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* 菜单选项label |
||||||
|
* |
||||||
|
* @author Link |
||||||
|
* @version 11.0 |
||||||
|
* Created by Link on 2022/9/18 |
||||||
|
*/ |
||||||
|
public class MenuLabel extends UILabel { |
||||||
|
|
||||||
|
private static final Color BACKGROUND_COLOR = Color.white; |
||||||
|
private static final Color SELECTED_COLOR = new Color(0x419BF9); |
||||||
|
private static final Color HOVERED_COLOR = new Color(0xd9ebfe); |
||||||
|
private static final int HEIGHT = 23; |
||||||
|
private static final int WIDTH = 147; |
||||||
|
|
||||||
|
private MenuLabelPane parentMenu; |
||||||
|
private final Function function; |
||||||
|
private boolean selected; |
||||||
|
|
||||||
|
public MenuLabel(String text, Function function) { |
||||||
|
super(text); |
||||||
|
this.function = function; |
||||||
|
setOpaque(true); |
||||||
|
addMouseListener(createMouseListener()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParentMenu(MenuLabelPane menu) { |
||||||
|
this.parentMenu = menu; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void setUI(LabelUI ui) { |
||||||
|
super.setUI(ui); |
||||||
|
this.setBackground(BACKGROUND_COLOR); |
||||||
|
this.setBorder(BorderFactory.createEmptyBorder(2, 10, 1, 10)); |
||||||
|
this.setPreferredSize(new Dimension(WIDTH, HEIGHT)); |
||||||
|
this.setFont(DesignUtils.getDefaultGUIFont().applySize(12)); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSelected() { |
||||||
|
return selected; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSelected(boolean selected) { |
||||||
|
if (selected) { |
||||||
|
parentMenu.setNoneSelected(); |
||||||
|
setBackground(SELECTED_COLOR); |
||||||
|
function.apply(this); |
||||||
|
this.selected = true; |
||||||
|
} else { |
||||||
|
setBackground(BACKGROUND_COLOR); |
||||||
|
this.selected = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
MouseListener createMouseListener() { |
||||||
|
return new MouseAdapter() { |
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
super.mouseClicked(e); |
||||||
|
setSelected(true); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseEntered(MouseEvent e) { |
||||||
|
super.mouseEntered(e); |
||||||
|
if (!selected) { |
||||||
|
setBackground(HOVERED_COLOR); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseExited(MouseEvent e) { |
||||||
|
super.mouseExited(e); |
||||||
|
if (!selected) { |
||||||
|
setBackground(BACKGROUND_COLOR); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.design.actions.help.alphafine.component; |
||||||
|
|
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.FlowLayout; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 简单菜单面板 |
||||||
|
* |
||||||
|
* @author Link |
||||||
|
* @version 11.0 |
||||||
|
* Created by Link on 2022/9/18 |
||||||
|
*/ |
||||||
|
public class MenuLabelPane extends JPanel { |
||||||
|
|
||||||
|
private static final int GAP = 1; |
||||||
|
|
||||||
|
private List<MenuLabel> labels; |
||||||
|
|
||||||
|
public MenuLabelPane(List<MenuLabel> labels) { |
||||||
|
this.labels = labels; |
||||||
|
setLayout(new FlowLayout(FlowLayout.CENTER, GAP, GAP)); |
||||||
|
for (MenuLabel label : labels) { |
||||||
|
label.setParentMenu(this); |
||||||
|
add(label); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setNoneSelected() { |
||||||
|
for (MenuLabel label : labels) { |
||||||
|
label.setSelected(false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package com.fr.design.beans; |
||||||
|
|
||||||
|
import javax.swing.JComponent; |
||||||
|
|
||||||
|
public interface ErrorMsgTextFieldAdapter { |
||||||
|
void setText(String str); |
||||||
|
|
||||||
|
String getText(); |
||||||
|
|
||||||
|
JComponent getErrorMsgTextField(); |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package com.fr.design.beans; |
||||||
|
|
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
|
||||||
|
import javax.swing.JComponent; |
||||||
|
import javax.swing.event.DocumentEvent; |
||||||
|
import javax.swing.event.DocumentListener; |
||||||
|
|
||||||
|
public class UITextFieldAdapter implements ErrorMsgTextFieldAdapter { |
||||||
|
private final UITextField uiTextField = new UITextField(); |
||||||
|
|
||||||
|
public UITextFieldAdapter(){ |
||||||
|
addDocumentListener(); |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void setText(String str) { |
||||||
|
uiTextField.setText(str); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getText() { |
||||||
|
return uiTextField.getText(); |
||||||
|
} |
||||||
|
|
||||||
|
public void addDocumentListener() { |
||||||
|
uiTextField.getDocument().addDocumentListener(new DocumentListener() { |
||||||
|
|
||||||
|
public void changedUpdate(DocumentEvent e) { |
||||||
|
uiTextField.setToolTipText(uiTextField.getText()); |
||||||
|
} |
||||||
|
|
||||||
|
public void insertUpdate(DocumentEvent e) { |
||||||
|
uiTextField.setToolTipText(uiTextField.getText()); |
||||||
|
} |
||||||
|
|
||||||
|
public void removeUpdate(DocumentEvent e) { |
||||||
|
uiTextField.setToolTipText(uiTextField.getText()); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JComponent getErrorMsgTextField() { |
||||||
|
return uiTextField; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
package com.fr.design.constants; |
||||||
|
|
||||||
|
public class TableDataConstants { |
||||||
|
public static final String SEPARATOR = "_"; |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
package com.fr.design.data; |
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull; |
||||||
|
|
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author rinoux |
||||||
|
* @version 10.0 |
||||||
|
* Created by rinoux on 2022/3/28 |
||||||
|
*/ |
||||||
|
public final class MapCompareUtils { |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 |
||||||
|
* |
||||||
|
* 对比时默认用equals方法来判断是否为 EntryEventKind#UPDATED |
||||||
|
* |
||||||
|
* @param orig 原始map |
||||||
|
* @param other 参考的新map |
||||||
|
* @param eventHandler 有区别时的事件处理器 |
||||||
|
* @param <K> K |
||||||
|
* @param <V> V |
||||||
|
*/ |
||||||
|
public static <K, V> void contrastMapEntries(@NotNull Map<K, V> orig, @NotNull Map<K, V> other, @NotNull EventHandler<K, V> eventHandler) { |
||||||
|
|
||||||
|
contrastMapEntries(orig, other, eventHandler, UpdateRule.DEFAULT); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 |
||||||
|
* |
||||||
|
* 对比时用自定义的规则来判断是否为 EntryEventKind#UPDATED |
||||||
|
* |
||||||
|
* @param orig 原始map |
||||||
|
* @param other 参考的新map |
||||||
|
* @param eventHandler 有区别时的事件处理器 |
||||||
|
* @param updateRule 自定义的Update事件判定规则 |
||||||
|
* @param <K> |
||||||
|
* @param <V> |
||||||
|
*/ |
||||||
|
public static <K, V> void contrastMapEntries(@NotNull Map<K, V> orig, @NotNull Map<K, V> other, @NotNull EventHandler<K, V> eventHandler, @NotNull UpdateRule<K, V> updateRule) { |
||||||
|
|
||||||
|
Map<K, V> copiedOrig = new LinkedHashMap<>(orig); |
||||||
|
|
||||||
|
other.forEach((k, v) -> { |
||||||
|
V existedV = copiedOrig.remove(k); |
||||||
|
if (existedV != null) { |
||||||
|
if (updateRule.needUpdate(existedV, v)) { |
||||||
|
eventHandler.on(EntryEventKind.UPDATED, k, v); |
||||||
|
} |
||||||
|
} else { |
||||||
|
eventHandler.on(EntryEventKind.ADDED, k, v); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
copiedOrig.forEach((k, v) -> eventHandler.on(EntryEventKind.REMOVED, k, v)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 事件处理器,对应比较后的三种结果的事件处理 |
||||||
|
* @param <K> |
||||||
|
* @param <V> |
||||||
|
*/ |
||||||
|
public interface EventHandler<K, V> { |
||||||
|
void on(EntryEventKind entryEventKind, K k, V v); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判定 数据被修改 的判定规则 |
||||||
|
* @param <K> |
||||||
|
* @param <V> |
||||||
|
*/ |
||||||
|
public interface UpdateRule<K, V> { |
||||||
|
|
||||||
|
EntryEventKind eventKind = EntryEventKind.UPDATED; |
||||||
|
|
||||||
|
UpdateRule DEFAULT = new UpdateRule() {}; |
||||||
|
|
||||||
|
default boolean needUpdate(V origin, V v) { |
||||||
|
return !v.equals(origin); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public enum EntryEventKind { |
||||||
|
ADDED, |
||||||
|
REMOVED, |
||||||
|
UPDATED; |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.design.gui.frpane.RegFieldPane; |
||||||
|
import com.fr.stable.fun.mark.Immutable; |
||||||
|
|
||||||
|
public interface RegPaneProvider extends Immutable { |
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
String XML_TAG = "RegPaneProvider"; |
||||||
|
|
||||||
|
RegFieldPane createRegPane(); |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.design.beans.ErrorMsgTextFieldAdapter; |
||||||
|
import com.fr.stable.fun.mark.Immutable; |
||||||
|
|
||||||
|
public interface TextFieldAdapterProvider extends Immutable { |
||||||
|
String XML_TAG = "TextFieldAdapterProvider"; |
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
ErrorMsgTextFieldAdapter createTextFieldAdapter(); |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.RegPaneProvider; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Joe |
||||||
|
* 2021/10/8 15:19 |
||||||
|
*/ |
||||||
|
@API(level = RegPaneProvider.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractRegPaneProvider implements RegPaneProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int layerIndex() { |
||||||
|
return DEFAULT_LAYER_INDEX; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.TextFieldAdapterProvider; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Joe |
||||||
|
* 2021/10/8 15:17 |
||||||
|
*/ |
||||||
|
@API(level = TextFieldAdapterProvider.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractTextFieldAdapterProvider implements TextFieldAdapterProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int layerIndex() { |
||||||
|
return DEFAULT_LAYER_INDEX; |
||||||
|
} |
||||||
|
} |
@ -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,25 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/12/29 |
||||||
|
*/ |
||||||
|
public class ExtensionFilter { |
||||||
|
|
||||||
|
private final String des; |
||||||
|
private final String[] extensions; |
||||||
|
|
||||||
|
public ExtensionFilter(String des, String... extensions) { |
||||||
|
this.des = des; |
||||||
|
this.extensions = extensions; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDes() { |
||||||
|
return des; |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getExtensions() { |
||||||
|
return extensions; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser; |
||||||
|
|
||||||
|
/** |
||||||
|
* 文件选择器可设置的参数集合 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/12/21 |
||||||
|
*/ |
||||||
|
public class FileChooserArgs { |
||||||
|
|
||||||
|
private final FileSelectionMode fileSelectionMode; |
||||||
|
private final String filterDes; |
||||||
|
private final String[] extensions; |
||||||
|
private final String selectedPath; |
||||||
|
private final ExtensionFilter[] filters; |
||||||
|
private final String tipText; |
||||||
|
private final boolean multiSelectionEnabled; |
||||||
|
|
||||||
|
public static Builder newBuilder() { |
||||||
|
return new Builder(); |
||||||
|
} |
||||||
|
|
||||||
|
private FileChooserArgs(Builder builder) { |
||||||
|
this.fileSelectionMode = builder.fileSelectionMode; |
||||||
|
this.filterDes = builder.filterDes; |
||||||
|
this.extensions = builder.extensions; |
||||||
|
this.selectedPath = builder.selectedPath; |
||||||
|
this.filters = builder.filters; |
||||||
|
this.tipText = builder.tipText; |
||||||
|
this.multiSelectionEnabled = builder.multiSelectionEnabled; |
||||||
|
} |
||||||
|
|
||||||
|
public FileSelectionMode getFileSelectionMode() { |
||||||
|
return fileSelectionMode; |
||||||
|
} |
||||||
|
|
||||||
|
public String getFilterDes() { |
||||||
|
return filterDes; |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getExtensions() { |
||||||
|
return extensions; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSelectedPath() { |
||||||
|
return selectedPath; |
||||||
|
} |
||||||
|
|
||||||
|
public ExtensionFilter[] getFilters() { |
||||||
|
return filters; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTipText() { |
||||||
|
return tipText; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isMultiSelectionEnabled() { |
||||||
|
return multiSelectionEnabled; |
||||||
|
} |
||||||
|
|
||||||
|
public static class Builder { |
||||||
|
|
||||||
|
private FileSelectionMode fileSelectionMode; |
||||||
|
private String filterDes; |
||||||
|
private String[] extensions; |
||||||
|
private String selectedPath; |
||||||
|
private ExtensionFilter[] filters = new ExtensionFilter[0]; |
||||||
|
private String tipText; |
||||||
|
private boolean multiSelectionEnabled; |
||||||
|
|
||||||
|
public Builder setFileSelectionMode(FileSelectionMode fileSelectionMode) { |
||||||
|
this.fileSelectionMode = fileSelectionMode; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setFilter(String filterDes, String... extensions) { |
||||||
|
this.filterDes = filterDes; |
||||||
|
this.extensions = extensions; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setSelectedPath(String selectedPath) { |
||||||
|
this.selectedPath = selectedPath; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setFilters(ExtensionFilter[] filters) { |
||||||
|
this.filters = filters; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setTipText(String tipText) { |
||||||
|
this.tipText = tipText; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setMultiSelectionEnabled(boolean multiSelectionEnabled) { |
||||||
|
this.multiSelectionEnabled = multiSelectionEnabled; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public FileChooserArgs build() { |
||||||
|
return new FileChooserArgs(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser; |
||||||
|
|
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.os.impl.SupportOSImpl; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/12/21 |
||||||
|
*/ |
||||||
|
public class FileChooserFactory { |
||||||
|
|
||||||
|
public static FileChooserProvider createFileChooser(FileChooserArgs fileChooserArgs) { |
||||||
|
if (SupportOSImpl.OLD_STYLE_CHOOSER.support()) { |
||||||
|
return new SwingFileChooser.Builder(). |
||||||
|
setFileSelectionMode(fileChooserArgs.getFileSelectionMode()). |
||||||
|
setFileFilter(fileChooserArgs.getFilterDes(), fileChooserArgs.getExtensions()). |
||||||
|
setSelectedFile(fileChooserArgs.getSelectedPath()). |
||||||
|
setMultiSelectionEnabled(fileChooserArgs.isMultiSelectionEnabled()). |
||||||
|
setTipText(fileChooserArgs.getTipText()). |
||||||
|
setFileFilter(fileChooserArgs.getFilters()).build(); |
||||||
|
} else { |
||||||
|
return new JavaFxNativeFileChooser.Builder(). |
||||||
|
fileSelectionMode(fileChooserArgs.getFileSelectionMode()). |
||||||
|
filter(fileChooserArgs.getFilterDes(), fileChooserArgs.getExtensions()). |
||||||
|
currentDirectory(fileChooserArgs.getSelectedPath()). |
||||||
|
title(fileChooserArgs.getTipText()). |
||||||
|
filters(fileChooserArgs.getFilters()).build(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static FileChooserProvider createImageFileChooser() { |
||||||
|
if (SupportOSImpl.OLD_STYLE_CHOOSER.support()) { |
||||||
|
return new SwingImageFileChooser(); |
||||||
|
} else { |
||||||
|
return new JavaFxNativeFileChooser.Builder(). |
||||||
|
fileSelectionMode(FileSelectionMode.FILE). |
||||||
|
title(Toolkit.i18nText("Fine-Design_Basic_Open")). |
||||||
|
filter(Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files"), "*.jpg", "*.gif", "*.png", "*.bmp"). |
||||||
|
build(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,134 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser; |
||||||
|
|
||||||
|
import com.fr.common.annotations.Negative; |
||||||
|
import com.fr.design.upm.UpmUtils; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import java.awt.Component; |
||||||
|
import java.io.File; |
||||||
|
import javax.swing.JFileChooser; |
||||||
|
import javax.swing.filechooser.FileFilter; |
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/12/21 |
||||||
|
*/ |
||||||
|
@Negative(until = "2022-6-1") |
||||||
|
class SwingFileChooser implements FileChooserProvider { |
||||||
|
|
||||||
|
private final JFileChooser fileChooser; |
||||||
|
private final Builder builder; |
||||||
|
|
||||||
|
private SwingFileChooser(Builder builder) { |
||||||
|
fileChooser = new JFileChooser(); |
||||||
|
fileChooser.setFileSelectionMode(builder.fileSelectionMode); |
||||||
|
fileChooser.setFileFilter(builder.fileFilter); |
||||||
|
fileChooser.setSelectedFile(builder.selectedFile); |
||||||
|
fileChooser.setMultiSelectionEnabled(builder.multiSelectionEnabled); |
||||||
|
this.builder = builder; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public File[] getSelectedFiles() { |
||||||
|
if (ArrayUtils.isNotEmpty(fileChooser.getSelectedFiles())) { |
||||||
|
return fileChooser.getSelectedFiles(); |
||||||
|
} else { |
||||||
|
return new File[]{fileChooser.getSelectedFile()}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public File getSelectedFile() { |
||||||
|
return fileChooser.getSelectedFile(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showDialog(Component parent) { |
||||||
|
if (StringUtils.isEmpty(builder.tipText)) { |
||||||
|
return fileChooser.showOpenDialog(parent); |
||||||
|
} else { |
||||||
|
return fileChooser.showDialog(parent, builder.tipText); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showOpenDialog(Component parent, String approveButtonText) { |
||||||
|
return fileChooser.showDialog(parent, approveButtonText); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setCurrentDirectory(File file) { |
||||||
|
fileChooser.setCurrentDirectory(file); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setMultiSelectionEnabled(boolean multiple) { |
||||||
|
fileChooser.setMultiSelectionEnabled(multiple); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 和一般builder不同的是 setXXX还做参数转换逻辑 |
||||||
|
*/ |
||||||
|
public static class Builder { |
||||||
|
|
||||||
|
private int fileSelectionMode = JFileChooser.FILES_ONLY; |
||||||
|
private FileFilter fileFilter; |
||||||
|
private File selectedFile; |
||||||
|
private boolean multiSelectionEnabled; |
||||||
|
private String tipText; |
||||||
|
|
||||||
|
public Builder setFileSelectionMode(FileSelectionMode fileSelectionMode) { |
||||||
|
if (FileSelectionMode.DIR.equals(fileSelectionMode)) { |
||||||
|
this.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY; |
||||||
|
} else if (FileSelectionMode.FILE.equals(fileSelectionMode)) { |
||||||
|
this.fileSelectionMode = JFileChooser.FILES_ONLY; |
||||||
|
} else if (FileSelectionMode.MULTIPLE_FILE.equals(fileSelectionMode)) { |
||||||
|
this.fileSelectionMode = JFileChooser.FILES_AND_DIRECTORIES; |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setFileFilter(String des, String... extension) { |
||||||
|
if (StringUtils.isNotEmpty(des) && ArrayUtils.isNotEmpty(extension)) { |
||||||
|
this.fileFilter = new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(extension)); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setFileFilter(ExtensionFilter[] extensionFilters) { |
||||||
|
StringBuilder desBuilder = new StringBuilder(); |
||||||
|
String[] extensions = new String[0]; |
||||||
|
for (ExtensionFilter extensionFilter : extensionFilters) { |
||||||
|
desBuilder.append(extensionFilter.getDes()).append(" "); |
||||||
|
extensions = ArrayUtils.addAll(extensions, UpmUtils.findMatchedExtension(extensionFilter.getExtensions())); |
||||||
|
} |
||||||
|
if (ArrayUtils.isNotEmpty(extensionFilters)) { |
||||||
|
this.fileFilter = new FileNameExtensionFilter(desBuilder.toString().trim(), extensions); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setSelectedFile(String selectedPath) { |
||||||
|
if (StringUtils.isNotEmpty(selectedPath)) { |
||||||
|
this.selectedFile = new File(selectedPath); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setMultiSelectionEnabled(boolean multiSelectionEnabled) { |
||||||
|
this.multiSelectionEnabled = multiSelectionEnabled; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Builder setTipText(String tipText) { |
||||||
|
this.tipText = tipText; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public SwingFileChooser build() { |
||||||
|
return new SwingFileChooser(this); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,276 @@ |
|||||||
|
package com.fr.design.gui.ifilechooser; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.common.annotations.Negative; |
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.design.style.ChooseFileView; |
||||||
|
import com.fr.design.style.background.image.ExpandFileChooser; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.io.File; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.Hashtable; |
||||||
|
import javax.swing.filechooser.FileFilter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/12/30 |
||||||
|
*/ |
||||||
|
@Negative(until = "2022-6-1") |
||||||
|
class SwingImageFileChooser extends ExpandFileChooser implements FileChooserProvider { |
||||||
|
|
||||||
|
public SwingImageFileChooser() { |
||||||
|
super(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Compress"),com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open")); |
||||||
|
ExampleFileFilter bothFilter = new ExampleFileFilter( |
||||||
|
new String[]{"jpg", "gif", "png", "bmp"}, |
||||||
|
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files")); |
||||||
|
bothFilter.setExtensionListInDescription(true); |
||||||
|
this.addChoosableFileFilter(bothFilter); |
||||||
|
this.setAcceptAllFileFilterUsed(false); |
||||||
|
|
||||||
|
// Create Custom FileView
|
||||||
|
ChooseFileView fileView = new ChooseFileView(); |
||||||
|
fileView.putIcon("jpg", BaseUtils.readIcon("/com/fr/base/images/dialog/file/jpgFile.gif")); |
||||||
|
fileView.putIcon("gif", BaseUtils.readIcon("/com/fr/base/images/dialog/file/gifFile.gif")); |
||||||
|
fileView.putIcon("png", BaseUtils.readIcon("/com/fr/base/images/dialog/file/pngFile.png")); |
||||||
|
fileView.putIcon("bmp", BaseUtils.readIcon("/com/fr/base/images/dialog/file/bmpFile.gif")); |
||||||
|
|
||||||
|
this.setFileView(fileView); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showDialog(Component parent, String approveButtonText) { |
||||||
|
return super.showDialog(parent, approveButtonText); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ActionListener checkAction() { |
||||||
|
return new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
DesignerEnvManager.getEnvManager().setImageCompress(isCheckSelected()); |
||||||
|
DesignerEnvManager.getEnvManager().saveXMLFile(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int showDialog(Component parent) { |
||||||
|
return showOpenDialog(parent); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* A convenience implementation of FileFilter that filters out |
||||||
|
* all files except for those type extensions that it knows about. |
||||||
|
* <p/>D:\finereport\develop\code\test\TestCase\WEB-INF\reportlets\TestCase\01903.cpt |
||||||
|
* <p> |
||||||
|
* Extensions are of the type ".foo", which is typically found on |
||||||
|
* Windows and Unix boxes, but not on Macinthosh. Case is ignored. |
||||||
|
* <p/> |
||||||
|
* Example - create a new filter that filerts out all files |
||||||
|
* but gif and jpg image files: |
||||||
|
* <p/> |
||||||
|
* JFileChooser chooser = new JFileChooser(); |
||||||
|
* ExampleFileFilter filter = new ExampleFileFilter( |
||||||
|
* new String{"gif", "jpg"}, "JPEG & GIF Images") |
||||||
|
* chooser.addChoosableFileFilter(filter); |
||||||
|
* chooser.showOpenDialog(this); |
||||||
|
* |
||||||
|
* @author Jeff Dinkins |
||||||
|
* @version 1.12 12/03/01 |
||||||
|
*/ |
||||||
|
class ExampleFileFilter extends FileFilter { |
||||||
|
private Hashtable filters = null; |
||||||
|
private String description = null; |
||||||
|
private String fullDescription = null; |
||||||
|
private boolean useExtensionsInDescription = true; |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a file filter. If no filters are added, then all |
||||||
|
* files are accepted. |
||||||
|
* |
||||||
|
* @see #addExtension |
||||||
|
*/ |
||||||
|
public ExampleFileFilter() { |
||||||
|
this.filters = new Hashtable(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a file filter that accepts files with the given extension. |
||||||
|
* Example: new ExampleFileFilter("jpg"); |
||||||
|
* |
||||||
|
* @see #addExtension |
||||||
|
*/ |
||||||
|
public ExampleFileFilter(String extension) { |
||||||
|
this(extension, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a file filter that accepts the given file type. |
||||||
|
* Example: new ExampleFileFilter("jpg", "JPEG Image Images"); |
||||||
|
* <p/> |
||||||
|
* Note that the "." before the extension is not needed. If |
||||||
|
* provided, it will be ignored. |
||||||
|
* |
||||||
|
* @see #addExtension |
||||||
|
*/ |
||||||
|
public ExampleFileFilter(String extension, String description) { |
||||||
|
this(); |
||||||
|
if (extension != null) addExtension(extension); |
||||||
|
if (description != null) setDescription(description); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a file filter from the given string array. |
||||||
|
* Example: new ExampleFileFilter(String {"gif", "jpg"}); |
||||||
|
* <p/> |
||||||
|
* Note that the "." before the extension is not needed adn |
||||||
|
* will be ignored. |
||||||
|
* |
||||||
|
* @see #addExtension |
||||||
|
*/ |
||||||
|
public ExampleFileFilter(String[] filters) { |
||||||
|
this(filters, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a file filter from the given string array and description. |
||||||
|
* Example: new ExampleFileFilter(String {"gif", "jpg"}, "Gif and JPG Images"); |
||||||
|
* <p/> |
||||||
|
* Note that the "." before the extension is not needed and will be ignored. |
||||||
|
* |
||||||
|
* @see #addExtension |
||||||
|
*/ |
||||||
|
public ExampleFileFilter(String[] filters, String description) { |
||||||
|
this(); |
||||||
|
for (int i = 0; i < filters.length; i++) { |
||||||
|
// add filters one by one
|
||||||
|
addExtension(filters[i]); |
||||||
|
} |
||||||
|
if (description != null) setDescription(description); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return true if this file should be shown in the directory pane, |
||||||
|
* false if it shouldn't. |
||||||
|
* <p/> |
||||||
|
* Files that begin with "." are ignored. |
||||||
|
* |
||||||
|
* @see #getExtension |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean accept(File f) { |
||||||
|
if (f != null) { |
||||||
|
if (f.isDirectory()) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
String extension = getExtension(f); |
||||||
|
if (extension != null && filters.get(getExtension(f)) != null) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the extension portion of the file's name . |
||||||
|
* |
||||||
|
* @see #getExtension |
||||||
|
* @see FileFilter#accept |
||||||
|
*/ |
||||||
|
public String getExtension(File f) { |
||||||
|
if (f != null) { |
||||||
|
String filename = f.getName(); |
||||||
|
int i = filename.lastIndexOf('.'); |
||||||
|
if (i > 0 && i < filename.length() - 1) { |
||||||
|
return filename.substring(i + 1).toLowerCase(); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds a filetype "dot" extension to filter against. |
||||||
|
* <p/> |
||||||
|
* For example: the following code will create a filter that filters |
||||||
|
* out all files except those that end in ".jpg" and ".tif": |
||||||
|
* <p/> |
||||||
|
* ExampleFileFilter filter = new ExampleFileFilter(); |
||||||
|
* filter.addExtension("jpg"); |
||||||
|
* filter.addExtension("tif"); |
||||||
|
* <p/> |
||||||
|
* Note that the "." before the extension is not needed and will be ignored. |
||||||
|
*/ |
||||||
|
public void addExtension(String extension) { |
||||||
|
if (filters == null) { |
||||||
|
filters = new Hashtable(5); |
||||||
|
} |
||||||
|
filters.put(extension.toLowerCase(), this); |
||||||
|
fullDescription = null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the human readable description of this filter. For |
||||||
|
* example: "JPEG and GIF Image Files (*.jpg, *.gif)" |
||||||
|
* |
||||||
|
* @see FileFilter#getDescription |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String getDescription() { |
||||||
|
if (fullDescription == null) { |
||||||
|
if (description == null || isExtensionListInDescription()) { |
||||||
|
fullDescription = description == null ? "(" : description + " ("; |
||||||
|
// build the description from the extension list
|
||||||
|
Enumeration extensions = filters.keys(); |
||||||
|
if (extensions != null) { |
||||||
|
fullDescription += "." + extensions.nextElement(); |
||||||
|
while (extensions.hasMoreElements()) { |
||||||
|
fullDescription += ", ." + extensions.nextElement(); |
||||||
|
} |
||||||
|
} |
||||||
|
fullDescription += ")"; |
||||||
|
} else { |
||||||
|
fullDescription = description; |
||||||
|
} |
||||||
|
} |
||||||
|
return fullDescription; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the human readable description of this filter. For |
||||||
|
* example: filter.setDescription("Gif and JPG Images"); |
||||||
|
*/ |
||||||
|
public void setDescription(String description) { |
||||||
|
this.description = description; |
||||||
|
fullDescription = null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determines whether the extension list (.jpg, .gif, etc) should |
||||||
|
* show up in the human readable description. |
||||||
|
* <p/> |
||||||
|
* Only relevent if a description was provided in the constructor |
||||||
|
* or using setDescription(); |
||||||
|
*/ |
||||||
|
public void setExtensionListInDescription(boolean b) { |
||||||
|
useExtensionsInDescription = b; |
||||||
|
fullDescription = null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns whether the extension list (.jpg, .gif, etc) should |
||||||
|
* show up in the human readable description. |
||||||
|
* <p/> |
||||||
|
* Only relevent if a description was provided in the constructor |
||||||
|
* or using setDescription(); |
||||||
|
*/ |
||||||
|
public boolean isExtensionListInDescription() { |
||||||
|
return useExtensionsInDescription; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.fr.design.locale.impl; |
||||||
|
|
||||||
|
import com.fr.general.GeneralContext; |
||||||
|
import com.fr.general.locale.LocaleMark; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class ShowOnlineWidgetMark implements LocaleMark<Boolean> { |
||||||
|
private Map<Locale, Boolean> map = new HashMap<>(); |
||||||
|
|
||||||
|
public ShowOnlineWidgetMark() { |
||||||
|
map.put(Locale.CHINA, true); |
||||||
|
map.put(Locale.TAIWAN, true); |
||||||
|
map.put(Locale.US, false); |
||||||
|
map.put(Locale.KOREA, false); |
||||||
|
map.put(Locale.JAPAN, false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean getValue() { |
||||||
|
Boolean result = map.get(GeneralContext.getLocale()); |
||||||
|
return result == null ? false : result; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue