Browse Source

Pull request #5983: REPORT-57813 新功能引导

Merge in DESIGN/design from ~TOMMY/design:feature/x to feature/x

* commit 'df617491579d70e9b237464755ce239ae5b84fe6':
  REPORT-59858 引导页场景开发
  REPORT-59629 引导页框架
research/11.0
Tommy 3 years ago
parent
commit
78b79d1c8a
  1. 1
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  2. 1
      designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java
  3. 160
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/Guide.java
  4. 46
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideBuilder.java
  5. 51
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideGroup.java
  6. 32
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycle.java
  7. 28
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideLifecycleAdaptor.java
  8. 88
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideManager.java
  9. 132
      designer-base/src/main/java/com/fr/design/mainframe/guide/base/GuideView.java
  10. 155
      designer-base/src/main/java/com/fr/design/mainframe/guide/collect/GuideCollector.java
  11. 386
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/AbstractGuideScene.java
  12. 90
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/ClickScene.java
  13. 33
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DisplayScene.java
  14. 63
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/DragScene.java
  15. 18
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideScene.java
  16. 20
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycle.java
  17. 18
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/GuideSceneLifecycleAdaptor.java
  18. 5
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/SceneFilter.java
  19. 60
      designer-base/src/main/java/com/fr/design/mainframe/guide/scene/drag/DragAndDropDragGestureListener.java
  20. 83
      designer-base/src/main/java/com/fr/design/mainframe/guide/tip/BubbleTip.java
  21. 14
      designer-base/src/main/java/com/fr/design/mainframe/guide/tip/GuideTip.java
  22. 74
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHint.java
  23. 30
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/BubbleHintDialog.java
  24. 78
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/ExpandPane.java
  25. 117
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideCompleteDialog.java
  26. 226
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/GuideManageDialog.java
  27. 152
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/Bubble.java
  28. 255
      designer-base/src/main/java/com/fr/design/mainframe/guide/ui/bubble/BubbleWithClose.java
  29. 98
      designer-base/src/main/java/com/fr/design/mainframe/guide/utils/ScreenImage.java
  30. 1
      designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java
  31. 5
      designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java
  32. 4
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java
  33. 60
      designer-base/src/main/java/com/fr/design/utils/ComponentUtils.java
  34. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_down.png
  35. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/arrow_right.png
  36. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/close.png
  37. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_all.png
  38. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_none.png
  39. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/complete_some.png
  40. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/guide.png
  41. BIN
      designer-base/src/main/resources/com/fr/design/mainframe/guide/success.png
  42. 15
      designer-form/src/main/java/com/fr/design/mainframe/FormArea.java
  43. 2
      designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java
  44. 4
      designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java
  45. 11
      designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java
  46. 28
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java
  47. 19
      designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallComponentHelper.java
  48. 20
      designer-form/src/main/java/com/fr/design/widget/ui/designer/NewFormPane.java
  49. 15
      designer-realize/src/main/java/com/fr/design/mainframe/guide/GuideIds.java
  50. 30
      designer-realize/src/main/java/com/fr/design/mainframe/guide/GuideRegister.java
  51. 118
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideCreateUtils.java
  52. 63
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideSceneHelper.java
  53. 133
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/ChangeLayoutComponentGuide.java
  54. 242
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/UseLayoutAndComponentGuide.java
  55. 22
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/theme/DownloadComponentPackageGuide.java
  56. 237
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/theme/ThemeToggleGuide.java
  57. 79
      designer-realize/src/main/java/com/fr/design/mainframe/guide/entry/GuideEntryPane.java
  58. 5
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  59. 3
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

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

@ -1439,6 +1439,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);

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() {

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

@ -0,0 +1,160 @@
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.stable.StringUtils;
import javax.swing.SwingUtilities;
public class Guide {
public enum GuideState {
NONE, DONE
}
private String id;
private String name;
private String description;
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 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() {
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();
end();
GuideCompleteDialog.getInstance().showDialog(getName());
}
public void terminate() {
if (lifecycle != null) {
lifecycle.onTerminate();
}
end();
}
public void end() {
GuideManager.getInstance().setCurrentGuide(null);
guideView.dismissGuide();
if (lifecycle != null) {
lifecycle.onEnd();
}
}
public void registerLifecycle(GuideLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public void removeGuideLifecycle() {
this.lifecycle = null;
}
}

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

@ -0,0 +1,46 @@
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 addScene(GuideScene scene) {
guide.setScene(scene);
return this;
}
public GuideBuilder registerLifecycle(GuideLifecycle lifecycle) {
guide.registerLifecycle(lifecycle);
return this;
}
public Guide getGuide() {
return guide;
}
}

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

@ -0,0 +1,51 @@
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 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() {
}
}

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

