Browse Source

Merge remote-tracking branch 'origin/feature/x' into feature/x

research/11.0
pengda 3 years ago
parent
commit
7fe462a7c9
  1. 88
      designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java
  2. 74
      designer-base/src/main/java/com/fr/design/formula/FormulaPane.java
  3. 3
      designer-base/src/main/java/com/fr/design/gui/chart/ChartEditPaneProvider.java
  4. 5
      designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java
  5. 41
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  6. 1
      designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java
  7. 10
      designer-base/src/main/java/com/fr/design/mainframe/OpenFailedPane.java
  8. 90
      designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java
  9. 24
      designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java
  10. 176
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/Guide.java
  11. 51
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideBuilder.java
  12. 55
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideGroup.java
  13. 32
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycle.java
  14. 28
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycleAdaptor.java
  15. 109
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideManager.java
  16. 29
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideVersion.java
  17. 124
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideView.java
  18. 155
      designer-base/src/main/java/com/fr/design/mainframe/guide/collect/GuideCollector.java
  19. 481
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/AbstractGuideScene.java
  20. 101
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/ClickScene.java
  21. 37
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DisplayScene.java
  22. 63
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DragScene.java
  23. 18
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideScene.java
  24. 20
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycle.java
  25. 18
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycleAdaptor.java
  26. 5
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/SceneFilter.java
  27. 60
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/drag/DragAndDropDragGestureListener.java
  28. 97
      designer-base/src/main/java/com/fr/design/mainframe/guide/tip/BubbleTip.java
  29. 14
      designer-base/src/main/java/com/fr/design/mainframe/guide/tip/GuideTip.java
  30. 74
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHint.java
  31. 47
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHintDialog.java
  32. 78
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/ExpandPane.java
  33. 117
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideCompleteDialog.java
  34. 233
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideManageDialog.java
  35. 152
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/Bubble.java
  36. 255
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/BubbleWithClose.java
  37. 98
      designer-base/src/main/java/com/fr/design/mainframe/guide/utils/ScreenImage.java
  38. 1
      designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java
  39. 5
      designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java
  40. 4
      designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java
  41. 67
      designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java
  42. 44
      designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java
  43. 4
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java
  44. 228
      designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java
  45. 51
      designer-base/src/main/java/com/fr/design/report/fit/CptFitAttrModel.java
  46. 44
      designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java
  47. 53
      designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java
  48. 10
      designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java
  49. 104
      designer-base/src/main/java/com/fr/design/report/fit/menupane/TemplateFitAttrPane.java
  50. 18
      designer-base/src/main/java/com/fr/design/report/fit/provider/AbstractFitAttrModelProvider.java
  51. 11
      designer-base/src/main/java/com/fr/design/report/fit/provider/FitAttrModelProvider.java
  52. 22
      designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java
  53. 60
      designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java
  54. 26
      designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java
  55. 8
      designer-base/src/main/java/com/fr/design/write/submit/CustomJobPane.java
  56. 10
      designer-base/src/main/java/com/fr/file/FILEChooserPane.java
  57. 2
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java
  58. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_down.png
  59. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_right.png
  60. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/close.png
  61. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_all.png
  62. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_none.png
  63. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_some.png
  64. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/guide.png
  65. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/success.png
  66. 2
      designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java
  67. 4
      designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java
  68. 7
      designer-chart/src/main/java/com/fr/van/chart/drillmap/designer/other/VanChartDrillMapInteractivePane.java
  69. 6
      designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java
  70. 8
      designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java
  71. 15
      designer-form/src/main/java/com/fr/design/designer/beans/models/NewFormModel.java
  72. 18
      designer-form/src/main/java/com/fr/design/designer/creator/XCreatorUtils.java
  73. 1
      designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java
  74. 551
      designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java
  75. 15
      designer-form/src/main/java/com/fr/design/mainframe/FormArea.java
  76. 18
      designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java
  77. 4
      designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java
  78. 11
      designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java
  79. 11
      designer-form/src/main/java/com/fr/design/mainframe/JForm.java
  80. 17
      designer-form/src/main/java/com/fr/design/mainframe/share/AbstractWidgetSelectPane.java
  81. 153
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/DownloadSuitableThemeAction.java
  82. 41
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java
  83. 15
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/base/AbstractWidgetPopupPreviewPane.java
  84. 14
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/base/LocalWidgetPopupPreviewPane.java
  85. 36
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/AbstractOnlineWidgetBlock.java
  86. 28
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java
  87. 3
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java
  88. 3
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetPackageBlock.java
  89. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java
  90. 9
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetSelectPane.java
  91. 212
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java
  92. 8
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetSelectPane.java
  93. 4
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackageSelectPane.java
  94. 5
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java
  95. 42
      designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java
  96. 22
      designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallComponentHelper.java
  97. 2
      designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java
  98. 99
      designer-form/src/main/java/com/fr/design/widget/ui/designer/NewFormPane.java
  99. 2
      designer-form/src/main/java/com/fr/design/widget/ui/designer/PredefinedLayoutPane.java
  100. 6
      designer-form/src/main/resources/com/fr/design/form/layouts/config.json
  101. Some files were not shown because too many files have changed in this diff Show More

88
designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java

@ -0,0 +1,88 @@
package com.fr.design.formula;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
import com.fr.parser.FRLexer;
import com.fr.parser.FRParser;
import com.fr.script.checker.FunctionCheckerDispatcher;
import com.fr.script.checker.exception.ConditionCheckWrongException;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.rules.FunctionParameterType;
import com.fr.script.rules.FunctionRule;
import com.fr.stable.StringUtils;
import com.fr.stable.script.Expression;
import com.fr.stable.script.Node;
import java.io.StringReader;
import java.util.List;
/**
* @author Hoky
* @date 2021/9/28
*/
public class FormulaChecker {
private static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
private static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
public static final String COLON = ":";
public static String check(String formulaText) {
StringReader in = new StringReader(formulaText);
FRLexer lexer = new FRLexer(in);
FRParser parser = new FRParser(lexer);
try {
Expression expression = parser.parse();
Node node = expression.getConditionalExpression();
return FunctionCheckerDispatcher.getInstance()
.getFunctionChecker(node)
.checkFunction(node) ? VALID_FORMULA : INVALID_FORMULA;
} catch (ConditionCheckWrongException cce) {
String functionName = cce.getFunctionName();
return functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + COLON;
} catch (FunctionCheckWrongException ce) {
List<FunctionRule> rules = ce.getRules();
String functionName = ce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + COLON);
for (int i = 0; i < rules.size(); i++) {
errorMsg.append("(");
if (rules.get(i).getParameterList().isEmpty()) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param"));
}
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) {
errorMsg.append(getTypeString(functionParameterType)).append(",");
}
if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) {
errorMsg.deleteCharAt(errorMsg.length() - 1);
}
errorMsg.append(")");
if (i != rules.size() - 1) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or"));
}
}
return errorMsg.toString();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return INVALID_FORMULA;
// alex:继续往下面走,expression为null时告知不合法公式
}
}
private static String getTypeString(FunctionParameterType type) {
switch (type) {
case NUMBER:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number");
case STRING:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String");
case ANY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any");
case DATE:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date");
case BOOLEAN:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean");
case ARRAY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array");
}
return StringUtils.EMPTY;
}
}

74
designer-base/src/main/java/com/fr/design/formula/FormulaPane.java

