Browse Source

Merge branch 'release/10.0' of https://code.fineres.com/scm/~yuan.wang/design into release/10.0

feature/big-screen
Yuan.Wang 4 years ago
parent
commit
cac9c6d151
  1. 4
      designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBoxTest.java
  2. 2
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java
  3. 4
      designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java
  4. 6
      designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java
  5. 1
      designer-form/src/main/java/com/fr/design/designer/creator/XButton.java
  6. 34
      designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java
  7. 38
      designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java
  8. 19
      designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java
  9. 6
      designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteBodyLayout.java
  10. 8
      designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java
  11. 7
      designer-form/src/main/java/com/fr/design/designer/creator/XWParameterLayout.java
  12. 6
      designer-form/src/main/java/com/fr/design/designer/creator/XWTitleLayout.java
  13. 11
      designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java
  14. 1
      designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java
  15. 1
      designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTitleLayout.java
  16. 8
      designer-form/src/main/java/com/fr/design/designer/treeview/ComponentTreeCellRenderer.java
  17. 41
      designer-form/src/main/java/com/fr/design/mainframe/ComponentTree.java
  18. 4
      designer-form/src/main/java/com/fr/design/mainframe/CoverPane.java
  19. 29
      designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java
  20. 60
      designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java
  21. 5
      designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java
  22. 7
      designer-form/src/main/java/com/fr/design/mainframe/FormHierarchyTreePane.java
  23. 70
      designer-form/src/main/java/com/fr/design/mainframe/widget/topxcreator/BasicTopXCreator.java
  24. 49
      designer-form/src/main/java/com/fr/design/mainframe/widget/topxcreator/TopXCreator.java
  25. 101
      designer-form/src/main/java/com/fr/design/mainframe/widget/topxcreator/TopXCreators.java
  26. 208
      designer-realize/src/main/java/com/fr/start/fx/FastGifImage.java
  27. 208
      designer-realize/src/main/java/com/fr/start/fx/PrismImageLoader2.java
  28. 59
      designer-realize/src/main/java/com/fr/start/fx/SplashFx.java
  29. 194
      designer-realize/src/main/java/com/fr/start/fx/SplashFxWindow.java
  30. 69
      designer-realize/src/main/java/com/fr/start/jni/SplashJNI.java
  31. 100
      designer-realize/src/main/java/com/fr/start/jni/SplashMac.java
  32. BIN
      designer-realize/src/main/resources/com/fr/start/jni/splash.dylib

4
designer-base/src/main/java/com/fr/design/gui/icombobox/LazyComboBoxTest.java

@ -3,10 +3,10 @@
*/
package com.fr.design.gui.icombobox;
import com.fr.design.gui.UILookAndFeel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.log.FineLoggerFactory;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
import javax.swing.JFrame;
import javax.swing.JPanel;
@ -23,7 +23,7 @@ import java.awt.event.ItemListener;
public class LazyComboBoxTest {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new WindowsLookAndFeel());
UIManager.setLookAndFeel(new UILookAndFeel());
} catch (UnsupportedLookAndFeelException e1) {
FineLoggerFactory.getLogger().error(e1.getMessage(), e1);
}

2
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java

@ -856,7 +856,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
BorderLayout.CENTER);
this.setSize(340, 180);
this.setSize(380, 180);
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Mkdir"));
this.setResizable(false);
this.setAlwaysOnTop(true);

4
designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java

@ -62,6 +62,10 @@ public class FineEmbedServerActivator extends Activator {
tomcat.setPort(DesignerEnvManager.getEnvManager().getEmbedServerPort());
// 设置解码uri使用的字符编码
tomcat.getConnector().setURIEncoding(EncodeConstants.ENCODING_UTF_8);
// 参考 https://jira.atlassian.com/browse/CONFSERVER-57582
// https://tomcat.apache.org/tomcat-8.5-doc/config/http.html
// 8.5.x 请求参数带特殊字符被tomcat拒绝 []|{}^\`"<>
tomcat.getConnector().setProperty("relaxedQueryChars", "[]|{}^&#x5c;&#x60;&quot;&lt;&gt;");
setMaxPostSize();
String docBase = new File(WorkContext.getCurrent().getPath()).getParent();

6
designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java

@ -77,12 +77,13 @@ public class SelectionModel {
* @param e 鼠标事件
*/
public void selectACreatorAtMouseEvent(MouseEvent e) {
//单选因为要先从已选择的组件中筛选一遍,所以先选择再reset
XCreator comp = designer.getComponentAt(e);
if (e.getButton() == MouseEvent.BUTTON3 || (!InputEventBaseOnOS.isControlDown(e) && !e.isShiftDown())) {
// 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件
selection.reset();
} else {
//按下Ctrl或者shift键时鼠标可以进行多选,两次点击同一控件就取消选中
XCreator comp = designer.getComponentAt(e);
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(comp).getTopLayout();
if (topLayout != null && !topLayout.isEditable()) {
comp = topLayout;
@ -93,9 +94,9 @@ public class SelectionModel {
selection.removeCreator(selected);
}
}
comp = designer.getComponentAt(e);
}
// 获取e所在的组件
XCreator comp = designer.getComponentAt(e);
selectACreator(comp);
}
@ -309,6 +310,7 @@ public class SelectionModel {
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_DELETED);
setSelectedCreator(isInPara ? designer.getParaComponent() : designer.getRootComponent());
designer.getTopXCreators().refresh();
// 触发事件

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

@ -308,5 +308,4 @@ public class XButton extends XWidgetCreator {
}
}
}

34
designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java