@ -0,0 +1,88 @@
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 Guide currentGuide;
private List<GuideGroup> guideGroupList;
private static GuideManager guideManager;
public static GuideManager getInstance() {
if (guideManager == null) {
guideManager = new GuideManager();
}
return guideManager;
}
public GuideManager() {
guideGroupList = new ArrayList<>();
}
public Guide getCurrentGuide() {
return currentGuide;
}
public void setCurrentGuide(Guide currentGuide) {
this.currentGuide = currentGuide;
}
public void addGuideGroup(GuideGroup guideGroup) {
this.guideGroupList.add(guideGroup);
}
public void addGuide(String groupId, Guide guide) {
for (GuideGroup group : guideGroupList) {
if (StringUtils.equals(groupId, group.getID())) {
group.addGuide(guide);
}
}
}
public List<GuideGroup> getGuideGroupList() {
return guideGroupList;
}
public List<Guide> getAllGuide() {
List<Guide> guideList = new ArrayList<>();
for (GuideGroup group : getGuideGroupList()) {
for (Guide guide : group.getGuideList()) {
guideList.add(guide);
}
}
return guideList;
}
public GuideGroup getGuideGroup(String groupId) {
for (GuideGroup group : getGuideGroupList()) {
if (StringUtils.equals(groupId, group.getID())) {
return group;
}
}
return null;
}
public Guide getGuide(String guideId) {
for (GuideGroup group : getGuideGroupList()) {
for (Guide guide : group.getGuideList()) {
if (StringUtils.equals(guideId, guide.getID())) {
return guide;
}
}
}
return null;
}
public void completeAll() {
for (GuideGroup group : getGuideGroupList()) {
for (Guide guide : group.getGuideList()) {
guide.setComplete(true);
}
}
GuideCollector.getInstance().saveInfo();
}
}

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

@ -0,0 +1,132 @@
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.JWindow;
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.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
public class GuideView extends JWindow{
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.window = window;
this.modalColor = Color.BLACK;
this.modalOpacity = 0.6f;
this.setPreferredSize(window.getSize());
this.setSize(window.getSize());
this.setLayout(FRGUIPaneFactory.createBorderLayout());
setBg();
window.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
setLocationRelativeTo(window);
}
@Override
public void componentMoved(ComponentEvent e) {
setLocation(window.getLocation());
}
});
window.addWindowFocusListener(new WindowFocusListener() {
@Override
public void windowGainedFocus(WindowEvent e) {
requestFocus();
setLocationRelativeTo(window);
}
@Override
public void windowLostFocus(WindowEvent e) {
}
});
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (scene == null) {
invoker.terminate();
}
if (scene instanceof AbstractGuideScene && invoker != null) {
if (((AbstractGuideScene) scene).getHighlightList().size() == 0) {
invoker.terminate();
}
}
}
});
}
public GuideView(Window window, Guide guide) {
this(DesignerContext.getDesignerFrame());
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() {
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() {
this.getLayeredPane().removeAll();
revalidate();
repaint();
this.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;
}
}

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

@ -0,0 +1,386 @@
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.Color;
import java.awt.Component;
import java.awt.Dimension;
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 GuideScene nextScene;
private SceneFilter sceneFilter;
private GuideSceneLifecycle lifecycle;
private GuideView container;
private List<Component> targetList;
private List<Component> highlightList;
private Component nextButton;
public AbstractGuideScene() {
this.setLayout(null);
this.setOpaque(false);
targetList = new ArrayList<>();
highlightList = 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){
Window window = (Window) component;
window.toFront();
window.requestFocus();
image = ScreenImage.createImage(component);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
container.toFront();
container.requestFocus();
}
});
} else {
image = captureImage(component);
}
targetList.add(component);
highlightList.add(getTargetComponentWithImage(image, rectangle));
return true;
} catch (AWTException e) {
e.printStackTrace();
return false;
}
}
/**
* 根据设计器上选定区域获取高亮视图采用截屏的方式
* @param rectangle 选定区域相对屏幕
* @return
*/
public boolean addTarget(Rectangle rectangle) {
try {
targetList.add(null);
container.setVisible(false);
BufferedImage image = captureImage(rectangle);
highlightList.add(getTargetComponentWithImage(image, rectangle));
return true;
} catch (AWTException e) {
e.printStackTrace();
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());
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();
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 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;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
showScene();
}
});
}
@Override
public void showScene() {
if (container != null) {
container.setContentPane(this);
this.setBounds(0, 0 , getSceneWidth(), getSceneWidth());
// show target
for (int index = highlightList.size() - 1; index >= 0; index--) {
this.add(highlightList.get(index));
}
// show next button
if (nextButton != null) {
nextButton.setBounds((getSceneWidth() - 60) / 2, getSceneHeight() - 100, 60, 30);
this.add(nextButton);
}
container.revalidate();
container.repaint();
}
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();
}
}

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

@ -0,0 +1,90 @@
package com.fr.design.mainframe.guide.scene;
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()));
}
}

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

@ -0,0 +1,33 @@
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;
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类
new Timer().schedule(new TimerTask() {
public void run() {
complete();
}
}, 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;
}
}
}

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

@ -0,0 +1,83 @@
package com.fr.design.mainframe.guide.tip;
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 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) {
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);
}
}

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

@ -0,0 +1,30 @@
package com.fr.design.mainframe.guide.ui;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import javax.swing.JDialog;
import java.awt.Color;
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;
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);
}
}

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);
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();
GuideManageDialog.getInstance().showDialog();
}
});
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(Toolkit.i18nText("Fine-Design_Guide_Complete_Hint", str));
repaint();
this.setVisible(true);
}
}

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

@ -0,0 +1,226 @@
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.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);
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 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();
JPanel expandContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 5);
for (GuideGroup guideGroup : GuideManager.getInstance().getGuideGroupList()) {
JPanel guideGroupCard = createGuideGroupCard(guideGroup);
expandContent.add(guideGroupCard);
}
ExpandPane expandPane = new ExpandPane(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Version_Title", "11.0.0"), expandContent);
scrollContent.add(expandPane);
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.5f));
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/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();
}

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;
}
}

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

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);
}
});

2
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);
// 获取该组件所在的焦点容器

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);

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);

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