@ -38,18 +38,11 @@ import com.fr.log.FineLoggerFactory;
import com.fr.parser.ArrayExpression;
import com.fr.parser.BlockIntervalLiteral;
import com.fr.parser.ColumnRowRangeInPage;
import com.fr.parser.FRLexer;
import com.fr.parser.FRParser;
import com.fr.parser.NumberLiteral;
import com.fr.parser.SheetIntervalLiteral;
import com.fr.report.core.namespace.SimpleCellValueNameSpace;
import com.fr.script.Calculator;
import com.fr.script.ScriptConstants;
import com.fr.script.checker.FunctionCheckerDispatcher;
import com.fr.script.checker.exception.ConditionCheckWrongException;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.rules.FunctionParameterType;
import com.fr.script.rules.FunctionRule;
import com.fr.stable.EncodeConstants;
import com.fr.stable.EssentialUtils;
import com.fr.stable.ParameterProvider;
@ -657,7 +650,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
public void actionPerformed(ActionEvent evt) {
// Execute Formula default cell element.
String formulaText = formulaTextArea.getText().trim();
String formulaValidMessage = getFormulaValidMessage(formulaText);
String formulaValidMessage = FormulaChecker.check(formulaText);
FineJOptionPane.showMessageDialog(
FormulaPane.this,
formulaValidMessage + ".",
@ -666,73 +659,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
};
private static String getFormulaValidMessage(String formulaText) {
StringReader in = new StringReader(formulaText);
FRLexer lexer = new FRLexer(in);
FRParser parser = new FRParser(lexer);
try {
Expression expression = parser.parse();
Node node = expression.getConditionalExpression();
return FunctionCheckerDispatcher.getInstance()
.getFunctionChecker(node)
.checkFunction(node) ? VALID_FORMULA : INVALID_FORMULA;
} catch (ConditionCheckWrongException cce) {
String functionName = cce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + ":");
return errorMsg.toString();
} catch (FunctionCheckWrongException ce) {
List<FunctionRule> rules = ce.getRules();
String functionName = ce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + ":");
for (int i = 0; i < rules.size(); i++) {
errorMsg.append("(");
if (rules.get(i).getParameterList().isEmpty()) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param"));
}
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) {
errorMsg.append(getTypeString(functionParameterType)).append(",");
}
if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) {
errorMsg.deleteCharAt(errorMsg.length() - 1);
}
errorMsg.append(")");
if (i != rules.size() - 1) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or"));
}
}
return errorMsg.toString();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return INVALID_FORMULA;
// alex:继续往下面走,expression为null时告知不合法公式
}
}
private static String getTypeString(FunctionParameterType type) {
switch (type) {
case NUMBER:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number");
case STRING:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String");
case ANY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any");
case DATE:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date");
case BOOLEAN:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean");
case ARRAY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array");
}
return "";
}
private final ActionListener calculateActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String formulaText = formulaTextArea.getText().trim();
String formulaValidMessage = getFormulaValidMessage(formulaText);
String formulaValidMessage = FormulaChecker.check(formulaText);
;
String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText);
if (unSupportFormula != null) {
FineJOptionPane.showMessageDialog(

3
designer-base/src/main/java/com/fr/design/gui/chart/ChartEditPaneProvider.java

@ -16,4 +16,7 @@ public interface ChartEditPaneProvider {
default void removeChartEditPaneActionListener(ChartEditPaneActionListener l) {
}
default void resetLastChartCollection() {
}
}

5
designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java

@ -92,7 +92,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
} else if (jt.isOpening()) {
showOpenStatus();
} else if (jt.isOpenFailed()) {
showOpenFailedCover();
showOpenFailedCover(jt.getTemplateOpenFailedTip());
} else {
hideCover();
}
@ -121,7 +121,8 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
layeredPane.moveToFront(loadingPane);
}
public void showOpenFailedCover() {
public void showOpenFailedCover(String text) {
failedPane.setFailedTip(text);
layeredPane.moveToFront(failedPane);
}

41
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -19,7 +19,6 @@ import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.TableDataSourceAction;
import com.fr.design.actions.edit.RedoAction;
import com.fr.design.actions.edit.UndoAction;
import com.fr.design.actions.file.BatchCompileAction;
import com.fr.design.actions.file.SaveAsTemplateAction;
import com.fr.design.actions.file.SaveTemplateAction;
import com.fr.design.actions.file.WebPreviewUtils;
@ -135,6 +134,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
private JComponent centerPane;
private DesignModelAdapter<T, ?> designModel;
private PreviewProvider previewType;
private String templateOpenFailedTip;
/**
* 统计模板制作耗时
*
@ -974,7 +975,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
} else if (DesignerMode.isAuthorityEditing()) {
return new ShortCut[]{new SaveTemplateAction(this), new UndoAction(this), new RedoAction(this)};
} else {
return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new BatchCompileAction(), new UndoAction(this), new RedoAction(this)};
return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new UndoAction(this), new RedoAction(this)};
}
}
@ -1130,35 +1131,49 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
/**
* 判断是否是新版设计器
*
* @param showTipPane 是否需要展示弹窗
* @return 是返回true
*/
public boolean isNewDesigner() {
public boolean isNewDesigner(boolean showTipPane) {
String xmlDesignerVersion = getTarget().getXMLDesignerVersion();
if (isLowerThanHBB(xmlDesignerVersion)) {
String info = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open-New_Form_Tip");
String moreInfo = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Server_Version_Tip_More_Info");
new InformationWarnPane(info, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).show();
if (showTipPane) {
new InformationWarnPane(info, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).show();
}
return true;
}
return false;
}
public boolean isNewDesigner() {
return isNewDesigner(true);
}
/**
* 是否是就版本设计器
*
* @param showTipPane 是否需要展示弹窗
* @return 是就返回true
*/
public boolean isOldDesigner() {
public boolean isOldDesigner(boolean showTipPane) {
String xmlDesignerVersion = getTarget().getXMLDesignerVersion();
if (isHigherThanCurrent(xmlDesignerVersion)) {
String infor = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Template_Version_Not_Match", DesignUtils.parseVersion(xmlDesignerVersion));
String moreInfo = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Server_Version_Tip_More_Info");
new InformationWarnPane(infor, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).show();
if (showTipPane) {
new InformationWarnPane(infor, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).show();
}
return true;
}
return false;
}
public boolean isOldDesigner() {
return isOldDesigner(true);
}
/**
*
*/
@ -1411,9 +1426,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
* @return 按钮组
*/
public UIButton[] createExtraButtons() {
UIButton[] uiButtons = new UIButton[]{
(UIButton) new CompileAction().createToolBarComponent()
};
UIButton[] uiButtons = new UIButton[0];
Set<DesignerFrameUpButtonProvider> providers = ExtraDesignClassManager.getInstance().getArray(DesignerFrameUpButtonProvider.XML_TAG);
for (DesignerFrameUpButtonProvider provider : providers) {
uiButtons = ArrayUtils.addAll(uiButtons, provider.getUpButtons(getMenuState()));
@ -1439,6 +1452,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
};
button.setToolTipText(getTemplateTheme().getName());
button.setText(getTemplateTheme().getName());
button.setName(getTemplateTheme().getName());
button.setAlignmentX(SwingConstants.LEFT);
button.set4ToolbarButton();
button.setEnabled(true);
@ -1779,6 +1793,15 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
themeAttrMark.setDark(theme.isDark());
}
public String getTemplateOpenFailedTip() {
return templateOpenFailedTip;
}
public void setTemplateOpenFailedTip(String templateOpenFailedTip) {
this.templateOpenFailedTip = templateOpenFailedTip;
}
}
@Override
public void setTemplateTheme(TemplateTheme newTheme, TemplateThemeCompatible compatible) {
ThemedTemplate.super.setTemplateTheme(newTheme, compatible);

1
designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java

@ -116,6 +116,7 @@ public class NorthRegionContainerPane extends JPanel {
if (!DesignerEnvManager.getEnvManager().getAlphaFineConfigManager().isEnabled()) {
ad.createAlphaFinePane().setVisible(false);
}
northEastPane.add(ad.createGuideEntryPane());
northEastPane.add(ad.createNotificationCenterPane());
OSSupportCenter.buildAction(new OSBasedAction() {

10
designer-base/src/main/java/com/fr/design/mainframe/OpenFailedPane.java

@ -24,6 +24,7 @@ public class OpenFailedPane extends JPanel {
private UILabel label;
private MessageWithLink link;
private String defaultFailedText;
public OpenFailedPane() {
this.setLayout(new LayoutManager() {
@ -83,11 +84,18 @@ public class OpenFailedPane extends JPanel {
});
}
};
this.defaultFailedText = link.getText();
link.setBackground(Color.WHITE);
this.add(label);
this.add(link);
}
public void setFailedTip(String text) {
if (StringUtils.isEmpty(text)) {
this.link.setText(defaultFailedText);
} else {
this.link.setText(text);
}
}
}

90
designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java

@ -1,27 +1,97 @@
package com.fr.design.mainframe.authority;
import com.fr.base.Formula;
import com.fr.general.ComparatorUtils;
import com.fr.parser.FunctionCall;
import com.fr.parser.StringLiteral;
import com.fr.script.Calculator;
import com.fr.stable.script.Node;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FormulaAuthorityChecker extends ElementAuthorityChecker<Formula> {
private static final Pattern FORMULA_PATTERN = Pattern.compile("^=SQL\\(\"(.+?)\",");
private static final Set<FormulaParser> CONNECTION_NAME_FORMULA_PARSER = new HashSet<>();
private static final Set<FormulaParser> DATASET_NAME_FORMULA_PARSER = new HashSet<>();
static {
CONNECTION_NAME_FORMULA_PARSER.add(new FormulaParser("SQL", 0));
DATASET_NAME_FORMULA_PARSER.add(new FormulaParser("VALUE", 0));
}
@Override
@Nullable
public Set<String> getNoAuthConnectionNames(Formula formula, Set<String> authConnectionNames) {
String content = formula.getContent();
Matcher matcher = FORMULA_PATTERN.matcher(content);
if (matcher.find()) {
if (!authConnectionNames.contains(matcher.group(1))) {
return new HashSet<>(Arrays.asList(matcher.group(1)));
return getNoAuthNames(formula, CONNECTION_NAME_FORMULA_PARSER, authConnectionNames);
}
@Override
@Nullable
Set<String> getNoAuthDatasetNames(Formula formula, Set<String> authDatasetNames) {
return getNoAuthNames(formula, DATASET_NAME_FORMULA_PARSER, authDatasetNames);
}
private Set<String> getNoAuthNames(Formula formula, Set<FormulaParser> formulaParsers, Set<String> authNames) {
Set<String> noAuthNames = new HashSet<>();
try {
FunctionCall functionCall = (FunctionCall) Calculator.createCalculator().parse(formula.getContent()).getConditionalExpression();
handleNoAuthNames(functionCall, formulaParsers, authNames, noAuthNames);
} catch (Exception ignore) {
} finally {
return noAuthNames;
}
}
private void handleNoAuthNames(FunctionCall functionCall, Set<FormulaParser> formulaParsers, Set<String> authNames, Set<String> noAuthNames) {
for (FormulaParser formulaPattern : formulaParsers) {
String noAuthName = formulaPattern.getNoAuthName(functionCall, authNames);
if (noAuthName != null) {
noAuthNames.add(noAuthName);
}
}
return null;
Node[] nodes = functionCall.getArguments();
if (nodes != null) {
for (int i = 0; i < nodes.length; i++) {
Node node = nodes[i];
if (node instanceof FunctionCall) {
handleNoAuthNames((FunctionCall) node, formulaParsers, authNames, noAuthNames);
}
}
}
}
static class FormulaParser {
//函数的名称
public String name;
//要检测的位置
public int index;
FormulaParser(String name, int index) {
this.name = name;
this.index = index;
}
String getNoAuthName(FunctionCall functionCall, Set<String> authNames) {
if (functionCall.getName() != null && ComparatorUtils.equals(functionCall.getName().toUpperCase(), name)) {
Node node = functionCall.getArguments()[index];
if (node instanceof StringLiteral) {
String stringLiteral = node.toString();
if (stringLiteral.length() > 2) {
String value = stringLiteral.substring(1, stringLiteral.length() - 1);
if (!authNames.contains(value)) {
return value;
}
}
}
}
return null;
}
}
}

24
designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java

@ -7,11 +7,11 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mod.ModClassFilter;
import com.fr.file.ConnectionConfig;
import com.fr.file.TableDataConfig;
import com.fr.invoke.ClassHelper;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
import com.fr.rpc.RPCInvokerExceptionInfo;
import com.fr.stable.Filter;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.authority.user.UserAuthority;
@ -19,7 +19,6 @@ import com.fr.workspace.server.authority.user.UserAuthority;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@ -29,7 +28,9 @@ import static javax.swing.JOptionPane.WARNING_MESSAGE;
public class JTemplateAuthorityChecker {
JTemplate<?, ?> jTemplate;
Set<String> allConnectionNames;
Set<String> authConnectionNames;
Set<String> allDatasetNames;
Set<String> authDatasetNames;
Map<String, ElementAuthorityChecker> checkerMap = new HashMap<>();
Set<String> authFailConnectionNames = new HashSet<>();
@ -45,18 +46,20 @@ public class JTemplateAuthorityChecker {
}
private void initAuthNames() {
allDatasetNames = new HashSet<>();
for (String authServerDataSetName : TableDataConfig.getInstance().getTableDatas().keySet()) {
allDatasetNames.add(authServerDataSetName);
}
allConnectionNames = ConnectionConfig.getInstance().getConnections().keySet();
UserAuthority templateAuthority = WorkContext.getCurrent().get(UserAuthority.class);
Map<String, Set<String>> authNamesMap = templateAuthority.getAuthServerDataSetAndConnectionNames();
if (authNamesMap != null) {
//有权限的数据连接名称
authConnectionNames = authNamesMap.get(UserAuthority.AUTH_CONNECTION_NAMES);
//有权限的数据集名称(模板数据集和服务器数据集)
//有权限的数据集名称
authDatasetNames = authNamesMap.get(UserAuthority.AUTH_SERVER_DATASET_NAMES);
Iterator<String> iterator = jTemplate.getTarget().getTableDataNameIterator();
while (iterator.hasNext()) {
String datasetName = iterator.next();
authDatasetNames.add(datasetName);
}
}
}
@ -95,7 +98,8 @@ public class JTemplateAuthorityChecker {
}
}
}
authFailConnectionNames.retainAll(allConnectionNames);
authFailDatasetNames.retainAll(allDatasetNames);
FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker check time consume:" + (System.currentTimeMillis() - s));
return authFailConnectionNames.size() == 0 && authFailDatasetNames.size() == 0;
}

176
designer-base/src/main/java/com/fr/design/mainframe/guide/base/Guide.java

@ -0,0 +1,176 @@
package com.fr.design.mainframe.guide.base;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import com.fr.design.mainframe.guide.scene.GuideScene;
import com.fr.design.mainframe.guide.ui.GuideCompleteDialog;
import com.fr.design.mainframe.guide.ui.GuideManageDialog;
import com.fr.stable.StringUtils;
import javax.swing.SwingUtilities;
public class Guide {
public enum GuideState {
NONE, DONE
}
private String id;
private String name;
private String description;
private String completeMessage;
private GuideState state;
private GuideView guideView;
private GuideLifecycle lifecycle;
private boolean isComplete;
private GuideScene scene;
public Guide() {
this(null, null, null);
}
public Guide(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
this.state = GuideState.NONE;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
if (StringUtils.isNotEmpty(description)) {
return description;
}
return name;
}
public String getCompleteMessage() {
return completeMessage;
}
public void setCompleteMessage(String completeMessage) {
this.completeMessage = completeMessage;
}
public GuideState getState() {
return state;
}
public void setState(GuideState state) {
this.state = state;
}
public void setGuideView(GuideView guideView) {
this.guideView = guideView;
}
public GuideView getGuideView() {
return guideView;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public boolean isComplete() {
return isComplete;
}
public void setScene(GuideScene scene) {
this.scene = scene;
}
public GuideScene getScene() {
return scene;
}
/**
* 开启引导流程
*/
public void go() {
// 同时只能启动一个引导
if (GuideManager.getInstance().getCurrentGuide() != null) {
return;
}
try {
if (lifecycle != null && !lifecycle.prepared()) {
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
start();
}
});
} catch (Exception e) {
e.printStackTrace();
end();
}
}
public void start() {
if (scene != null) {
guideView.setScene(scene);
guideView.showGuide();
GuideManager.getInstance().setCurrentGuide(this);
if (lifecycle != null) {
lifecycle.onStart();
}
} else {
complete();
}
}
public void complete() {
if (lifecycle != null) {
lifecycle.onComplete();
}
setComplete(true);
GuideCollector.getInstance().saveInfo();
guideView.dismissGuide();
GuideCompleteDialog.getInstance().showDialog(getCompleteMessage());
end();
}
public void terminate() {
if (lifecycle != null) {
lifecycle.onTerminate();
}
end();
}
public void end() {
guideView.dismissGuide();
if (lifecycle != null) {
lifecycle.onEnd();
}
GuideManager.getInstance().setCurrentGuide(null);
GuideManageDialog.getInstance().showDialog();
}
public void registerLifecycle(GuideLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public void removeGuideLifecycle() {
this.lifecycle = null;
}
}

51
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideBuilder.java

@ -0,0 +1,51 @@
package com.fr.design.mainframe.guide.base;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.guide.scene.GuideScene;
public class GuideBuilder {
private Guide guide;
public static GuideBuilder newInstance() {
return new GuideBuilder();
}
public GuideBuilder() {
guide = new Guide();
guide.setGuideView(new GuideView(DesignerContext.getDesignerFrame(), guide));
}
public GuideBuilder setID(String id) {
guide.setId(id);
return this;
}
public GuideBuilder setName(String name) {
guide.setName(name);
return this;
}
public GuideBuilder setDescription(String description) {
guide.setDescription(description);
return this;
}
public GuideBuilder setCompleteMessage(String message) {
guide.setCompleteMessage(message);
return this;
}
public GuideBuilder addScene(GuideScene scene) {
guide.setScene(scene);
return this;
}
public GuideBuilder registerLifecycle(GuideLifecycle lifecycle) {
guide.registerLifecycle(lifecycle);
return this;
}
public Guide getGuide() {
return guide;
}
}

55
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideGroup.java

@ -0,0 +1,55 @@
package com.fr.design.mainframe.guide.base;
import java.util.ArrayList;
import java.util.List;
public class GuideGroup {
private List<Guide> guideList;
private String id;
private String name;
public GuideGroup(String id, String name) {
this.id = id;
this.name = name;
guideList = new ArrayList<>();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void addGuide(Guide guide) {
guideList.add(guide);
}
public List<Guide> getGuideList() {
return guideList;
}
public List<Guide> getCompleteGuideList() {
List<Guide> complete = new ArrayList<>();
for (Guide guide : getGuideList()) {
if (guide.isComplete()) {
complete.add(guide);
}
}
return complete;
}
public boolean isCompleteAll() {
return getCompleteGuideList().size() == getGuideList().size();
}
public boolean isCompleteSome() {
List<Guide> completeGuides = getCompleteGuideList();
return completeGuides.size() > 0 && completeGuides.size() < getGuideList().size();
}
}

32
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycle.java

@ -0,0 +1,32 @@
package com.fr.design.mainframe.guide.base;
public interface GuideLifecycle{
/**
* 准备环境
* @return 返回true引导可继续执行
*/
boolean prepared();
/**
* 开始引导教程
*/
void onStart();
/**
* 完成引导教程
*/
void onComplete();
/**
* 终止引导教程
*/
void onTerminate();
/**
* 结束引导教程
*/
void onEnd();
}

28
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycleAdaptor.java

@ -0,0 +1,28 @@
package com.fr.design.mainframe.guide.base;
public abstract class GuideLifecycleAdaptor implements GuideLifecycle{
@Override
public boolean prepared() {
return true;
}
@Override
public void onStart() {
}
@Override
public void onComplete() {
}
@Override
public void onTerminate() {
}
@Override
public void onEnd() {
}
}

109
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideManager.java

@ -0,0 +1,109 @@
package com.fr.design.mainframe.guide.base;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class GuideManager {
private static GuideManager guideManager;
private Guide currentGuide;
private List<GuideVersion> guideVersionList;
public static GuideManager getInstance() {
if (guideManager == null) {
guideManager = new GuideManager();
}
return guideManager;
}
public GuideManager() {
guideVersionList = new ArrayList<>();
}
public Guide getCurrentGuide() {
return currentGuide;
}
public void setCurrentGuide(Guide currentGuide) {
this.currentGuide = currentGuide;
}
public void addGuideGroup(String version, GuideGroup guideGroup) {
GuideVersion guideVersion = getGuideVersion(version);
if (guideVersion == null) {
guideVersion = new GuideVersion(version);
guideVersionList.add(guideVersion);
}
guideVersion.addGuideGroup(guideGroup);
}
public void addGuide(String groupId, Guide guide) {
GuideGroup guideGroup = getGuideGroup(groupId);
if (guideGroup != null) {
guideGroup.addGuide(guide);
}
}
public List<GuideVersion> getGuideVersionList() {
return guideVersionList;
}
public List<Guide> getAllGuide() {
List<Guide> guideList = new ArrayList<>();
for (GuideVersion version : guideVersionList) {
for (GuideGroup group : version.getGuideGroupList()) {
for (Guide guide : group.getGuideList()) {
guideList.add(guide);
}
}
}
return guideList;
}
public GuideVersion getGuideVersion(String version) {
for (GuideVersion guideVersion : guideVersionList) {
if (StringUtils.equals(version, guideVersion.getVersion())) {
return guideVersion;
}
}
return null;
}
public GuideGroup getGuideGroup(String groupId) {
for (GuideVersion version : guideVersionList) {
for (GuideGroup group : version.getGuideGroupList()) {
if (StringUtils.equals(groupId, group.getId())) {
return group;
}
}
}
return null;
}
public Guide getGuide(String guideId) {
for (GuideVersion version : guideVersionList) {
for (GuideGroup group : version.getGuideGroupList()) {
for (Guide guide : group.getGuideList()) {
if (StringUtils.equals(guideId, guide.getId())) {
return guide;
}
}
}
}
return null;
}
public void completeAll() {
for (GuideVersion version : guideVersionList) {
for (GuideGroup group : version.getGuideGroupList()) {
for (Guide guide : group.getGuideList()) {
guide.setComplete(true);
}
}
}
GuideCollector.getInstance().saveInfo();
}
}

29
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideVersion.java

@ -0,0 +1,29 @@
package com.fr.design.mainframe.guide.base;
import java.util.ArrayList;
import java.util.List;
public class GuideVersion {
private String version;
private List<GuideGroup> guideGroupList;
public GuideVersion(String version) {
guideGroupList = new ArrayList<>();
this.version = version;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public List<GuideGroup> getGuideGroupList() {
return guideGroupList;
}
public void addGuideGroup(GuideGroup guideGroup) {
guideGroupList.add(guideGroup);
}
}

124
designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideView.java

@ -0,0 +1,124 @@
package com.fr.design.mainframe.guide.base;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.guide.scene.AbstractGuideScene;
import com.fr.design.mainframe.guide.scene.GuideScene;
import javax.swing.JDialog;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
public class GuideView extends JDialog {
private static GuideView guideView;
private Guide invoker;
private GuideScene scene;
private Color modalColor;
private float modalOpacity;
private Window window;
public static GuideView getInstance(Guide guide) {
if (guideView == null) {
guideView = new GuideView(DesignerContext.getDesignerFrame(), guide);
}
return guideView;
}
public GuideView(Window window) {
super(window);
this.setUndecorated(true);
this.window = window;
this.modalColor = Color.BLACK;
this.modalOpacity = 0.4f;
this.setPreferredSize(window.getSize());
this.setSize(window.getSize());
this.setLayout(FRGUIPaneFactory.createBorderLayout());
setBg();
}
private WindowFocusListener windowFocusListener = new WindowFocusListener() {
@Override
public void windowGainedFocus(WindowEvent e) {
requestFocus();
setLocationRelativeTo(window);
}
@Override
public void windowLostFocus(WindowEvent e) {
}
};
private ComponentListener componentListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
setLocationRelativeTo(window);
}
@Override
public void componentMoved(ComponentEvent e) {
setLocation(window.getLocation());
}
};
public GuideView(Window window, Guide guide) {
this(window);
this.invoker = guide;
}
public void setModalColor(Color color) {
modalColor = color;
setBg();
}
public void setModalOpacity(float opacity){
modalOpacity = opacity;
setBg();
}
private void setBg() {
Color newColor = new Color(modalColor.getRed(), modalColor.getGreen(), modalColor.getBlue(), (int) (255 * modalOpacity));
this.setBackground(newColor);
}
public void setScene(GuideScene scene) {
if (scene instanceof AbstractGuideScene) {
((AbstractGuideScene) scene).setContainer(this);
}
this.scene = scene;
}
public void showGuide() {
window.addComponentListener(componentListener);
window.addWindowFocusListener(windowFocusListener);
this.setLocationRelativeTo(window);
this.setSize(window.getSize());
this.setLocation(window.getLocation());
this.setVisible(true);
if (scene != null) {
scene.start();
} else {
GuideManager.getInstance().getCurrentGuide().complete();
}
}
public void dismissGuide() {
window.removeComponentListener(componentListener);
window.removeWindowFocusListener(windowFocusListener);
this.getLayeredPane().removeAll();
revalidate();
repaint();
setVisible(false);
}
@Override
public void paint(Graphics g) {
super.paint(g);
}
}

155
designer-base/src/main/java/com/fr/design/mainframe/guide/collect/GuideCollector.java

@ -0,0 +1,155 @@
package com.fr.design.mainframe.guide.collect;
import com.fr.base.io.XMLReadHelper;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.javax.xml.stream.XMLStreamException;
import com.fr.third.org.apache.commons.io.FileUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class GuideCollector implements XMLable {
private static final String ROOT_XML = "GuideCollector";
private static final String GUIDE_XML = "Guide";
private static final String FILE_NAME = "guide.info";
private static GuideCollector collector;
private boolean showHint;
private List<Guide> cacheGuides;
public static GuideCollector getInstance() {
if (collector == null) {
collector = new GuideCollector();
}
return collector;
}
public GuideCollector() {
cacheGuides = new ArrayList<>();
}
public boolean isShowHint() {
return showHint;
}
public void setShowHint(boolean showHint) {
this.showHint = showHint;
saveInfo();
}
public void load() {
for(Guide cacheGuide : cacheGuides) {
Guide guide = GuideManager.getInstance().getGuide(cacheGuide.getId());
if (guide != null) {
guide.setComplete(cacheGuide.isComplete());
}
}
}
public void saveInfo() {
cacheGuides = GuideManager.getInstance().getAllGuide();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLTools.writeOutputStreamXML(this, out);
out.flush();
out.close();
String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);
FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8);
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage());
}
}
private File getInfoFile() {
File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME));
try {
if (!file.exists()) {
file.createNewFile();
}
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
return file;
}
public void loadFromFile() {
if (!getInfoFile().exists()) {
return;
}
XMLableReader reader = null;
try (InputStream in = new FileInputStream(getInfoFile())) {
reader = XMLReadHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER);
if (reader == null) {
return;
}
reader.readXMLObject(this);
} catch (FileNotFoundException e) {
} catch (XMLStreamException | IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (XMLStreamException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
@Override
public void readXML(XMLableReader xmLableReader) {
String tagName = xmLableReader.getTagName();
if (tagName.equals(ROOT_XML)) {
showHint = xmLableReader.getAttrAsBoolean("showHint", false);
xmLableReader.readXMLObject(new XMLReadable() {
public void readXML(XMLableReader reader) {
String tagName = reader.getTagName();
if (tagName.equals(GUIDE_XML)) {
Guide guide = new Guide();
guide.setId(reader.getAttrAsString("id", null));
guide.setComplete(reader.getAttrAsBoolean("isComplete", false));
cacheGuides.add(guide);
}
}
});
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(ROOT_XML);
writer.attr("showHint", showHint);
for(Guide guide : GuideManager.getInstance().getAllGuide()) {
writer.startTAG(GUIDE_XML);
writer.attr("id", guide.getId());
writer.attr("isComplete", guide.isComplete());
writer.end();
}
writer.end();
}
@Override
public Object clone() throws CloneNotSupportedException {
return null;
}
}

481
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/AbstractGuideScene.java

@ -0,0 +1,481 @@
package com.fr.design.mainframe.guide.scene;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.base.GuideView;
import com.fr.design.mainframe.guide.utils.ScreenImage;
import com.fr.design.mainframe.guide.tip.BubbleTip;
import com.fr.design.mainframe.guide.tip.GuideTip;
import com.fr.stable.StringUtils;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractGuideScene extends JPanel implements GuideScene {
private static final int DEFAULT_ARROW_HEIGHT = 12;
private static final int DEFAULT_ARROW_WIDTH = 18;
private GuideScene nextScene;
private SceneFilter sceneFilter;
private GuideSceneLifecycle lifecycle;
private GuideView container;
private List<Component> targetList;
private List<Component> highlightList;
private Component nextButton;
private List<Point[]> pointsList;
public AbstractGuideScene() {
this.setLayout(null);
this.setOpaque(false);
targetList = new ArrayList<>();
highlightList = new ArrayList<>();
pointsList = new ArrayList<>();
}
/**
* 根据设计器上组件添加高亮区域视图
* JComponent 采用组件绘制方式
* Component 采用屏幕截图方式
* @param component 设计器组件对象
* @return
*/
public boolean addTarget(Component component) {
try {
if (component == null || container == null) {
return false;
}
Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane());
Rectangle rectangle = new Rectangle(point, component.getSize());
BufferedImage image;
if (component instanceof JComponent) {
JComponent jComponent = (JComponent) component;
image = ScreenImage.createImage(jComponent);
} else if (component instanceof Window) {
image = ScreenImage.createImage(component);
} else {
image = captureImage(component);
}
targetList.add(component);
highlightList.add(getTargetComponentWithImage(image, rectangle));
return true;
} catch (AWTException e) {
e.printStackTrace();
GuideManager.getInstance().getCurrentGuide().terminate();
return false;
}
}
/**
* 根据设计器上选定区域获取高亮视图采用截屏的方式
* @param rectangle 选定区域相对屏幕
* @return
*/
public boolean addTarget(Rectangle rectangle) {
try {
targetList.add(null);
BufferedImage image = captureImage(rectangle);
highlightList.add(getTargetComponentWithImage(image, rectangle));
return true;
} catch (AWTException e) {
e.printStackTrace();
GuideManager.getInstance().getCurrentGuide().terminate();
return false;
}
}
/**
* 根据设计器组件选定其中某个区域添加高亮视图
* @param component 设计器组件
* @param origin 相对组件的区域
* @return
*/
public boolean addTarget(Component component, Rectangle origin) {
try {
if (component == null) {
return false;
}
Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane());
origin = origin.intersection(new Rectangle(0,0,component.getWidth(), component.getHeight()));
Rectangle rectangle = new Rectangle(point.x + origin.x, point.y + origin.y, origin.width, origin.height);
BufferedImage image;
if (component instanceof JComponent) {
JComponent jComponent = (JComponent) component;
image = ScreenImage.createImage(jComponent, origin);
} else {
image = ScreenImage.createImage(component).getSubimage(origin.x, origin.y, origin.width, origin.height);
}
targetList.add(component);
highlightList.add(getTargetComponentWithImage(image, rectangle));
return true;
} catch (AWTException e) {
e.printStackTrace();
GuideManager.getInstance().getCurrentGuide().terminate();
return false;
}
}
/**
* 添加自定义组件
* @param component 自定义组件
* @param rectangle 相对引导页的区域
* @return
*/
public boolean addCustomTarget(Component component, Rectangle rectangle) {
if (component == null) {
return false;
}
component.setBounds(rectangle);
targetList.add(component);
highlightList.add(component);
return true;
}
public boolean addCustomTarget(Component component, Point location) {
return addCustomTarget(component, new Rectangle(location, component.getPreferredSize()));
}
protected List<Component> getTargetList() {
return targetList;
}
public List<Component> getHighlightList() {
return highlightList;
}
private UILabel getTargetComponentWithImage(BufferedImage image, Rectangle rectangle) {
ImageIcon ic = new ImageIcon(image);
UILabel label = new UILabel(ic);
label.setOpaque(true);
label.setBounds(rectangle);
return label;
}
private BufferedImage captureImage(Rectangle rectangle) throws AWTException {
container.setVisible(false);
BufferedImage image = ScreenImage.createImage(rectangle);
showContainer();
return image;
}
private BufferedImage captureImage(Component component) throws AWTException {
container.setVisible(false);
BufferedImage image = ScreenImage.createImage(component);
showContainer();
return image;
}
private void showContainer() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
container.setVisible(true);
container.toFront();
container.requestFocus();
}
});
}
/**
* 自定义位置添加气泡提示组件
* @param title 提示标题
* @param content 提示内容
* @param direction 气泡窗口位置方向
* @param anchor 气泡窗口箭头坐标
* @param bubbleTailStart 气泡窗口箭头坐标相对于位置方向交叉轴的比例从左到右从上到下
*/
public void addBubbleTip(String title, String content, GuideTip.Direction direction, Point anchor, float bubbleTailStart) {
BubbleTip bt = new BubbleTip(title, content, direction, bubbleTailStart);
bt.setAnchor(anchor);
this.add(bt.getTip());
}
/**
* 以上一个添加的引导目标窗口为基础添加对应的气泡窗
* @param title 提示标题
* @param content 提示内容
* @param direction
* @param anchorStart
* @param bubbleTailStart
*/
public void addBubbleTip(String title, String content, GuideTip.Direction direction, float anchorStart, float bubbleTailStart) {
if (highlightList.size() == 0) {
return;
}
Component lastTarget = highlightList.get(highlightList.size() - 1);
Rectangle bounds = lastTarget.getBounds();
Point anchor = new Point(0,0);
if (direction == GuideTip.Direction.TOP) {
anchor = new Point(bounds.x + (int)(bounds.width * anchorStart), bounds.y);
} else if (direction == GuideTip.Direction.BOTTOM) {
anchor = new Point(bounds.x + (int)(bounds.width * anchorStart), bounds.y + bounds.height);
} else if (direction == GuideTip.Direction.LEFT) {
anchor = new Point(bounds.x, bounds.y + (int)(bounds.height * anchorStart));
} else if (direction == GuideTip.Direction.RIGHT) {
anchor = new Point(bounds.x + bounds.width, bounds.y + (int) (bounds.height * anchorStart));
}
addBubbleTip(title, content, direction, anchor, bubbleTailStart);
}
public void addBubbleTip(String title, String content, GuideTip.Direction direction) {
addBubbleTip(title, content, direction, 0.5f, 0.5f);
}
public void addBubbleTip(String title, GuideTip.Direction direction) {
addBubbleTip(title, StringUtils.EMPTY, direction);
}
public void addTip(GuideTip tip) {
this.add(tip.getTip());
}
public void addLineArrow(Point... points) {
pointsList.add(points);
}
public void setContainer(GuideView container) {
this.container = container;
}
public GuideView getContainer() {
return container;
}
@Override
public GuideScene nextScene(GuideScene scene) {
nextScene = scene;
return nextScene;
}
@Override
public void addSceneFilter(SceneFilter filter) {
sceneFilter = filter;
}
@Override
public void start() {
clear();
if (lifecycle != null && !lifecycle.prepared()) {
return;
}
showScene();
}
@Override
public void showScene() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (container != null) {
container.setContentPane(AbstractGuideScene.this);
setBounds(0, 0 , getSceneWidth(), getSceneWidth());
// show target
for (int index = highlightList.size() - 1; index >= 0; index--) {
add(highlightList.get(index));
}
// show next button
if (nextButton != null) {
nextButton.setBounds((getSceneWidth() - 60) / 2, getSceneHeight() - 100, 60, 30);
add(nextButton);
}
container.revalidate();
container.repaint();
}
showContainer();
if (lifecycle != null) {
lifecycle.onShow();
}
}
});
}
@Override
public void complete() {
container.getLayeredPane().remove(this);
container.repaint();
if (lifecycle != null) {
lifecycle.onComplete();
}
if (sceneFilter != null) {
nextScene = sceneFilter.getFilterScene();
}
if (nextScene != null) {
if (nextScene instanceof AbstractGuideScene) {
((AbstractGuideScene) nextScene).setContainer(container);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
nextScene.start();
}
});
} else {
GuideManager.getInstance().getCurrentGuide().complete();
}
}
@Override
public void registerLifecycle(GuideSceneLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
@Override
public void removeLifecycle() {
this.lifecycle = null;
}
public void showNextButton() {
UIButton nextButton = new UIButton("Next");
nextButton.setPreferredSize(new Dimension(60, 30));
nextButton.setOpaque(false);
nextButton.setFont(nextButton.getFont().deriveFont(20));
nextButton.setRoundBorder(true, 8);
nextButton.setForeground(Color.WHITE);
nextButton.setNormalPainted(false);
nextButton.setPressedPainted(false);
nextButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
complete();
}
});
this.nextButton = nextButton;
}
private int getSceneWidth() {
if (container == null) {
return 0;
}
return container.getLayeredPane().getWidth();
}
private int getSceneHeight() {
if (container == null) {
return 0;
}
return container.getLayeredPane().getHeight();
}
private void clear() {
targetList = new ArrayList<>();
highlightList = new ArrayList<>();
this.nextButton = null;
this.removeAll();
invalidate();
repaint();
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (pointsList.isEmpty()) {
return;
}
Graphics2D g2d = (Graphics2D) g;
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
g2d.setColor(Color.WHITE);
for (Point[] points : pointsList) {
if (points.length <= 1) {
continue;
}
Point startPoint = points[0];
Point endPoint = startPoint;
for (int index = 1; index < points.length; index++) {
startPoint = endPoint;
endPoint = points[index];
g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
}
drawArrow(g2d, startPoint, endPoint);
}
g2d.setComposite(oldComposite);
}
/**
* 根据最后两点坐标计算出三角箭头的三个点坐标绘制箭头
* 这里实现以终点坐标为坐标轴圆点计算
* @param start 起始点坐标
* @param end 重点坐标
*/
private void drawArrow(Graphics2D g2d, Point start, Point end) {
try{
double dealtPointX = start.x - end.x;
double dealtPointY = -(start.y - end.y);
double pointDistance = calDistance(dealtPointX, dealtPointY);
double triangleHeight = Math.min(DEFAULT_ARROW_HEIGHT, pointDistance);
double triangleWidth = triangleHeight * (DEFAULT_ARROW_WIDTH / 2) / DEFAULT_ARROW_WIDTH;
if (triangleHeight < 1 || triangleWidth < 1 || pointDistance < 1) {
return;
}
double pointAngle;
double abs = 1;
if (dealtPointX == 0) {
pointAngle = Math.PI / 2;
} else {
pointAngle = Math.atan(dealtPointY / dealtPointX);
}
if (dealtPointY < 0) {
pointAngle += Math.PI;
abs = -1;
}
double deltaAngle = Math.atan(triangleWidth / triangleHeight);
double triangleDistance = calDistance(triangleWidth, triangleHeight);
Point p1 =calPoint(end, triangleDistance, pointAngle - deltaAngle, abs);
Point p2 = calPoint(end, triangleDistance, pointAngle + deltaAngle, abs);
int xPoints[] = {end.x, p1.x, p2.x};
int yPoints[] = {end.y, p1.y, p2.y};
g2d.fillPolygon(xPoints, yPoints, 3);
} catch (Exception e) {
e.printStackTrace();
GuideManager.getInstance().getCurrentGuide().terminate();
}
}
private double calDistance(double x, double y) {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
private Point calPoint(Point relativePoint, double distance, double angle, double abs) {
int x = (int)(relativePoint.x + abs * distance * Math.cos(angle));
int y = (int)(relativePoint.y - abs * distance * Math.sin(angle));
return new Point(x, y);
}
}