@ -17,6 +17,8 @@ import com.fr.design.mainframe.CoverReportPane;
import com.fr.design.mainframe.EditingMouseListener;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.HelpDialogManager;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.design.mainframe.widget.topxcreator.TopXCreator;
import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
import com.fr.design.module.DesignModuleFactory;
import com.fr.form.ui.BaseChartEditor;
@ -258,6 +260,7 @@ public class XChartEditor extends XBorderStyleWidgetCreator {
(e.getClickCount() == 2 || designer.getCursor().getType() == Cursor.HAND_CURSOR);
displayCoverPane(!isEditing);
selectionModel.selectACreatorAtMouseEvent(e);
editingMouseListener.refreshTopXCreator(isEditing);
if (editingMouseListener.stopEditing()) {
if (this != (XCreator) designer.getRootComponent()) {
@ -357,4 +360,35 @@ public class XChartEditor extends XBorderStyleWidgetCreator {
public boolean supportMobileStyle() {
return false;
}
@Override
public BasicTopXCreator getTopXCreator() {
return new TopXChart(this);
}
private class TopXChart extends TopXCreator {
private final DesignerEditor designerEditor;
public TopXChart(XCreator creator) {
super(creator);
designerEditor = creator.getDesignerEditor();
Rectangle bounds = getBounds();
designerEditor.getEditorTarget().setBounds(bounds.x + 1, bounds.y + 1, bounds.width - 2, bounds.height - 2);
}
/**
* 更新designerEditor的大小
*/
protected void resetSize(Rectangle bounds) {
super.resetSize(bounds);
designerEditor.getEditorTarget().setBounds(bounds.x + 1, bounds.y + 1, bounds.width - 2, bounds.height - 2);
}
@Override
public void paint(Graphics g) {
designerEditor.paintEditor(g, this.getSize());
super.paint(g);
}
}
}

38
designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java

@ -19,16 +19,22 @@ import com.fr.design.mainframe.CoverReportPane;
import com.fr.design.mainframe.EditingMouseListener;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.NoSupportAuthorityEdit;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WTitleLayout;
import com.fr.stable.Constants;
import com.fr.stable.CoreGraphHelper;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.third.javax.annotation.Nullable;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import java.awt.BorderLayout;
@ -38,6 +44,7 @@ import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List;
@ -539,6 +546,8 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo
selectionModel.selectACreatorAtMouseEvent(e);
}
editingMouseListener.refreshTopXCreator();
if (editingMouseListener.stopEditing() && this != designer.getRootComponent()) {
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);
editingMouseListener.startEditing(this, adapter.getDesignerEditor(), adapter);
@ -798,10 +807,37 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo
/**
* 是否支持共享-现只支持报表块图表tab块绝对布局
* @return
*/
public boolean isSupportShared() {
return false;
}
/**
* 获得该组件的顶层显示组件
*/
@Nullable
public BasicTopXCreator getTopXCreator() {
return new BasicTopXCreator(this) {
@Override
protected void addComponent() {
Icon icon = new ImageIcon(getImage());
JLabel jLabel = new JLabel(icon, JLabel.CENTER);
jLabel.setSize(getSize());
this.add(jLabel);
}
};
}
/**
* 获得组件的图像
*/
public BufferedImage getImage() {
BufferedImage image = CoreGraphHelper.createBufferedImage(getWidth(), getHeight());
Graphics g = image.createGraphics();
this.paint(g);
return image;
}
}

19
designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java

@ -13,6 +13,8 @@ import com.fr.design.mainframe.widget.editors.ElementCaseToolBarEditor;
import com.fr.design.mainframe.widget.editors.PaddingMarginEditor;
import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
import com.fr.design.mainframe.widget.propertypane.BrowserFitPropertyEditor;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.design.mainframe.widget.topxcreator.TopXCreator;
import com.fr.form.FormElementCaseContainerProvider;
import com.fr.form.FormElementCaseProvider;
import com.fr.form.FormProvider;
@ -319,6 +321,7 @@ public class XElementCase extends XBorderStyleWidgetCreator implements FormEleme
public void respondClick(EditingMouseListener editingMouseListener,MouseEvent e){
HelpDialogManager.getInstance().setPane(coverPanel);
super.respondClick(editingMouseListener, e);
editingMouseListener.refreshTopXCreator();
if (this.isHelpBtnOnFocus()) {
coverPanel.setMsgDisplay(e);
} else {
@ -370,4 +373,20 @@ public class XElementCase extends XBorderStyleWidgetCreator implements FormEleme
public boolean isSupportShared() {
return true;
}
@Override
public BasicTopXCreator getTopXCreator() {
return new TopXElementCase(this);
}
private class TopXElementCase extends TopXCreator {
private UILabel imageLabel;
public TopXElementCase(XCreator creator) {
super(creator);
imageLabel = initImageBackground();
add(imageLabel);
}
}
}

6
designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteBodyLayout.java

@ -7,6 +7,7 @@ import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.fun.WidgetPropertyUIProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.form.ui.container.WAbsoluteBodyLayout;
import com.fr.stable.core.PropertyChangeAdapter;
@ -130,4 +131,9 @@ public class XWAbsoluteBodyLayout extends XWAbsoluteLayout {
public boolean isSupportShared() {
return false;
}
@Override
public BasicTopXCreator getTopXCreator() {
return null;
}
}

8
designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java

@ -25,6 +25,8 @@ import com.fr.design.mainframe.FormArea;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.WidgetHelpDialog;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.design.mainframe.widget.topxcreator.TopXCreator;
import com.fr.form.ui.Connector;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteLayout;
@ -542,6 +544,7 @@ public class XWAbsoluteLayout extends XLayoutContainer {
selectionModel.selectACreatorAtMouseEvent(e);
designer.repaint();
editingMouseListener.refreshTopXCreator(isEditing);
if (editingMouseListener.stopEditing()) {
if (this != designer.getRootComponent()) {
@ -606,4 +609,9 @@ public class XWAbsoluteLayout extends XLayoutContainer {
return super.getWidgetPropertyUIProviders();
}
}
@Override
public BasicTopXCreator getTopXCreator() {
return new TopXCreator(this);
}
}

7
designer-form/src/main/java/com/fr/design/designer/creator/XWParameterLayout.java

@ -15,6 +15,7 @@ import com.fr.design.mainframe.widget.editors.BooleanEditor;
import com.fr.design.mainframe.widget.editors.WidgetDisplayPosition;
import com.fr.design.mainframe.widget.renderer.BackgroundRenderer;
import com.fr.design.mainframe.widget.renderer.WidgetDisplayPositionRender;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WParameterLayout;
@ -251,4 +252,10 @@ public class XWParameterLayout extends XWAbsoluteLayout {
return false;
}
@Override
public BasicTopXCreator getTopXCreator() {
return null;
}
}

6
designer-form/src/main/java/com/fr/design/designer/creator/XWTitleLayout.java

@ -7,6 +7,7 @@ import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.adapters.layout.FRTitleLayoutAdapter;
import com.fr.design.form.layout.FRTitleLayout;
import com.fr.design.fun.WidgetPropertyUIProvider;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.form.ui.Label;
import com.fr.form.ui.Widget;
import com.fr.form.ui.WidgetTitle;
@ -189,4 +190,9 @@ public class XWTitleLayout extends DedicateLayoutContainer {
XCreator creator = getPropertyDescriptorCreator();
return creator.getWidgetPropertyUIProviders();
}
@Override
public BasicTopXCreator getTopXCreator() {
return getEditingChildCreator().getTopXCreator();
}
}

11
designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java

@ -16,16 +16,15 @@ import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWBorderLayout;
import com.fr.design.designer.creator.XWidgetCreator;
import com.fr.design.designer.properties.mobile.MobileBooKMarkUsePropertyUI;
import com.fr.design.form.util.FormDesignerUtils;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.fun.WidgetPropertyUIProvider;
import com.fr.design.icon.IconPathConstants;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.EditingMouseListener;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.WidgetHelpDialog;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.mainframe.widget.topxcreator.BasicTopXCreator;
import com.fr.design.mainframe.widget.topxcreator.TopXCreator;
import com.fr.form.event.Listener;
import com.fr.form.ui.CardSwitchButton;
import com.fr.form.ui.LayoutBorderStyle;
@ -438,6 +437,7 @@ public class XWCardMainBorderLayout extends XWBorderLayout {
setEditable(isEditing);
selectionModel.selectACreatorAtMouseEvent(e);
editingMouseListener.refreshTopXCreator(isEditing);
designer.repaint();
if (editingMouseListener.stopEditing()) {
@ -514,4 +514,9 @@ public class XWCardMainBorderLayout extends XWBorderLayout {
public boolean isSupportShared() {
return true;
}
@Override
public BasicTopXCreator getTopXCreator() {
return new TopXCreator(this);
}
}

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

@ -248,6 +248,7 @@ public class XWCardTagLayout extends XWHorizontalBoxLayout {
if (e.getClickCount() <= 1) {
selectionModel.selectACreatorAtMouseEvent(e);
}
editingMouseListener.refreshTopXCreator();
if (editingMouseListener.stopEditing()) {
if (this != designer.getRootComponent()) {
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);

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

@ -204,6 +204,7 @@ public class XWCardTitleLayout extends XWBorderLayout {
if (e.getClickCount() <= 1) {
selectionModel.selectACreatorAtMouseEvent(e);
}
editingMouseListener.refreshTopXCreator();
if (editingMouseListener.stopEditing()) {
if (this != designer.getRootComponent()) {

8
designer-form/src/main/java/com/fr/design/designer/treeview/ComponentTreeCellRenderer.java

@ -4,6 +4,7 @@ import com.fr.design.constants.UIConstants;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.gui.ilable.UILabel;
import com.fr.log.FineLoggerFactory;
import javax.swing.Icon;
import javax.swing.JTree;
@ -23,7 +24,12 @@ public class ComponentTreeCellRenderer extends DefaultTreeCellRenderer {
if (value instanceof XCreator) {
String name = ((XCreator) value).toData().getWidgetName();
setText(name);
Icon icon = XCreatorUtils.getCreatorIcon((XCreator) value);
Icon icon = null;
try {
icon = XCreatorUtils.getCreatorIcon((XCreator) value);
} catch (Exception e) {
FineLoggerFactory.getLogger().info("{} has not icon or has been deleted", name);
}
if (icon != null) {
setIcon(icon);
}

41
designer-form/src/main/java/com/fr/design/mainframe/ComponentTree.java

@ -2,6 +2,7 @@ package com.fr.design.mainframe;
import com.fr.design.constants.UIConstants;
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.treeview.ComponentTreeCellRenderer;
import com.fr.design.designer.treeview.ComponentTreeModel;
@ -15,7 +16,9 @@ import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.BorderLayout;
@ -30,6 +33,9 @@ import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
public class ComponentTree extends JTree {
@ -81,6 +87,7 @@ public class ComponentTree extends JTree {
public void setSelectionPath(TreePath path) {
// 不管点击哪一项,都要先退出编辑状态(图表、报表块、绝对布局、tab块)
designer.stopEditing(path);
designer.getTopXCreators().refresh();
super.setSelectionPath(path);
}
@ -129,6 +136,7 @@ public class ComponentTree extends JTree {
setSelectionPaths(treepath);
if (treepath.length > 0) {
scrollPathToVisible(treepath[0]);
//expandPath(treepath[0]);
}
}
@ -228,6 +236,39 @@ public class ComponentTree extends JTree {
repaint();
}
/**
* 获得树的展开路径
* */
public void getExpandNodes(List<TreePath> searchList) {
getExpandNodes((XLayoutContainer)designer.getTopContainer(),searchList);
}
public void getExpandNodes(XLayoutContainer container, List<TreePath> searchList) {
for (int i = 0, size = container.getXCreatorCount(); i < size; i++) {
XCreator creator = container.getXCreator(i);
TreePath treePath=buildTreePath(creator);
if(isExpanded(treePath)) searchList.add(treePath);
if (creator instanceof XLayoutContainer) {
getExpandNodes((XLayoutContainer) creator, searchList);
}
}
}
/**
* 将树按照展开路径进行展开
* */
public void expandNodes(List<TreePath> list){
for(TreePath treePath:list) {
if (treePath.getLastPathComponent() instanceof XLayoutContainer) {
XLayoutContainer creator= (XLayoutContainer) treePath.getLastPathComponent();
if (XCreatorUtils.getParentXLayoutContainer(creator) == null) {
continue;
}
expandPath(treePath);
}
}
}
private TreePath buildTreePath(Component comp) {
ArrayList<Component> path = new ArrayList<Component>();
Component parent = comp;

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

@ -8,7 +8,7 @@ import com.fr.general.IOUtils;
import com.fr.stable.Constants;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
@ -28,7 +28,7 @@ import java.awt.Rectangle;
* Date: 14-7-24
* Time: 上午9:09
*/
public class CoverPane extends JPanel {
public class CoverPane extends JComponent {
private UIButton editButton;
private AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);

29
designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java

@ -210,6 +210,7 @@ public class EditingMouseListener extends MouseInputAdapter {
*/
public void mouseReleased(MouseEvent e) {
MouseEvent transEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
MouseEvent clickEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
int oldX = e.getX();
int oldY = e.getY();
offsetEventPoint(e);
@ -234,14 +235,21 @@ public class EditingMouseListener extends MouseInputAdapter {
lastPressEvent = null;
lastXCreator = null;
e.translatePoint(oldX - e.getX(), oldY - e.getY());
if (pressX != oldX || pressY != oldY) {
if (isAutoFire(transEvent, clickEvent)) {
// click只有在mouseReleased和mousePressed前后x/y坐标相等时才会被触发在mouseReleased之后
// 但是当使用者来回点击切换时 存在mouseReleased和mousePressed前后x/y坐标不相等的情况 即鼠标按下去的位置和鼠标释放的位置不相等 存在偏移
// 当这种偏移很小时 看起来就好像是点击了 实际上是手抖了或者鼠标轻微滑动了 所以这里对这种情况要有容错处理
mouseClicked(transEvent);
mouseClicked(clickEvent);
}
}
private boolean isAutoFire(MouseEvent transEvent, MouseEvent clickEvent ) {
offsetEventPoint(transEvent);
XCreator xCreator = designer.getComponentAt(transEvent);
return (pressX != clickEvent.getX() || pressY != clickEvent.getY())
&& xCreator != null && xCreator.acceptType(XCardSwitchButton.class);
}
private void mouseDraggingRelease(MouseEvent e) {
// 当前鼠标所在的组件
XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY());
@ -308,6 +316,7 @@ public class EditingMouseListener extends MouseInputAdapter {
XCreator component = designer.getComponentAt(e);
setCoverPaneNotDisplay(component, e, false);
designer.getTopXCreators().displayCoverPane(e);
if (processTopLayoutMouseMove(component, e)) {
return;
@ -692,6 +701,7 @@ public class EditingMouseListener extends MouseInputAdapter {
currentXCreator.stopEditing();
currentXCreator = null;
currentEditor = null;
refreshTopXCreator();
return true;
}
return true;
@ -719,4 +729,19 @@ public class EditingMouseListener extends MouseInputAdapter {
}
currentEditor.getEditorTarget().setBounds(bounds);
}
/**
* 刷新顶层组件
* */
public void refreshTopXCreator(boolean isEditing){
designer.refreshTopXCreator(isEditing);
}
/**
* 刷新顶层组件
* */
public void refreshTopXCreator(){
refreshTopXCreator(false);
}
}

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

@ -35,7 +35,9 @@ import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteBodyLayout;
import com.fr.design.designer.creator.XWAbsoluteLayout;
import com.fr.design.designer.creator.XWBorderLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.creator.XWTitleLayout;
import com.fr.design.designer.properties.FormWidgetAuthorityEditPane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.event.DesignerOpenedListener;
@ -43,6 +45,7 @@ import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.fun.RightSelectionHandlerProvider;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.mainframe.widget.topxcreator.TopXCreators;
import com.fr.design.menu.MenuDef;
import com.fr.design.menu.ShortCut;
import com.fr.design.menu.ToolBarDef;
@ -121,6 +124,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
private FormArea formArea;
private ConnectorHelper connectorHelper;
private boolean isReportBlockEditing = false;
private TopXCreators topXCreators;
//组件重叠
private boolean isWidgetsIntersect = false;
@ -184,6 +188,8 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
new FormDesignerDropTarget(this);// 添加Drag and Drop.
this.switchAction = switchAction;
topXCreators=new TopXCreators(this);
add(topXCreators);
// 必须刷新"参数/控件树"面板,否则,若最近一次打开模版为 cpt,重启设计器,打开 frm,控件树消失
populateParameterPropertyPane();
@ -825,6 +831,40 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
return null;
}
/**
* 从已选择的组件中找x,y所在的组件
*/
private XCreator xCreatorAt(int x, int y, XCreator[] xCreators) {
for (XCreator creator : xCreators) {
if (creator == null || !creator.isVisible()) {
continue;
}
if (creator instanceof XWAbsoluteBodyLayout || creator instanceof XWFitLayout || creator instanceof XWParameterLayout) {
continue;
}
x -= creator.getX();
y -= creator.getY();
Rectangle rect = ComponentUtils.computeVisibleRect(creator);
// 判断是否处于交叉区域
if (!isIntersectArea(x, y, rect)) {
continue;
}
if (creator instanceof XWTitleLayout) {
return creator.getEditingChildCreator();
}
return creator;
}
return null;
}
/**
* 刷新顶层组件
* */
public void refreshTopXCreator(boolean isEditing){
topXCreators.refresh();
topXCreators.setVisible(!isEditing);
}
private boolean isIntersectArea(int x, int y, Rectangle rect) {
return x >= rect.getX() && (x <= (rect.getX() + rect.getWidth())) && (y >= rect.getY())
&& (y <= (rect.getY() + rect.getHeight()));
@ -984,6 +1024,10 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
invalidateLayout();
}
public TopXCreators getTopXCreators() {
return topXCreators;
}
public StateModel getStateModel() {
return stateModel;
}
@ -1001,9 +1045,19 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
return getComponentAt(p.x, p.y);
}
/**
* 先从已选择则的组件中去找再遍历root去找
* */
@Override
public XCreator getComponentAt(int x, int y) {
return getComponentAt(x, y, null);
XLayoutContainer container = y < paraHeight - formArea.getVerticalValue() ? paraComponent : rootComponent;
if (container == null) {
container = rootComponent;
}
int relativeX = x + (int) (formArea.getHorizontalValue() / scale) - container.getX();
int relativeY = y + (int) (formArea.getVerticalValue() / scale) - container.getY();
XCreator result = xCreatorAt(relativeX, relativeY, selectionModel.getSelection().getSelectedCreators());
return result == null ? getComponentAt(x, y, null) : result;
}
@Nullable
@ -1311,6 +1365,10 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
}
public void paintTopCreators(Graphics clipg){
topXCreators.paint(clipg);
}
/**
* 重置组件边界
*/

5
designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java

@ -84,6 +84,7 @@ public class FormDesignerUI extends ComponentUI {
// 设计参数面板
repaintPara(g, paraComponent, c);
}
repaintTopXCreators(g);
if (designer.isDrawLineMode() && designer.getDrawLineHelper().drawLining()) {
designer.getDrawLineHelper().drawAuxiliaryLine(g);
@ -445,4 +446,8 @@ public class FormDesignerUI extends ComponentUI {
ComponentUtils.resetBuffer(dbcomponents);
}
private void repaintTopXCreators(Graphics g){
designer.paintTopCreators(g);
}
}

7
designer-form/src/main/java/com/fr/design/mainframe/FormHierarchyTreePane.java

@ -24,12 +24,14 @@ import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
/**
@ -89,10 +91,13 @@ public class FormHierarchyTreePane extends FormDockView implements HierarchyTree
/**
* 刷新
*/
//TODO 太乱了,需要重写,监听器里加了监听器是什么意思,每次调用该方法都会添加一个新的监听器
public void refreshDockingView() {
FormDesigner formDesigner = this.getEditingFormDesigner();
List<TreePath> list = new ArrayList<>();
removeAll();
if (this.componentTree != null) {
componentTree.getExpandNodes(list);
this.componentTree.removeAll();
}
if (formDesigner == null) {
@ -100,6 +105,8 @@ public class FormHierarchyTreePane extends FormDockView implements HierarchyTree
return;
}
componentTree = new ComponentTree(formDesigner);
//保证删除组件后组件树不收起
componentTree.expandNodes(list);
formDesigner.addDesignerEditListener(new DesignerEditListener() {
@Override
public void fireCreatorModified(DesignerEvent evt) {

70
designer-form/src/main/java/com/fr/design/mainframe/widget/topxcreator/BasicTopXCreator.java

@ -0,0 +1,70 @@
package com.fr.design.mainframe.widget.topxcreator;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.utils.ComponentUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* @Author: Yuan.Wang
* @Date: 2020/8/31
*/
public class BasicTopXCreator extends JComponent {
private FormDesigner designer;
private XCreator creator;
public BasicTopXCreator(XCreator creator) {
this.designer = WidgetPropertyPane.getInstance().getEditingFormDesigner();
this.creator = creator;
init();
}
private void init() {
setOpaque(false);
setBackground(null);
setLayout(null);
setBounds(calculateBounds());
addComponent();
}
//子类可能会重写该方法
protected void resetSize(Rectangle bounds) {
//do nothing
}
protected void addComponent() {
}
/**
* 重新设置组件大小
* */
public void resizeTopXCreator() {
Rectangle bounds=calculateBounds();
setBounds(bounds);
resetSize(bounds);
}
public void displayCoverPane(MouseEvent e, boolean visible) {}
/**
* 计算显示大小
* */
private Rectangle calculateBounds() {
Rectangle rect = ComponentUtils.getRelativeBounds(creator);
Rectangle bounds = new Rectangle(0, 0, creator.getWidth(), creator.getHeight());
bounds.x += (rect.x - designer.getHorizontalScaleValue());
bounds.y += (rect.y - designer.getVerticalScaleValue());
return bounds;
}
@Override
public void paint(Graphics g) {
super.paint(g);
}
}

49
designer-form/src/main/java/com/fr/design/mainframe/widget/topxcreator/TopXCreator.java

@ -0,0 +1,49 @@
package com.fr.design.mainframe.widget.topxcreator;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.mainframe.CoverReportPane;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* @Author: Yuan.Wang
* @Date: 2020/8/26
*/
public class TopXCreator extends BasicTopXCreator {
private final CoverReportPane coverPanel;
public TopXCreator(XCreator creator) {
super(creator);
coverPanel = new CoverReportPane();
init();
}
private void init() {
coverPanel.setSize(getSize());
coverPanel.setVisible(false);
add(coverPanel);
}
protected void resetSize(Rectangle bounds) {
coverPanel.setSize(getSize());
}
/**
* 设置是否显示蒙层
* */
public void displayCoverPane(boolean visible) {
coverPanel.setVisible(visible);
}
/**
* 依据鼠标事件和visible设置是否显示蒙层
* */
public void displayCoverPane(MouseEvent event, boolean visible) {
boolean isVisible = visible && getBounds().contains(event.getX(), event.getY());
coverPanel.setVisible(isVisible);
}
}

101
designer-form/src/main/java/com/fr/design/mainframe/widget/topxcreator/TopXCreators.java

@ -0,0 +1,101 @@
package com.fr.design.mainframe.widget.topxcreator;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.beans.models.SelectionModel;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.mainframe.FormDesigner;
import java.awt.event.MouseEvent;
import javax.swing.*;
import java.awt.*;
/**
* 需要显示顶层的组件层
*
* @Author: Yuan.Wang
* @Date: 2020/8/25
*/
public class TopXCreators extends JComponent {
final private FormDesigner designer;
public TopXCreators(FormDesigner designer) {
this.designer = designer;
init();
}
private void init() {
setLayout(null);
setVisible(false);
setBackground(null);
setOpaque(false);
designer.addDesignerEditListener(e -> {
if (e.getCreatorEventID() == DesignerEvent.CREATOR_EDITED) {
refresh();
}
});
}
/**
* 选中的组件有变化时刷新
*/
public void refresh() {
removeAll();
addXCreators();
}
@Override
public void paint(Graphics g) {
setSize(designer.getSize());
resizeTopXCreators();
super.paint(g);
}
@Override
public void setVisible(boolean aFlag) {
super.setVisible(aFlag);
for (int i = 0, count = getComponentCount(); i < count; i++) {
if (getComponent(i) instanceof TopXCreator) {
TopXCreator xCreator = (TopXCreator) getComponent(i);
xCreator.displayCoverPane(aFlag);
}
}
repaint();
}
/**
* 依据MouseEvent坐标来设置是否显示蒙层
*/
public void displayCoverPane(MouseEvent e) {
for (int i = 0, count = getComponentCount(); i < count; i++) {
BasicTopXCreator xCreator = (BasicTopXCreator) getComponent(i);
xCreator.displayCoverPane(e, isVisible());
}
}
/**
* 加入被选择的组件
*/
private void addXCreators() {
SelectionModel selectionModel = designer.getSelectionModel();
XCreator[] xCreators = selectionModel.getSelection().getSelectedCreators();
for (XCreator creator : xCreators) {
BasicTopXCreator topXCreator = creator.getTopXCreator();
if (topXCreator != null) {
add(topXCreator);
}
}
}
/**
* 更新顶层组件的位置和大小
*/
private void resizeTopXCreators() {
for (int i = 0, count = getComponentCount(); i < count; i++) {
BasicTopXCreator topXCreator = (BasicTopXCreator) getComponent(i);
topXCreator.resizeTopXCreator();
}
repaint();
}
}

208
designer-realize/src/main/java/com/fr/start/fx/FastGifImage.java

@ -1,208 +0,0 @@
package com.fr.start.fx;
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.gif.GIFImageReaderSpi;
import com.sun.javafx.tk.ImageLoader;
import com.sun.javafx.tk.PlatformImage;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.image.WritableImage;
import javafx.util.Duration;
import javax.imageio.stream.FileImageInputStream;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.regex.Pattern;
/**
* 边加载边播放的gif加载器
*
* @author daniel
*/
public class FastGifImage extends WritableImage {
private String url;
private int gifCount;
public FastGifImage(String url, int w, int h) {
super(w, h);
this.url = validateUrl(url);
seekCount();
initialize();
}
/**
* 给出gif帧数加快加载速度
*
* @param url gif url
* @param gifCount gif帧数
* @param w
* @param h
*/
public FastGifImage(String url, int gifCount, int w, int h) {
super(w, h);
this.url = validateUrl(url);
this.gifCount = gifCount;
initialize();
}
private void seekCount() {
try {
GIFImageReaderSpi spi = new GIFImageReaderSpi();
GIFImageReader gifReader = (GIFImageReader) spi.createReaderInstance();
gifReader.setInput(new FileImageInputStream(new File(new URI(url))));
gifCount = gifReader.getNumImages(true);
} catch (Exception e) {
e.printStackTrace();
}
}
private static final Pattern URL_QUICKMATCH = Pattern.compile("^\\p{Alpha}[\\p{Alnum}+.-]*:.*$");
private static String validateUrl(final String url) {
if (url == null) {
throw new NullPointerException("URL must not be null");
}
if (url.trim().isEmpty()) {
throw new IllegalArgumentException("URL must not be empty");
}
try {
if (!URL_QUICKMATCH.matcher(url).matches()) {
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
URL resource;
if (url.charAt(0) == '/') {
resource = contextClassLoader.getResource(url.substring(1));
} else {
resource = contextClassLoader.getResource(url);
}
if (resource == null) {
throw new IllegalArgumentException("Invalid URL or resource not found");
}
return resource.toString();
}
// Use URL constructor for validation
return new URL(url).toString();
} catch (final IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid URL" + e.getMessage());
} catch (final MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL" + e.getMessage());
}
}
private void finishImage(ImageLoader loader) {
initializeAnimatedImage(loader);
}
// Generates the animation Timeline for multiframe images.
private void initializeAnimatedImage(ImageLoader loader) {
animation = new Animation(this, loader);
animation.start();
}
// Support for animated images.
private Animation animation;
private static final class Animation {
final WeakReference<FastGifImage> imageRef;
final Timeline timeline;
private ImageLoader loader;
public Animation(final FastGifImage image, final ImageLoader loader) {
this.loader = loader;
imageRef = new WeakReference<FastGifImage>(image);
timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
final int frameCount = loader.getFrameCount();
int duration = 0;
for (int i = 0; i < frameCount; ++i) {
addKeyFrame(i, duration);
duration = duration + loader.getFrameDelay(i);
}
// Note: we need one extra frame in the timeline to define how long
// the last frame is shown, the wrap around is "instantaneous"
addKeyFrame(0, duration);
}
public void start() {
timeline.play();
}
public void stop() {
timeline.stop();
loader = null;
}
private void updateImage(final int frameIndex) {
final FastGifImage image = imageRef.get();
if (image != null) {
image.setPlatformImagePropertyImpl(
loader.getFrame(frameIndex));
} else {
timeline.stop();
}
}
private void addKeyFrame(final int index, final double duration) {
timeline.getKeyFrames().add(
new KeyFrame(Duration.millis(duration),
new EventHandler() {
@Override
public void handle(Event event) {
updateImage(index);
}
}
));
}
}
private static Method method;
static {
try {
method = FastGifImage.class.getSuperclass().getSuperclass().getDeclaredMethod("platformImagePropertyImpl");
method.setAccessible(true);
} catch (Exception e) {
}
}
private void setPlatformImagePropertyImpl(PlatformImage image) {
try {
Object o = method.invoke(this);
Method method = o.getClass().getDeclaredMethod("set", Object.class);
method.setAccessible(true);
method.invoke(o, image);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private void initialize() {
finishImage(new PrismImageLoader2(url, gifCount, (int) getRequestedWidth(), (int) getRequestedHeight(), isPreserveRatio(), isSmooth()));
}
/**
* 销毁gif动画
*/
public void destroy() {
animation.stop();
}
}

208
designer-realize/src/main/java/com/fr/start/fx/PrismImageLoader2.java

@ -1,208 +0,0 @@
package com.fr.start.fx;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.log.FineLoggerFactory;
import com.sun.javafx.iio.ImageFrame;
import com.sun.javafx.iio.ImageLoadListener;
import com.sun.javafx.iio.ImageLoader;
import com.sun.javafx.iio.ImageMetadata;
import com.sun.javafx.iio.ImageStorageException;
import com.sun.javafx.iio.common.ImageTools;
import com.sun.javafx.iio.gif.GIFImageLoaderFactory;
import com.sun.javafx.tk.PlatformImage;
import com.sun.prism.Image;
import com.sun.prism.impl.PrismSettings;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 边加载边播放的gif加载器
*
* @author daniel
*/
class PrismImageLoader2 implements com.sun.javafx.tk.ImageLoader {
private Image[] images;
private int[] delayTimes;
private int width;
private int height;
private int gifCount = 1;
private Exception exception;
public PrismImageLoader2(final String url, int gifCount, final int width, final int height,
final boolean preserveRatio, final boolean smooth) {
this.gifCount = gifCount;
images = new Image[gifCount];
delayTimes = new int[gifCount];
this.width = width;
this.height = height;
ExecutorService es = Executors.newSingleThreadExecutor(new NamedThreadFactory("PrismImageLoader2"));
es.execute(new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
try {
inputStream = ImageTools.createInputStream(url);
loadAll(inputStream, width, height, preserveRatio, smooth);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
es.shutdown();
}
@Override
public int getWidth() {
return width;
}
@Override
public int getHeight() {
return height;
}
@Override
public int getFrameCount() {
return gifCount;
}
@Override
@SuppressWarnings("squid:S2142")
public PlatformImage getFrame(int index) {
while (images[index] == null) {
synchronized (this) {
if (images[index] == null) {
try {
this.wait();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
}
return images[index];
}
@Override
public int getFrameDelay(int index) {
// while (images[0] == null) {
// synchronized (this) {
// if(images[0] == null) {
// try {
// this.wait();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
// return 0;
// }
// return delayTimes[0];
// 直接使用第一帧的时间
return 40;
}
@Override
public int getLoopCount() {
return 0;
}
@Override
public Exception getException() {
return exception;
}
@SuppressWarnings("squid:S244")
private void loadAll(InputStream stream, int w, int h,
boolean preserveRatio, boolean smooth) {
ImageLoadListener listener = new PrismLoadListener();
try {
ImageLoader loader = null;
loader = GIFImageLoaderFactory.getInstance().createImageLoader(stream);
loader.addListener(listener);
for (int i = 0; i < gifCount; i++) {
ImageFrame imageFrame = loader.load(i, w, h, preserveRatio, smooth);
images[i] = convert(imageFrame);
synchronized (this) {
notifyAll();
}
}
} catch (ImageStorageException e) {
handleException(e);
} catch (Exception e) {
handleException(e);
}
}
private void handleException(final ImageStorageException isException) {
// unwrap ImageStorageException if possible
final Throwable exceptionCause = isException.getCause();
if (exceptionCause instanceof Exception) {
handleException((Exception) exceptionCause);
} else {
handleException((Exception) isException);
}
}
private void handleException(final Exception exception) {
if (PrismSettings.verbose) {
exception.printStackTrace(System.err);
}
this.exception = exception;
}
private Image convert(ImageFrame imgFrames) {
ImageFrame frame = imgFrames;
Image image = Image.convertImageFrame(frame);
ImageMetadata metadata = frame.getMetadata();
if (metadata != null) {
Integer delay = metadata.delayTime;
if (delay != null) {
delayTimes[0] = delay.intValue();
}
}
return image;
}
private class PrismLoadListener implements ImageLoadListener {
@Override
public void imageLoadWarning(ImageLoader loader, String message) {
}
@Override
public void imageLoadProgress(ImageLoader loader,
float percentageComplete) {
// progress only matters when backgroundLoading=true, but
// currently we are relying on AbstractRemoteResource for tracking
// progress of the InputStream, so there's no need to implement
// this for now; eventually though we might want to consider
// moving away from AbstractRemoteResource and instead use
// the built-in support for progress in the javafx-iio library...
}
@Override
public void imageLoadMetaData(ImageLoader loader, ImageMetadata metadata) {
// We currently have no need to listen for ImageMetadata ready.
}
}
}

59
designer-realize/src/main/java/com/fr/start/fx/SplashFx.java

@ -1,59 +0,0 @@
package com.fr.start.fx;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.start.SplashFxActionListener;
import com.fr.start.SplashStrategy;
import javafx.application.Application;
import javafx.application.Platform;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* JavaFx方式启动启动动画这种方式在mac下与
* swing一起启动会会出现线程死锁jvm等问题
* 所以这个方式仅用于windows上
*
* @author vito
* @date 2018/6/4
* @see com.fr.start.jni.SplashMac
*/
public class SplashFx implements SplashStrategy {
private SplashFxWindow fxWindow;
private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("SplashFx"));
@Override
public void show() {
Platform.setImplicitExit(false);
SERVICE.execute(new Runnable() {
@Override
public void run() {
Application.launch(SplashFxWindow.class);
}
});
fxWindow = SplashFxWindow.waitForStartUpTest();
fxWindow.addSplashActionListener(new SplashFxActionListener() {
@Override
public void splashClose() {
DesignerContext.getDesignerFrame().setVisible(true);
}
});
}
@Override
public void hide() {
fxWindow.close();
}
@Override
public void updateModuleLog(final String text) {
fxWindow.updateModuleInfo(text);
}
@Override
public void updateThanksLog(final String text) {
fxWindow.updateThanks(text);
}
}

194
designer-realize/src/main/java/com/fr/start/fx/SplashFxWindow.java

@ -1,194 +0,0 @@
package com.fr.start.fx;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.OperatingSystem;
import com.fr.start.SplashContext;
import com.fr.start.SplashFxActionListener;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* JavaFx启动动画窗口
*
* @author vito
*/
public class SplashFxWindow extends Application {
private static final String ARIAL_FONT_NAME = "Arial";
private static final String PF_FONT_NAME = "PingFang";
private static final String YAHEI_FONT_NAME = "Microsoft YaHei";
private static final int MODULE_INFO_LEFT_MARGIN = 36;
private static final int MODULE_INFO_BOTTOM_MARGIN = 28;
private static final int THINKS_BOTTOM_RIGHT = 35;
private static final int THINKS_BOTTOM_MARGIN = 27;
private static final int WINDOW_WIDTH = 640;
private static final int WINDOW_HEIGHT = 360;
private static final int FONT = 12;
private static final int FRAME_COUNT = 315;
private static final String THINKS_COLOR = "#82b1ce";
private static final CountDownLatch LATCH = new CountDownLatch(1);
private static SplashFxWindow app = null;
private Text moduleInfo;
private Text thanks;
private FastGifImage image;
private List<SplashFxActionListener> listeners = new ArrayList<SplashFxActionListener>();
/**
* 获取当前运行实例黑科技
*
* @return 运行实例
*/
@SuppressWarnings("squid:S2142")
public static SplashFxWindow waitForStartUpTest() {
try {
LATCH.await();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return app;
}
private static void setApp(SplashFxWindow window) {
app = window;
LATCH.countDown();
}
public SplashFxWindow() {
setApp(this);
}
@Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
primaryStage.initStyle(StageStyle.TRANSPARENT);
image = new FastGifImage(SplashContext.SPLASH_PATH, FRAME_COUNT, WINDOW_WIDTH, WINDOW_HEIGHT);
ImageView gif = new ImageView(image);
AnchorPane.setBottomAnchor(gif, 0d);
AnchorPane.setTopAnchor(gif, 0d);
AnchorPane.setLeftAnchor(gif, 0d);
AnchorPane.setRightAnchor(gif, 0d);
Font font;
if (OperatingSystem.isWindows()) {
font = new Font(YAHEI_FONT_NAME, FONT);
} else if (OperatingSystem.isMacOS()) {
font = new Font(PF_FONT_NAME, FONT);
} else {
font = new Font(ARIAL_FONT_NAME, FONT);
}
moduleInfo = new Text();
moduleInfo.setFont(font);
moduleInfo.setFill(Color.WHITE);
AnchorPane.setLeftAnchor(moduleInfo,(double) MODULE_INFO_LEFT_MARGIN);
AnchorPane.setBottomAnchor(moduleInfo,(double) MODULE_INFO_BOTTOM_MARGIN);
thanks = new Text();
thanks.setFont(font);
thanks.setFill(Color.valueOf(THINKS_COLOR));
AnchorPane.setRightAnchor(thanks, (double) THINKS_BOTTOM_RIGHT);
AnchorPane.setBottomAnchor(thanks, (double) THINKS_BOTTOM_MARGIN);
root.getChildren().add(gif);
root.getChildren().add(moduleInfo);
root.getChildren().add(thanks);
primaryStage.setWidth(WINDOW_WIDTH);
primaryStage.setHeight(WINDOW_HEIGHT);
primaryStage.setScene(new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT, null));
setWindowCenter(primaryStage);
primaryStage.show();
}
public void close() {
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
((Stage) moduleInfo.getScene().getWindow()).close();
image.destroy();
fireSplashClose();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
});
}
/**
* 设置窗口居中
*
* @param stage 窗口
*/
private void setWindowCenter(Stage stage) {
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
stage.setX(primaryScreenBounds.getMinX() + (primaryScreenBounds.getWidth() - stage.getWidth()) / 2.0);
stage.setY(primaryScreenBounds.getMinY() + (primaryScreenBounds.getHeight() - stage.getHeight()) / 2.0);
}
/**
* 更新模块信息
*
* @param s 文字
*/
public void updateModuleInfo(final String s) {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (moduleInfo != null) {
moduleInfo.setText(s);
}
}
});
}
/**
* 更新欢迎信息
*
* @param s 文字
*/
public void updateThanks(final String s) {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (thanks != null) {
thanks.setText(s);
}
}
});
}
/**
* 添加一个动画状态监听
*
* @param listener
*/
public void addSplashActionListener(SplashFxActionListener listener) {
listeners.add(listener);
}
public void fireSplashClose() {
for (SplashFxActionListener listener : listeners) {
listener.splashClose();
}
}
}

69
designer-realize/src/main/java/com/fr/start/jni/SplashJNI.java

@ -1,69 +0,0 @@
package com.fr.start.jni;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
/**
* Splash JNI调用jni类改名或者移包之后
* 必须重新编译动态库
*
* @author vito
* @date 2018/6/4
*/
public class SplashJNI {
static {
try {
System.setProperty("java.library.path", ".");
System.loadLibrary("splash");
} catch (UnsatisfiedLinkError e) {
loadLibraryFromJar("/com/fr/start/jni/splash.dylib");
}
}
/**
* 显示启动动画窗口
*/
public native void show(String path);
/**
* 隐藏启动动画窗口
*/
public native void hide();
/**
* 设置模块加载信息
*/
public native void updateModuleLog(String text);
/**
* 设置感谢文字
*/
public native void updateThanksLog(String text);
/**
* 从jar中加载动态库
*
* @param path 路径/com/a/b
* @throws UnsatisfiedLinkError 没有找到合适的动态库
*/
private static void loadLibraryFromJar(String path) throws UnsatisfiedLinkError {
try (InputStream inputStream = SplashJNI.class.getResourceAsStream(path)) {
File tempLib = File.createTempFile(path, "");
byte[] buffer = new byte[1024];
int read = -1;
try (FileOutputStream fileOutputStream = new FileOutputStream(tempLib)) {
while ((read = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
}
System.load(tempLib.getAbsolutePath());
} catch (Exception e) {
throw new UnsatisfiedLinkError("Unable to open " + path + " from jar file.");
}
}
}

100
designer-realize/src/main/java/com/fr/start/jni/SplashMac.java

@ -1,100 +0,0 @@
package com.fr.start.jni;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.start.SplashContext;
import com.fr.start.SplashStrategy;
import javax.swing.JFrame;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* mac上使用jni方式绘制gif不使用javafx有两个原因
* 1.mac上javafx和swing同时启动会导致卡死
* 2.platform.exit会导致设计器崩溃
*
* @author vito
* @see com.fr.start.fx.SplashFx
*/
public class SplashMac implements SplashStrategy {
private SplashJNI jni;
private static final int EXILE = 10000;
public SplashMac() {
jni = new SplashJNI();
}
/**
* 将jar中的资源拷贝到缓存文件夹
*
* @return 路径
*/
private static String loadResFromJar() {
File tempLib = null;
try (InputStream inputStream = SplashContext.class.getResourceAsStream(SplashContext.SPLASH_PATH)) {
if (inputStream == null) {
FineLoggerFactory.getLogger().error("Unable to copy " + SplashContext.SPLASH_PATH + " from jar file.");
return StringUtils.EMPTY;
}
tempLib = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), SplashContext.SPLASH_CACHE_NAME));
byte[] buffer = new byte[1024];
int read = -1;
try (FileOutputStream fileOutputStream = new FileOutputStream(tempLib)) {
while ((read = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
}
return tempLib.getAbsolutePath();
} catch (IOException e) {
if (tempLib != null) {
tempLib.deleteOnExit();
}
// 直接抛异常
throw new RuntimeException("Unable to copy " + SplashContext.SPLASH_PATH + " from jar file.");
}
}
@Override
public void show() {
if (jni != null) {
// mac下安装版模糊的hack
JFrame jFrame = new JFrame();
jFrame.setLocation(EXILE, EXILE);
jFrame.setVisible(true);
jFrame.setVisible(false);
File splash = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), SplashContext.SPLASH_CACHE_NAME));
String path = splash.exists() ? splash.getAbsolutePath() : loadResFromJar();
jni.show(path);
}
}
@Override
public void hide() {
if (jni != null) {
jni.hide();
jni = null;
}
}
@Override
public void updateModuleLog(String text) {
if (jni != null) {
jni.updateModuleLog(text);
}
}
@Override
public void updateThanksLog(String text) {
if (jni != null) {
jni.updateThanksLog(text);
}
}
}

BIN
designer-realize/src/main/resources/com/fr/start/jni/splash.dylib

Binary file not shown.
Loading…
Cancel
Save