@ -21,7 +21,7 @@ import java.io.InputStream;
public class InstallComponentHelper {
private static final String PRE_INSTALL_PATH = "/com/fr/form/share/components";
private static final String[] PRE_INSTALL_COMPONENTS = new String[]{
public static final String[] PRE_INSTALL_COMPONENTS = new String[]{
"单行指标卡.f3df58b3-4302-4cab-ab77-caaf225de60a.reu",
"分层雷达图-深色.49f8397c-e6a6-482a-acc7-46d8cec353a4.reu",
"红绿灯表格-浅色.d0466992-328a-4ccf-ad67-6cbc844d669c.reu",
@ -45,6 +45,23 @@ public class InstallComponentHelper {
}
public static String[] installPreComponent(int count) {
count = Math.max(Math.min(count, PRE_INSTALL_COMPONENTS.length), 0);
String[] installNames = new String[count];
for (int index = 0; index < count; index ++) {
try {
String componentPath = PRE_INSTALL_COMPONENTS[index];
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);
installNames[index] = componentPath;
} catch (Exception e) {
FineLoggerFactory.getLogger().error("install Component filed" + e.getMessage(), e);
}
}
return installNames;
}
private static boolean needPreInstallComponent() {
try {
//老用户或者组件库里已有组件,不预装组件

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

@ -55,14 +55,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 {
@ -87,6 +83,18 @@ public class NewFormPane extends BasicPane {
GUICoreUtils.centerWindow(dialog);
dialog.setTitle(this.title4PopupWindow());
dialog.setResizable(false);
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_New_Template");
}
public UIDialog getWindow() {
return dialog;
}
public void showWindow() {
dialog.setVisible(true);
}

15
designer-realize/src/main/java/com/fr/design/mainframe/guide/GuideIds.java

@ -0,0 +1,15 @@
package com.fr.design.mainframe.guide;
public class GuideIds {
public static class GuideGroup {
public static final String F01 = "F01";
public static final String F02 = "F02";
}
public static class Guide {
public static final String F001001 = "F001001";
public static final String F001002 = "F001002";
public static final String F002001 = "F002001";
public static final String F002002 = "F002002";
}
}

30
designer-realize/src/main/java/com/fr/design/mainframe/guide/GuideRegister.java

@ -0,0 +1,30 @@
package com.fr.design.mainframe.guide;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.guide.base.GuideGroup;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import com.fr.design.mainframe.guide.creator.layout.ChangeLayoutComponentGuide;
import com.fr.design.mainframe.guide.creator.layout.UseLayoutAndComponentGuide;
import com.fr.design.mainframe.guide.creator.theme.DownloadComponentPackageGuide;
import com.fr.design.mainframe.guide.creator.theme.ThemeToggleGuide;
public class GuideRegister {
public static void register() {
GuideCollector.getInstance().loadFromFile();
registerGroup();
registerGuide();
}
private static void registerGroup() {
GuideManager.getInstance().addGuideGroup(new GuideGroup(GuideIds.GuideGroup.F01, Toolkit.i18nText("Fine-Design_Guide_Group_F01_Name")));
GuideManager.getInstance().addGuideGroup(new GuideGroup(GuideIds.GuideGroup.F02, Toolkit.i18nText("Fine-Design_Guide_Group_F02_Name")));
}
private static void registerGuide() {
GuideManager.getInstance().addGuide(GuideIds.GuideGroup.F01, UseLayoutAndComponentGuide.createGuide());
GuideManager.getInstance().addGuide(GuideIds.GuideGroup.F01, ChangeLayoutComponentGuide.createGuide());
GuideManager.getInstance().addGuide(GuideIds.GuideGroup.F02, ThemeToggleGuide.createGuide());
GuideManager.getInstance().addGuide(GuideIds.GuideGroup.F02, DownloadComponentPackageGuide.createGuide());
}
}

118
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideCreateUtils.java

@ -0,0 +1,118 @@
package com.fr.design.mainframe.guide.creator;
import com.fr.design.designer.beans.models.AddingModel;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XOccupiedLayout;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.FormCreatorDropTarget;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.utils.ScreenImage;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import sun.java2d.xr.XcbRequestCounter;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.UUID;
public class GuideCreateUtils {
public static FormDesigner getFormDesigner() {
JForm jForm = (JForm) DesignerContext.getDesignerFrame().getSelectedJTemplate();
FormDesigner designer = jForm.getFormDesign();
return designer;
}
public static Rectangle getXCreatorBoundsRelative2FormDesigner(XCreator xCreator) {
FormDesigner designer = getFormDesigner();
Point point = SwingUtilities.convertPoint(xCreator, 0, 0, designer.getRootComponent());
return new Rectangle(point.x + designer.getPaintX(), point.y + designer.getPaintY(), xCreator.getWidth(), xCreator.getHeight());
}
public static XCreator getXCreatorFormDesigner(String name) {
FormDesigner designer = getFormDesigner();
XLayoutContainer rootComponent = designer.getRootComponent();
return findXCreator(rootComponent, name);
}
public static XCreator findXCreator(XLayoutContainer container, String name) {
if (StringUtils.equals(container.toData().getWidgetName(), name)) {
return container;
}
for (Component component : container.getComponents()) {
if (component instanceof XLayoutContainer) {
XCreator xCreator = findXCreator((XLayoutContainer) component, name);
if (xCreator != null) {
return xCreator;
}
} else if (component instanceof XCreator) {
XCreator xCreator = (XCreator) component;
if (StringUtils.equals(xCreator.toData().getWidgetName(), name)) {
return xCreator;
}
}
}
return null;
}
public static void addXCreatorToXLayoutContainer(XCreator xCreator, XLayoutContainer xLayoutContainer, boolean isDragComponent) {
if (xCreator == null) {
return;
}
FormDesigner designer = GuideCreateUtils.getFormDesigner();
designer.getSelectionModel().selectACreator(xLayoutContainer);
if (isDragComponent) {
designer.setAddingModel(new AddingModel(xCreator, 0,0));
designer.setDropTarget(new FormCreatorDropTarget(designer));
designer.repaint();
} else {
designer.startDraggingBean(xCreator);
}
FormCreatorDropTarget dropTarget = (FormCreatorDropTarget) designer.getDropTarget();
dropTarget.adding(xLayoutContainer.getX(), xLayoutContainer.getY());
designer.getSelectionModel().selectACreator(xCreator);
}
public static UILabel createModalTarget(JComponent component) {
ImageIcon ic = new ImageIcon(ScreenImage.createImageWithModal(component));
return new UILabel(ic);
}
public static Rectangle getPopupMenuBounds(JPopupMenu popupMenu, Component parent, int x, int y) {
Point point = SwingUtilities.convertPoint(parent,0,0, GuideManager.getInstance().getCurrentGuide().getGuideView().getRootPane());
return new Rectangle(point.x + x, point.y + y, popupMenu.getWidth(), popupMenu.getHeight());
}
public static String openGuideFile(String sourcePath, String fileName, String suffix) {
String fileWorkPath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, UUID.randomUUID().toString() + suffix);
InputStream inputStream = GuideCreateUtils.class.getResourceAsStream(StableUtils.pathJoin(sourcePath, fileName + suffix));
byte[] data = ResourceIOUtils.inputStream2Bytes(inputStream);
WorkContext.getWorkResource().write(fileWorkPath, data);
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(fileWorkPath, false)));
return fileWorkPath;
}
public static void deleteGuideFile(String filePath) {
WorkContext.getWorkResource().delete(filePath);
}
}

63
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideSceneHelper.java

@ -0,0 +1,63 @@
package com.fr.design.mainframe.guide.creator;
import com.fr.design.actions.file.WebPreviewUtils;
import com.fr.design.gui.ibutton.UIPreviewButton;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.CenterRegionContainerPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.scene.ClickScene;
import com.fr.design.mainframe.guide.scene.DisplayScene;
import com.fr.design.mainframe.guide.scene.GuideScene;
import com.fr.design.mainframe.guide.scene.GuideSceneLifecycleAdaptor;
import com.fr.design.mainframe.guide.tip.GuideTip;
import com.fr.design.utils.ComponentUtils;
import java.awt.Window;
public class GuideSceneHelper {
public static GuideScene createWindowDisplayScene(Window window) {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addTarget(window);
return true;
}
});
return scene;
}
public static GuideScene createFormDesignerBodyDisplayScene() {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
FormDesigner formDesigner = GuideCreateUtils.getFormDesigner();
scene.addTarget(formDesigner, GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(formDesigner.getRootComponent()));
return true;
}
});
return scene;
}
public static GuideScene createPreviewClickScene() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addClickTarget(ComponentUtils.findComponentByClass(CenterRegionContainerPane.getInstance(), UIPreviewButton.class), ClickScene.ClickType.LEFT);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_Base_Click_Preview"), null, GuideTip.Direction.BOTTOM, 0.5f, 0.2f);
return true;
}
@Override
public void onComplete() {
GuideManager.getInstance().getCurrentGuide().getGuideView().dismissGuide();
WebPreviewUtils.preview(DesignerContext.getDesignerFrame().getSelectedJTemplate());
}
});
return scene;
}
}