101
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/ClickScene.java

@ -0,0 +1,101 @@
package com.fr.design.mainframe.guide.scene;
import com.fr.design.mainframe.guide.base.GuideManager;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class ClickScene extends AbstractGuideScene{
public enum ClickType {
LEFT, LEFT_DOUBLE, RIGHT
}
public void addClickTarget(Component component, ClickType clickType) {
addClickTarget(component, clickType, false);
}
public void addClickTarget(Component component, ClickType clickType, boolean isDispatch) {
if (super.addTarget(component)) {
addTargetClickListener(clickType, isDispatch);
}
}
public void addClickTarget(Rectangle rectangle, ClickType clickType) {
if (super.addTarget(rectangle)) {
addTargetClickListener(clickType,false);
}
}
public void addClickTarget(Component component, Rectangle rectangle, ClickType clickType) {
if (super.addTarget(component, rectangle)) {
addTargetClickListener(clickType, false);
}
}
public void addCustomClickTarget(Component component, Rectangle rectangle, ClickType clickType) {
if (super.addCustomTarget(component, rectangle)) {
addTargetClickListener(clickType, false);
}
}
public void addCustomClickTarget(Component component, Point location, ClickType clickType) {
if (super.addCustomTarget(component, location)) {
addTargetClickListener(clickType, false);
}
}
private void addTargetClickListener(ClickType clickType, boolean isDispatch) {
Component highlight = getHighlightList().get(getHighlightList().size() - 1);
Component target = getTargetList().get(getTargetList().size() - 1);
highlight.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if ((e.getClickCount() == 1 && clickType == ClickType.LEFT) || (e.getClickCount() == 2 && clickType == ClickType.LEFT_DOUBLE)) {
if (isDispatch) {
redispatchMouseEvent(e, target);
}
complete();
}
} else if (e.getButton() == MouseEvent.BUTTON3 && clickType == ClickType.RIGHT) {
if (isDispatch) {
redispatchMouseEvent(e, target);
}
complete();
}
}
@Override
public void mousePressed(MouseEvent e) {
if (isDispatch) {
redispatchMouseEvent(e, target);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (isDispatch) {
redispatchMouseEvent(e, target);
}
}
});
}
private void redispatchMouseEvent(MouseEvent e, Component component) {
component.dispatchEvent(new MouseEvent(component, e.getID(), e
.getWhen(), e.getModifiers(), e.getX(),
e.getY(), e.getClickCount(), e.isPopupTrigger()));
}
@Override
public void showScene() {
super.showScene();
// 交互类的 scene 如果没有高亮内容块载,需要及时终止Guide,否则就没法去掉模态框影响到设计器主功能的使用了
if (this.getComponentCount() == 0) {
GuideManager.getInstance().getCurrentGuide().terminate();
}
}
}

37
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DisplayScene.java

@ -0,0 +1,37 @@
package com.fr.design.mainframe.guide.scene;
import java.util.Timer;
import java.util.TimerTask;
public class DisplayScene extends AbstractGuideScene {
private long delay;
private static final long DEFAULT_DELAY = 1000;
private static Timer displayTimer = new Timer();
public DisplayScene() {
this(DEFAULT_DELAY);
}
public DisplayScene(long delay) {
super();
this.delay = delay;
}
public void setDelay(long delay) {
this.delay = delay;
}
@Override
public void showScene() {
super.showScene();
// 实例化Timer类
displayTimer.schedule(new TimerTask() {
@Override
public void run() {
complete();
displayTimer.purge();
}
}, delay);
}
}

63
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DragScene.java

@ -0,0 +1,63 @@
package com.fr.design.mainframe.guide.scene;
import com.fr.design.mainframe.guide.scene.drag.DragAndDropDragGestureListener;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
public class DragScene extends AbstractGuideScene{
public enum DragType{
NONE, FROM, TO
}
public void addDragTarget(Component component, DragType type) {
if (super.addTarget(component)) {
addDragTargetListener(type);
}
}
public void addDragTarget(Rectangle rectangle, DragType type) {
if (super.addTarget(rectangle)) {
addDragTargetListener(type);
}
}
public void addDragTarget(Component component, Rectangle rectangle, DragType type) {
if (super.addTarget(component, rectangle)) {
addDragTargetListener(type);
}
}
public void addCustomDragTarget(Component component, Rectangle rectangle, DragType type) {
if (super.addCustomTarget(component, rectangle)) {
addDragTargetListener(type);
}
}
private void addDragTargetListener(DragType dragType) {
Component target = getHighlightList().get(getHighlightList().size() - 1);
if (dragType == DragType.FROM) {
new DragAndDropDragGestureListener(target, DnDConstants.ACTION_COPY_OR_MOVE){
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {
complete();
}
};
} else if (dragType == DragType.TO) {
target.setDropTarget(new DropTarget());
}
}
private class DropSceneTarget extends DropTarget {
@Override
public synchronized void drop(DropTargetDropEvent dtde) {
super.drop(dtde);
complete();
}
}
}

18
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideScene.java

@ -0,0 +1,18 @@
package com.fr.design.mainframe.guide.scene;
public interface GuideScene {
GuideScene nextScene(GuideScene scene);
void addSceneFilter(SceneFilter filter);
void start();
void showScene();
void complete();
void registerLifecycle(GuideSceneLifecycle lifecycle);
void removeLifecycle();
}

20
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycle.java

@ -0,0 +1,20 @@
package com.fr.design.mainframe.guide.scene;
public interface GuideSceneLifecycle {
/**
* 引导场景准备工作
* scene 添加 target 应该在这个阶段处理
* @return
*/
boolean prepared();
/**
* scene 显示后
*/
void onShow();
/**
* scene 完成后
*/
void onComplete();
}

18
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycleAdaptor.java

@ -0,0 +1,18 @@
package com.fr.design.mainframe.guide.scene;
public abstract class GuideSceneLifecycleAdaptor implements GuideSceneLifecycle {
@Override
public boolean prepared() {
return true;
}
@Override
public void onShow() {
}
@Override
public void onComplete() {
}
}

5
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/SceneFilter.java

@ -0,0 +1,5 @@
package com.fr.design.mainframe.guide.scene;
public interface SceneFilter {
GuideScene getFilterScene();
}

60
designer-base/src/main/java/com/fr/design/mainframe/guide/scene/drag/DragAndDropDragGestureListener.java

@ -0,0 +1,60 @@
package com.fr.design.mainframe.guide.scene.drag;
import com.fr.general.ComparatorUtils;
import org.jetbrains.annotations.NotNull;
import java.awt.Component;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceAdapter;
public class DragAndDropDragGestureListener extends DragSourceAdapter implements DragGestureListener {
private Component component;
public DragAndDropDragGestureListener(Component component, int actions) {
this.component = component;
DragSource source = new DragSource();
source.createDefaultDragGestureRecognizer(component, actions, this);
}
public void dragGestureRecognized(DragGestureEvent dge) {
if (component != null) {
try {
DragAndDropTransferable dragAndDropTransferable = new DragAndDropTransferable(component);
dge.startDrag(DragSource.DefaultCopyDrop, dragAndDropTransferable, this);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class DragAndDropTransferable implements Transferable {
private Component component;
public DragAndDropTransferable(Component component) {
this.component = component;
}
DataFlavor[] flavors = {new DataFlavor(Component.class, "Component")};
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor df : flavors) {
if (ComparatorUtils.equals(df, flavor)) {
return true;
}
}
return false;
}
@NotNull
public Object getTransferData(DataFlavor df) {
return component;
}
}
}

97
designer-base/src/main/java/com/fr/design/mainframe/guide/tip/BubbleTip.java

@ -0,0 +1,97 @@
package com.fr.design.mainframe.guide.tip;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.ui.bubble.Bubble;
import com.fr.design.mainframe.guide.ui.bubble.BubbleWithClose;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class BubbleTip implements GuideTip {
private BubbleWithClose bubbleBox;
private Point anchor;
/**
*
* @param title 标题
* @param content 内容
* @param direction 气泡提示相对anchor的方向这里方向会和气泡组件箭头方向相反
* @param tailStart 气泡尾巴相对当前边垂直方向偏移位置比例值在0-1范围
*/
public BubbleTip(String title, String content, Direction direction, float tailStart) {
bubbleBox = new BubbleWithClose(title, content, getBubbleBoxTailDirection(direction), tailStart);
bubbleBox.addCloseActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Guide currentGuide = GuideManager.getInstance().getCurrentGuide();
if (currentGuide != null) {
int returnVal = FineJOptionPane.showConfirmDialog(
currentGuide.getGuideView(),
"确认退出当前教学引导?",
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (returnVal == JOptionPane.YES_OPTION) {
currentGuide.terminate();
}
}
}
});
}
@Override
public JComponent getTip() {
if(anchor == null) {
return new BubbleWithClose(bubbleBox.getTitle(), bubbleBox.getContent(), Bubble.TailDirection.TOP, 0);
} else {
setBubbleBoxBound();
return bubbleBox;
}
}
/**
* 设置锚点坐标
* 这里可以指定气泡组件箭头坐标的箭头坐标
* @param anchor
*/
public void setAnchor(Point anchor) {
this.anchor = anchor;
}
private void setBubbleBoxBound() {
int bubbleW = bubbleBox.getPreferredSize().width;
int bubbleH = bubbleBox.getPreferredSize().height;
if (bubbleBox.isTailHorizontal()) {
int x = bubbleBox.isTailLeft() ? anchor.x : anchor.x - bubbleW;
int y = anchor.y - (int) (bubbleH * bubbleBox.getTailStart());
bubbleBox.setBounds(x, y, bubbleW, bubbleH);
} else if (bubbleBox.isTailVertical()) {
int x = anchor.x - (int) (bubbleW * bubbleBox.getTailStart());
int y = bubbleBox.isTailTop() ? anchor.y : anchor.y - bubbleH;
bubbleBox.setBounds(x, y, bubbleW, bubbleH);
}
}
private Bubble.TailDirection getBubbleBoxTailDirection(Direction direction) {
switch (direction) {
case TOP:
return Bubble.TailDirection.BOTTOM;
case BOTTOM:
return Bubble.TailDirection.TOP;
case LEFT:
return Bubble.TailDirection.RIGHT;
case RIGHT:
default:
return Bubble.TailDirection.LEFT;
}
}
}

14
designer-base/src/main/java/com/fr/design/mainframe/guide/tip/GuideTip.java

@ -0,0 +1,14 @@
package com.fr.design.mainframe.guide.tip;
import javax.swing.JComponent;
import java.awt.Point;
public interface GuideTip {
enum Direction {
TOP, BOTTOM, LEFT, RIGHT
}
JComponent getTip();
void setAnchor(Point anchor);
}

74
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHint.java

@ -0,0 +1,74 @@
package com.fr.design.mainframe.guide.ui;
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.mainframe.guide.ui.bubble.Bubble;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionListener;
public class BubbleHint extends Bubble {
private UIButton confirmButton;
public BubbleHint() {
super(TailDirection.TOP, 0.9f);
initComponent();
}
private void initComponent() {
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createEmptyBorder(10 + Bubble.TAIL_HEIGHT, 15, 10, 15));
this.setPreferredSize(new Dimension(220, 140));
JPanel contentPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(false, VerticalFlowLayout.CENTER, 0, 0);
contentPane.setOpaque(false);
UILabel title = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Tips_Title"));
title.setFont(title.getFont().deriveFont(16.0f));
title.setForeground(new Color(62, 155, 249));
title.setPreferredSize(new Dimension(190, 30));
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
UILabel content1 = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Tips_Content1"));
content1.setPreferredSize(new Dimension(190,20));
content1.setHorizontalAlignment(SwingConstants.CENTER);
UILabel content2 = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Tips_Content2"));
content2.setPreferredSize(new Dimension(190,20));
content2.setHorizontalAlignment(SwingConstants.CENTER);
JPanel buttonContainer= FRGUIPaneFactory.createCenterFlowZeroGapBorderPane();
buttonContainer.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
buttonContainer.setPreferredSize(new Dimension(190,40));
buttonContainer.setOpaque(false);
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Guide_Tips_Know"));
confirmButton.setPreferredSize(new Dimension(78, 24));
buttonContainer.add(confirmButton);
contentPane.add(title);
contentPane.add(content1);
contentPane.add(content2);
contentPane.add(buttonContainer);
this.add(contentPane, BorderLayout.CENTER);
}
public void addConfirmAction(ActionListener listener) {
confirmButton.addActionListener(listener);
}
public void removeConfirmAction(ActionListener listener) {
confirmButton.removeActionListener(listener);
}
}

47
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHintDialog.java

@ -0,0 +1,47 @@
package com.fr.design.mainframe.guide.ui;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import javax.swing.JDialog;
import java.awt.Color;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class BubbleHintDialog extends JDialog {
private static final int DIALOG_WIDTH = 220;
private static final int DIALOG_HEIGHT = 140;
private static BubbleHintDialog dialog;
public static BubbleHintDialog getInstance(){
if (dialog == null) {
dialog = new BubbleHintDialog(DesignerContext.getDesignerFrame());
}
return dialog;
}
public BubbleHintDialog(Window parent) {
super(parent);
setUndecorated(true);
this.setBackground(new Color(0,0,0,0));
setSize(DIALOG_WIDTH, DIALOG_HEIGHT);
BubbleHint bubbleHint = new BubbleHint();
bubbleHint.addConfirmAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
dispose();
GuideCollector.getInstance().setShowHint(true);
}
});
this.setContentPane(bubbleHint);
}
public void showDialog(Point location) {
dialog.setLocation(location);
dialog.setVisible(true);
}
}

78
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/ExpandPane.java

@ -0,0 +1,78 @@
package com.fr.design.mainframe.guide.ui;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.general.IOUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class ExpandPane extends JPanel {
private static final Icon downIcon = IOUtils.readIcon("/com/fr/design/mainframe/guide/arrow_down.png");
private static final Icon rightIcon = IOUtils.readIcon("/com/fr/design/mainframe/guide/arrow_right.png");
private String title;
private boolean expand;
private UILabel arrow;
private JPanel headerPane;
private JPanel contentPane;
public ExpandPane(String title, JPanel contentPane) {
this.title = title;
this.expand = true;
this.contentPane = contentPane;
initComponent();
}
private void initComponent() {
VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5);
layout.setAlignLeft(true);
this.setLayout(layout);
JPanel headerPane = createHeader();
this.add(headerPane);
this.add(contentPane);
headerPane.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
setExpand(!expand);
}
});
}
private JPanel createHeader() {
headerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
headerPane.setPreferredSize(new Dimension(200, 24));
UILabel headerTitle = new UILabel(this.title);
headerTitle.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
arrow = new UILabel(downIcon);
arrow.setOpaque(false);
arrow.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
headerPane.add(headerTitle, BorderLayout.CENTER);
headerPane.add(arrow, BorderLayout.WEST);
return headerPane;
}
@Override
public void setPreferredSize(Dimension preferredSize) {
super.setPreferredSize(preferredSize);
headerPane.setPreferredSize(new Dimension(preferredSize.width, headerPane.getPreferredSize().height));
contentPane.setPreferredSize(new Dimension(preferredSize.width, contentPane.getPreferredSize().height));
}
public void setExpand(boolean isExpand) {
this.expand = isExpand;
arrow.setIcon(isExpand ? downIcon : rightIcon);
contentPane.setVisible(isExpand);
}
public boolean isExpand() {
return expand;
}
}

117
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideCompleteDialog.java

@ -0,0 +1,117 @@
package com.fr.design.mainframe.guide.ui;
import com.fr.design.gui.frpane.UITextPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.general.IOUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GuideCompleteDialog extends JDialog {
private static final int DIALOG_WIDTH = 340;
private static final int DIALOG_HEIGHT = 367;
private static final Icon SUCCESS_ICON = IOUtils.readIcon("/com/fr/design/mainframe/guide/success.png");
private static final int ICON_HEIGHT = 182;
private static final Color FONT_COLOR = new Color(51, 51, 52);
private static final Color BUTTON_BG_COLOR = new Color(65, 155,249);
private static GuideCompleteDialog dialog;
public static GuideCompleteDialog getInstance() {
if (dialog == null) {
dialog = new GuideCompleteDialog(DesignerContext.getDesignerFrame());
}
return dialog;
}
private UITextPane textArea;
public GuideCompleteDialog(Window window) {
super(window);
setSize(DIALOG_WIDTH, DIALOG_HEIGHT);
setUndecorated(true);
setModal(true);
setLocationRelativeTo(window);
this.setContentPane(getContentPane());
}
@Override
public Container getContentPane() {
JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel completeImage = new UILabel(SUCCESS_ICON);
completeImage.setPreferredSize(new Dimension(DIALOG_WIDTH, ICON_HEIGHT));
JPanel container = new JPanel(new BorderLayout(0, 10));
container.setBorder(BorderFactory.createEmptyBorder(0, 52, 25, 52));
UILabel title = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Complete_Confirm"));
title.setFont(title.getFont().deriveFont(22.0f));
title.setPreferredSize(new Dimension(190, 30));
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setForeground(FONT_COLOR);
textArea = new UITextPane();
textArea.setEnabled(false);
textArea.setOpaque(false);
textArea.setFont(textArea.getFont().deriveFont(18.0f));
textArea.setPreferredSize(new Dimension(236, 52));
textArea.setBorder(null);
textArea.setDisabledTextColor(FONT_COLOR);
StyledDocument doc = textArea.getStyledDocument();
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes(0, doc.getLength(), center, false);
JPanel buttonContainer= FRGUIPaneFactory.createCenterFlowZeroGapBorderPane();
buttonContainer.setPreferredSize(new Dimension(190,38));
buttonContainer.setOpaque(false);
JButton button = new JButton(Toolkit.i18nText("Fine-Design_Guide_Complete_End"));
button.setPreferredSize(new Dimension(122, 38));
button.setBackground(BUTTON_BG_COLOR);
button.setForeground(Color.WHITE);
button.setBorder(null);
button.setContentAreaFilled(false);
button.setOpaque(true);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
dispose();
}
});
buttonContainer.add(button);
container.add(title, BorderLayout.NORTH);
container.add(textArea, BorderLayout.CENTER);
container.add(buttonContainer,BorderLayout.SOUTH);
contentPane.add(completeImage, BorderLayout.NORTH);
contentPane.add(container, BorderLayout.CENTER);
return contentPane;
}
public void showDialog(String str) {
textArea.setText(str);
repaint();
this.setVisible(true);
}
}

233
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideManageDialog.java

@ -0,0 +1,233 @@
package com.fr.design.mainframe.guide.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
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.mainframe.DesignerContext;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideGroup;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.base.GuideVersion;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.IOUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.Border;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GuideManageDialog extends JDialog {
private static final int DEFAULT_HEIGHT = 400;
private static final int DEFAULT_WIDTH = 600;
private static final Icon GROUP_COMPLETE_NONE = IOUtils.readIcon("/com/fr/design/mainframe/guide/complete_none.png");
private static final Icon GROUP_COMPLETE_SOME = IOUtils.readIcon("/com/fr/design/mainframe/guide/complete_some.png");
private static final Icon GROUP_COMPLETE_ALL = IOUtils.readIcon("/com/fr/design/mainframe/guide/complete_all.png");
private static final Color BORDER_COLOR = new Color(224, 224, 225);
private static final Color UNCOMPLETE_FONT_COLOR = new Color(51, 51, 52);
private static final Color COMPLETE_FONT_COLOR = new Color(51,51,52,128);
private static GuideManageDialog dialog;
private JPanel scrollContent;
public static GuideManageDialog getInstance() {
if (dialog == null) {
dialog = new GuideManageDialog(DesignerContext.getDesignerFrame());
}
return dialog;
}
public GuideManageDialog(Window parent) {
super(parent);
GuideCollector.getInstance().load();
initComponent();
}
private void initComponent() {
this.setTitle(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Title"));
setResizable(false);
setModal(true);
setLayout(FRGUIPaneFactory.createBorderLayout());
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
GUICoreUtils.centerWindow(this);
JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
contentPane.add(createContentPanel(), BorderLayout.CENTER);
contentPane.add(createActionsPane(), BorderLayout.SOUTH);
setContentPane(contentPane);
}
private UIScrollPane createContentPanel() {
scrollContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 5);
UIScrollPane scrollPane = new UIScrollPane(scrollContent);
return scrollPane;
}
private JPanel createGuideVersionPane(GuideVersion guideVersion) {
JPanel expandContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 5);
for (GuideGroup guideGroup : guideVersion.getGuideGroupList()) {
JPanel guideGroupCard = createGuideGroupCard(guideGroup);
expandContent.add(guideGroupCard);
}
ExpandPane expandPane = new ExpandPane(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Version_Title", guideVersion.getVersion()), expandContent);
return expandPane;
}
private JPanel createGuideGroupCard(GuideGroup guideGroup) {
JPanel card = FRGUIPaneFactory.createBorderLayout_S_Pane();
card.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
card.setBackground(Color.WHITE);
JPanel cardContainer = FRGUIPaneFactory.createBorderLayout_S_Pane();
cardContainer.setOpaque(false);
cardContainer.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
card.add(cardContainer, BorderLayout.CENTER);
cardContainer.add(createGroupTitlePane(guideGroup), BorderLayout.NORTH);
cardContainer.add(createGroupContentPane(guideGroup), BorderLayout.CENTER);
return card;
}
private JPanel createGroupTitlePane(GuideGroup guideGroup) {
JPanel titleContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.CENTER, 0, 0);
titleContainer.setBorder(getBottomBorder());
titleContainer.setOpaque(false);
titleContainer.setPreferredSize(new Dimension(500, 40));
JPanel titlePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 8,0 );
titlePane.setOpaque(false);
UILabel iconLabel = new UILabel(getGroupStateIcon(guideGroup));
iconLabel.setPreferredSize(new Dimension(16, 16));
iconLabel.setOpaque(false);
UILabel titleLabel = new UILabel(guideGroup.getName());
titleLabel.setPreferredSize(new Dimension(200, 16));
titleLabel.setForeground(new Color(65, 155, 249));
titleLabel.setOpaque(false);
titlePane.add(iconLabel);
titlePane.add(titleLabel);
titleContainer.add(titlePane);
return titleContainer;
}
private JPanel createGroupContentPane(GuideGroup guideGroup) {
JPanel groupContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 0);
groupContainer.setBorder(BorderFactory.createEmptyBorder(0,10,0,0));
groupContainer.setOpaque(false);
for (int index = 0; index < guideGroup.getGuideList().size(); index++) {
JPanel guidePane = createGuidePane(guideGroup.getGuideList().get(index), index);
if (index != guideGroup.getGuideList().size() - 1) {
guidePane.setBorder(getBottomBorder());
}
groupContainer.add(guidePane);
}
return groupContainer;
}
private JPanel createGuidePane(Guide guide, int index) {
JPanel guidePaneContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.CENTER, 0, 0);
guidePaneContainer.setPreferredSize(new Dimension(540, 40));
guidePaneContainer.setOpaque(false);
JPanel guidePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 50,0 );
guidePane.setOpaque(false);
UILabel title = new UILabel((index + 1) + "、" + guide.getDescription());
title.setPreferredSize(new Dimension(440, 20));
title.setForeground(guide.isComplete() ? COMPLETE_FONT_COLOR : UNCOMPLETE_FONT_COLOR);
title.setOpaque(false);
UIButton button = new UIButton(guide.isComplete() ? Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Retry") : Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Show"));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
guide.go();
}
});
button.setPreferredSize(new Dimension(48, 20));
guidePane.add(title);
guidePane.add(button);
guidePaneContainer.add(guidePane);
return guidePaneContainer;
}
private Border getBottomBorder() {
return BorderFactory.createMatteBorder(
0,0,1, 0, BORDER_COLOR
);
}
public void showDialog() {
resetScrollContent();
this.setVisible(true);
}
private Icon getGroupStateIcon(GuideGroup guideGroup) {
if (guideGroup.isCompleteAll()) {
return GROUP_COMPLETE_ALL;
} else if (guideGroup.isCompleteSome()) {
return GROUP_COMPLETE_SOME;
} else {
return GROUP_COMPLETE_NONE;
}
}
private UIButton createCompleteAllButton() {
UIButton button = new UIButton(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Complete_All")));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
GuideManager.getInstance().completeAll();
resetScrollContent();
}
});
return button;
}
private UIButton createCloseButton() {
UIButton button = new UIButton(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Close")));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
return button;
}
private JPanel createActionsPane() {
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(BorderFactory.createEmptyBorder(7, 10, 7, 10));
container.add(createCompleteAllButton(), BorderLayout.WEST);
container.add(createCloseButton(), BorderLayout.EAST);
return container;
}
private void resetScrollContent() {
scrollContent.removeAll();
for (GuideVersion guideVersion : GuideManager.getInstance().getGuideVersionList()) {
scrollContent.add(createGuideVersionPane(guideVersion));
}
revalidate();
repaint();
}
}

152
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/Bubble.java

@ -0,0 +1,152 @@
package com.fr.design.mainframe.guide.ui.bubble;
import javax.swing.JComponent;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Bubble extends JComponent {
public enum TailDirection {
TOP, BOTTOM, LEFT, RIGHT
}
protected static final int TAIL_HEIGHT = 7;
protected static final int TAIL_WIDTH = 14;
protected static final int BUBBLE_WIDTH = 170;
protected static final Color BG_COLOR = new Color(240,240,241);
protected static final int BORDER_RADIUS = 10;
private TailDirection tailDirection;
private float tailStart;
public Bubble() {
this(TailDirection.LEFT, 0.5f);
}
public Bubble(TailDirection tailDirection, float tailStart) {
this.tailDirection = tailDirection;
this.tailStart = tailStart;
this.setOpaque(false);
}
public void setTailDirection(TailDirection tailDirection) {
this.tailDirection = tailDirection;
}
public TailDirection getTailDirection() {
return tailDirection;
}
public void setTailStart(float tailStart) {
this.tailStart = tailStart;
}
public float getTailStart() {
return tailStart;
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(getDefaultWidth(), getDefaultHeight());
}
protected int getDefaultWidth() {
return (isTailHorizontal() ? TAIL_HEIGHT : 0) + BUBBLE_WIDTH;
}
protected int getDefaultHeight() {
return (isTailVertical() ? TAIL_HEIGHT : 0);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Composite oldComposite = g2.getComposite();
paintBubbleBg(g2);
g2.setComposite(oldComposite);
super.paintComponent(g);
}
protected void paintBubbleBg(Graphics2D g2) {
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
paintRectBg(g2);
paintTailBg(g2);
}
protected void paintRectBg(Graphics2D g2) {
g2.setColor(BG_COLOR);
Rectangle bounds = getRectBounds();
g2.fillRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, BORDER_RADIUS, BORDER_RADIUS);
}
protected void paintTailBg(Graphics2D g2) {
int width = getWidth();
int height = getHeight();
if (isTailVertical()) {
int tailX = (int) (width * tailStart);
int startX = Math.max(tailX - TAIL_WIDTH / 2, 0);
int endX = startX + TAIL_WIDTH;
int[] xPoints = {startX, endX, tailX};
int[] yPoints = isTailTop() ? new int[]{TAIL_HEIGHT, TAIL_HEIGHT, 0} : new int[]{height - TAIL_HEIGHT, height - TAIL_HEIGHT, height};
g2.fillPolygon(xPoints, yPoints, 3);
} else if (isTailHorizontal()) {
int tailY = (int) (height * tailStart);
int startY = Math.max(tailY - TAIL_WIDTH / 2, 0);
int endY = startY + TAIL_WIDTH;
int[] xPoints = isTailLeft() ? new int[]{TAIL_HEIGHT, TAIL_HEIGHT, 0} : new int[]{width - TAIL_HEIGHT, width - TAIL_HEIGHT, width};
int[] yPoints = {startY, endY, tailY};
g2.fillPolygon(xPoints, yPoints, 3);
}
}
public Rectangle getRectBounds() {
int width = getWidth();
int height = getHeight();
switch (tailDirection) {
case TOP:
return new Rectangle(0, TAIL_HEIGHT, width, height - TAIL_HEIGHT);
case LEFT:
return new Rectangle(TAIL_HEIGHT, 0, width - TAIL_HEIGHT, height);
case RIGHT:
return new Rectangle(0, 0 , width - TAIL_HEIGHT, height);
case BOTTOM:
return new Rectangle(0, 0, width, height - TAIL_HEIGHT);
default:
return new Rectangle(0,0,0,0);
}
}
public boolean isTailHorizontal() {
return isTailLeft() || isTailRight();
}
public boolean isTailVertical() {
return isTailTop() || isTailBottom();
}
public boolean isTailLeft() {
return tailDirection == TailDirection.LEFT;
}
public boolean isTailRight() {
return tailDirection == TailDirection.RIGHT;
}
public boolean isTailTop() {
return tailDirection == TailDirection.TOP;
}
public boolean isTailBottom() {
return tailDirection == TailDirection.BOTTOM;
}
}

255
designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/BubbleWithClose.java

@ -0,0 +1,255 @@
package com.fr.design.mainframe.guide.ui.bubble;
import com.fr.base.GraphHelper;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.itextarea.UITextArea;
import com.fr.general.IOUtils;
import com.fr.stable.StringUtils;
import javax.swing.JTextArea;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
public class BubbleWithClose extends Bubble {
private static final Font FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 14);
private static final int HEADER_HEIGHT = 24;
private static final Color HEADER_COLOR = new Color(245, 245, 246);
private static final Color TITLE_COLOR = new Color(51, 51, 52);
private static final Color CONTENT_COLOR = new Color(51,51,52,128);
private static final Insets DEFAULT_INSET = new Insets(10, 15, 10, 15);
private String title;
private String content;
private UITextArea titleTextArea;
private UITextArea contentTextArea;
private UIButton closeButton;
public BubbleWithClose(String title, String content) {
this(title, content, TailDirection.LEFT, 0.5f);
}
public BubbleWithClose(String title, String content, TailDirection tailDirection, float tailStart) {
super(tailDirection, tailStart);
this.title = title;
this.content = content;
this.initComponent();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
protected void initComponent() {
this.setLayout(getLayoutManager());
createCloseButton();
createContentPane();
this.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
super.componentShown(e);
}
@Override
public void componentResized(ComponentEvent e) {
Rectangle rectBounds = getRectBounds();
Dimension buttonSize = closeButton.getPreferredSize();
closeButton.setBounds(getWidth() - 10 - buttonSize.width, rectBounds.y + (HEADER_HEIGHT - buttonSize.height) / 2, buttonSize.width, buttonSize.height);
Dimension titleSize = new Dimension(0,0);
Dimension contentSize = new Dimension(0, 0);
if (titleTextArea != null) {
titleSize = calTextSize(titleTextArea, getTextAreaMaxWidth());
int x = rectBounds.x + (rectBounds.width - getHorizontalInsets() - titleSize.width) / 2 + DEFAULT_INSET.left;
int y = rectBounds.y + HEADER_HEIGHT + DEFAULT_INSET.top;
titleTextArea.setBounds(x, y, titleSize.width, titleSize.height);
}
if (contentTextArea != null) {
contentSize = calTextSize(contentTextArea, getTextAreaMaxWidth());
int x = rectBounds.x + (rectBounds.width - getHorizontalInsets() - contentSize.width) / 2 + DEFAULT_INSET.left;
int y = rectBounds.y = HEADER_HEIGHT + DEFAULT_INSET.top + (titleSize.height == 0 ? 0 : titleSize.height + 10);
contentTextArea.setBounds(x,y, contentSize.width, contentSize.height);
}
setSize(getPreferredSize().width, getPreferredSize().height);
repaint();
}
});
}
private void createCloseButton() {
closeButton = new UIButton();
closeButton.setIcon(IOUtils.readIcon("/com/fr/design/mainframe/guide/close.png"));
closeButton.set4ToolbarButton();
closeButton.setPreferredSize(new Dimension(16, 16));
closeButton.setRolloverEnabled(false);
closeButton.setPressedPainted(false);
this.add(closeButton);
}
public void addCloseActionListener(ActionListener actionListener) {
closeButton.addActionListener(actionListener);
}
public void removeCloseActionListener(ActionListener actionListener){
closeButton.removeActionListener(actionListener);
}
private void createContentPane() {
createTitleTextArea();
createContentTextArea();
}
private void createTitleTextArea() {
if (StringUtils.isNotEmpty(title)) {
titleTextArea = createTextArea(title, FONT, TITLE_COLOR);
this.add(titleTextArea);
}
}
private void createContentTextArea() {
if (StringUtils.isNotEmpty(content)) {
contentTextArea = createTextArea(content, FONT, CONTENT_COLOR);
this.add(contentTextArea);
}
}
private UITextArea createTextArea(String str, Font font, Color foreground) {
UITextArea textArea= new UITextArea(str){
@Override
public Insets getInsets() {
return new Insets(0, 0, 0, 0);
}
};
textArea.setEnabled(true);
textArea.setBorder(null);
textArea.setFont(font);
textArea.setOpaque(false);
textArea.setForeground(foreground);
return textArea;
}
protected int getDefaultHeight() {
Dimension titleSize = calTextSize(titleTextArea, getDefaultTextAreaMaxWidth());
Dimension contentSize = calTextSize(contentTextArea, getDefaultTextAreaMaxWidth());
return (isTailVertical() ? TAIL_HEIGHT : 0) + HEADER_HEIGHT + titleSize.height + (titleSize.height == 0 ? 0 : 5) + contentSize.height + getVerticalInsets();
}
private LayoutManager getLayoutManager() {
return new LayoutManager() {
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return parent.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
}
};
}
@Override
protected void paintBubbleBg(Graphics2D g2) {
super.paintBubbleBg(g2);
paintHeaderBg(g2);
}
private void paintHeaderBg(Graphics2D g2) {
g2.setColor(HEADER_COLOR);
Rectangle bounds = getRectBounds();
g2.fillRoundRect(bounds.x, bounds.y, bounds.width, HEADER_HEIGHT, 10, 10);
}
private int countLines(JTextArea textArea, int max_width) {
AttributedString text = new AttributedString(textArea.getText());
text.addAttribute(TextAttribute.FONT, textArea.getFont());
FontRenderContext frc = textArea.getFontMetrics(textArea.getFont())
.getFontRenderContext();
AttributedCharacterIterator charIt = text.getIterator();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc);
lineMeasurer.setPosition(charIt.getBeginIndex());
int lines = 0;
while (lineMeasurer.getPosition() < charIt.getEndIndex()) {
lineMeasurer.nextLayout(max_width);
lines++;
}
return lines;
}
private Dimension calTextSize(JTextArea textArea, int maxWidth) {
if (textArea == null) {
return new Dimension(0, 0);
}
FontMetrics fontMetrics = GraphHelper.getFontMetrics(textArea.getFont());
int line = countLines(textArea, maxWidth);
int width = maxWidth;
if (line == 1) {
width = fontMetrics.stringWidth(textArea.getText());
}
int height = fontMetrics.getHeight() * line;
return new Dimension(width, height);
}
private int getTextAreaMaxWidth() {
return getWidth() - (isTailHorizontal() ? TAIL_HEIGHT : 0) -getHorizontalInsets();
}
private int getDefaultTextAreaMaxWidth() {
return BUBBLE_WIDTH - getHorizontalInsets();
}
private int getHorizontalInsets() {
return DEFAULT_INSET.left + DEFAULT_INSET.right;
}
private int getVerticalInsets() {
return DEFAULT_INSET.top + DEFAULT_INSET.bottom;
}
}

98
designer-base/src/main/java/com/fr/design/mainframe/guide/utils/ScreenImage.java

@ -0,0 +1,98 @@
package com.fr.design.mainframe.guide.utils;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
public class ScreenImage {
public static BufferedImage createImage(JComponent component) {
return ScreenImage.createImage(component, getRegion(component));
}
public static BufferedImage createImage(JComponent component, Rectangle region) {
if (! component.isDisplayable()) {
Dimension d = component.getSize();
if (d.width == 0 || d.height == 0) {
d = component.getPreferredSize();
component.setSize( d );
}
layoutComponent( component );
}
BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
if (! component.isOpaque()) {
g2d.setColor( component.getBackground() );
g2d.fillRect(region.x, region.y, region.width, region.height);
}
g2d.translate(-region.x, -region.y);
component.print( g2d );
g2d.dispose();
return image;
}
public static BufferedImage createImage(Component component)
throws AWTException {
Point p = new Point(0, 0);
SwingUtilities.convertPointToScreen(p, component);
Rectangle region = component.getBounds();
region.x = p.x;
region.y = p.y;
return ScreenImage.createImage(region);
}
public static BufferedImage createImageWithModal(JComponent component) {
Rectangle region = getRegion(component);
BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(createImage(component), 0, 0, null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, region.width, region.height);
g2d.dispose();
return image;
}
public static BufferedImage createImage(Rectangle region)
throws AWTException {
BufferedImage image = new Robot().createScreenCapture( region );
return image;
}
private static Rectangle getRegion(Component component) {
Dimension d = component.getSize();
if (d.width == 0 || d.height == 0) {
d = component.getPreferredSize();
component.setSize( d );
}
return new Rectangle(0, 0, d.width, d.height);
}
static void layoutComponent(Component component) {
synchronized (component.getTreeLock()) {
component.doLayout();
if (component instanceof Container) {
for (Component child : ((Container)component).getComponents()) {
layoutComponent(child);
}
}
}
}
}

1
designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java