133
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/ChangeLayoutComponentGuide.java

@ -0,0 +1,133 @@
package com.fr.design.mainframe.guide.creator.layout;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.CenterRegionContainerPane;
import com.fr.design.mainframe.FormArea;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.guide.GuideIds;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideBuilder;
import com.fr.design.mainframe.guide.base.GuideLifecycleAdaptor;
import com.fr.design.mainframe.guide.creator.GuideCreateUtils;
import com.fr.design.mainframe.guide.creator.GuideSceneHelper;
import com.fr.design.mainframe.guide.scene.ClickScene;
import com.fr.design.mainframe.guide.scene.DisplayScene;
import com.fr.design.mainframe.guide.scene.DragScene;
import com.fr.design.mainframe.guide.scene.GuideScene;
import com.fr.design.mainframe.guide.scene.GuideSceneLifecycleAdaptor;
import com.fr.design.mainframe.guide.tip.GuideTip;
import com.fr.design.utils.ComponentUtils;
import java.awt.Rectangle;
public class ChangeLayoutComponentGuide {
private static UIButton switchButton;
private static String filePath;
public static Guide createGuide() {
GuideScene scene = createScene();
scene.nextScene(createScene2())
.nextScene(GuideSceneHelper.createFormDesignerBodyDisplayScene())
.nextScene(createScene3())
.nextScene(createScene4())
.nextScene(GuideSceneHelper.createPreviewClickScene());
Guide guide = GuideBuilder.newInstance()
.setID(GuideIds.Guide.F001002)
.setName(Toolkit.i18nText("Fine-Design_Guide_Scene_F001002_Name"))
.setDescription(Toolkit.i18nText("Fine-Design_Guide_Scene_F001002_Description"))
.addScene(scene)
.registerLifecycle(new GuideLifecycleAdaptor() {
@Override
public boolean prepared() {
filePath = GuideCreateUtils.openGuideFile("/com/fr/report/guide/template", "layout_recommend", ".frm");
return true;
}
@Override
public void onEnd() {
GuideCreateUtils.deleteGuideFile(filePath);
}
})
.getGuide();
return guide;
}
private static GuideScene createScene() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
switchButton = (UIButton) ComponentUtils.findComponentByName(CenterRegionContainerPane.getInstance(), FormArea.FIX_LAYOUT_SWITCH_BUTTON);
scene.addClickTarget(switchButton, ClickScene.ClickType.LEFT, true);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001002_Tip_Click_No_Fix_Layout"), GuideTip.Direction.TOP);
return true;
}
});
return scene;
}
private static GuideScene createScene2() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addCustomTarget(
GuideCreateUtils.createModalTarget(switchButton.getComponentPopupMenu()),
GuideCreateUtils.getPopupMenuBounds(switchButton.getComponentPopupMenu(), switchButton,0, -switchButton.getComponentPopupMenu().getHeight())
);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001002_Tip_Select_Fix_layout"), null, GuideTip.Direction.RIGHT, 0.5f, 0.8f);
scene.addClickTarget(switchButton.getComponentPopupMenu().getComponent(1), ClickScene.ClickType.LEFT, true);
switchButton.getComponentPopupMenu().setVisible(false);
return true;
}
});
return scene;
}
private static GuideScene createScene3() {
DragScene scene = new DragScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addDragTarget(GuideCreateUtils.getFormDesigner(), GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(GuideCreateUtils.getXCreatorFormDesigner("absolute0")), DragScene.DragType.FROM);
scene.addDragTarget(GuideCreateUtils.getFormDesigner(), GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(GuideCreateUtils.getXCreatorFormDesigner("absolute1")), DragScene.DragType.TO);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001002_Tip_Drag"), GuideTip.Direction.TOP);
return super.prepared();
}
@Override
public void onComplete() {
FormDesigner formDesigner = GuideCreateUtils.getFormDesigner();
XCreator from = GuideCreateUtils.getXCreatorFormDesigner("absolute0");
XLayoutContainer to = (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("absolute1");
formDesigner.getSelectionModel().removeCreator(from, from.getWidth(), from.getHeight());
formDesigner.getSelectionModel().removeCreator(to, to.getWidth(),to.getHeight());
GuideCreateUtils.addXCreatorToXLayoutContainer(from, (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("box1"), true);
GuideCreateUtils.addXCreatorToXLayoutContainer(to, (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("box0"), true);
}
});
return scene;
}
private static GuideScene createScene4() {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
Rectangle rootBounds = GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(GuideCreateUtils.getFormDesigner().getRootComponent());
Rectangle bound3 = GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(GuideCreateUtils.getXCreatorFormDesigner("absolute2"));
Rectangle targetBounds = new Rectangle(rootBounds.x, rootBounds.y, rootBounds.width, bound3.y - rootBounds.y);
scene.addTarget(GuideCreateUtils.getFormDesigner(), targetBounds);
return true;
}
});
return scene;
}
}