@ -64,6 +64,7 @@ public class TemplateThemeBlock<T extends TemplateTheme> extends JPanel {
TemplateThemeConfig<T> config,
TemplateThemeProfilePane<T> profilePane) {
this.name = name;
this.setName(name);
this.displayTheme4NewTemplateMarker = displayTheme4NewTemplateMarker;
this.config = config;
this.profilePane = profilePane;

5
designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java

@ -25,8 +25,8 @@ import java.awt.event.ActionListener;
* @version 1.0
* Created by Starryi on 2021/8/13
*/
public class
TemplateThemeUsingDialog<T extends TemplateTheme> extends TemplateThemeDialog {
public class TemplateThemeUsingDialog<T extends TemplateTheme> extends TemplateThemeDialog {
public static final String COMPLETE_BUTTON = "theme_button_complete";
public static final int CONTENT_WIDTH = TemplateThemeListPane.CONTENT_WIDTH + 42;
public static final int CONTENT_HEIGHT = TemplateThemeListPane.CONTENT_HEIGHT + 23;
@ -94,6 +94,7 @@ TemplateThemeUsingDialog<T extends TemplateTheme> extends TemplateThemeDialog {
private UIButton createCompleteButton() {
UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Complete"));
button.setName(COMPLETE_BUTTON);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {

4
designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java

@ -65,7 +65,7 @@ public class FormThemePreviewPane extends TemplateThemePreviewPane<FormTheme> {
}
};
columnChartPanel.setLayout(new BorderLayout());
columnChartPreviewPane = createChartPreviewPane(initColumnChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Column_Title"));
columnChartPreviewPane = createChartPreviewPane(initColumnChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Comp_Title1"));
columnChartPanel.add(columnChartPreviewPane, BorderLayout.CENTER);
JPanel pieChartPanel = new UINoOpaquePanel() {
@ -74,7 +74,7 @@ public class FormThemePreviewPane extends TemplateThemePreviewPane<FormTheme> {
}
};
pieChartPanel.setLayout(new BorderLayout());
pieChartPreviewPane = createChartPreviewPane(initPieChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Pie_Title"));
pieChartPreviewPane = createChartPreviewPane(initPieChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Comp_Title2"));
pieChartPanel.add(pieChartPreviewPane, BorderLayout.CENTER);
chartContent.add(columnChartPanel, BorderLayout.CENTER);
chartContent.add(pieChartPanel, BorderLayout.EAST);

67
designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java

@ -2,20 +2,16 @@ package com.fr.design.mainframe.theme.preview.ecpreview;
import com.fr.base.theme.TemplateTheme;
import com.fr.base.theme.settings.ThemedCellStyleList;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.theme.preview.UINoOpaquePanel;
import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell;
import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell;
import com.fr.log.FineLoggerFactory;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
@ -25,70 +21,41 @@ import java.util.List;
* Created by Starryi on 2021/8/13
*/
public class ECPreviewPane extends AbstractECPreviewPane {
private static String csv =
"城市 当月目标 当月完成 月完成率 年完成率\n" +
"合肥市 248,938 348,938 140% 140%\n" +
"邵阳市 248,938 348,938 140% 140%\n" +
"合计 1,071,460 1,371,460 128% 128%";
private final List<String[]> DATA_LIST = createDataList();
private static final String BLANK_CHAR = " ";
private List<AbstractPreviewCell> headerCellList = new ArrayList<>();
private List<AbstractPreviewCell> contentCellList = new ArrayList<>();
private List<AbstractPreviewCell> hightLightCellList = new ArrayList<>();
private List<String[]> createDataList() {
List<String[]> data = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new StringReader(csv))) {
String textLine;
while ((textLine = reader.readLine()) != null) {
String[] texts = textLine.split(BLANK_CHAR);
data.add(texts);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return data;
}
private final List<AbstractPreviewCell> headerCellList = new ArrayList<>();
private final List<AbstractPreviewCell> contentCellList = new ArrayList<>();
private final List<AbstractPreviewCell> highLightCellList = new ArrayList<>();
private static final int COL_COUNT = 5;
private static final int CONTENT_ROW_COUNT = 2;
public ECPreviewPane() {
this.setPreferredSize(new Dimension(517, 147));
this.setBorder(BorderFactory.createEmptyBorder(0, 1, 2, 1));
this.setLayout(FRGUIPaneFactory.createBorderLayout());
String[] titleArr = DATA_LIST.get(0);
String[] endArr = DATA_LIST.get(DATA_LIST.size() - 1);
JPanel titlePane = new UINoOpaquePanel(new GridLayout());
this.add(titlePane, BorderLayout.NORTH);
for (String title : titleArr) {
PreviewCell cell = new PreviewCell(title);
for (int i = 0; i < COL_COUNT; i++) {
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header"));
cell.setPreferredSize(new Dimension(103, 36));
titlePane.add(cell);
headerCellList.add(cell);
}
JPanel contentPane = new UINoOpaquePanel(new GridLayout(2, 5, 0, 0));
this.add(contentPane, BorderLayout.CENTER);
for (int i = 1; i < DATA_LIST.size() - 1; i++) {
String[] textLine = DATA_LIST.get(i);
for (int j = 0; j < textLine.length; j++) {
String text = textLine[j];
PreviewCell cell = new PreviewCell(text);
cell.setPreferredSize(new Dimension(103, 33));
contentPane.add(cell);
contentCellList.add(cell);
}
for (int i = 0; i < COL_COUNT * CONTENT_ROW_COUNT; i++) {
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text"));
cell.setPreferredSize(new Dimension(103, 33));
contentPane.add(cell);
contentCellList.add(cell);
}
JPanel endPane = new UINoOpaquePanel(new GridLayout());
this.add(endPane, BorderLayout.SOUTH);
for (String text : endArr) {
PreviewCell cell = new PreviewCell(text);
for (int i = 0; i < COL_COUNT; i++) {
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text"));
cell.setPreferredSize(new Dimension(103, 33));
endPane.add(cell);
hightLightCellList.add(cell);
highLightCellList.add(cell);
}
}
@Override
@ -96,7 +63,7 @@ public class ECPreviewPane extends AbstractECPreviewPane {
ThemedCellStyleList cellStyleConfig = theme.getCellStyleList();
refresh(headerCellList, getReportHeaderStyle(cellStyleConfig));
refresh(contentCellList, getMainContentStyle(cellStyleConfig));
refresh(hightLightCellList, getHighLightStyle(cellStyleConfig));
refresh(highLightCellList, getHighLightStyle(cellStyleConfig));
}

44
designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java

@ -22,13 +22,15 @@ import java.util.ArrayList;
import java.util.List;
public class ECReportPreviewPane extends UINoOpaquePanel implements ThemePreviewed<ReportTheme> {
private List<AbstractPreviewCell> headerTitleCellList = new ArrayList<>();
private List<AbstractPreviewCell> headerCellList = new ArrayList<>();
private List<AbstractPreviewCell> titleCellList = new ArrayList<>();
private List<AbstractPreviewCell> contentCellList = new ArrayList<>();
private List<AbstractPreviewCell> highLightCellList = new ArrayList<>();
private final List<AbstractPreviewCell> headerTitleCellList = new ArrayList<>();
private final List<AbstractPreviewCell> headerCellList = new ArrayList<>();
private final List<AbstractPreviewCell> titleCellList = new ArrayList<>();
private final List<AbstractPreviewCell> contentCellList = new ArrayList<>();
private final List<AbstractPreviewCell> highLightCellList = new ArrayList<>();
private static final int CONTENT_ROW_COUNT = 3;
private static final int COL_COUNT = 5;
private PreviewPane previewPane;
private final PreviewPane previewPane;
public ECReportPreviewPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
@ -58,26 +60,26 @@ public class ECReportPreviewPane extends UINoOpaquePanel implements ThemePreview
private JPanel createNorthPane() {
JPanel northPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane();
AbstractPreviewCell bigTitleCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Big_Title"));
AbstractPreviewCell bigTitleCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Cell_Style_Big_Title"));
bigTitleCell.setPreferredSize(new Dimension(615, 46));
headerTitleCellList.add(bigTitleCell);
northPane.add(bigTitleCell, BorderLayout.NORTH);
CornerPreviewCell cornerCell = new CornerPreviewCell(new String[]{Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Product"),
Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Data"), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Statistical_Dimension")},
CornerPreviewCell cornerCell = new CornerPreviewCell(new String[]{Toolkit.i18nText("Fine-Design_Basic_Column_Name"),
Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Data"), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Row_Name")},
new Point2D[]{new Point(159, 71), new Point(225, 49)});
cornerCell.setPreferredSize(new Dimension(225, 71));
headerCellList.add(cornerCell);
northPane.add(cornerCell, BorderLayout.WEST);
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane();
northPane.add(centerPane, BorderLayout.CENTER);
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Statistical_By_Area"));
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Small_Title"));
titleCellList.add(cell);
cell.setPreferredSize(new Dimension(308, 38));
centerPane.add(cell, BorderLayout.NORTH);
JPanel eastSouthPane = new UINoOpaquePanel(new GridLayout());
PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_East_China"));
PreviewCell cell2 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_South_China"));
PreviewCell cell3 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Subtotal"));
PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header"));
PreviewCell cell2 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header"));
PreviewCell cell3 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header"));
headerCellList.add(cell1);
headerCellList.add(cell2);
headerCellList.add(cell3);
@ -92,13 +94,13 @@ public class ECReportPreviewPane extends UINoOpaquePanel implements ThemePreview
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane();
JPanel westPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane();
centerPane.add(westPane, BorderLayout.WEST);
PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Drink"));
PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Small_Title"));
titleCellList.add(cell1);
cell1.setPreferredSize(new Dimension(112, 153));
westPane.add(cell1, BorderLayout.WEST);
JPanel gridPane = new UINoOpaquePanel(new GridLayout(5, 1));
for (int i = 0; i < 5; i++) {
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Apple_Juice"));
for (int i = 0; i < COL_COUNT; i++) {
PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Header"));
cell.setPreferredSize(new Dimension(113, 31));
headerCellList.add(cell);
gridPane.add(cell);
@ -107,14 +109,16 @@ public class ECReportPreviewPane extends UINoOpaquePanel implements ThemePreview
JPanel innerCenterPane = new UINoOpaquePanel(new GridLayout(5, 3));
centerPane.add(innerCenterPane, BorderLayout.CENTER);
for (int i = 0; i < 15; i++) {
PreviewCell cell = new PreviewCell("35600");
cell.setPreferredSize(new Dimension(123, 31));
if ((i + 1) % 3 == 0) {
for (int i = 0; i < COL_COUNT * CONTENT_ROW_COUNT; i++) {
PreviewCell cell ;
if ((i + 1) % CONTENT_ROW_COUNT == 0) {
cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Highlight_Text"));
highLightCellList.add(cell);
} else {
cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Predefined_Style_Main_Text"));
contentCellList.add(cell);
}
cell.setPreferredSize(new Dimension(123, 31));
innerCenterPane.add(cell);
}

4
designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java

@ -469,6 +469,10 @@ public abstract class ToolBarMenuDock {
return new UILabel();
}
public Component createGuideEntryPane() {
return new UILabel();
}
public Component createNotificationCenterPane(){
return new UILabel();
}

228
designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java

@ -0,0 +1,228 @@
package com.fr.design.report.fit;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.report.fit.menupane.FitPreviewPane;
import com.fr.design.report.fit.menupane.FitRadioGroup;
import com.fr.design.report.fit.menupane.FontRadioGroup;
import com.fr.design.report.fit.provider.FitAttrModelProvider;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Set;
import java.util.stream.Collectors;
import static com.fr.design.i18n.Toolkit.i18nText;
public abstract class BaseFitAttrPane extends BasicBeanPane<ReportFitAttr> {
protected JPanel contentJPanel;
protected UIComboBox itemChoose;
protected java.util.List<FitAttrModel> fitAttrModelList = new ArrayList<>();
public FontRadioGroup fontRadioGroup;
public FitRadioGroup adaptRadioGroup;
public JPanel attrJPanel;
public FitPreviewPane previewJPanel;
public FitAttrModel fitAttrModel;
protected BaseFitAttrPane() {
initFitAttrModel();
}
private void initFitAttrModel() {
fitAttrModelList.add(new FrmFitAttrModel());
fitAttrModelList.add(new CptFitAttrModel());
Set<FitAttrModelProvider> fitAttrModelProviders = ExtraDesignClassManager.getInstance().getArray(FitAttrModelProvider.XML_TAG);
for (FitAttrModelProvider fitAttrModelProvider : fitAttrModelProviders) {
fitAttrModelList.add(fitAttrModelProvider);
}
fitAttrModelList = fitAttrModelList.stream().sorted(Comparator.comparing(FitAttrModel::getPriority).reversed()).collect(Collectors.toList());
}
protected void populateModel(FitAttrModel fitAttrModel) {
this.fitAttrModel = fitAttrModel;
if (attrJPanel != null) {
contentJPanel.remove(attrJPanel);
}
if (previewJPanel != null) {
contentJPanel.remove(previewJPanel);
}
fontRadioGroup = new FontRadioGroup();
adaptRadioGroup = new FitRadioGroup();
initAttrJPanel();
initPreviewJPanel();
}
protected void initAttrJPanel() {
int colCount = fitAttrModel.getFitTypes().length + 1;
Component[][] components = new Component[2][colCount];
initFitRadioGroup(fontRadioGroup, i18nText("Fine-Designer_Fit-Font"), new String[]{i18nText("Fine-Designer_Fit"), i18nText("Fine-Designer_Fit-No")}, components[0]);
initFitRadioGroup(adaptRadioGroup, fitAttrModel.getFitName(), Arrays.stream(fitAttrModel.getFitTypes()).map(FitType::description).toArray(String[]::new), components[1]);
double[] rowSize = new double[2];
double[] columnSize = new double[colCount];
for (int i = 0; i < rowSize.length; i++) {
rowSize[i] = 20;
}
for (int i = 0; i < columnSize.length; i++) {
if (i == 0) {
columnSize[i] = 80;
} else {
columnSize[i] = 100;
}
}
attrJPanel = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize);
attrJPanel.setBorder(new EmptyBorder(0, 100, 10, 100));
contentJPanel.add(attrJPanel);
}
private void initFitRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) {
components[0] = new UILabel(name);
for (int i = 0; i < options.length; i++) {
if (options[i] != null) {
UIRadioButton fontFitRadio = new UIRadioButton(options[i]);
fitRadioGroup.add(fontFitRadio);
components[i + 1] = fontFitRadio;
} else {
components[i + 1] = null;
}
}
fitRadioGroup.addActionListener(getPreviewActionListener());
}
protected ActionListener getPreviewActionListener() {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
refreshPreviewJPanel();
}
};
}
protected void refreshPreviewJPanel() {
String previewIndex = getPreviewIndex();
previewJPanel.refreshPreview(previewIndex, fontRadioGroup.isEnabled());
}
protected String getPreviewIndex() {
return getStateInPC(adaptRadioGroup.getSelectRadioIndex()) + "" + fontRadioGroup.getSelectRadioIndex();
}
protected void initPreviewJPanel() {
previewJPanel = new FitPreviewPane();
contentJPanel.add(previewJPanel);
}
protected int getStateInPC(int index) {
FitType[] fitTypes = fitAttrModel.getFitTypes();
return fitTypes[index].getState();
}
protected int getOptionIndex(int state) {
FitType[] fitTypes = fitAttrModel.getFitTypes();
for (int i = 0; i < fitTypes.length; i++) {
if (ComparatorUtils.equals(state, fitTypes[i].getState())) {
return i;
}
}
return 0;
}
@Override
public void populateBean(ReportFitAttr ob) {
fontRadioGroup.selectIndexButton(ob.isFitFont() ? 0 : 1);
adaptRadioGroup.selectIndexButton(getOptionIndex(ob.fitStateInPC()));
refreshPreviewJPanel();
}
@Override
public ReportFitAttr updateBean() {
ReportFitAttr reportFitAttr = new ReportFitAttr();
reportFitAttr.setFitFont(fontRadioGroup.isFontFit());
reportFitAttr.setFitStateInPC(getStateInPC(adaptRadioGroup.getSelectRadioIndex()));
return reportFitAttr;
}
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
fontRadioGroup.setEnabled(enabled);
adaptRadioGroup.setEnabled(enabled);
refreshPreviewJPanel();
}
@Override
protected String title4PopupWindow() {
return i18nText("Fine-Designer_PC_Element_Case_Fit_Attr");
}
protected abstract String[] getItemNames();
protected void initComponents() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentJPanel = new JPanel();
contentJPanel.setLayout(FRGUIPaneFactory.createCenterFlowLayout());
this.add(contentJPanel);
initItemChoose();
}
private void initItemChoose() {
JPanel chooseJPanel = new JPanel();
chooseJPanel.setLayout(FRGUIPaneFactory.createLabelFlowLayout());
ItemListener itemListener = getItemListener();
itemChoose = new UIComboBox(getItemNames());
itemChoose.addItemListener(itemListener);
UILabel belowSetLabel = new UILabel(i18nText("Fine-Design_Report_Blow_Set"));
JPanel buttonPane = GUICoreUtils.createFlowPane(new Component[]{
belowSetLabel, itemChoose}, FlowLayout.LEFT, 0, 0);
chooseJPanel.add(buttonPane);
chooseJPanel.setPreferredSize(new Dimension(500, 50));
JPanel jPanel = new JPanel();
jPanel.setLayout(FRGUIPaneFactory.createBorderLayout());
jPanel.add(chooseJPanel, BorderLayout.WEST);
contentJPanel.add(jPanel);
}
protected abstract ItemListener getItemListener();
public void populate(ReportFitAttr reportFitAttr) {
}
protected void refresh() {
validate();
repaint();
revalidate();
}
}

51
designer-base/src/main/java/com/fr/design/report/fit/CptFitAttrModel.java

@ -0,0 +1,51 @@
package com.fr.design.report.fit;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.JTemplate;
import com.fr.report.fit.ReportFitAttr;
import com.fr.report.fit.ReportFitConfig;
public class CptFitAttrModel implements FitAttrModel {
@Override
public FitType[] getFitTypes() {
return new FitType[]{
FitType.HORIZONTAL_FIT,
FitType.DOUBLE_FIT,
FitType.NOT_FIT
};
}
@Override
public String getFitName() {
return Toolkit.i18nText("Fine-Designer_Fit-Element");
}
@Override
public String getModelName() {
return Toolkit.i18nText("Fine-Design_Basic_Plain_Report");
}
@Override
public ReportFitAttr getGlobalReportFitAttr() {
return ReportFitConfig.getInstance().getCptFitAttr();
}
@Override
public void setGlobalReportFitAttr(ReportFitAttr reportFitAttr) {
ReportFitConfig.getInstance().setCptFitAttr(reportFitAttr);
}
@Override
public int getPriority() {
return 0;
}
@Override
public boolean isAvailable(JTemplate jTemplate) {
return jTemplate.isJWorkBook();
}
}

44
designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java

@ -0,0 +1,44 @@
package com.fr.design.report.fit;
import com.fr.design.mainframe.JTemplate;
import com.fr.report.fit.ReportFitAttr;
public interface FitAttrModel {
/**
* @Description 名称比如普通报表决策报表等
**/
String getModelName();
/**
* @Description 自适应选项的名称比如返回表格
**/
String getFitName();
/**
* @Description 自适应选项
**/
FitType[] getFitTypes();
/**
* @Description 获取全局的自适应属性
**/
ReportFitAttr getGlobalReportFitAttr();
/**
* @Description 设置全局的自适应属性
* @param: reportFitAttr
**/
void setGlobalReportFitAttr(ReportFitAttr reportFitAttr);
/**
* @Description 优先级
**/
int getPriority();
/**
* @Description 是否可用
* @param: jTemplate
**/
boolean isAvailable(JTemplate jTemplate);
}

53
designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java

@ -0,0 +1,53 @@
package com.fr.design.report.fit;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.JTemplate;
import com.fr.report.fit.ReportFitAttr;
import com.fr.report.fit.ReportFitConfig;
public class FrmFitAttrModel implements FitAttrModel {
@Override
public String getModelName() {
return Toolkit.i18nText("Fine-Design_Basic_Decision_Report");
}
@Override
public String getFitName() {
return Toolkit.i18nText("Fine-Designer_Fit-Element");
}
public FitType[] getFitTypes() {
return new FitType[]{
FitType.DEFAULT,
FitType.HORIZONTAL_FIT,
FitType.DOUBLE_FIT,
FitType.NOT_FIT
};
}
@Override
public ReportFitAttr getGlobalReportFitAttr() {
return ReportFitConfig.getInstance().getFrmFitAttr();
}
@Override
public void setGlobalReportFitAttr(ReportFitAttr reportFitAttr) {
ReportFitConfig.getInstance().setFrmFitAttr(reportFitAttr);
}
@Override
public int getPriority() {
return 1;
}
@Override
public boolean isAvailable(JTemplate jTemplate) {
return !jTemplate.isJWorkBook();
}
}

10
designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java

@ -1,6 +1,5 @@
package com.fr.design.report.fit.menupane;
import com.fr.base.svg.IconUtils;
import com.fr.design.actions.JTemplateAction;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.dialog.DialogActionAdapter;
@ -82,13 +81,8 @@ public class ReportFitAttrAction extends JTemplateAction {
}
final FitProvider wbTpl = (FitProvider) jwb.getTarget();
ReportFitAttr fitAttr = wbTpl.getReportFitAttr();
if (jwb.isJWorkBook()) {
final TemplateFitAttrPane attrPane = new TemplateFitAttrPane();
showReportFitDialog(fitAttr, jwb, wbTpl, attrPane);
} else {
final ReportFitAttrPane attrPane = new ReportFitAttrPane();
showReportFitDialog(fitAttr, jwb, wbTpl, attrPane);
}
TemplateFitAttrPane templateFitAttrPane = new TemplateFitAttrPane();
showReportFitDialog(fitAttr, jwb, wbTpl, templateFitAttrPane);
}
private void showReportFitDialog(ReportFitAttr fitAttr, final JTemplate jwb, final FitProvider wbTpl, final BasicBeanPane<ReportFitAttr> attrPane) {

104
designer-base/src/main/java/com/fr/design/report/fit/menupane/TemplateFitAttrPane.java

@ -1,55 +1,91 @@
package com.fr.design.report.fit.menupane;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.report.fit.BaseFitAttrPane;
import com.fr.design.report.fit.FitAttrModel;
import com.fr.general.ComparatorUtils;
import com.fr.report.fit.FitProvider;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* Created by 夏翔 on 2016/6/24.
*/
public class TemplateFitAttrPane extends BasicBeanPane<ReportFitAttr> {
private TemplateBrowserFitAttrPane attrPane;
public class TemplateFitAttrPane extends BaseFitAttrPane {
public TemplateFitAttrPane() {
initComponents();
}
private void initComponents() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
attrPane = new TemplateBrowserFitAttrPane();
this.add(attrPane);
@Override
protected void initComponents() {
super.initComponents();
for (FitAttrModel fitAttrModel : fitAttrModelList) {
if (fitAttrModel.isAvailable(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate())) {
populateModel(fitAttrModel);
break;
}
}
}
@Override
public void populateBean(ReportFitAttr reportFitAttr) {
if (reportFitAttr == null) {
itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings"));
} else {
itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single"));
}
populate(reportFitAttr);
}
/**
* 展示界面
*
* @param fitAttr 自适应属性
*/
public void populateBean(ReportFitAttr fitAttr) {
attrPane.populateBean(fitAttr);
public void populate(ReportFitAttr reportFitAttr) {
if (reportFitAttr == null) {
reportFitAttr = fitAttrModel.getGlobalReportFitAttr();
}
super.setEnabled(isTemplateSingleSet());
super.populateBean(reportFitAttr);
}
/**
* 提交数据
*
* @return 界面上的更新数据
*/
public ReportFitAttr updateBean() {
return attrPane.updateBean();
if (!isTemplateSingleSet()) {
return null;
} else {
return super.updateBean();
}
}
@Override
protected String[] getItemNames() {
return new String[]{Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings"),
Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")};
}
@Override
protected ItemListener getItemListener() {
return new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if(isTemplateSingleSet()){
JTemplate jwb = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (jwb != null) {
FitProvider wbTpl = (FitProvider) jwb.getTarget();
ReportFitAttr fitAttr = wbTpl.getReportFitAttr();
populate(fitAttr);
}
}else {
populate(fitAttrModel.getGlobalReportFitAttr());
}
}
}
};
}
/**
* 标题
*
* @return 标题
*/
protected String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_PC_Fit_Attr");
private boolean isTemplateSingleSet() {
return ComparatorUtils.equals(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single"), itemChoose.getSelectedItem());
}
}
}

18
designer-base/src/main/java/com/fr/design/report/fit/provider/AbstractFitAttrModelProvider.java

@ -0,0 +1,18 @@
package com.fr.design.report.fit.provider;
import com.fr.stable.fun.mark.API;
@API(level = FitAttrModelProvider.CURRENT_LEVEL)
public abstract class AbstractFitAttrModelProvider implements FitAttrModelProvider {
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
}
@Override
public String mark4Provider() {
return getClass().getName();
}
}

11
designer-base/src/main/java/com/fr/design/report/fit/provider/FitAttrModelProvider.java

@ -0,0 +1,11 @@
package com.fr.design.report.fit.provider;
import com.fr.design.report.fit.FitAttrModel;
import com.fr.stable.fun.mark.Mutable;
public interface FitAttrModelProvider extends Mutable, FitAttrModel {
String XML_TAG = "FitAttrModelProvider";
int CURRENT_LEVEL = 1;
}

22
designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java

@ -39,8 +39,10 @@ import java.util.List;
public class NewColorSelectPane extends BasicPane implements ColorSelectable {
private static final long serialVersionUID = -8634152305687249392L;
private static final int WIDTH = 197;
private static final int HEIGHT = 250;
private static final int WIDTH = 216;
private static final int HEIGHT = 230;
private static final int DEFAULT_COLOR_HOR_INTERVAL = 4;
//颜色衍生的数量
private static final int DEFAULT_DERIVE_COUNT = 5;
@ -81,7 +83,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
initSelectButton(isSupportTransparent);
// center
JPanel centerPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
centerPane.setBorder(BorderFactory.createEmptyBorder(10, 4, 0, 4));
centerPane.setBorder(BorderFactory.createEmptyBorder(10, 6, 0, 6));
this.add(centerPane, BorderLayout.CENTER);
menuColorPane = getMenuColorPane();
@ -126,14 +128,14 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
customButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
JPanel centerPane1 = new JPanel(new BorderLayout(0, 0));
centerPane1.setBorder(BorderFactory.createEmptyBorder(9, 0, 11, 0));
centerPane1.setBorder(BorderFactory.createEmptyBorder(8, 0, 9, 0));
centerPane1.add(customButton, BorderLayout.CENTER);
customButton.setPreferredSize(new Dimension(197, 20));
centerPane.add(centerPane1);
}
private JPanel createStandardColorPane() {
JPanel jPanel = new JPanel(new GridLayout(1, 10, 3, 0));
JPanel jPanel = new JPanel(new GridLayout(1, 10, DEFAULT_COLOR_HOR_INTERVAL, 0));
Color[] colorArray = ColorFactory.STANDARD_COLORS;
for (int i = 0; i < colorArray.length; i++) {
jPanel.add(new ColorCell(colorArray[i], this));
@ -150,8 +152,8 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
themeColorPane.add(menuColorPane, BorderLayout.SOUTH);
menuColorPane.setLayout(new BorderLayout(0, 10));
JPanel northPane = new JPanel(new GridLayout(1, 8, 3, 0));
JPanel centerPane = new JPanel(new GridLayout(1, 8, 3, 0));
JPanel northPane = new JPanel(new GridLayout(1, 8, DEFAULT_COLOR_HOR_INTERVAL, 0));
JPanel centerPane = new JPanel(new GridLayout(1, 8, DEFAULT_COLOR_HOR_INTERVAL, 0));
menuColorPane.add(northPane, BorderLayout.NORTH);
menuColorPane.add(centerPane, BorderLayout.CENTER);
@ -189,7 +191,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
northPane.add(themeColorCellGrid[i][0]);
}
for (int i = 0; i < colorArray.length; i++) {
JPanel columnPane = new JPanel(new GridLayout(DEFAULT_DERIVE_COUNT - 1, 1, 0, 3));
JPanel columnPane = new JPanel(new GridLayout(DEFAULT_DERIVE_COUNT - 1, 1, 0, 0));
for (int j = 1; j < DEFAULT_DERIVE_COUNT; j++) {
columnPane.add(themeColorCellGrid[i][j]);
}
@ -233,7 +235,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
private void initMenuColorPane() {
menuColorPane.setLayout(new GridLayout(5, 8, 3, 3));
menuColorPane.setLayout(new GridLayout(5, 8, DEFAULT_COLOR_HOR_INTERVAL, 0));
Color[] colorArray = this.getColorArray();
for (int i = 0; i < colorArray.length; i++) {
Color color = colorArray[i] == null ? UsedColorPane.DEFAULT_COLOR : colorArray[i];
@ -409,7 +411,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
private void initialComponents() {
int total = columns;
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, columns + 1, 3, 3));
panel.setLayout(new GridLayout(1, columns + 1, DEFAULT_COLOR_HOR_INTERVAL, 0));
panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
//最近使用颜色
Color[] colors = DesignerEnvManager.getEnvManager().getColorConfigManager().getColors();

60
designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java

@ -1,11 +1,13 @@
package com.fr.design.utils;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
/**
* 工具类提供常用的工具方法
@ -151,4 +153,62 @@ public class ComponentUtils {
}
return false;
}
public static Component findComponentByName(Component container, String componentName) {
Component target = null;
if (container instanceof Container) {
for (Component component: ((Container)container).getComponents()) {
if (componentName.equals(component.getName())) {
return component;
}
if (component instanceof JRootPane) {
JRootPane nestedJRootPane = (JRootPane)component;
target = findComponentByName(nestedJRootPane.getContentPane(), componentName);
} else if (component instanceof Container){
target = findComponentByName( component, componentName);
}
if (target != null) {
return target;
}
}
}
return null;
}
public static Component findComponentByClass(Component container, Class clazz) {
Component target = null;
if (container instanceof Container) {
for (Component component: ((Container)container).getComponents()) {
if (clazz.isInstance(component)) {
return component;
}
if (component instanceof JRootPane) {
JRootPane nestedJRootPane = (JRootPane)component;
target = findComponentByClass(nestedJRootPane.getContentPane(), clazz);
} else if (component instanceof Container){
target = findComponentByClass(component, clazz);
}
if (target != null) {
return target;
}
}
}
return null;
}
public static List<Component> findComponentsByClass(Component container, Class clazz) {
List<Component> components= new ArrayList<>();
if (container instanceof Container) {
for (Component component: ((Container)container).getComponents()) {
if (clazz.isInstance(component)) {
components.add(component);
continue;
}
if (component instanceof Container){
components.addAll(findComponentsByClass(component, clazz));
}
}
}
return components;
}
}

26
designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java

@ -7,12 +7,14 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.utils.DesignUtils;
import com.fr.design.worker.WorkerManager;
import com.fr.exception.DecryptTemplateException;
import com.fr.file.FILE;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
@ -51,6 +53,7 @@ public class OpenWorker<T> extends SwingWorker<T, Void> {
@Override
protected T doInBackground() throws Exception {
TimeUnit.SECONDS.sleep(5);
return this.callable.call();
}
@ -61,7 +64,7 @@ public class OpenWorker<T> extends SwingWorker<T, Void> {
} catch (CancellationException ignored) {
return;
} catch (Throwable t) {
processFailed();
processFailed(StringUtils.EMPTY);
Throwable cause = t.getCause();
if (cause instanceof DecryptTemplateException) {
FineJOptionPane.showMessageDialog(
@ -91,6 +94,11 @@ public class OpenWorker<T> extends SwingWorker<T, Void> {
if (slowly && templateCallable != null) {
try {
JTemplate<?, ?> book = templateCallable.call();
if (inValidDesigner(book)) {
String text = Toolkit.i18nText("Fine-Design_Report_Template_Version_Not_Match", DesignUtils.parseVersion(book.getTarget().getDesignerVersion()));
processFailed(text);
return;
}
FILE tplFile = book.getEditingFILE();
JTemplate<?, ?> currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
// 当前tab页是正在打开的模板
@ -117,11 +125,21 @@ public class OpenWorker<T> extends SwingWorker<T, Void> {
WorkerManager.getInstance().removeWorker(taskName);
}
private void processFailed() {
private boolean inValidDesigner(JTemplate<?, ?> jt) {
return jt.isOldDesigner(false) || (!jt.isJWorkBook() && jt.isNewDesigner(false));
}
private void processFailed(String text) {
this.template.setOpenFailed(true);
this.template.setOpening(false);
DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showOpenFailedCover();
DesignerFrameFileDealerPane.getInstance().stateChange();
JTemplate<?, ?> currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
// 需要判断当前打开的模板是不是异步执行后失败的模板 是的话立即展示失败后的提示内容 否则只设置下失败的提示内容
if (ComparatorUtils.equals(currentTemplate.getEditingFILE().getName(), this.template.getName())) {
DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showOpenFailedCover(text);
DesignerFrameFileDealerPane.getInstance().stateChange();
} else {
this.template.setTemplateOpenFailedTip(text);
}
WorkerManager.getInstance().removeWorker(taskName);
}

8
designer-base/src/main/java/com/fr/design/write/submit/CustomJobPane.java

@ -13,6 +13,7 @@ import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.stable.ListMap;
import com.fr.stable.StringUtils;
import com.fr.design.utils.gui.GUICoreUtils;
@ -115,7 +116,12 @@ public abstract class CustomJobPane extends BasicBeanPane {
@Override
public void populateBean(Object ob) {
if (ob instanceof AbstractClassJob) {
if (ob == null) {
// 自定义提交新增时初始化页面 REPORT-59256
this.classNameTextField.setText(StringUtils.EMPTY);
this.objectProperiesPane.populateBean(new ListMap());
}
else if (ob instanceof AbstractClassJob) {
AbstractClassJob cj = (AbstractClassJob) ob;
this.classNameTextField.setText(cj.getClassName());
this.objectProperiesPane.populateBean(cj.getPropertyMap());

10
designer-base/src/main/java/com/fr/file/FILEChooserPane.java

@ -648,7 +648,7 @@ public class FILEChooserPane extends BasicPane {
this.suffix = suffix;
if (!text.endsWith(suffix)) {
text = text + suffix;
text = removeSuffix(text) + suffix;
}
fileNameTextField.removeDocumentListener();
fileNameTextField.setText(text);
@ -664,6 +664,14 @@ public class FILEChooserPane extends BasicPane {
fileNameTextField.setFilter(new DefaultCompletionFilter(names));
}
/**
* 移除文件后缀的方法
* 解决cptx文件的另存为操作默认会出现双后缀的bug(xxx.cptx.cpt)
**/
private String removeSuffix(String text){
return FileExtension.CPTX.matchExtension(text) ? text.substring(0, text.length() - FileExtension.CPTX.getSuffix().length()) : text;
}
/**
* 打开对话框

2
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java

@ -57,7 +57,7 @@ public class TransformResultInfo {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip");
case UNSUPPORT:
return transformLog + "\n"
+ InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip");
+ InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_X_Unsupport_Tip");
}
return transformLog;
}

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_down.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_right.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/close.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_all.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_none.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_some.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/guide.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
designer-base/src/main/resources/com/fr/design/mainframe/guide/success.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

2
designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java

@ -55,6 +55,8 @@ public class ChartPropertyPane extends BaseChartPropertyPane {
chartEditPane.setContainer(container);
currentID = plotID;
resetChartEditPane();
} else {
chartEditPane.resetLastChartCollection();
}
}

4
designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java

@ -118,6 +118,10 @@ public class ChartEditPane extends BasicPane implements AttributeChange, Prepare
this.listenerList.remove(ChartEditPaneActionListener.class, l);
}
public void resetLastChartCollection() {
this.lastCollection = null;
}
private void fireAttributeChange(ChartCollection chartCollection) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();

7
designer-chart/src/main/java/com/fr/van/chart/drillmap/designer/other/VanChartDrillMapInteractivePane.java

@ -100,7 +100,12 @@ public class VanChartDrillMapInteractivePane extends VanChartInteractivePaneWith
double f = TableLayout.FILL;
double[] columnSize = {f};
double[] rowSize = {p, p, p, p, p, p};
Component[][] components = new Component[][]{
Component[][] components = ChartEditContext.duchampMode() ? new Component[][]{
new Component[]{null},
new Component[]{createTitlePane(Toolkit.i18nText("Fine-Design_Chart_Character"), textAttrPane)},
new Component[]{backgroundPane},
new Component[]{selectBackgroundPane}
} : new Component[][]{
new Component[]{null},
new Component[]{createTitlePane(Toolkit.i18nText("Fine-Design_Chart_Character"), textAttrPane)},
new Component[]{backgroundPane},

6
designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java

@ -160,8 +160,10 @@ public class FRFitLayoutAdapter extends FRBodyLayoutAdapter {
//布局控件要先判断是不是可编辑
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout();
boolean access = topLayout != null && !isMatchEdge && !topLayout.isEditable() && !topLayout.acceptType(XWAbsoluteLayout.class) && !isExtraContainer(comp) && !topLayout.isDragInAble();
if (access) {
boolean access = topLayout != null && !isMatchEdge && !topLayout.acceptType(XWAbsoluteLayout.class) && !isExtraContainer(comp) && !topLayout.isDragInAble();
//topLayout.getParent() != container说明当前增加的组件所在容器是嵌套在外部的自适应容器内部的,此时需要判断增加组件所在容器是否可编辑,不可编辑的话就直接返回 false
//否则说明就是往当前自适应容器内部添加组件,不需要判断其是否可编辑
if (access && (topLayout.getParent() != container && !topLayout.isEditable())) {
return false;
}

8
designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java

@ -4,8 +4,8 @@ import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.ComponentAdapter;
import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.utils.ComponentUtils;
@ -124,11 +124,10 @@ public class AddingModel {
*/
public boolean add2Container(FormDesigner designer, XLayoutContainer container, int x, int y) {
//考虑不同布局嵌套的情况,获取顶层容器
XLayoutContainer xLayoutContainer = container.getTopLayout();
if (xLayoutContainer != null && xLayoutContainer.acceptType(XWAbsoluteLayout.class)) {
XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(container);
if (xLayoutContainer != null) {
container = xLayoutContainer;
}
Rectangle rect = ComponentUtils.getRelativeBounds(container);
if (!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())) {
added = container.getLayoutAdapter().addBean(creator,
@ -141,4 +140,5 @@ public class AddingModel {
y + designer.getVerticalScaleValue() - rect.y);
return added;
}
}

15
designer-form/src/main/java/com/fr/design/designer/beans/models/NewFormModel.java

@ -1,6 +1,7 @@
package com.fr.design.designer.beans.models;
import com.fr.design.designer.beans.PredefinedLayout;
import com.fr.design.i18n.Toolkit;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
@ -9,13 +10,20 @@ import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class NewFormModel implements Serializable {
private static final String CONFIG_FILE_PATH = "/com/fr/design/form/layouts/config.json";
private static NewFormModel holder = null;
private Map<String, List<PredefinedLayout>> config = new HashMap<>();
private Map<String, List<PredefinedLayout>> config = new LinkedHashMap<>();
private final Map<String, String> i18nMap = new HashMap<String, String>() {{
put("2-4", Toolkit.i18nText("Fine-Design_Layout_Two_To_Four_Module"));
put("5-7", Toolkit.i18nText("Fine-Design_Layout_Five_To_Seven_Module"));
put("multi", Toolkit.i18nText("Fine-Design_Layout_Multi_Module"));
}};
public static NewFormModel getInstance() {
if (holder == null) {
@ -52,6 +60,9 @@ public class NewFormModel implements Serializable {
}
public void setConfig(Map<String, List<PredefinedLayout>> config) {
this.config = config;
for (String key : config.keySet()) {
String i18nKey = StringUtils.isNotEmpty(i18nMap.get(key)) ? i18nMap.get(key) : key;
this.config.put(i18nKey, config.get(key));
}
}
}

18
designer-form/src/main/java/com/fr/design/designer/creator/XCreatorUtils.java

@ -402,4 +402,22 @@ public class XCreatorUtils {
FineColorFlushUtils.replaceCacheObject(container.toData(), colorGather);
FineColorManager.traverse(container.toData(), colorGather);
}
/**
* 获取容器组件的顶层正编辑的组件
*/
@Nullable
public static XLayoutContainer getTopEditableContainer(XLayoutContainer container) {
if (container == null) {
return null;
}
XLayoutContainer xLayoutContainer = container.getTopLayout();
if (xLayoutContainer != null && xLayoutContainer.getParent() != null) {
if (!xLayoutContainer.isEditable()) {
return (XLayoutContainer) xLayoutContainer.getParent();
}
}
return null;
}
}

1
designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java

@ -796,6 +796,7 @@ public class XWFitLayout extends XLayoutContainer {
layout.setContainerHeight(containerHeight);
layout.setContainerWidth(containerWidth);
addCompInterval(getAcualInterval());
LayoutUtils.layoutContainer(this);
// REPORT-54410: 决策报表,模板中其他组件的宽高修改会影响绝对画布块中组件的宽高和位置
// 绝对布局内的组件尺寸调整需要在绝对布局的bound排除GAP后进行,否则计算出的

551
designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java

@ -1,36 +1,54 @@
package com.fr.design.gui.xpane;
import com.fr.base.Utils;
import com.fr.base.svg.IconUtils;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.formula.TinyFormulaPane;
import com.fr.design.gui.frpane.UIPercentDragPane;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.ibutton.UIColorButton;
import com.fr.design.gui.ibutton.UIToggleButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.gui.style.BackgroundSpecialPane;
import com.fr.design.gui.style.ComponentBodyStylePane;
import com.fr.design.gui.style.ComponentIntegralStylePane;
import com.fr.design.gui.style.ComponentTitleStylePane;
import com.fr.design.gui.style.FRFontPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.form.ui.WidgetTitle;
import com.fr.general.Background;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.general.act.TitlePacker;
import com.fr.stable.Constants;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import static com.fr.design.i18n.Toolkit.i18nText;
/**
* @author Starryi
* @version 10.0.18
@ -39,19 +57,51 @@ import static com.fr.design.i18n.Toolkit.i18nText;
* 可配置图片类型边框的样式设置面板
*/
public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> {
public static final String[] BORDER_STYLE = new String[]{
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow")
};
private static final Dimension BUTTON_SIZE = new Dimension(20, 20);
public static final int SETTING_LABEL_WIDTH = 60;
protected LayoutBorderStyle style = new LayoutBorderStyle();
public JPanel namedTitleStylePane;
public JPanel namedBodyStylePane;
public JPanel namedIntegralStylePane;
protected ComponentTitleStylePane titleStylePane;
protected ComponentBodyStylePane bodyStylePane;
protected ComponentIntegralStylePane integralStylePane;
private final boolean supportBorderImage;
//渲染风格:有无阴影
protected UIComboBox borderStyleCombo;
// 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色)
protected BorderLineAndImagePane borderLineAndImagePane;
//边框圆角或圆角裁剪
protected UISpinner cornerSpinner;
//主体背景
protected BackgroundSpecialPane backgroundPane;
//主体背景透明度
protected UIPercentDragPane backgroundOpacityPane;
// 标题可见
protected UICheckBox titleVisibleCheckbox;
//标题文字内容
protected TinyFormulaPane titleTextPane;
//标题字体格式
protected UIComboBox titleFontFamilyComboBox;
//标题字体大小
protected UIComboBox titleFontSizeComboBox;
//标题字体颜色
protected UIColorButton titleFontColorSelectPane;
//标题字体特殊效果:粗体、斜体、下划线
private UIToggleButton titleFontBoldButton;
private UIToggleButton titleFontItalicButton;
private UIToggleButton titleFontUnderlineButton;
// private LineComboBox titleFontUnderlineCombo; // 目前前端仅支持短横线类型的下划线,因此设计器端暂时就不展示线型选择框了,待后续优化
// 标题图文混排
protected TitleInsetImagePane titleInsetImagePane;
//对齐方式
protected UIButtonGroup titleAlignPane;
//标题整体背景
protected BackgroundSpecialPane titleBackgroundPane;
//标题背景透明度
protected UIPercentDragPane titleBackgroundOpacityPane;
private boolean supportBorderImage = false;
public LayoutStylePane() {
this(false);
@ -59,92 +109,350 @@ public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> {
public LayoutStylePane(boolean supportBorderImage) {
this.supportBorderImage = supportBorderImage;
this.initializePane();
this.initLayout();
}
protected void initializePane() {
protected void initLayout() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
boolean isRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane();
boolean currentIsRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane();
namedTitleStylePane = createNamedTitleStylePane(isRootLayout);
namedBodyStylePane = createNamedBodyStylePane(isRootLayout);
namedIntegralStylePane = createNamedIntegralStylePane(isRootLayout, true);
JPanel titlePane = createTitleStylePane();
JPanel bodyContentPane = currentIsRootLayout ? createBodyContentPane4RootLayout() : createBodyContentPane();
JPanel backgroundPane = createBackgroundStylePane(true);
addComponents(new JComponent[] { namedTitleStylePane, namedBodyStylePane, namedIntegralStylePane });
}
protected JPanel createNamedTitleStylePane(boolean isRootLayout) {
if (isRootLayout) {
return null;
if (titlePane != null) {
container.add(titlePane, BorderLayout.NORTH);
if (currentIsRootLayout) {
titlePane.setVisible(false);
}
}
this.titleStylePane = new ComponentTitleStylePane(SETTING_LABEL_WIDTH);
return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget_Style_Title"), this.titleStylePane);
}
JPanel nextContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.add(nextContainerPane, BorderLayout.CENTER);
protected JPanel createNamedBodyStylePane(boolean isRootLayout) {
this.bodyStylePane = new ComponentBodyStylePane(SETTING_LABEL_WIDTH);
if (isRootLayout) {
return this.bodyStylePane;
if (bodyContentPane != null) {
//界面上表单主体只有背景和透明度可以设置
nextContainerPane.add(bodyContentPane, BorderLayout.NORTH);
}
if (backgroundPane != null) {
nextContainerPane.add(backgroundPane, BorderLayout.CENTER);
if (currentIsRootLayout) {
backgroundPane.setVisible(false);
}
}
return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget-Style_Body_Content"), this.bodyStylePane);
this.add(container, BorderLayout.CENTER);
}
protected JPanel createNamedIntegralStylePane(boolean isRootLayout, boolean supportCornerRadius) {
if (isRootLayout) {
return null;
}
this.integralStylePane = new ComponentIntegralStylePane(SETTING_LABEL_WIDTH, supportBorderImage, supportCornerRadius);
return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget-Style_Integral_Style"), this.integralStylePane);
protected JPanel createBackgroundStylePane(boolean supportCornerRadius) {
borderStyleCombo = new UIComboBox(BORDER_STYLE);
borderLineAndImagePane = new BorderLineAndImagePane(this.supportBorderImage);
cornerSpinner = new UISpinner(0,1000,1,0);
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = supportCornerRadius ? new double[] {p, p, p, p} : new double[]{p, p, p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Background_Style"));
Font font = uiLabel.getFont().deriveFont(Font.BOLD);
uiLabel.setFont(font);
uiLabel.setForeground(new Color(143, 143, 146));
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{
{uiLabel, null},
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), createBorderLayoutNorthPaneWithComponent(borderStyleCombo)},
{this.borderLineAndImagePane, null},
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner},
},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(new BottomLineBorder());
container.add(contentPane, BorderLayout.NORTH);
return container;
}
protected JPanel createNamedSubStylePane(String name, JPanel stylePane) {
UILabel uiLabel = new UILabel(name);
protected JPanel createBodyContentPane() {
backgroundPane = new LayoutBackgroundSpecialPane();
backgroundOpacityPane = new UIPercentDragPane();
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p, p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
JPanel bodyBackground = createBackgroundAndOpacityPane(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill"),
this.backgroundPane,
this.backgroundOpacityPane);
UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Content"));
Font font = uiLabel.getFont().deriveFont(Font.BOLD);
uiLabel.setFont(font);
uiLabel.setForeground(new Color(143, 143, 146));
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{
{uiLabel, null},
{bodyBackground, null},
},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(new BottomLineBorder());
container.add(contentPane, BorderLayout.NORTH);
return container;
}
JPanel content = TableLayoutHelper.createGapTableLayoutPane( new JComponent[][] {
{uiLabel},
{stylePane}
}, TableLayoutHelper.FILL_LASTCOLUMN, 0, IntervalConstants.INTERVAL_L1);
content.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0));
protected JPanel createBodyContentPane4RootLayout() {
backgroundPane = new LayoutBackgroundSpecialPane();
backgroundOpacityPane = new UIPercentDragPane();
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
JPanel bodyBackground = createBackgroundAndOpacityPane(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill"),
this.backgroundPane,
this.backgroundOpacityPane);
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{
{bodyBackground, null},
},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.add(content, BorderLayout.NORTH);
container.setBorder(new BottomLineBorder());
container.add(contentPane, BorderLayout.NORTH);
return container;
}
private void addComponents(JComponent[] components) {
JPanel container = this;
for (JComponent component: components) {
if (component != null) {
container.add(component, BorderLayout.NORTH);
JPanel nextContainer = new JPanel(FRGUIPaneFactory.createBorderLayout());
container.add(nextContainer, BorderLayout.CENTER);
container = nextContainer;
protected void initTitleComponents() {
titleVisibleCheckbox = new UICheckBox();
titleTextPane = new TinyFormulaPane();
titleFontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report());
TitlePacker title = style.getTitle();
if (title != null) {
FRFont frFont = title.getFrFont();
if (frFont != null) {
String fontFamily = frFont.getFamily();
// 使用style中默认的字体初始化titleFontFamilyComboBox,保证UI和数据的一致性
this.titleFontFamilyComboBox.setSelectedItem(fontFamily);
}
}
titleFontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family"));
titleFontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES);
titleFontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size"));
titleFontColorSelectPane = new UIColorButton();
titleFontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground"));
titleFontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground"));
titleFontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png"));
titleFontBoldButton.setPreferredSize(BUTTON_SIZE);
titleFontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold"));
titleFontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold"));
titleFontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png"));
titleFontItalicButton.setPreferredSize(BUTTON_SIZE);
titleFontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic"));
titleFontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic"));
titleFontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png"));
titleFontUnderlineButton.setPreferredSize(BUTTON_SIZE);
titleFontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline"));
titleFontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline"));
// titleFontUnderlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY);
// titleFontUnderlineCombo.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Line_Style"));
titleInsetImagePane = new TitleInsetImagePane();
titleAlignPane = new UIButtonGroup<Integer>(
new Icon[] {
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"),
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"),
IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png")
},
new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT});
titleAlignPane.setAllToolTips(
new String[] {
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right")
});
titleBackgroundPane = new LayoutBackgroundSpecialPane();
titleBackgroundOpacityPane = new UIPercentDragPane();
}
protected JPanel createTitleStylePane() {
initTitleComponents();
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p,p,p,p,p,p};
double[] columnSize = {SETTING_LABEL_WIDTH, f};
final JPanel bottomPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), titleTextPane},
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), createBorderLayoutNorthPaneWithComponent(titleFontFamilyComboBox)},
{null, createTitleFontButtonPane()},
{titleInsetImagePane, null},
{FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), titleAlignPane},
{this.createTitleBackgroundAndOpacityPane(), null},
},
rowSize, columnSize, IntervalConstants.INTERVAL_L1);
bottomPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
bottomPane.setVisible(false);
JPanel visibleComposedPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
titleVisibleCheckbox.setSelected(false);
visibleComposedPane.add(titleVisibleCheckbox, BorderLayout.WEST);
visibleComposedPane.add(FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER);
UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title"));
Font font = uiLabel.getFont().deriveFont(Font.BOLD);
uiLabel.setFont(font);
uiLabel.setForeground(new Color(143, 143, 146));
JPanel topPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] {
{uiLabel, null},
{visibleComposedPane, null}
}, new double[]{p, p}, new double[]{SETTING_LABEL_WIDTH, p}, IntervalConstants.INTERVAL_L1);
topPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(new BottomLineBorder());
container.add(topPane, BorderLayout.NORTH);
container.add(bottomPane, BorderLayout.CENTER);
titleVisibleCheckbox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
bottomPane.setVisible(titleVisibleCheckbox.isSelected());
}
});
return container;
}
private JPanel createBorderLayoutNorthPaneWithComponent(JComponent content) {
JPanel jPanel = new JPanel(new BorderLayout());
jPanel.add(content, BorderLayout.NORTH);
return jPanel;
}
protected JPanel createTitleFontButtonPane(){
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p};
double[] columnSize = {f, p, p, p, p};
JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] {
{titleFontSizeComboBox, titleFontColorSelectPane, titleFontItalicButton, titleFontBoldButton, titleFontUnderlineButton},
}, rowSize, columnSize, IntervalConstants.INTERVAL_W0);
JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
containerPane.add(buttonPane, BorderLayout.NORTH);
// containerPane.add(titleFontUnderlineCombo, BorderLayout.CENTER);
// titleFontUnderlineCombo.setVisible(false);
// titleFontUnderlineButton.addChangeListener(new ChangeListener() {
// @Override
// public void stateChanged(ChangeEvent e) {
// titleFontUnderlineCombo.setVisible(titleFontUnderlineButton.isSelected());
// }
// });
return containerPane;
}
protected JPanel createTitleBackgroundAndOpacityPane() {
return createBackgroundAndOpacityPane(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background"),
titleBackgroundPane,
titleBackgroundOpacityPane);
}
@Override
public LayoutBorderStyle updateBean() {
LayoutBorderStyle style = new LayoutBorderStyle();
updateMain(style);
updateTitle(style);
return style;
}
if (this.titleStylePane != null) {
this.titleStylePane.updateBean(style);
protected void updateMain(LayoutBorderStyle style) {
if (borderStyleCombo != null) {
style.setBorderStyle(borderStyleCombo.getSelectedIndex());
}
if (this.bodyStylePane != null) {
this.bodyStylePane.updateBean(style);
if (cornerSpinner != null) {
style.setBorderRadius((int) cornerSpinner.getValue());
}
if (this.integralStylePane != null) {
this.integralStylePane.updateBean(style);
if (borderLineAndImagePane != null) {
borderLineAndImagePane.updateBean(style);
}
return style;
if (backgroundPane != null) {
style.setBackground(backgroundPane.update());
}
if (backgroundOpacityPane != null) {
style.setAlpha((float)backgroundOpacityPane.updateBean());
}
}
protected void updateTitle(LayoutBorderStyle style) {
style.setType(titleVisibleCheckbox != null && titleVisibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD);
TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle();
title.setTextObject(titleTextPane.updateBean());
FRFont frFont = title.getFrFont();
frFont = frFont.applySize((Integer) titleFontSizeComboBox.getSelectedItem());
frFont = frFont.applyName(titleFontFamilyComboBox.getSelectedItem().toString());
frFont = frFont.applyForeground(titleFontColorSelectPane.getColor());
frFont = updateTitleFontItalicBold(frFont);
// int line = titleFontUnderlineButton.isSelected() ? this.titleFontUnderlineCombo.getSelectedLineStyle() : Constants.LINE_NONE;
int line = titleFontUnderlineButton.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE;
frFont = frFont.applyUnderline(line);
title.setFrFont(frFont);
title.setPosition((Integer) titleAlignPane.getSelectedItem());
titleInsetImagePane.updateBean(title);
title.setBackground(titleBackgroundPane.update());
title.setBackgroundOpacity((float)titleBackgroundOpacityPane.updateBean());
style.setTitle(title);
}
private FRFont updateTitleFontItalicBold(FRFont frFont) {
int italic_bold = frFont.getStyle();
boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC);
boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC);
if (titleFontItalicButton.isSelected() && !isItalic) {
italic_bold += Font.ITALIC;
} else if (!titleFontItalicButton.isSelected() && isItalic) {
italic_bold -= Font.ITALIC;
}
frFont = frFont.applyStyle(italic_bold);
if (titleFontBoldButton.isSelected() && !isBold) {
italic_bold += Font.BOLD;
} else if (!titleFontBoldButton.isSelected() && isBold) {
italic_bold -= Font.BOLD;
}
frFont = frFont.applyStyle(italic_bold);
return frFont;
}
@Override
@ -154,20 +462,104 @@ public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> {
}
this.style.setStyle(style);
if (this.titleStylePane != null) {
this.titleStylePane.populateBean(this.style);
populateMain();
populateTitle();
}
protected void populateMain() {
if (this.borderStyleCombo != null) {
this.borderStyleCombo.setSelectedIndex(style.getBorderStyle());
}
if (this.bodyStylePane != null) {
this.bodyStylePane.populateBean(this.style);
if (this.borderLineAndImagePane != null) {
this.borderLineAndImagePane.populateBean(style);
}
if (this.integralStylePane != null) {
this.integralStylePane.populateBean(this.style);
if (this.backgroundPane != null) {
this.backgroundPane.populateBean(style.getBackground());
if (this.backgroundOpacityPane != null) {
this.backgroundOpacityPane.populateBean(style.getAlpha());
}
}
if (this.cornerSpinner != null) {
this.cornerSpinner.setValue(style.getBorderRadius());
}
}
protected void populateTitle() {
TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle();
widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle;
titleVisibleCheckbox.setSelected(style.getType() != LayoutBorderStyle.STANDARD);
this.titleTextPane.populateBean(widgetTitle.getTextObject().toString());
FRFont frFont = widgetTitle.getFrFont();
this.titleFontSizeComboBox.setSelectedItem(frFont.getSize());
this.titleFontFamilyComboBox.setSelectedItem(frFont.getFamily());
this.titleFontColorSelectPane.setColor(frFont.getForeground());
this.titleFontColorSelectPane.repaint();
titleFontBoldButton.setSelected(frFont.isBold());
titleFontItalicButton.setSelected(frFont.isItalic());
int line = frFont.getUnderline();
if (line == Constants.LINE_NONE) {
titleFontUnderlineButton.setSelected(false);
// titleFontUnderlineCombo.setVisible(false);
} else {
titleFontUnderlineButton.setSelected(true);
// titleFontUnderlineCombo.setVisible(true);
// this.titleFontUnderlineCombo.setSelectedLineStyle(line);
}
titleAlignPane.setSelectedItem(widgetTitle.getPosition());
titleInsetImagePane.populateBean(widgetTitle);
titleBackgroundPane.populateBean(widgetTitle.getBackground());
titleBackgroundOpacityPane.populateBean(widgetTitle.getBackgroundOpacity());
}
@Override
protected String title4PopupWindow() {
return i18nText("Fine-Design_Form_Widget_Style");
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style");
}
private static JPanel createBackgroundAndOpacityPane(String name, BackgroundSpecialPane backgroundPane, UIPercentDragPane opacityPane) {
JPanel container = new JPanel();
container.setLayout(new BorderLayout(0, 6));
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] columnSize = {SETTING_LABEL_WIDTH, f};
// 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐
JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(7, 0, 0, 0));
backgroundLabelPane.add(FRWidgetFactory.createLineWrapLabel(name), BorderLayout.NORTH);
JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane(
new JComponent[][]{
{backgroundLabelPane, backgroundPane}
},
new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane(
new JComponent[][]{
{new UILabel(""), FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))},
{new UILabel(""), opacityPane}
},
new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
container.add(backgroundComposedPane, BorderLayout.NORTH, 0);
container.add(opacityComposedPane, BorderLayout.CENTER, 1);
opacityComposedPane.setVisible(false);
backgroundPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Background background = backgroundPane.update();
opacityComposedPane.setVisible(background != null);
}
});
return container;
}
protected static class BottomLineBorder extends LineBorder {
@ -201,23 +593,4 @@ public class LayoutStylePane extends BasicBeanPane<LayoutBorderStyle> {
return new GradientBackgroundQuickPane(140);
}
}
public void supportTitleStyle(boolean supportTitleVisible, boolean supportTitleContent, boolean supportOtherSetting) {
if (titleStylePane != null) {
titleStylePane.setSupportTitleVisible(supportTitleVisible);
titleStylePane.setSupportTitleContent(supportTitleContent);
titleStylePane.setSupportOtherSetting(supportOtherSetting);
}
}
public void supportBodyStyle(boolean supporting) {
if (namedBodyStylePane != null) {
namedBodyStylePane.setVisible(supporting);
}
}
public void supportIntegralStyle(boolean supporting) {
if (namedIntegralStylePane != null) {
namedIntegralStylePane.setVisible(supporting);
}
}
}

15
designer-form/src/main/java/com/fr/design/mainframe/FormArea.java

@ -74,6 +74,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
private static final double SLIDER_MIN = 10.0;
private static final String SCALE_PLUS_COMMAND = "scale_plus";
private static final String SCALE_MINUS_COMMAND = "scale_minus";
public static final String FIX_LAYOUT_SWITCH_BUTTON = "fix_layout_switch_button";
public static final double DEFAULT_SLIDER = 100.0;
private static final int ROTATIONS = 50;
public static final int SHOWVALMAX = 400;
@ -188,6 +189,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
private UIButton createFixLayoutSwitchButton(){
UIButton button = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_No_Fix_Layout"));
button.setIcon(IOUtils.readIcon("/com/fr/base/images/share/filter_combo.png"));
button.setName(FIX_LAYOUT_SWITCH_BUTTON);
button.setUI(new UIButtonUI(){
@Override
protected void paintBorder(Graphics g, UIButton b) {
@ -202,15 +204,16 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
}
});
button.setHorizontalTextPosition(SwingConstants.LEFT);
UIPopupMenu popupMenu = new UIPopupMenu();
popupMenu.setPreferredSize(new Dimension(180, 59));
popupMenu.setOnlyText(true);
popupMenu.setBackground(UIConstants.DEFAULT_BG_RULER);
popupMenu.add(new PopupMenuItem(new Switch2NoFixLayoutAction()));
popupMenu.add(new PopupMenuItem(new Switch2FixLayoutAction()));
button.setComponentPopupMenu(popupMenu);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
UIPopupMenu popupMenu = new UIPopupMenu();
popupMenu.setPreferredSize(new Dimension(180, 59));
popupMenu.setOnlyText(true);
popupMenu.setBackground(UIConstants.DEFAULT_BG_RULER);
popupMenu.add(new PopupMenuItem(new Switch2NoFixLayoutAction()));
popupMenu.add(new PopupMenuItem(new Switch2FixLayoutAction()));
GUICoreUtils.showPopupMenu(popupMenu, fixLayoutSwitchButton, 0, -59);
}
});