242
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/UseLayoutAndComponentGuide.java

@ -0,0 +1,242 @@
package com.fr.design.mainframe.guide.creator.layout;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XOccupiedLayout;
import com.fr.design.dialog.UIDialog;
import com.fr.design.gui.imenu.UIHeadMenu;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.EastRegionContainerPane;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormWidgetDetailPane;
import com.fr.design.mainframe.NorthRegionContainerPane;
import com.fr.design.mainframe.guide.GuideIds;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideBuilder;
import com.fr.design.mainframe.guide.base.GuideLifecycleAdaptor;
import com.fr.design.mainframe.guide.creator.GuideCreateUtils;
import com.fr.design.mainframe.guide.creator.GuideSceneHelper;
import com.fr.design.mainframe.guide.scene.ClickScene;
import com.fr.design.mainframe.guide.scene.DisplayScene;
import com.fr.design.mainframe.guide.scene.DragScene;
import com.fr.design.mainframe.guide.scene.GuideScene;
import com.fr.design.mainframe.guide.scene.GuideSceneLifecycleAdaptor;
import com.fr.design.mainframe.guide.tip.GuideTip;
import com.fr.design.mainframe.share.ui.block.LocalWidgetBlock;
import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane;
import com.fr.design.mainframe.share.util.InstallComponentHelper;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.widget.ui.designer.NewFormPane;
import com.fr.design.widget.ui.designer.PredefinedLayoutPane;
import com.fr.form.share.Group;
import com.fr.form.share.group.DefaultShareGroup;
import com.fr.form.share.group.DefaultShareGroupManager;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
public class UseLayoutAndComponentGuide {
private static UIHeadMenu fileHeadMenu;
private static NewFormPane newFormPane;
private static int autoInstallComponentCount;
private static String[] autoInstallComponentNames;
public static Guide createGuide() {
GuideScene scene = createScene();
scene.nextScene(createScene2())
.nextScene(createScene3())
.nextScene(createScene4())
.nextScene(createScene5())
.nextScene(createScene6("box0",0))
.nextScene(createScene6("box1",1))
.nextScene(createScene6("box2",2))
.nextScene(GuideSceneHelper.createFormDesignerBodyDisplayScene())
.nextScene(GuideSceneHelper.createPreviewClickScene());
Guide guide = GuideBuilder.newInstance()
.setID(GuideIds.Guide.F001001)
.setName(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Name"))
.setDescription(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Description"))
.addScene(scene)
.registerLifecycle(new GuideLifecycleAdaptor() {
@Override
public boolean prepared() {
preloadShareComponent();
Component component = ComponentUtils.findComponentByName(NorthRegionContainerPane.getInstance(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_File"));
fileHeadMenu = ((UIHeadMenu) component);
fileHeadMenu.setSelected(true);
fileHeadMenu.getPopupMenu().show(fileHeadMenu, 0, fileHeadMenu.getHeight());
return true;
}
@Override
public void onEnd() {
fileHeadMenu.setSelected(false);
fileHeadMenu.getPopupMenu().setVisible(false);
if (newFormPane != null) {
newFormPane.getWindow().dispose();
}
removeAutoInstalledComponent();
}
})
.getGuide();
return guide;
}
public static GuideScene createScene() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addClickTarget(fileHeadMenu.getMenuComponent(2), ClickScene.ClickType.LEFT);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Tip_New_Form"), GuideTip.Direction.BOTTOM);
scene.showScene();
return true;
}
@Override
public void onComplete() {
fileHeadMenu.setSelected(false);
fileHeadMenu.getPopupMenu().setVisible(false);
newFormPane = new NewFormPane();
newFormPane.getWindow().setModal(false);
newFormPane.showWindow();
}
});
return scene;
}
public static GuideScene createScene2() {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addTarget(newFormPane.getWindow());
return true;
}
});
return scene;
}
public static GuideScene createScene3() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
List<Component> componentList = ComponentUtils.findComponentsByClass(newFormPane.getWindow().getContentPane(), PredefinedLayoutPane.class);
if (componentList.get(1) != null) {
PredefinedLayoutPane layoutPane = (PredefinedLayoutPane) componentList.get(1);
scene.addClickTarget(layoutPane, ClickScene.ClickType.LEFT, true);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Tip_Select_Layout"), GuideTip.Direction.RIGHT);
}
return super.prepared();
}
});
return scene;
}
public static GuideScene createScene4() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
Component component = ComponentUtils.findComponentByName(newFormPane.getWindow().getContentPane(), UIDialog.OK_BUTTON);
if (component != null) {
scene.addClickTarget(component, ClickScene.ClickType.LEFT, true);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Tip_Click_Confirm"), GuideTip.Direction.TOP);
}
return super.prepared();
}
@Override
public void onComplete() {
newFormPane.getWindow().dispose();
}
});
return scene;
}
public static GuideScene createScene5() {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
FormWidgetDetailPane.getInstance().switch2Local();
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB);
FormDesigner formDesigner = GuideCreateUtils.getFormDesigner();
scene.addTarget(formDesigner, GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(formDesigner.getRootComponent()));
return true;
}
});
return scene;
}
public static GuideScene createScene6(String name, int blockIndex) {
DragScene scene = new DragScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addDragTarget(GuideCreateUtils.getFormDesigner(), GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(getXOccupiedLayout(name)), DragScene.DragType.TO);
scene.addDragTarget(getLocalWidgetBlock(blockIndex), DragScene.DragType.FROM);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Tip_Drag"), GuideTip.Direction.LEFT);
return super.prepared();
}
@Override
public void onComplete() {
LocalWidgetBlock block = getLocalWidgetBlock(blockIndex);
XCreator xCreator = block.transformXCreator(block);
XOccupiedLayout xOccupiedLayout = getXOccupiedLayout(name);
GuideCreateUtils.addXCreatorToXLayoutContainer(xCreator, xOccupiedLayout, false);
}
});
return scene;
}
private static XOccupiedLayout getXOccupiedLayout(String name) {
return (XOccupiedLayout) GuideCreateUtils.getXCreatorFormDesigner(name);
}
private static LocalWidgetBlock getLocalWidgetBlock(int index) {
return (LocalWidgetBlock) ComponentUtils.findComponentsByClass(LocalWidgetRepoPane.getInstance(), LocalWidgetBlock.class).get(index);
}
private static void preloadShareComponent() {
autoInstallComponentCount = 3;
try {
DefaultShareGroupManager.getInstance().refresh();
Group shareGroup = DefaultShareGroupManager.getInstance().getGroup(DefaultShareGroup.GROUP_NAME);
if (shareGroup != null) {
DefaultShareGroup defaultShareGroup = (DefaultShareGroup) shareGroup;
int currentWidgetCount = defaultShareGroup.getAllBindInfoList().length;
autoInstallComponentCount = autoInstallComponentCount - (Math.min(autoInstallComponentCount, currentWidgetCount));
}
if (autoInstallComponentCount > 0) {
autoInstallComponentNames = InstallComponentHelper.installPreComponent(autoInstallComponentCount);
DefaultShareGroupManager.getInstance().refresh();
LocalWidgetRepoPane.getInstance().refreshAllGroupPane();
}
} catch (Exception e) {
e.printStackTrace();
}
}
static private void removeAutoInstalledComponent() {
Group shareGroup = DefaultShareGroupManager.getInstance().getGroup(DefaultShareGroup.GROUP_NAME);
if (shareGroup != null && autoInstallComponentNames != null) {
DefaultShareGroup defaultShareGroup = (DefaultShareGroup) shareGroup;
List<String> installedList = new ArrayList<>();
for (String componentName : autoInstallComponentNames) {
if (componentName != null) {
String uuid = componentName.split("\\.")[1];
installedList.add(uuid);
}
}
defaultShareGroup.unInstallSelect(installedList);
LocalWidgetRepoPane.getInstance().refreshAllGroupPane();
}
}
}

22
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/theme/DownloadComponentPackageGuide.java

@ -0,0 +1,22 @@
package com.fr.design.mainframe.guide.creator.theme;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.guide.GuideIds;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideBuilder;
import com.fr.design.mainframe.guide.base.GuideLifecycleAdaptor;
public class DownloadComponentPackageGuide {
public static Guide createGuide() {
Guide guide = GuideBuilder.newInstance()
.setID(GuideIds.Guide.F002002)
.setName(Toolkit.i18nText("Fine-Design_Guide_Scene_F002002_Name"))
.setDescription(Toolkit.i18nText("Fine-Design_Guide_Scene_F002002_Description"))
.registerLifecycle(new GuideLifecycleAdaptor() {
})
.getGuide();
return guide;
}
}

237
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/theme/ThemeToggleGuide.java

@ -0,0 +1,237 @@
package com.fr.design.mainframe.guide.creator.theme;
import com.fr.base.theme.FormTheme;
import com.fr.base.theme.FormThemeConfig;
import com.fr.base.theme.TemplateTheme;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.style.FollowingThemePane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.CenterRegionContainerPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.mainframe.EastRegionContainerPane;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.guide.GuideIds;
import com.fr.design.mainframe.guide.base.Guide;
import com.fr.design.mainframe.guide.base.GuideBuilder;
import com.fr.design.mainframe.guide.base.GuideLifecycleAdaptor;
import com.fr.design.mainframe.guide.base.GuideManager;
import com.fr.design.mainframe.guide.creator.GuideCreateUtils;
import com.fr.design.mainframe.guide.creator.GuideSceneHelper;
import com.fr.design.mainframe.guide.scene.ClickScene;
import com.fr.design.mainframe.guide.scene.DisplayScene;
import com.fr.design.mainframe.guide.scene.GuideScene;
import com.fr.design.mainframe.guide.scene.GuideSceneLifecycleAdaptor;
import com.fr.design.mainframe.guide.tip.BubbleTip;
import com.fr.design.mainframe.guide.tip.GuideTip;
import com.fr.design.mainframe.theme.TemplateThemeBlock;
import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog;
import com.fr.design.utils.ComponentUtils;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.stable.StableUtils;
import com.fr.stable.project.ProjectConstants;
import com.teamdev.jxbrowser.internal.ui.ToolkitKey;
import javax.swing.SwingUtilities;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Timer;
import java.util.TimerTask;
public class ThemeToggleGuide {
private static TemplateThemeUsingDialog<FormTheme> themeDialog;
private static String filePath;
public static Guide createGuide() {
GuideScene scene1 = createScene1();
scene1.nextScene(createScene2())
.nextScene(createScene3())
.nextScene(createScene4())
.nextScene(createScene5())
.nextScene(createScene6())
.nextScene(GuideSceneHelper.createPreviewClickScene());
Guide guide = GuideBuilder.newInstance()
.setID(GuideIds.Guide.F002001)
.setName(Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Name"))
.setDescription(Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Description"))
.addScene(scene1)
.registerLifecycle(new GuideLifecycleAdaptor() {
@Override
public boolean prepared() {
filePath = GuideCreateUtils.openGuideFile("/com/fr/report/guide/template", "toggle_theme", ".frm");
return true;
}
@Override
public void onEnd() {
GuideCreateUtils.deleteGuideFile(filePath);
}
})
.getGuide();
return guide;
}
private static GuideScene createScene1() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
TemplateTheme templateTheme = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme();
Component component = ComponentUtils.findComponentByName(CenterRegionContainerPane.getInstance(), templateTheme.getName());
scene.addClickTarget(component, ClickScene.ClickType.LEFT);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Tip_Click_Template_Theme"), GuideTip.Direction.BOTTOM);
return true;
}
@Override
public void onComplete() {
showTemplateThemeUsingDialog();
}
});
return scene;
}
private static GuideScene createScene2() {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
scene.addTarget(themeDialog);
scene.showScene();
}
},100);
return true;
}
public void onShow() {
GuideManager.getInstance().getCurrentGuide().getGuideView().toFront(); // brings to front without needing to setAlwaysOnTop
GuideManager.getInstance().getCurrentGuide().getGuideView().requestFocus();
}
@Override
public void onComplete() {
}
});
return scene;
}
private static GuideScene createScene3() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
String name = FormThemeConfig.getInstance().getThemeNames().get(4);
Component component = ComponentUtils.findComponentByName(themeDialog.getContentPane(), name);
if (component instanceof TemplateThemeBlock) {
scene.addClickTarget(component, ClickScene.ClickType.LEFT, true);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Tip_Toggle_Theme"), BubbleTip.Direction.TOP);
}
return true;
}
@Override
public void onComplete() {
}
});
return scene;
}
private static GuideScene createScene4() {
ClickScene scene = new ClickScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
scene.addClickTarget(ComponentUtils.findComponentByName(themeDialog, TemplateThemeUsingDialog.COMPLETE_BUTTON), ClickScene.ClickType.LEFT, true);
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Tip_Click_Confirm"), BubbleTip.Direction.TOP);
return true;
}
});
return scene;
}
private static GuideScene createScene5() {
DisplayScene scene = new DisplayScene();
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
JForm jForm = (JForm) DesignerContext.getDesignerFrame().getSelectedJTemplate();
scene.addTarget(jForm.getFormDesign());
return true;
}
@Override
public void onShow() {
JForm jForm = (JForm) DesignerContext.getDesignerFrame().getSelectedJTemplate();
FormDesigner designer = jForm.getFormDesign();
XCreator xCreator = (XCreator) designer.getRootComponent().getComponent(0);
jForm.getFormDesign().getSelectionModel().reset();
jForm.getFormDesign().getSelectionModel().selectACreator(xCreator);
}
});
return scene;
}
private static GuideScene createScene6() {
ClickScene scene = new ClickScene();
final UIButtonGroup[] uiButtonGroup = new UIButtonGroup[1];
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() {
@Override
public boolean prepared() {
JForm jForm = (JForm) DesignerContext.getDesignerFrame().getSelectedJTemplate();
FormDesigner designer = jForm.getFormDesign();
XCreator xCreator = (XCreator) designer.getRootComponent().getComponent(0);
scene.addTarget(designer, GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(xCreator));
Component target2 = ComponentUtils.findComponentByClass(EastRegionContainerPane.getInstance(), FollowingThemePane.class);
target2 = ComponentUtils.findComponentByClass(target2, UIButtonGroup.class);
if (target2 != null) {
uiButtonGroup[0] = (UIButtonGroup) target2;
target2 = ((UIButtonGroup) target2).getButton(0);
scene.addClickTarget(target2, ClickScene.ClickType.LEFT);
scene.addBubbleTip(
Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Tip_Toggle_Follow_Theme"),
Toolkit.i18nText("Fine-Design_Guide_Scene_F002001_Tip_Toggle_Follow_Theme_Description"),
GuideTip.Direction.BOTTOM,
0.5f,
0.8f
);
}
return true;
}
@Override
public void onComplete() {
if (uiButtonGroup[0] != null) {
uiButtonGroup[0].setSelectedIndex(0);
}
}
});
return scene;
}
private static void showTemplateThemeUsingDialog() {
if (themeDialog == null) {
DesignerFrame designerFrame = DesignerContext.getDesignerFrame();
themeDialog = new TemplateThemeUsingDialog<>(designerFrame, DesignerContext.getDesignerFrame().getSelectedJTemplate(), FormThemeConfig.getInstance());
themeDialog.setModal(false);
}
if (!themeDialog.isVisible()) {
themeDialog.setVisible(true);
}
themeDialog.requestFocus();
}
}