18
designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java

@ -79,7 +79,7 @@ public class FormCreatorDropTarget extends DropTarget {
this.tabDragInner = new TabDragInner(designer);
}
private void adding(int x, int y) {
public void adding(int x, int y) {
// 当前鼠标所在的组件
XCreator hoveredComponent = designer.getComponentAt(x, y);
// 获取该组件所在的焦点容器
@ -193,7 +193,6 @@ public class FormCreatorDropTarget extends DropTarget {
private void dealWithContainer(int x, int y, XLayoutContainer container) {
HoverPainter painter = null;
if (container != current || designer.getPainter() == null) {
// 如果焦点容器不是当前容器
if (current != null) {
@ -204,15 +203,9 @@ public class FormCreatorDropTarget extends DropTarget {
throw new IllegalArgumentException("container can not be null!");
}
//获取painter的时候要考虑布局之间嵌套的问题
XLayoutContainer xLayoutContainer = container.getTopLayout();
if (xLayoutContainer != null && xLayoutContainer.getParent() != null
&& ((XLayoutContainer) xLayoutContainer.getParent()).acceptType(XWAbsoluteLayout.class)) {
if (!xLayoutContainer.isEditable()) {
xLayoutContainer = (XLayoutContainer) xLayoutContainer.getParent();
}
}
XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(container);
painter = AdapterBus.getContainerPainter(designer,
xLayoutContainer != null && xLayoutContainer.acceptType(XWAbsoluteLayout.class) ? xLayoutContainer : container);
xLayoutContainer != null ? xLayoutContainer : container);
// 为界面设计器设置提示渲染提示器
designer.setPainter(painter);
@ -227,8 +220,9 @@ public class FormCreatorDropTarget extends DropTarget {
}
}
if (painter != null) {
XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(container);
// 为提示渲染器设置焦点位置、区域等渲染参数
Rectangle rect = ComponentUtils.getRelativeBounds(container);
Rectangle rect = ComponentUtils.getRelativeBounds(xLayoutContainer != null ? xLayoutContainer : container);
rect.x -= designer.getArea().getHorizontalValue();
rect.y -= designer.getArea().getVerticalValue();
painter.setRenderingBounds(rect);
@ -236,7 +230,7 @@ public class FormCreatorDropTarget extends DropTarget {
painter.setCreator(addingModel.getXCreator());
}
}
private void promptUser(int x, int y, XLayoutContainer container) {
if (!addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class)) {
promptButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Para_Pane"));

4
designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java

@ -1120,6 +1120,10 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
return addingModel;
}
public void setAddingModel(AddingModel addingModel) {
this.addingModel = addingModel;
}
public XCreator getComponentAt(MouseEvent e) {
return getComponentAt(e.getX(), e.getY());
}

11
designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java

@ -36,6 +36,7 @@ public class FormWidgetDetailPane extends FormDockView{
private JPanel centerPane;
private UIHeadGroup headGroup;
private List<BasicPane> paneList;
private CardLayout cardLayout;
private boolean isEmptyPane = false;
@ -86,7 +87,7 @@ public class FormWidgetDetailPane extends FormDockView{
initPaneList();
this.setBorder(null);
final CardLayout cardLayout = new CardLayout();
cardLayout = new CardLayout();
centerPane = new JPanel(cardLayout);
String[] paneNames = new String[paneList.size()];
for (int i = 0; i < paneList.size(); i++) {
@ -137,6 +138,14 @@ public class FormWidgetDetailPane extends FormDockView{
this.add(panel, BorderLayout.CENTER);
}
public void switch2Local() {
cardLayout.show(centerPane, paneList.get(0).getTitle());
}
public void swich2Online() {
cardLayout.show(centerPane, paneList.get(1).getTitle());
}
private UILabel tipLabel(String text) {
UILabel tipLabel = new UILabel(text);
tipLabel.setHorizontalAlignment(SwingConstants.CENTER);

11
designer-form/src/main/java/com/fr/design/mainframe/JForm.java

@ -6,7 +6,6 @@ import com.fr.base.Parameter;
import com.fr.base.Releasable;
import com.fr.base.extension.FileExtension;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.base.iofile.attr.TemplateLayoutIdAttrMark;
import com.fr.base.theme.FormTheme;
import com.fr.base.theme.FormThemeConfig;
import com.fr.base.theme.TemplateTheme;
@ -117,7 +116,6 @@ import java.util.List;
public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<Form>, Releasable {
private static final String FORM_CARD = "FORM";
private static final String ELEMENTCASE_CARD = "ELEMENTCASE";
private static final String EMPTY_FORM_LAYOUTID = "9ebf6aff-ad53-45a9-a175-9633f4162a3a";
private static final String[] CARDNAME = new String[]{FORM_CARD, ELEMENTCASE_CARD};
private static final int TOOLBARPANEDIMHEIGHT_FORM = 60;
@ -138,8 +136,7 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
protected int index = FORM_TAB;
public JForm() {
super(new Form(new WBorderLayout("form")), "Form");
initEmptyFormLayoutId();
this(new Form(new WBorderLayout("form")));
}
public JForm(Form form) {
@ -154,12 +151,6 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
super(form, file);
}
private void initEmptyFormLayoutId() {
Form form = this.getTarget();
form.addAttrMark(new TemplateLayoutIdAttrMark(EMPTY_FORM_LAYOUTID));
form.setLayoutId(EMPTY_FORM_LAYOUTID);
}
@Override
protected void addPane(PropertyItemPaneProvider provider) {

17
designer-form/src/main/java/com/fr/design/mainframe/share/AbstractWidgetSelectPane.java

@ -1,6 +1,7 @@
package com.fr.design.mainframe.share;
import com.fr.design.mainframe.share.ui.base.PopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.LocalWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
@ -13,16 +14,16 @@ import java.awt.Container;
* @Author: Yuan.Wang
* @Date: 2021/1/15
*/
public abstract class AbstractWidgetSelectPane extends JPanel {
public abstract class AbstractWidgetSelectPane<T> extends JPanel {
private static final int SCROLL_BAR_HEIGHT = 10;
private final PopupPreviewPane previewPane;
private final AbstractWidgetPopupPreviewPane<T> previewPane;
private String currentShowWidgetID;
public AbstractWidgetSelectPane() {
this.previewPane = new PopupPreviewPane();
this.previewPane = createPopupPreviewPane();
}
public void showPreviewPane(PreviewWidgetBlock<?> comp, String showWidgetID) {
public void showPreviewPane(PreviewWidgetBlock<T> comp, String showWidgetID) {
if (ComparatorUtils.equals(currentShowWidgetID, showWidgetID)) {
return;
}
@ -36,7 +37,7 @@ public abstract class AbstractWidgetSelectPane extends JPanel {
this.currentShowWidgetID = StringUtils.EMPTY;
}
private void popupPreviewPane(PreviewWidgetBlock<?> comp, String showWidgetID) {
private void popupPreviewPane(PreviewWidgetBlock<T> comp, String showWidgetID) {
if (previewPane.isVisible()) {
previewPane.setVisible(false);
}
@ -44,7 +45,7 @@ public abstract class AbstractWidgetSelectPane extends JPanel {
if (!previewPane.isVisible() && comp.getWidth() != 0 && comp.getHeight() != 0) {
//父容器是GroupPane,要获得的是GroupPane的父容器
Container parentContainer =getParentContainer();
previewPane.setComp(comp.getPreviewImage());
previewPane.populateBean(comp);
int popupPosY = comp.getLocationOnScreen().y - parentContainer.getLocationOnScreen().y;
if (previewPane.getHeight() + popupPosY > parentContainer.getHeight() + SCROLL_BAR_HEIGHT) {
popupPosY -= (previewPane.getHeight() + popupPosY - parentContainer.getHeight() - SCROLL_BAR_HEIGHT);
@ -58,5 +59,7 @@ public abstract class AbstractWidgetSelectPane extends JPanel {
}
}
protected abstract AbstractWidgetPopupPreviewPane<T> createPopupPreviewPane();
abstract protected Container getParentContainer();
}

153
designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/DownloadSuitableThemeAction.java

@ -0,0 +1,153 @@
package com.fr.design.mainframe.share.ui.actions;
import com.fr.base.theme.FormTheme;
import com.fr.base.theme.FormThemeConfig;
import com.fr.base.theme.TemplateTheme;
import com.fr.base.theme.TemplateThemeConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.stable.StringUtils;
import com.fr.transaction.CallBackAdaptor;
import com.fr.workspace.WorkContext;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import java.awt.event.ActionEvent;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/28
*/
public class DownloadSuitableThemeAction extends UpdateAction {
private final String themePath;
private boolean downloading = false;
public DownloadSuitableThemeAction(String themePath) {
this.themePath = themePath;
this.putValue(Action.SMALL_ICON, null);
this.setName(Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme"));
}
@Override
public void actionPerformed(ActionEvent e) {
if (checkAuthority()) {
saveTheme();
}
}
private boolean checkAuthority() {
if (!WorkContext.getCurrent().isRoot()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_No_Authority_Tip_Message"),
Toolkit.i18nText("Fine-Design_Share_Download_Suitable_Theme_No_Authority_Tip_Title"),
JOptionPane.WARNING_MESSAGE);
return false;
}
String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername();
if (StringUtils.isEmpty(userName)) {
DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL);
return false;
}
return true;
}
private void saveTheme() {
if (downloading) {
return;
}
downloading = true;
final JTemplate<?,?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() {
FormTheme theme = fetchRemoteTheme();
if (theme == null) {
return false;
}
theme = ensureThemeHasUniqueName(theme, theme.getName());
if (theme == null) {
return false;
}
String themeName = theme.getName();
saveThemeToConfig(theme, new SaveToThemeConfigCallback(template, themeName));
return true;
}
@Override
protected void done() {
downloading = false;
}
}.execute();
}
private FormTheme fetchRemoteTheme() {
return DownloadUtils.downloadThemeFile(themePath);
}
private FormTheme ensureThemeHasUniqueName(FormTheme theme, String expectedName) {
if (!FormThemeConfig.getInstance().contains(expectedName)) {
theme.setName(expectedName);
return theme;
} else {
String newName = (String) FineJOptionPane.showInputDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Rename_Suitable_Theme_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Rename"),
FineJOptionPane.QUESTION_MESSAGE, null, null,
expectedName);
return StringUtils.isEmpty(newName) ? null : ensureThemeHasUniqueName(theme, newName);
}
}
private void saveThemeToConfig(final FormTheme theme, CallBackAdaptor callback) {
FormThemeConfig.getInstance().addTheme(theme, true, callback);
}
public static class SaveToThemeConfigCallback extends CallBackAdaptor {
private final JTemplate<?,?> template;
private final String themeName;
public SaveToThemeConfigCallback(JTemplate<?, ?> template, String themeName) {
this.template = template;
this.themeName = themeName;
}
@Override
public void afterCommit() {
super.afterCommit();
int returnVal = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Apply_Suitable_Theme_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
FineJOptionPane.OK_CANCEL_OPTION);
if (returnVal == JOptionPane.YES_OPTION) {
applyTheme(template, themeName);
}
}
private void applyTheme(JTemplate<?,?> template, final String name) {
TemplateThemeConfig<? extends TemplateTheme> config = template.getUsingTemplateThemeConfig();
TemplateTheme theme = config.cachedFetch(name);
template.setTemplateTheme(theme);
}
}
}

41
designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java

@ -0,0 +1,41 @@
package com.fr.design.mainframe.share.ui.actions;
import com.fr.design.actions.UpdateAction;
import com.fr.design.i18n.Toolkit;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.stable.StringUtils;
import javax.swing.Action;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/28
*/
public class Jump2DetailAction extends UpdateAction {
private static final String ONLINE_WIDGET_DETAIL_FORMATTED_URL = "https://market.fanruan.com/reuse/%s";
private final String id;
public Jump2DetailAction(String id) {
this.id = id;
this.putValue(Action.SMALL_ICON, null);
this.setName(Toolkit.i18nText("Fine-Design_Share_Jump_To_Detail"));
}
@Override
public void actionPerformed(ActionEvent e) {
if (StringUtils.isNotEmpty(id)) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(new URI(String.format(ONLINE_WIDGET_DETAIL_FORMATTED_URL, id)));
} catch (IOException | URISyntaxException ioException) {
ioException.printStackTrace();
}
}
}
}

15
designer-form/src/main/java/com/fr/design/mainframe/share/ui/base/AbstractWidgetPopupPreviewPane.java

@ -0,0 +1,15 @@
package com.fr.design.mainframe.share.ui.base;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import javax.swing.JPopupMenu;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/15
*/
public abstract class AbstractWidgetPopupPreviewPane<T> extends JPopupMenu {
public abstract void populateBean(PreviewWidgetBlock<T> block);
}

14
designer-form/src/main/java/com/fr/design/mainframe/share/ui/base/PopupPreviewPane.java → designer-form/src/main/java/com/fr/design/mainframe/share/ui/base/LocalWidgetPopupPreviewPane.java

@ -1,6 +1,9 @@
package com.fr.design.mainframe.share.ui.base;
import com.fr.design.constants.UIConstants;
import com.fr.design.mainframe.share.ui.block.LocalWidgetBlock;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.general.IOUtils;
import javax.swing.BorderFactory;
@ -17,17 +20,16 @@ import java.awt.Toolkit;
/**
* Created by kerry on 2020-06-23
*/
public class PopupPreviewPane extends JPopupMenu {
private Container contentPane;
public class LocalWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane<DefaultSharableWidget> {
private Image compImage;
private static final int WIDTH = 400;
private static final int STANDARD_DPI = 128;
private static final int MAX_HEIGHT = 400;
private static final int HEIGHT = 210;
public PopupPreviewPane() {
public LocalWidgetPopupPreviewPane() {
setFocusable(false);
contentPane = new JPanel();
Container contentPane = new JPanel();
contentPane.setBackground(Color.white);
this.setLayout(new BorderLayout());
this.add(contentPane, BorderLayout.CENTER);
@ -36,9 +38,9 @@ public class PopupPreviewPane extends JPopupMenu {
setBorder(BorderFactory.createLineBorder(UIConstants.LINE_COLOR));
}
public void setComp(Image compImage) {
public void populateBean(PreviewWidgetBlock<DefaultSharableWidget> block) {
try {
this.compImage = compImage;
this.compImage = block.getPreviewImage();
this.updateSize();
} catch (Exception e) {
e.printStackTrace();

36
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/AbstractOnlineWidgetBlock.java

@ -1,20 +1,28 @@
package com.fr.design.mainframe.share.ui.block;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.mainframe.share.ui.actions.DownloadSuitableThemeAction;
import com.fr.design.mainframe.share.ui.actions.Jump2DetailAction;
import com.fr.design.mainframe.share.ui.online.OnlineResourceManager;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.online.ResourceLoader;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StringUtils;
import com.fr.third.springframework.web.util.UriUtils;
import org.jetbrains.annotations.NotNull;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URL;
@ -91,4 +99,32 @@ public abstract class AbstractOnlineWidgetBlock extends PreviewWidgetBlock<Onlin
this.parentPane.repaint();
}
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == MouseEvent.BUTTON3) {
this.parentPane.hidePreviewPane();
JPopupMenu popupMenu = createRightClickPopupMenu();
GUICoreUtils.showPopupMenu(popupMenu, this, e.getX(), e.getY());
}
}
public JPopupMenu createRightClickPopupMenu() {
UIPopupMenu popupMenu = new UIPopupMenu();
popupMenu.setOnlyText(true);
popupMenu.setBackground(UIConstants.DEFAULT_BG_RULER);
OnlineShareWidget widget = getWidget();
String suitableThemeFile = widget.getThemePath();
if (StringUtils.isNotEmpty(suitableThemeFile)) {
popupMenu.add(new DownloadSuitableThemeAction(suitableThemeFile).createMenuItem());
}
popupMenu.add(new Jump2DetailAction(getWidget().getId()).createMenuItem());
return popupMenu;
}
}

28
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java

@ -195,30 +195,36 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
hidePreview();
ComponentCollector.getInstance().collectPopupJump();
Object source = e.getSource();
Widget creatorSource;
String shareId;
if (source instanceof LocalWidgetBlock) {
LocalWidgetBlock no = (LocalWidgetBlock) e.getSource();
if (no == null) {
return;
}
shareId = no.getBindInfo().getId();
creatorSource = getGroup().getElCaseEditorById(shareId);
if (creatorSource == null) {
ShareUIUtils.showErrorMessageDialog(Toolkit.i18nText("Fine-Design_Share_Drag_Error_Info"));
XCreator xCreator= transformXCreator(no);
if (xCreator == null) {
return;
}
creatorSource.setWidgetID(UUID.randomUUID().toString());
((AbstractBorderStyleWidget) creatorSource).addWidgetAttrMark(new SharableAttrMark(true));
//tab布局WCardMainBorderLayout通过反射出来的大小是960*480
String suitableTemplateThemeName = no.getWidget().getSuitableTemplateThemeName();
XCreator xCreator = ShareComponentUtils.createThemedXCreator(creatorSource, suitableTemplateThemeName, shareId, no.getBindInfo());
WidgetToolBarPane.getTarget().startDraggingBean(xCreator);
lastPressEvent = null;
this.setBorder(null);
}
}
public XCreator transformXCreator(LocalWidgetBlock block) {
String shareId = block.getBindInfo().getId();
Widget creatorSource = getGroup().getElCaseEditorById(shareId);
if (creatorSource == null) {
ShareUIUtils.showErrorMessageDialog(Toolkit.i18nText("Fine-Design_Share_Drag_Error_Info"));
return null;
}
creatorSource.setWidgetID(UUID.randomUUID().toString());
((AbstractBorderStyleWidget) creatorSource).addWidgetAttrMark(new SharableAttrMark(true));
//tab布局WCardMainBorderLayout通过反射出来的大小是960*480
String suitableTemplateThemeName = block.getWidget().getSuitableTemplateThemeName();
XCreator xCreator = ShareComponentUtils.createThemedXCreator(creatorSource, suitableTemplateThemeName, shareId, block.getBindInfo());
return xCreator;
}
@Override
public void paint(Graphics g) {
super.paint(g);

3
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java

@ -112,7 +112,8 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (!checkWidgetInstalled() && getDownloadIconRec().contains(e.getX(), e.getY())) {
boolean isLeftClickDownloadIcon = e.getButton() != MouseEvent.BUTTON3 && getDownloadIconRec().contains(e.getX(), e.getY());
if (isLeftClickDownloadIcon && !checkWidgetInstalled()) {
downLoadWidget();
}
}

3
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetPackageBlock.java

@ -35,7 +35,7 @@ public class OnlineWidgetPackageBlock extends AbstractOnlineWidgetBlock {
detailLabel.addMouseListener(new MouseClickListener() {
@Override
public void mouseClicked(MouseEvent e) {
parentPane.showWidgetDetailPane(widget.getId());
parentPane.showWidgetDetailPane(widget);
}
});
southPane.add(detailLabel, BorderLayout.EAST);
@ -51,7 +51,6 @@ public class OnlineWidgetPackageBlock extends AbstractOnlineWidgetBlock {
this.setPreferredSize(new Dimension(ShareComponentConstants.SHARE_PACKAGE_BLOCK_WIDTH, ShareComponentConstants.SHARE_PACKAGE_BLOCK_HEIGHT));
this.add(createSouthPane(widget, parentPane), BorderLayout.SOUTH);
}
}

2
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java

@ -40,7 +40,7 @@ import java.util.List;
* @Author: Yuan.Wang
* @Date: 2020/11/5
*/
class GroupPane extends JPanel {
public class GroupPane extends JPanel {
private static final Icon downIcon = IOUtils.readIcon("/com/fr/base/images/share/arrow_down.png");
private static final Icon rightIcon = IOUtils.readIcon("/com/fr/base/images/share/arrow_right.png");
private static final int DEFAULT_HEIGHT = 24;

9
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetSelectPane.java

@ -1,6 +1,8 @@
package com.fr.design.mainframe.share.ui.local;
import com.fr.design.mainframe.share.AbstractWidgetSelectPane;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.LocalWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.block.LocalWidgetBlock;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.SharableWidgetProvider;
@ -22,7 +24,7 @@ import java.awt.event.MouseEvent;
/**
* created by Harrison on 2020/03/23
**/
public class LocalWidgetSelectPane extends AbstractWidgetSelectPane {
public class LocalWidgetSelectPane extends AbstractWidgetSelectPane<DefaultSharableWidget> {
private LocalWidgetBlock selectedBlock;
private final Group group;
@ -105,6 +107,11 @@ public class LocalWidgetSelectPane extends AbstractWidgetSelectPane {
return selectedBlock;
}
@Override
protected AbstractWidgetPopupPreviewPane<DefaultSharableWidget> createPopupPreviewPane() {
return new LocalWidgetPopupPreviewPane();
}
@Override
protected Container getParentContainer() {
return this.getParent().getParent();

212
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java

@ -0,0 +1,212 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Toolkit;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/14
*/
public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane<OnlineShareWidget> {
private static final int POPUP_WIDTH = 412;
private static final int POPUP_TOP_HEIGHT = 28;
private static final int POPUP_BOTTOM_HEIGHT = 54;
private PreviewImagePane previewImagePane;
private UILabel versionLabel;
private UILabel downloadsLabel;
private UILabel priceLabel;
private final JPanel suitableThemeNamePane;
private UILabel suitableThemeNameLabel;
public OnlineWidgetPopupPreviewPane() {
setPreferredSize(new Dimension(POPUP_WIDTH, getPreferredSize().height));
setLayout(new BorderLayout(0, 0));
setOpaque(true);
setBackground(new Color(0xF0F0F1));
suitableThemeNamePane = createSuitableThemeNamePane();
JPanel previewImagePane = createPreviewImagePane();
JPanel widgetInfoPane = createWidgetInfoPane();
addComponents(suitableThemeNamePane, previewImagePane, widgetInfoPane);
}
private JPanel createSuitableThemeNamePane() {
suitableThemeNameLabel = new UILabel();
suitableThemeNameLabel.setOpaque(false);
suitableThemeNameLabel.setBackground(new Color(0xF5F5F7));
suitableThemeNameLabel.setIcon(IOUtils.readIcon("/com/fr/design/icon/icon_predefined_style.png"));
suitableThemeNameLabel.setIconTextGap(IntervalConstants.INTERVAL_L6);
JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane();
content.setPreferredSize(new Dimension(POPUP_WIDTH, POPUP_TOP_HEIGHT));
content.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
content.setOpaque(true);
content.setBackground(new Color(0xF5F5F7));
content.add(suitableThemeNameLabel, BorderLayout.CENTER);
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.add(content, BorderLayout.CENTER);
JSeparator separator = new JSeparator();
separator.setPreferredSize(new Dimension(POPUP_WIDTH, 1));
separator.setBackground(new Color(0xE8E8E9));
container.add(separator, BorderLayout.SOUTH);
return container;
}
private JPanel createPreviewImagePane() {
previewImagePane = new PreviewImagePane();
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
container.add(previewImagePane, BorderLayout.CENTER);
return container;
}
private JPanel createWidgetInfoPane() {
versionLabel = new UILabel();
versionLabel.setVerticalAlignment(SwingConstants.CENTER);
versionLabel.setFont(FRFont.getInstance(versionLabel.getFont()).deriveFont(12.0F));
downloadsLabel = new UILabel();
downloadsLabel.setVerticalAlignment(SwingConstants.TOP);
downloadsLabel.setFont(FRFont.getInstance(downloadsLabel.getFont()).deriveFont(12.0F));
priceLabel = new UILabel();
priceLabel.setVerticalAlignment(SwingConstants.CENTER);
priceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
priceLabel.setFont(FRFont.getInstance(priceLabel.getFont()).deriveFont(14.0F));
priceLabel.setForeground(new Color(0xE65251));
JPanel container = new JPanel();
container.setPreferredSize(new Dimension(POPUP_WIDTH - 20, POPUP_BOTTOM_HEIGHT));
container.setLayout(new GridBagLayout());
container.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
container.add(versionLabel, constraints);
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
container.add(downloadsLabel, constraints);
constraints.gridx = 1;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 2;
constraints.weightx = 1;
constraints.weighty = 2;
container.add(priceLabel, constraints);
return container;
}
private void addComponents(JComponent... components) {
if (components == null) {
return;
}
JComponent container = this;
for (int i = 0; i < components.length; i++) {
JComponent component = components[i];
if (component != null) {
container.add(component, BorderLayout.NORTH);
if (i < components.length - 1) {
JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.add(nextContainer, BorderLayout.CENTER);
container = nextContainer;
}
}
}
}
@Override
public void populateBean(PreviewWidgetBlock<OnlineShareWidget> block) {
OnlineShareWidget widget = block.getWidget();
String themeName = widget.getThemeName();
if (StringUtils.isNotEmpty(themeName)) {
suitableThemeNamePane.setVisible(true);
suitableThemeNameLabel.setText(themeName);
} else {
suitableThemeNamePane.setVisible(false);
}
String priceText = "¥" + widget.getPrice();
if (widget.getPrice() <= 0) {
priceText = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Price_Free");
}
priceLabel.setText(priceText);
versionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Version") + ": " + widget.getDesignerVersion());
downloadsLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Download_Times") + ": " + widget.getDownloadTimes());
previewImagePane.setPreviewImage(block.getPreviewImage());
int height = (suitableThemeNamePane.isVisible() ? POPUP_TOP_HEIGHT : 0) + 10 + previewImagePane.getPreferredSize().height + POPUP_BOTTOM_HEIGHT;
setPreferredSize(new Dimension(POPUP_WIDTH, height));
}
private static class PreviewImagePane extends JPanel {
private static final Image DEFAULT_IMAGE = IOUtils.readImage("com/fr/base/images/share/component_error.png");
private static final int PREVIEW_IMAGE_WIDTH = POPUP_WIDTH - 20;
private static final int STANDARD_DPI = 128;
private Image previewImage;
public void setPreviewImage(Image previewImage) {
this.previewImage = previewImage;
if (this.previewImage == null) {
this.previewImage = DEFAULT_IMAGE;
}
int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
int imageWidth = this.previewImage.getWidth(null);
int imageHeight = this.previewImage.getHeight(null);
double imageAspectRatio = (double) imageWidth / imageHeight;
int width = (PREVIEW_IMAGE_WIDTH * dpi) / STANDARD_DPI;
int height = (int) (width / imageAspectRatio);
setPreferredSize(new Dimension(width, height));
}
@Override
public void paint(Graphics g) {
g.drawImage(this.previewImage, 0, 0, getWidth(), getHeight(), null);
}
}
}

8
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetSelectPane.java

@ -3,6 +3,7 @@ package com.fr.design.mainframe.share.ui.online;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.AbstractWidgetSelectPane;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.LoadingPane;
import com.fr.design.mainframe.share.ui.base.NoMatchPane;
import com.fr.design.mainframe.share.ui.base.PagingFiledPane;
@ -30,7 +31,7 @@ import java.util.concurrent.ExecutionException;
/**
* Created by kerry on 2020-10-19
*/
public class OnlineWidgetSelectPane extends AbstractWidgetSelectPane {
public class OnlineWidgetSelectPane extends AbstractWidgetSelectPane<OnlineShareWidget> {
protected static final int H_GAP = 5;
protected static final int V_GAP = 10;
@ -219,6 +220,11 @@ public class OnlineWidgetSelectPane extends AbstractWidgetSelectPane {
}
}
@Override
protected AbstractWidgetPopupPreviewPane<OnlineShareWidget> createPopupPreviewPane() {
return new OnlineWidgetPopupPreviewPane();
}
protected Container getParentContainer() {
return this.getParent();
}

4
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackageSelectPane.java

@ -25,8 +25,8 @@ public class OnlineWidgetPackageSelectPane extends OnlineWidgetSelectPane {
}
public void showWidgetDetailPane(String id) {
this.parentPane.showWidgetDetailPane(id);
public void showWidgetDetailPane(OnlineShareWidget widgetPackage) {
this.parentPane.showWidgetDetailPane(widgetPackage);
}
protected PreviewWidgetBlock<OnlineShareWidget> createWidgetBlock(OnlineShareWidget provider) {

5
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java

@ -150,10 +150,11 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane {
return onlineShareWidgets.toArray(new OnlineShareWidget[onlineShareWidgets.size()]);
}
public void showWidgetDetailPane(final String id) {
public void showWidgetDetailPane(final OnlineShareWidget widgetPackage) {
String id = widgetPackage.getId();
currentPackageId = id;
boolean containsCache = cachePanelMap.containsKey(id);
onlineWidgetSelectPane = containsCache ? cachePanelMap.get(id) : new OnlineWidgetSelectPane(() -> ShareUtils.getPackageWidgets(id), 50);
onlineWidgetSelectPane = containsCache ? cachePanelMap.get(id) : new OnlineWidgetSelectPane(() -> ShareUtils.getPackageWidgets(widgetPackage), 50);
downloadLabel.setVisible(!containsCache);
showWidgetDetailPane(onlineWidgetSelectPane);
}

42
designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe.share.util;
import com.fr.base.theme.FormTheme;
import com.fr.design.DesignerEnvManager;
import com.fr.design.extra.PluginConstants;
import com.fr.form.share.base.CancelCheck;
@ -9,6 +10,10 @@ import com.fr.general.CloudCenter;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReaderHelper;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.HttpException;
import com.fr.third.org.apache.http.HttpStatus;
@ -23,9 +28,12 @@ import com.fr.third.org.apache.http.impl.client.HttpClients;
import org.jetbrains.annotations.NotNull;
import javax.crypto.Cipher;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
@ -130,6 +138,40 @@ public class DownloadUtils {
}
}
public static FormTheme downloadThemeFile(String themePath) {
try {
CloseableHttpResponse fileRes = getHttpResponse(themePath);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) {
fileRes = getHttpResponse(fileRes.getHeaders("Location")[0].getValue());
}
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = fileRes.getEntity();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
String content = stringBuilder.toString();
XMLableReader reader = XMLReaderHelper.createXMLableReader(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), XMLPrintWriter.XML_ENCODER);
FormTheme theme = new FormTheme();
reader.readXMLObject(theme);
if (StringUtils.isNotEmpty(theme.getName())) {
return theme;
}
} else {
FineLoggerFactory.getLogger().info("download theme {} failed", themePath);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
private static CloseableHttpResponse getHttpResponse(String url, String id) throws Exception {
//先登录一下。不然可能失败
CloseableHttpClient client = createClient();

22
designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallComponentHelper.java

@ -32,19 +32,23 @@ public class InstallComponentHelper {
public static void installPreComponent() {
if (needPreInstallComponent()) {
for (String componentPath : PRE_INSTALL_COMPONENTS) {
try {
InputStream inputStream = InstallComponentHelper.class.getResourceAsStream(StableUtils.pathJoin(PRE_INSTALL_PATH, componentPath));
byte[] data = ResourceIOUtils.inputStream2Bytes(inputStream);
WorkContext.getWorkResource().write(StableUtils.pathJoin(ComponentPath.SHARE_PATH.path(), componentPath), data);
} catch (Exception e) {
FineLoggerFactory.getLogger().error("install Component filed" + e.getMessage(), e);
}
}
installShareComponents(PRE_INSTALL_PATH, PRE_INSTALL_COMPONENTS);
}
}
public static void installShareComponents(String resourcePath, String[] components) {
for (String componentPath : components) {
try {
InputStream inputStream = InstallComponentHelper.class.getResourceAsStream(StableUtils.pathJoin(resourcePath, componentPath));
byte[] data = ResourceIOUtils.inputStream2Bytes(inputStream);
WorkContext.getWorkResource().write(StableUtils.pathJoin(ComponentPath.SHARE_PATH.path(), componentPath), data);
} catch (Exception e) {
FineLoggerFactory.getLogger().error("install Component filed" + e.getMessage(), e);
}
}
}
private static boolean needPreInstallComponent() {
try {
//老用户或者组件库里已有组件,不预装组件

2
designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java

@ -43,8 +43,8 @@ public class DeveloperPreview extends AbstractPreviewProvider {
@Override
public void onClick(JTemplate<?, ?> jt) {
MutilTempalteTabPane.getInstance().closeCurrentTpl();
super.onClick(jt);
MutilTempalteTabPane.getInstance().closeCurrentTpl();
}

99
designer-form/src/main/java/com/fr/design/widget/ui/designer/NewFormPane.java

@ -1,5 +1,6 @@
package com.fr.design.widget.ui.designer;
import com.fr.base.iofile.attr.TemplateLayoutIdAttrMark;
import com.fr.design.border.UITitledMatteBorder;
import com.fr.design.designer.beans.PredefinedLayout;
import com.fr.design.designer.beans.models.NewFormModel;
@ -15,6 +16,11 @@ import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.form.main.Form;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.OccupiedLayout;
import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
@ -43,6 +49,8 @@ import java.util.List;
import java.util.Map;
public class NewFormPane extends BasicPane {
private static final String EMPTY_FORM_LAYOUTID = "9ebf6aff-ad53-45a9-a175-9633f4162a3a";
private NewFormModel newFormModel;
private UIDialog dialog;
private PredefinedLayoutPane selectedLayoutPane = null;
@ -55,14 +63,10 @@ public class NewFormPane extends BasicPane {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.add(createModuleListPane(), BorderLayout.WEST);
this.add(createTemplateManagePane(), BorderLayout.CENTER);
initWindow();
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_New_Template");
}
public void showWindow() {
private void initWindow() {
dialog = new UIDialog(DesignerContext.getDesignerFrame(), this) {
@Override
public void checkValid() throws Exception {
@ -73,9 +77,7 @@ public class NewFormPane extends BasicPane {
dialog.addDialogActionListener(new DialogActionListener() {
@Override
public void doOk() {
if (selectedLayoutPane != null) {
NewFormPane.this.newForm(selectedLayoutPane.getTemplatePath());
}
createLayoutForm();
}
@Override
@ -87,6 +89,24 @@ public class NewFormPane extends BasicPane {
GUICoreUtils.centerWindow(dialog);
dialog.setTitle(this.title4PopupWindow());
dialog.setResizable(false);
}
public void createLayoutForm() {
if (selectedLayoutPane != null) {
NewFormPane.this.newForm(selectedLayoutPane.getTemplatePath());
}
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_New_Template");
}
public UIDialog getWindow() {
return dialog;
}
public void showWindow() {
dialog.setVisible(true);
}
@ -264,19 +284,66 @@ public class NewFormPane extends BasicPane {
private void newForm(String path) {
BaseJForm jForm;
try {
if (StringUtils.isNotEmpty(path)) {
Form form = new Form();
form.readStream(NewFormPane.class.getResourceAsStream(path));
jForm = StableFactory.getMarkedInstanceObjectFromClass(BaseJForm.XML_TAG, new Object[]{form}, BaseJForm.class);
} else {
jForm = StableFactory.getMarkedInstanceObjectFromClass(BaseJForm.XML_TAG, BaseJForm.class);
}
Form form = initEmptyBodyForm();
initLayoutInfo(form, path);
jForm = StableFactory.getMarkedInstanceObjectFromClass(BaseJForm.XML_TAG, new Object[]{form}, BaseJForm.class);
DesignerContext.getDesignerFrame().addAndActivateJTemplate((JTemplate<?, ?>) jForm);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private Form initEmptyBodyForm() {
WFitLayout body = new WFitLayout();
WBorderLayout borderLayout = new WBorderLayout("form");
borderLayout.addCenter(body);
return new Form(borderLayout);
}
/**
* 通过布局文件的位置初始化Form对象的布局信息
*
* @param form 新建的form对象
* @param path 布局文件位置
* @throws Exception
*/
private void initLayoutInfo(Form form, String path) throws Exception {
if (isNewEmptyForm(path)) {
initEmptyFormLayoutId(form);
} else {
Form layoutTemplate = new Form();
layoutTemplate.readStream(NewFormPane.class.getResourceAsStream(path));
if (layoutTemplate.getBody() != null && layoutTemplate.getBody() instanceof WFitLayout) {
WFitLayout layoutTemplateBody = (WFitLayout) layoutTemplate.getBody();
WFitLayout body = (WFitLayout) form.getBody();
body.setMargin(layoutTemplateBody.getMargin());
body.setCompInterval(layoutTemplateBody.getCompInterval());
for (int i = 0; i < layoutTemplateBody.getWidgetCount(); i++) {
Widget boundsWidget = layoutTemplateBody.getWidget(i);
if (boundsWidget != null && boundsWidget instanceof BoundsWidget) {
Widget widget = ((BoundsWidget) boundsWidget).getWidget();
if (widget != null && widget instanceof OccupiedLayout) {
body.addWidget((Widget) boundsWidget.clone());
}
}
}
form.setLayoutId(layoutTemplate.getLayoutId());
}
}
}
private void initEmptyFormLayoutId(Form form) {
form.addAttrMark(new TemplateLayoutIdAttrMark(EMPTY_FORM_LAYOUTID));
form.setLayoutId(EMPTY_FORM_LAYOUTID);
}
private boolean isNewEmptyForm(String layoutTemplatePath) {
return StringUtils.isEmpty(layoutTemplatePath);
}
private void setSelectedLayoutPane(PredefinedLayoutPane layoutPane) {
if (selectedLayoutPane != layoutPane) {
if (selectedLayoutPane != null) {

2
designer-form/src/main/java/com/fr/design/widget/ui/designer/PredefinedLayoutPane.java

@ -11,6 +11,7 @@ import com.fr.stable.StringUtils;
import javax.swing.JPanel;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
@ -37,6 +38,7 @@ public class PredefinedLayoutPane extends JPanel {
this.setLayout(cardLayout);
this.add(realStyle, 0);
this.add(simpleStyle, 1);
this.setPreferredSize(new Dimension(235, 134));
this.initListener();
}

6
designer-form/src/main/resources/com/fr/design/form/layouts/config.json

@ -1,6 +1,6 @@
{
"config":{
"2-4模块":[
"2-4":[
{
"template":"2-4/1.frm",
"realStyle":"real_style_1",
@ -32,7 +32,7 @@
"simpleStyle":"simple_style_6"
}
],
"5-7模块":[
"5-7":[
{
"template":"5-7/1.frm",
"realStyle":"real_style_7",
@ -64,7 +64,7 @@
"simpleStyle":"simple_style_12"
}
],
"多模块":[
"multi":[
{
"template":"multi/1.frm",
"realStyle":"real_style_13",

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save