79
designer-realize/src/main/java/com/fr/design/mainframe/guide/entry/GuideEntryPane.java

@ -0,0 +1,79 @@
package com.fr.design.mainframe.guide.entry;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import com.fr.design.mainframe.guide.ui.BubbleHintDialog;
import com.fr.design.mainframe.guide.ui.GuideManageDialog;
import com.fr.general.IOUtils;
import javax.swing.SwingUtilities;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class GuideEntryPane extends BasicPane {
private static GuideEntryPane guideEntryPane;
private UIButton button;
public static GuideEntryPane getGuideEntryPane() {
if (guideEntryPane == null) {
guideEntryPane = new GuideEntryPane();
}
return guideEntryPane;
}
@Override
protected String title4PopupWindow() {
return null;
}
private GuideEntryPane() {
setPreferredSize(new Dimension(24, 24));
setLayout(new BorderLayout());
button = new UIButton();
button.setIcon(IOUtils.readIcon("/com/fr/design/mainframe/guide/guide.png"));
button.setToolTipText(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Entry_Name")));
button.set4ToolbarButton();
button.setRolloverEnabled(false);
this.add(button);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
GuideManageDialog.getInstance().showDialog();
}
});
this.setBackground(UIConstants.TEMPLATE_TAB_PANE_BACKGROUND);
this.addAncestorListener(new AncestorListener() {
@Override
public void ancestorAdded(AncestorEvent event) {
if (!GuideCollector.getInstance().isShowHint()) {
BubbleHintDialog dialog = new BubbleHintDialog(DesignerContext.getDesignerFrame());
Point point = new Point(0,0);
SwingUtilities.convertPointToScreen(point, GuideEntryPane.this);
Dimension size = GuideEntryPane.this.getSize();
dialog.setLocationRelativeTo(GuideEntryPane.this);
dialog.setLocation(point.x - 187,point.y + size.height);
dialog.setVisible(true);
}
}
@Override
public void ancestorRemoved(AncestorEvent event) {
}
@Override
public void ancestorMoved(AncestorEvent event) {
}
});
}
}

5
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -31,6 +31,7 @@ import com.fr.design.mainframe.JWorkBook;
import com.fr.design.mainframe.alphafine.component.AlphaFinePane;
import com.fr.design.mainframe.bbs.UserInfoLabel;
import com.fr.design.mainframe.bbs.UserInfoPane;
import com.fr.design.mainframe.guide.entry.GuideEntryPane;
import com.fr.design.module.ChartPreStyleAction;
import com.fr.design.notification.SnapChatAllTypes;
import com.fr.design.notification.ui.NotificationCenterPane;
@ -422,6 +423,10 @@ public class MainDesigner extends BaseDesigner {
return AlphaFinePane.getAlphaFinePane();
}
public Component createGuideEntryPane() {
return GuideEntryPane.getGuideEntryPane();
}
public Component createNotificationCenterPane(){
return NotificationCenterPane.getNotificationCenterPane();
}

3
designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

@ -61,6 +61,8 @@ import com.fr.design.mainframe.form.FormECCompositeProvider;
import com.fr.design.mainframe.form.FormECDesignerProvider;
import com.fr.design.mainframe.form.FormElementCaseDesigner;
import com.fr.design.mainframe.form.FormReportComponentComposite;
import com.fr.design.mainframe.guide.GuideRegister;
import com.fr.design.mainframe.guide.collect.GuideCollector;
import com.fr.design.mainframe.loghandler.DesignerLogAppender;
import com.fr.design.mainframe.share.constants.ShareEntryKey;
import com.fr.design.mainframe.socketio.DesignerSocketIO;
@ -225,6 +227,7 @@ public class DesignerActivator extends Activator implements Prepare {
InformationCollector.getInstance().collectStartTime();
SharableManager.start();
GuideRegister.register();
}
private void createPluginListener() {

Loading…
Cancel
Save