@ -0,0 +1,167 @@
|
||||
package com.fr.design.mainframe.guide.base; |
||||
|
||||
import com.fr.design.mainframe.guide.collect.GuideCollector; |
||||
import com.fr.design.mainframe.guide.scene.GuideScene; |
||||
import com.fr.design.mainframe.guide.ui.GuideCompleteDialog; |
||||
import com.fr.design.mainframe.guide.ui.GuideManageDialog; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
|
||||
public class Guide { |
||||
public enum GuideState { |
||||
NONE, DONE |
||||
} |
||||
private String id; |
||||
private String name; |
||||
private String description; |
||||
private 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() { |
||||
// 同时只能启动一个引导
|
||||
if (GuideManager.getInstance().getCurrentGuide() != null) { |
||||
return; |
||||
} |
||||
try { |
||||
if (lifecycle != null && !lifecycle.prepared()) { |
||||
return; |
||||
} |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
start(); |
||||
} |
||||
}); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
end(); |
||||
} |
||||
|
||||
} |
||||
|
||||
public void start() { |
||||
if (scene != null) { |
||||
guideView.setScene(scene); |
||||
guideView.showGuide(); |
||||
GuideManager.getInstance().setCurrentGuide(this); |
||||
if (lifecycle != null) { |
||||
lifecycle.onStart(); |
||||
} |
||||
} else { |
||||
complete(); |
||||
} |
||||
|
||||
} |
||||
|
||||
public void complete() { |
||||
if (lifecycle != null) { |
||||
lifecycle.onComplete(); |
||||
} |
||||
setComplete(true); |
||||
GuideCollector.getInstance().saveInfo(); |
||||
guideView.dismissGuide(); |
||||
GuideCompleteDialog.getInstance().showDialog(getName()); |
||||
end(); |
||||
} |
||||
|
||||
public void terminate() { |
||||
if (lifecycle != null) { |
||||
lifecycle.onTerminate(); |
||||
} |
||||
end(); |
||||
} |
||||
|
||||
public void end() { |
||||
GuideManager.getInstance().setCurrentGuide(null); |
||||
guideView.dismissGuide(); |
||||
if (lifecycle != null) { |
||||
lifecycle.onEnd(); |
||||
} |
||||
GuideManageDialog.getInstance().showDialog(); |
||||
} |
||||
|
||||
public void registerLifecycle(GuideLifecycle lifecycle) { |
||||
this.lifecycle = lifecycle; |
||||
} |
||||
|
||||
public void removeGuideLifecycle() { |
||||
this.lifecycle = null; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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(); |
||||
|
||||
} |
@ -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() { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,109 @@
|
||||
package com.fr.design.mainframe.guide.base; |
||||
|
||||
import com.fr.design.mainframe.guide.collect.GuideCollector; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class GuideManager { |
||||
private static GuideManager guideManager; |
||||
|
||||
private Guide currentGuide; |
||||
private List<GuideVersion> guideVersionList; |
||||
|
||||
public static GuideManager getInstance() { |
||||
if (guideManager == null) { |
||||
guideManager = new GuideManager(); |
||||
} |
||||
return guideManager; |
||||
} |
||||
|
||||
public GuideManager() { |
||||
guideVersionList = new ArrayList<>(); |
||||
} |
||||
|
||||
public Guide getCurrentGuide() { |
||||
return currentGuide; |
||||
} |
||||
|
||||
public void setCurrentGuide(Guide currentGuide) { |
||||
this.currentGuide = currentGuide; |
||||
} |
||||
|
||||
public void addGuideGroup(String version, GuideGroup guideGroup) { |
||||
GuideVersion guideVersion = getGuideVersion(version); |
||||
if (guideVersion == null) { |
||||
guideVersion = new GuideVersion(version); |
||||
guideVersionList.add(guideVersion); |
||||
} |
||||
guideVersion.addGuideGroup(guideGroup); |
||||
} |
||||
|
||||
public void addGuide(String groupId, Guide guide) { |
||||
GuideGroup guideGroup = getGuideGroup(groupId); |
||||
if (guideGroup != null) { |
||||
guideGroup.addGuide(guide); |
||||
} |
||||
} |
||||
|
||||
public List<GuideVersion> getGuideVersionList() { |
||||
return guideVersionList; |
||||
} |
||||
|
||||
public List<Guide> getAllGuide() { |
||||
List<Guide> guideList = new ArrayList<>(); |
||||
for (GuideVersion version : guideVersionList) { |
||||
for (GuideGroup group : version.getGuideGroupList()) { |
||||
for (Guide guide : group.getGuideList()) { |
||||
guideList.add(guide); |
||||
} |
||||
} |
||||
} |
||||
return guideList; |
||||
} |
||||
|
||||
public GuideVersion getGuideVersion(String version) { |
||||
for (GuideVersion guideVersion : guideVersionList) { |
||||
if (StringUtils.equals(version, guideVersion.getVersion())) { |
||||
return guideVersion; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public GuideGroup getGuideGroup(String groupId) { |
||||
for (GuideVersion version : guideVersionList) { |
||||
for (GuideGroup group : version.getGuideGroupList()) { |
||||
if (StringUtils.equals(groupId, group.getID())) { |
||||
return group; |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public Guide getGuide(String guideId) { |
||||
for (GuideVersion version : guideVersionList) { |
||||
for (GuideGroup group : version.getGuideGroupList()) { |
||||
for (Guide guide : group.getGuideList()) { |
||||
if (StringUtils.equals(guideId, guide.getID())) { |
||||
return guide; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public void completeAll() { |
||||
for (GuideVersion version : guideVersionList) { |
||||
for (GuideGroup group : version.getGuideGroupList()) { |
||||
for (Guide guide : group.getGuideList()) { |
||||
guide.setComplete(true); |
||||
} |
||||
} |
||||
} |
||||
GuideCollector.getInstance().saveInfo(); |
||||
} |
||||
} |
@ -0,0 +1,29 @@
|
||||
package com.fr.design.mainframe.guide.base; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class GuideVersion { |
||||
private String version; |
||||
private List<GuideGroup> guideGroupList; |
||||
public GuideVersion(String version) { |
||||
guideGroupList = new ArrayList<>(); |
||||
this.version = version; |
||||
} |
||||
|
||||
public String getVersion() { |
||||
return version; |
||||
} |
||||
|
||||
public void setVersion(String version) { |
||||
this.version = version; |
||||
} |
||||
|
||||
public List<GuideGroup> getGuideGroupList() { |
||||
return guideGroupList; |
||||
} |
||||
|
||||
public void addGuideGroup(GuideGroup guideGroup) { |
||||
guideGroupList.add(guideGroup); |
||||
} |
||||
} |
@ -0,0 +1,124 @@
|
||||
package com.fr.design.mainframe.guide.base; |
||||
|
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.guide.scene.AbstractGuideScene; |
||||
import com.fr.design.mainframe.guide.scene.GuideScene; |
||||
|
||||
import javax.swing.JDialog; |
||||
import java.awt.Color; |
||||
import java.awt.Graphics; |
||||
import java.awt.Window; |
||||
import java.awt.event.ComponentAdapter; |
||||
import java.awt.event.ComponentEvent; |
||||
import java.awt.event.ComponentListener; |
||||
import java.awt.event.WindowEvent; |
||||
import java.awt.event.WindowFocusListener; |
||||
|
||||
public class GuideView extends JDialog { |
||||
private static GuideView guideView; |
||||
private Guide invoker; |
||||
private GuideScene scene; |
||||
private Color modalColor; |
||||
private float modalOpacity; |
||||
private Window window; |
||||
|
||||
public static GuideView getInstance(Guide guide) { |
||||
if (guideView == null) { |
||||
guideView = new GuideView(DesignerContext.getDesignerFrame(), guide); |
||||
} |
||||
return guideView; |
||||
} |
||||
|
||||
public GuideView(Window window) { |
||||
super(window); |
||||
this.setUndecorated(true); |
||||
this.window = window; |
||||
this.modalColor = Color.BLACK; |
||||
this.modalOpacity = 0.4f; |
||||
this.setPreferredSize(window.getSize()); |
||||
this.setSize(window.getSize()); |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
setBg(); |
||||
} |
||||
|
||||
private WindowFocusListener windowFocusListener = new WindowFocusListener() { |
||||
@Override |
||||
public void windowGainedFocus(WindowEvent e) { |
||||
requestFocus(); |
||||
setLocationRelativeTo(window); |
||||
} |
||||
|
||||
@Override |
||||
public void windowLostFocus(WindowEvent e) { |
||||
|
||||
} |
||||
}; |
||||
|
||||
private ComponentListener componentListener = new ComponentAdapter() { |
||||
@Override |
||||
public void componentResized(ComponentEvent e) { |
||||
setLocationRelativeTo(window); |
||||
} |
||||
|
||||
@Override |
||||
public void componentMoved(ComponentEvent e) { |
||||
setLocation(window.getLocation()); |
||||
} |
||||
}; |
||||
|
||||
public GuideView(Window window, Guide guide) { |
||||
this(window); |
||||
this.invoker = guide; |
||||
} |
||||
|
||||
public void setModalColor(Color color) { |
||||
modalColor = color; |
||||
setBg(); |
||||
} |
||||
|
||||
public void setModalOpacity(float opacity){ |
||||
modalOpacity = opacity; |
||||
setBg(); |
||||
} |
||||
|
||||
private void setBg() { |
||||
Color newColor = new Color(modalColor.getRed(), modalColor.getGreen(), modalColor.getBlue(), (int) (255 * modalOpacity)); |
||||
this.setBackground(newColor); |
||||
} |
||||
|
||||
public void setScene(GuideScene scene) { |
||||
if (scene instanceof AbstractGuideScene) { |
||||
((AbstractGuideScene) scene).setContainer(this); |
||||
} |
||||
this.scene = scene; |
||||
} |
||||
|
||||
public void showGuide() { |
||||
window.addComponentListener(componentListener); |
||||
window.addWindowFocusListener(windowFocusListener); |
||||
this.setLocationRelativeTo(window); |
||||
this.setSize(window.getSize()); |
||||
this.setLocation(window.getLocation()); |
||||
this.setVisible(true); |
||||
if (scene != null) { |
||||
scene.start(); |
||||
} else { |
||||
GuideManager.getInstance().getCurrentGuide().complete(); |
||||
} |
||||
} |
||||
|
||||
public void dismissGuide() { |
||||
window.removeComponentListener(componentListener); |
||||
window.removeWindowFocusListener(windowFocusListener); |
||||
this.getLayeredPane().removeAll(); |
||||
revalidate(); |
||||
repaint(); |
||||
setVisible(false); |
||||
} |
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
super.paint(g); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -0,0 +1,478 @@
|
||||
package com.fr.design.mainframe.guide.scene; |
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.mainframe.guide.base.GuideManager; |
||||
import com.fr.design.mainframe.guide.base.GuideView; |
||||
import com.fr.design.mainframe.guide.utils.ScreenImage; |
||||
import com.fr.design.mainframe.guide.tip.BubbleTip; |
||||
import com.fr.design.mainframe.guide.tip.GuideTip; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.ImageIcon; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingUtilities; |
||||
import java.awt.AWTException; |
||||
import java.awt.AlphaComposite; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Composite; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
import java.awt.Window; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.image.BufferedImage; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public abstract class AbstractGuideScene extends JPanel implements GuideScene { |
||||
private static final int DEFAULT_ARROW_HEIGHT = 12; |
||||
private static final int DEFAULT_ARROW_WIDTH = 18; |
||||
|
||||
private GuideScene nextScene; |
||||
private SceneFilter sceneFilter; |
||||
private GuideSceneLifecycle lifecycle; |
||||
private GuideView container; |
||||
private List<Component> targetList; |
||||
private List<Component> highlightList; |
||||
private Component nextButton; |
||||
private List<Point[]> pointsList; |
||||
|
||||
|
||||
public AbstractGuideScene() { |
||||
this.setLayout(null); |
||||
this.setOpaque(false); |
||||
targetList = new ArrayList<>(); |
||||
highlightList = new ArrayList<>(); |
||||
pointsList = new ArrayList<>(); |
||||
} |
||||
|
||||
/** |
||||
* 根据设计器上组件添加高亮区域视图, |
||||
* JComponent 采用组件绘制方式 |
||||
* Component 采用屏幕截图方式 |
||||
* @param component 设计器组件对象 |
||||
* @return |
||||
*/ |
||||
public boolean addTarget(Component component) { |
||||
try { |
||||
if (component == null || container == null) { |
||||
return false; |
||||
} |
||||
|
||||
Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane()); |
||||
Rectangle rectangle = new Rectangle(point, component.getSize()); |
||||
BufferedImage image; |
||||
|
||||
if (component instanceof JComponent) { |
||||
JComponent jComponent = (JComponent) component; |
||||
image = ScreenImage.createImage(jComponent); |
||||
} else { |
||||
image = captureImage(component); |
||||
showContainer(); |
||||
} |
||||
targetList.add(component); |
||||
highlightList.add(getTargetComponentWithImage(image, rectangle)); |
||||
return true; |
||||
} catch (AWTException e) { |
||||
e.printStackTrace(); |
||||
GuideManager.getInstance().getCurrentGuide().terminate(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 根据设计器上选定区域获取高亮视图,采用截屏的方式 |
||||
* @param rectangle 选定区域,相对屏幕 |
||||
* @return |
||||
*/ |
||||
public boolean addTarget(Rectangle rectangle) { |
||||
try { |
||||
targetList.add(null); |
||||
BufferedImage image = captureImage(rectangle); |
||||
highlightList.add(getTargetComponentWithImage(image, rectangle)); |
||||
return true; |
||||
} catch (AWTException e) { |
||||
e.printStackTrace(); |
||||
GuideManager.getInstance().getCurrentGuide().terminate(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 根据设计器组件,选定其中某个区域,添加高亮视图 |
||||
* @param component 设计器组件 |
||||
* @param origin 相对组件的区域 |
||||
* @return |
||||
*/ |
||||
public boolean addTarget(Component component, Rectangle origin) { |
||||
try { |
||||
if (component == null) { |
||||
return false; |
||||
} |
||||
Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane()); |
||||
|
||||
origin = origin.intersection(new Rectangle(0,0,component.getWidth(), component.getHeight())); |
||||
Rectangle rectangle = new Rectangle(point.x + origin.x, point.y + origin.y, origin.width, origin.height); |
||||
|
||||
BufferedImage image; |
||||
|
||||
if (component instanceof JComponent) { |
||||
JComponent jComponent = (JComponent) component; |
||||
image = ScreenImage.createImage(jComponent, origin); |
||||
} else { |
||||
image = ScreenImage.createImage(component).getSubimage(origin.x, origin.y, origin.width, origin.height); |
||||
} |
||||
targetList.add(component); |
||||
highlightList.add(getTargetComponentWithImage(image, rectangle)); |
||||
return true; |
||||
} catch (AWTException e) { |
||||
e.printStackTrace(); |
||||
GuideManager.getInstance().getCurrentGuide().terminate(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 添加自定义组件 |
||||
* @param component 自定义组件 |
||||
* @param rectangle 相对引导页的区域 |
||||
* @return |
||||
*/ |
||||
public boolean addCustomTarget(Component component, Rectangle rectangle) { |
||||
if (component == null) { |
||||
return false; |
||||
} |
||||
component.setBounds(rectangle); |
||||
targetList.add(component); |
||||
highlightList.add(component); |
||||
return true; |
||||
} |
||||
|
||||
public boolean addCustomTarget(Component component, Point location) { |
||||
return addCustomTarget(component, new Rectangle(location, component.getPreferredSize())); |
||||
} |
||||
|
||||
protected List<Component> getTargetList() { |
||||
return targetList; |
||||
} |
||||
|
||||
public List<Component> getHighlightList() { |
||||
return highlightList; |
||||
} |
||||
|
||||
private UILabel getTargetComponentWithImage(BufferedImage image, Rectangle rectangle) { |
||||
ImageIcon ic = new ImageIcon(image); |
||||
UILabel label = new UILabel(ic); |
||||
label.setOpaque(true); |
||||
label.setBounds(rectangle); |
||||
return label; |
||||
} |
||||
|
||||
private BufferedImage captureImage(Rectangle rectangle) throws AWTException { |
||||
container.setVisible(false); |
||||
BufferedImage image = ScreenImage.createImage(rectangle); |
||||
showContainer(); |
||||
return image; |
||||
} |
||||
|
||||
private BufferedImage captureImage(Component component) throws AWTException { |
||||
container.setVisible(false); |
||||
BufferedImage image = ScreenImage.createImage(component); |
||||
showContainer(); |
||||
return image; |
||||
} |
||||
|
||||
private void showContainer() { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
container.setVisible(true); |
||||
container.toFront(); |
||||
container.requestFocus(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 自定义位置添加气泡提示组件 |
||||
* @param title 提示标题 |
||||
* @param content 提示内容 |
||||
* @param direction 气泡窗口位置方向 |
||||
* @param anchor 气泡窗口箭头坐标 |
||||
* @param bubbleTailStart 气泡窗口箭头坐标相对于位置方向交叉轴的比例(从左到右,从上到下) |
||||
*/ |
||||
public void addBubbleTip(String title,String content, GuideTip.Direction direction, Point anchor, float bubbleTailStart) { |
||||
BubbleTip bt = new BubbleTip(title, content, direction, bubbleTailStart); |
||||
bt.setAnchor(anchor); |
||||
this.add(bt.getTip()); |
||||
} |
||||
|
||||
/** |
||||
* 以上一个添加的引导目标窗口为基础,添加对应的气泡窗 |
||||
* @param title 提示标题 |
||||
* @param content 提示内容 |
||||
* @param direction |
||||
* @param anchorStart |
||||
* @param bubbleTailStart |
||||
*/ |
||||
public void addBubbleTip(String title, String content, GuideTip.Direction direction, float anchorStart, float bubbleTailStart) { |
||||
if (highlightList.size() == 0) { |
||||
return; |
||||
} |
||||
Component lastTarget = highlightList.get(highlightList.size() - 1); |
||||
Rectangle bounds = lastTarget.getBounds(); |
||||
Point anchor = new Point(0,0); |
||||
if (direction == GuideTip.Direction.TOP) { |
||||
anchor = new Point(bounds.x + (int)(bounds.width * anchorStart), bounds.y); |
||||
} else if (direction == GuideTip.Direction.BOTTOM) { |
||||
anchor = new Point(bounds.x + (int)(bounds.width * anchorStart), bounds.y + bounds.height); |
||||
} else if (direction == GuideTip.Direction.LEFT) { |
||||
anchor = new Point(bounds.x, bounds.y + (int)(bounds.height * anchorStart)); |
||||
} else if (direction == GuideTip.Direction.RIGHT) { |
||||
anchor = new Point(bounds.x + bounds.width, bounds.y + (int) (bounds.height * anchorStart)); |
||||
} |
||||
addBubbleTip(title, content, direction, anchor, bubbleTailStart); |
||||
} |
||||
|
||||
public void addBubbleTip(String title, String content, GuideTip.Direction direction) { |
||||
addBubbleTip(title, content, direction, 0.5f, 0.5f); |
||||
} |
||||
|
||||
public void addBubbleTip(String title, GuideTip.Direction direction) { |
||||
addBubbleTip(title, StringUtils.EMPTY, direction); |
||||
} |
||||
|
||||
public void addTip(GuideTip tip) { |
||||
this.add(tip.getTip()); |
||||
} |
||||
|
||||
public void addLineArrow(Point... points) { |
||||
pointsList.add(points); |
||||
} |
||||
|
||||
public void setContainer(GuideView container) { |
||||
this.container = container; |
||||
} |
||||
|
||||
public GuideView getContainer() { |
||||
return container; |
||||
} |
||||
|
||||
@Override |
||||
public GuideScene nextScene(GuideScene scene) { |
||||
nextScene = scene; |
||||
return nextScene; |
||||
} |
||||
|
||||
@Override |
||||
public void addSceneFilter(SceneFilter filter) { |
||||
sceneFilter = filter; |
||||
} |
||||
|
||||
@Override |
||||
public void start() { |
||||
clear(); |
||||
showContainer(); |
||||
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(); |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
if (lifecycle != null) { |
||||
lifecycle.onComplete(); |
||||
} |
||||
if (sceneFilter != null) { |
||||
nextScene = sceneFilter.getFilterScene(); |
||||
} |
||||
if (nextScene != null) { |
||||
if (nextScene instanceof AbstractGuideScene) { |
||||
((AbstractGuideScene) nextScene).setContainer(container); |
||||
} |
||||
nextScene.start(); |
||||
} else { |
||||
GuideManager.getInstance().getCurrentGuide().complete(); |
||||
} |
||||
|
||||
} |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
public void registerLifecycle(GuideSceneLifecycle lifecycle) { |
||||
this.lifecycle = lifecycle; |
||||
} |
||||
|
||||
@Override |
||||
public void removeLifecycle() { |
||||
this.lifecycle = null; |
||||
} |
||||
|
||||
public void showNextButton() { |
||||
UIButton nextButton = new UIButton("Next"); |
||||
nextButton.setPreferredSize(new Dimension(60, 30)); |
||||
nextButton.setOpaque(false); |
||||
nextButton.setFont(nextButton.getFont().deriveFont(20)); |
||||
nextButton.setRoundBorder(true, 8); |
||||
nextButton.setForeground(Color.WHITE); |
||||
nextButton.setNormalPainted(false); |
||||
nextButton.setPressedPainted(false); |
||||
nextButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
complete(); |
||||
} |
||||
}); |
||||
this.nextButton = nextButton; |
||||
} |
||||
|
||||
private int getSceneWidth() { |
||||
if (container == null) { |
||||
return 0; |
||||
} |
||||
return container.getLayeredPane().getWidth(); |
||||
|
||||
} |
||||
|
||||
private int getSceneHeight() { |
||||
if (container == null) { |
||||
return 0; |
||||
} |
||||
return container.getLayeredPane().getHeight(); |
||||
} |
||||
|
||||
private void clear() { |
||||
targetList = new ArrayList<>(); |
||||
highlightList = new ArrayList<>(); |
||||
this.nextButton = null; |
||||
this.removeAll(); |
||||
invalidate(); |
||||
repaint(); |
||||
} |
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
super.paint(g); |
||||
if (pointsList.isEmpty()) { |
||||
return; |
||||
} |
||||
Graphics2D g2d = (Graphics2D) g; |
||||
Composite oldComposite = g2d.getComposite(); |
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); |
||||
g2d.setColor(Color.WHITE); |
||||
for (Point[] points : pointsList) { |
||||
if (points.length <= 1) { |
||||
continue; |
||||
} |
||||
Point startPoint = points[0]; |
||||
Point endPoint = startPoint; |
||||
for (int index = 1; index < points.length; index++) { |
||||
startPoint = endPoint; |
||||
endPoint = points[index]; |
||||
g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y); |
||||
} |
||||
|
||||
drawArrow(g2d, startPoint, endPoint); |
||||
} |
||||
g2d.setComposite(oldComposite); |
||||
} |
||||
|
||||
/** |
||||
* 根据最后两点坐标计算出三角箭头的三个点坐标,绘制箭头 |
||||
* 这里实现以终点坐标为坐标轴圆点计算 |
||||
* @param start 起始点坐标 |
||||
* @param end 重点坐标 |
||||
*/ |
||||
private void drawArrow(Graphics2D g2d, Point start, Point end) { |
||||
try{ |
||||
double dealtPointX = start.x - end.x; |
||||
double dealtPointY = -(start.y - end.y); |
||||
|
||||
double pointDistance = calDistance(dealtPointX, dealtPointY); |
||||
double triangleHeight = Math.min(DEFAULT_ARROW_HEIGHT, pointDistance); |
||||
double triangleWidth = triangleHeight * (DEFAULT_ARROW_WIDTH / 2) / DEFAULT_ARROW_WIDTH; |
||||
if (triangleHeight < 1 || triangleWidth < 1 || pointDistance < 1) { |
||||
return; |
||||
} |
||||
|
||||
double pointAngle; |
||||
double abs = 1; |
||||
if (dealtPointX == 0) { |
||||
pointAngle = Math.PI / 2; |
||||
} else { |
||||
pointAngle = Math.atan(dealtPointY / dealtPointX); |
||||
} |
||||
if (dealtPointY < 0) { |
||||
pointAngle += Math.PI; |
||||
abs = -1; |
||||
} |
||||
|
||||
double deltaAngle = Math.atan(triangleWidth / triangleHeight); |
||||
double triangleDistance = calDistance(triangleWidth, triangleHeight); |
||||
|
||||
Point p1 =calPoint(end, triangleDistance, pointAngle - deltaAngle, abs); |
||||
Point p2 = calPoint(end, triangleDistance, pointAngle + deltaAngle, abs); |
||||
|
||||
int xPoints[] = {end.x, p1.x, p2.x}; |
||||
int yPoints[] = {end.y, p1.y, p2.y}; |
||||
|
||||
g2d.fillPolygon(xPoints, yPoints, 3); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
GuideManager.getInstance().getCurrentGuide().terminate(); |
||||
} |
||||
} |
||||
|
||||
private double calDistance(double x, double y) { |
||||
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); |
||||
} |
||||
|
||||
private Point calPoint(Point relativePoint, double distance, double angle, double abs) { |
||||
int x = (int)(relativePoint.x + abs * distance * Math.cos(angle)); |
||||
int y = (int)(relativePoint.y - abs * distance * Math.sin(angle)); |
||||
return new Point(x, y); |
||||
} |
||||
} |
@ -0,0 +1,101 @@
|
||||
package com.fr.design.mainframe.guide.scene; |
||||
|
||||
import com.fr.design.mainframe.guide.base.GuideManager; |
||||
|
||||
import java.awt.Component; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
public class ClickScene extends AbstractGuideScene{ |
||||
public enum ClickType { |
||||
LEFT, LEFT_DOUBLE, RIGHT |
||||
} |
||||
|
||||
public void addClickTarget(Component component, ClickType clickType) { |
||||
addClickTarget(component, clickType, false); |
||||
} |
||||
|
||||
public void addClickTarget(Component component, ClickType clickType, boolean isDispatch) { |
||||
if (super.addTarget(component)) { |
||||
addTargetClickListener(clickType, isDispatch); |
||||
} |
||||
} |
||||
|
||||
public void addClickTarget(Rectangle rectangle, ClickType clickType) { |
||||
if (super.addTarget(rectangle)) { |
||||
addTargetClickListener(clickType,false); |
||||
} |
||||
} |
||||
|
||||
public void addClickTarget(Component component, Rectangle rectangle, ClickType clickType) { |
||||
if (super.addTarget(component, rectangle)) { |
||||
addTargetClickListener(clickType, false); |
||||
} |
||||
} |
||||
|
||||
public void addCustomClickTarget(Component component, Rectangle rectangle, ClickType clickType) { |
||||
if (super.addCustomTarget(component, rectangle)) { |
||||
addTargetClickListener(clickType, false); |
||||
} |
||||
} |
||||
|
||||
public void addCustomClickTarget(Component component, Point location, ClickType clickType) { |
||||
if (super.addCustomTarget(component, location)) { |
||||
addTargetClickListener(clickType, false); |
||||
} |
||||
} |
||||
|
||||
private void addTargetClickListener(ClickType clickType, boolean isDispatch) { |
||||
Component highlight = getHighlightList().get(getHighlightList().size() - 1); |
||||
Component target = getTargetList().get(getTargetList().size() - 1); |
||||
highlight.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
if (e.getButton() == MouseEvent.BUTTON1) { |
||||
if ((e.getClickCount() == 1 && clickType == ClickType.LEFT) || (e.getClickCount() == 2 && clickType == ClickType.LEFT_DOUBLE)) { |
||||
if (isDispatch) { |
||||
redispatchMouseEvent(e, target); |
||||
} |
||||
complete(); |
||||
} |
||||
} else if (e.getButton() == MouseEvent.BUTTON3 && clickType == ClickType.RIGHT) { |
||||
if (isDispatch) { |
||||
redispatchMouseEvent(e, target); |
||||
} |
||||
complete(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
if (isDispatch) { |
||||
redispatchMouseEvent(e, target); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseReleased(MouseEvent e) { |
||||
if (isDispatch) { |
||||
redispatchMouseEvent(e, target); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void redispatchMouseEvent(MouseEvent e, Component component) { |
||||
component.dispatchEvent(new MouseEvent(component, e.getID(), e |
||||
.getWhen(), e.getModifiers(), e.getX(), |
||||
e.getY(), e.getClickCount(), e.isPopupTrigger())); |
||||
} |
||||
|
||||
@Override |
||||
public void showScene() { |
||||
super.showScene(); |
||||
// 交互类的 scene 如果没有高亮内容块载,需要及时终止Guide,否则就没法去掉模态框影响到设计器主功能的使用了
|
||||
if (this.getComponentCount() == 0) { |
||||
GuideManager.getInstance().getCurrentGuide().terminate(); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
@ -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(); |
||||
} |
@ -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() { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
package com.fr.design.mainframe.guide.scene; |
||||
|
||||
public interface SceneFilter { |
||||
GuideScene getFilterScene(); |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@
|
||||
package com.fr.design.mainframe.guide.tip; |
||||
|
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.DesignerFrame; |
||||
import com.fr.design.mainframe.guide.base.Guide; |
||||
import com.fr.design.mainframe.guide.base.GuideManager; |
||||
import com.fr.design.mainframe.guide.ui.bubble.Bubble; |
||||
import com.fr.design.mainframe.guide.ui.bubble.BubbleWithClose; |
||||
|
||||
import javax.swing.JComponent; |
||||
import javax.swing.JOptionPane; |
||||
import java.awt.Point; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class BubbleTip implements GuideTip { |
||||
private BubbleWithClose bubbleBox; |
||||
private Point anchor; |
||||
|
||||
/** |
||||
* |
||||
* @param title 标题 |
||||
* @param content 内容 |
||||
* @param direction 气泡提示相对anchor的方向,这里方向会和气泡组件箭头方向相反 |
||||
* @param tailStart 气泡尾巴相对当前边垂直方向偏移位置比例,值在0-1范围 |
||||
*/ |
||||
public BubbleTip(String title, String content, Direction direction, float tailStart) { |
||||
bubbleBox = new BubbleWithClose(title, content, getBubbleBoxTailDirection(direction), tailStart); |
||||
bubbleBox.addCloseActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
Guide currentGuide = GuideManager.getInstance().getCurrentGuide(); |
||||
if (currentGuide != null) { |
||||
|
||||
int returnVal = FineJOptionPane.showConfirmDialog( |
||||
currentGuide.getGuideView(), |
||||
"确认退出当前教学引导?", |
||||
Toolkit.i18nText("Fine-Design_Basic_Confirm"), |
||||
JOptionPane.YES_NO_OPTION, |
||||
JOptionPane.QUESTION_MESSAGE); |
||||
if (returnVal == JOptionPane.YES_OPTION) { |
||||
currentGuide.terminate(); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
@Override |
||||
public JComponent getTip() { |
||||
if(anchor == null) { |
||||
return new BubbleWithClose(bubbleBox.getTitle(), bubbleBox.getContent(), Bubble.TailDirection.TOP, 0); |
||||
} else { |
||||
setBubbleBoxBound(); |
||||
return bubbleBox; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 设置锚点坐标 |
||||
* 这里可以指定气泡组件箭头坐标的箭头坐标 |
||||
* @param anchor |
||||
*/ |
||||
public void setAnchor(Point anchor) { |
||||
this.anchor = anchor; |
||||
} |
||||
|
||||
private void setBubbleBoxBound() { |
||||
int bubbleW = bubbleBox.getPreferredSize().width; |
||||
int bubbleH = bubbleBox.getPreferredSize().height; |
||||
if (bubbleBox.isTailHorizontal()) { |
||||
int x = bubbleBox.isTailLeft() ? anchor.x : anchor.x - bubbleW; |
||||
int y = anchor.y - (int) (bubbleH * bubbleBox.getTailStart()); |
||||
bubbleBox.setBounds(x, y, bubbleW, bubbleH); |
||||
} else if (bubbleBox.isTailVertical()) { |
||||
int x = anchor.x - (int) (bubbleW * bubbleBox.getTailStart()); |
||||
int y = bubbleBox.isTailTop() ? anchor.y : anchor.y - bubbleH; |
||||
bubbleBox.setBounds(x, y, bubbleW, bubbleH); |
||||
} |
||||
} |
||||
|
||||
private Bubble.TailDirection getBubbleBoxTailDirection(Direction direction) { |
||||
switch (direction) { |
||||
case TOP: |
||||
return Bubble.TailDirection.BOTTOM; |
||||
case BOTTOM: |
||||
return Bubble.TailDirection.TOP; |
||||
case LEFT: |
||||
return Bubble.TailDirection.RIGHT; |
||||
case RIGHT: |
||||
default: |
||||
return Bubble.TailDirection.LEFT; |
||||
} |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,117 @@
|
||||
package com.fr.design.mainframe.guide.ui; |
||||
|
||||
import com.fr.design.gui.frpane.UITextPane; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JButton; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import javax.swing.text.SimpleAttributeSet; |
||||
import javax.swing.text.StyleConstants; |
||||
import javax.swing.text.StyledDocument; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Container; |
||||
import java.awt.Dimension; |
||||
import java.awt.Window; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class GuideCompleteDialog extends JDialog { |
||||
private static final int DIALOG_WIDTH = 340; |
||||
private static final int DIALOG_HEIGHT = 367; |
||||
private static final Icon SUCCESS_ICON = IOUtils.readIcon("/com/fr/design/mainframe/guide/success.png"); |
||||
private static final int ICON_HEIGHT = 182; |
||||
private static final Color FONT_COLOR = new Color(51, 51, 52); |
||||
private static final Color BUTTON_BG_COLOR = new Color(65, 155,249); |
||||
private static GuideCompleteDialog dialog; |
||||
|
||||
public static GuideCompleteDialog getInstance() { |
||||
if (dialog == null) { |
||||
dialog = new GuideCompleteDialog(DesignerContext.getDesignerFrame()); |
||||
} |
||||
return dialog; |
||||
} |
||||
|
||||
private UITextPane textArea; |
||||
|
||||
public GuideCompleteDialog(Window window) { |
||||
super(window); |
||||
setSize(DIALOG_WIDTH, DIALOG_HEIGHT); |
||||
setUndecorated(true); |
||||
setModal(true); |
||||
setLocationRelativeTo(window); |
||||
this.setContentPane(getContentPane()); |
||||
} |
||||
|
||||
@Override |
||||
public Container getContentPane() { |
||||
JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
|
||||
UILabel completeImage = new UILabel(SUCCESS_ICON); |
||||
completeImage.setPreferredSize(new Dimension(DIALOG_WIDTH, ICON_HEIGHT)); |
||||
|
||||
JPanel container = new JPanel(new BorderLayout(0, 10)); |
||||
container.setBorder(BorderFactory.createEmptyBorder(0, 52, 25, 52)); |
||||
|
||||
UILabel title = new UILabel(Toolkit.i18nText("Fine-Design_Guide_Complete_Confirm")); |
||||
title.setFont(title.getFont().deriveFont(22.0f)); |
||||
title.setPreferredSize(new Dimension(190, 30)); |
||||
title.setHorizontalAlignment(SwingConstants.CENTER); |
||||
title.setForeground(FONT_COLOR); |
||||
|
||||
textArea = new UITextPane(); |
||||
textArea.setEnabled(false); |
||||
textArea.setOpaque(false); |
||||
textArea.setFont(textArea.getFont().deriveFont(18.0f)); |
||||
textArea.setPreferredSize(new Dimension(236, 52)); |
||||
textArea.setBorder(null); |
||||
textArea.setDisabledTextColor(FONT_COLOR); |
||||
StyledDocument doc = textArea.getStyledDocument(); |
||||
SimpleAttributeSet center = new SimpleAttributeSet(); |
||||
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); |
||||
doc.setParagraphAttributes(0, doc.getLength(), center, false); |
||||
|
||||
JPanel buttonContainer= FRGUIPaneFactory.createCenterFlowZeroGapBorderPane(); |
||||
buttonContainer.setPreferredSize(new Dimension(190,38)); |
||||
buttonContainer.setOpaque(false); |
||||
|
||||
JButton button = new JButton(Toolkit.i18nText("Fine-Design_Guide_Complete_End")); |
||||
button.setPreferredSize(new Dimension(122, 38)); |
||||
button.setBackground(BUTTON_BG_COLOR); |
||||
button.setForeground(Color.WHITE); |
||||
button.setBorder(null); |
||||
button.setContentAreaFilled(false); |
||||
button.setOpaque(true); |
||||
button.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
setVisible(false); |
||||
dispose(); |
||||
} |
||||
}); |
||||
|
||||
buttonContainer.add(button); |
||||
container.add(title, BorderLayout.NORTH); |
||||
container.add(textArea, BorderLayout.CENTER); |
||||
container.add(buttonContainer,BorderLayout.SOUTH); |
||||
|
||||
contentPane.add(completeImage, BorderLayout.NORTH); |
||||
contentPane.add(container, BorderLayout.CENTER); |
||||
|
||||
return contentPane; |
||||
} |
||||
|
||||
public void showDialog(String str) { |
||||
textArea.setText(Toolkit.i18nText("Fine-Design_Guide_Complete_Hint", str)); |
||||
repaint(); |
||||
this.setVisible(true); |
||||
} |
||||
} |
@ -0,0 +1,233 @@
|
||||
package com.fr.design.mainframe.guide.ui; |
||||
|
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.VerticalFlowLayout; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.guide.base.Guide; |
||||
import com.fr.design.mainframe.guide.base.GuideGroup; |
||||
import com.fr.design.mainframe.guide.base.GuideManager; |
||||
import com.fr.design.mainframe.guide.base.GuideVersion; |
||||
import com.fr.design.mainframe.guide.collect.GuideCollector; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.border.Border; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.Window; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class GuideManageDialog extends JDialog { |
||||
private static final int DEFAULT_HEIGHT = 400; |
||||
private static final int DEFAULT_WIDTH = 600; |
||||
private static final Icon GROUP_COMPLETE_NONE = IOUtils.readIcon("/com/fr/design/mainframe/guide/complete_none.png"); |
||||
private static final Icon GROUP_COMPLETE_SOME = IOUtils.readIcon("/com/fr/design/mainframe/guide/complete_some.png"); |
||||
private static final Icon GROUP_COMPLETE_ALL = IOUtils.readIcon("/com/fr/design/mainframe/guide/complete_all.png"); |
||||
private static final Color BORDER_COLOR = new Color(224, 224, 225); |
||||
private static final Color UNCOMPLETE_FONT_COLOR = new Color(51, 51, 52); |
||||
private static final Color COMPLETE_FONT_COLOR = new Color(51,51,52,128); |
||||
private static GuideManageDialog dialog; |
||||
|
||||
private JPanel scrollContent; |
||||
|
||||
public static GuideManageDialog getInstance() { |
||||
if (dialog == null) { |
||||
dialog = new GuideManageDialog(DesignerContext.getDesignerFrame()); |
||||
} |
||||
return dialog; |
||||
} |
||||
|
||||
public GuideManageDialog(Window parent) { |
||||
super(parent); |
||||
GuideCollector.getInstance().load(); |
||||
initComponent(); |
||||
} |
||||
|
||||
private void initComponent() { |
||||
this.setTitle(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Title")); |
||||
setResizable(false); |
||||
setModal(true); |
||||
setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); |
||||
GUICoreUtils.centerWindow(this); |
||||
JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
contentPane.add(createContentPanel(), BorderLayout.CENTER); |
||||
contentPane.add(createActionsPane(), BorderLayout.SOUTH); |
||||
setContentPane(contentPane); |
||||
} |
||||
|
||||
private UIScrollPane createContentPanel() { |
||||
scrollContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 5); |
||||
UIScrollPane scrollPane = new UIScrollPane(scrollContent); |
||||
return scrollPane; |
||||
} |
||||
|
||||
private JPanel createGuideVersionPane(GuideVersion guideVersion) { |
||||
JPanel expandContent = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 5); |
||||
for (GuideGroup guideGroup : guideVersion.getGuideGroupList()) { |
||||
JPanel guideGroupCard = createGuideGroupCard(guideGroup); |
||||
expandContent.add(guideGroupCard); |
||||
} |
||||
ExpandPane expandPane = new ExpandPane(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Version_Title", guideVersion.getVersion()), expandContent); |
||||
return expandPane; |
||||
} |
||||
|
||||
|
||||
private JPanel createGuideGroupCard(GuideGroup guideGroup) { |
||||
JPanel card = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
card.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); |
||||
card.setBackground(Color.WHITE); |
||||
|
||||
JPanel cardContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
cardContainer.setOpaque(false); |
||||
cardContainer.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); |
||||
card.add(cardContainer, BorderLayout.CENTER); |
||||
|
||||
cardContainer.add(createGroupTitlePane(guideGroup), BorderLayout.NORTH); |
||||
cardContainer.add(createGroupContentPane(guideGroup), BorderLayout.CENTER); |
||||
return card; |
||||
} |
||||
|
||||
private JPanel createGroupTitlePane(GuideGroup guideGroup) { |
||||
JPanel titleContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.CENTER, 0, 0); |
||||
titleContainer.setBorder(getBottomBorder()); |
||||
titleContainer.setOpaque(false); |
||||
|
||||
titleContainer.setPreferredSize(new Dimension(500, 40)); |
||||
JPanel titlePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 8,0 ); |
||||
titlePane.setOpaque(false); |
||||
|
||||
UILabel iconLabel = new UILabel(getGroupStateIcon(guideGroup)); |
||||
iconLabel.setPreferredSize(new Dimension(16, 16)); |
||||
iconLabel.setOpaque(false); |
||||
|
||||
UILabel titleLabel = new UILabel(guideGroup.getName()); |
||||
titleLabel.setPreferredSize(new Dimension(200, 16)); |
||||
titleLabel.setForeground(new Color(65, 155, 249)); |
||||
titleLabel.setOpaque(false); |
||||
|
||||
titlePane.add(iconLabel); |
||||
titlePane.add(titleLabel); |
||||
titleContainer.add(titlePane); |
||||
return titleContainer; |
||||
} |
||||
|
||||
private JPanel createGroupContentPane(GuideGroup guideGroup) { |
||||
JPanel groupContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 0); |
||||
groupContainer.setBorder(BorderFactory.createEmptyBorder(0,10,0,0)); |
||||
groupContainer.setOpaque(false); |
||||
for (int index = 0; index < guideGroup.getGuideList().size(); index++) { |
||||
JPanel guidePane = createGuidePane(guideGroup.getGuideList().get(index), index); |
||||
if (index != guideGroup.getGuideList().size() - 1) { |
||||
guidePane.setBorder(getBottomBorder()); |
||||
} |
||||
groupContainer.add(guidePane); |
||||
} |
||||
return groupContainer; |
||||
} |
||||
|
||||
|
||||
|
||||
private JPanel createGuidePane(Guide guide, int index) { |
||||
JPanel guidePaneContainer = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.CENTER, 0, 0); |
||||
guidePaneContainer.setPreferredSize(new Dimension(540, 40)); |
||||
guidePaneContainer.setOpaque(false); |
||||
|
||||
JPanel guidePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 50,0 ); |
||||
guidePane.setOpaque(false); |
||||
|
||||
UILabel title = new UILabel((index + 1) + "、" + guide.getDescription()); |
||||
title.setPreferredSize(new Dimension(440, 20)); |
||||
title.setForeground(guide.isComplete() ? COMPLETE_FONT_COLOR : UNCOMPLETE_FONT_COLOR); |
||||
title.setOpaque(false); |
||||
|
||||
|
||||
UIButton button = new UIButton(guide.isComplete() ? Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Retry") : Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Show")); |
||||
button.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
setVisible(false); |
||||
guide.go(); |
||||
} |
||||
}); |
||||
|
||||
button.setPreferredSize(new Dimension(48, 20)); |
||||
guidePane.add(title); |
||||
guidePane.add(button); |
||||
|
||||
guidePaneContainer.add(guidePane); |
||||
return guidePaneContainer; |
||||
} |
||||
|
||||
private Border getBottomBorder() { |
||||
return BorderFactory.createMatteBorder( |
||||
0,0,1, 0, BORDER_COLOR |
||||
); |
||||
} |
||||
|
||||
public void showDialog() { |
||||
resetScrollContent(); |
||||
this.setVisible(true); |
||||
} |
||||
|
||||
private Icon getGroupStateIcon(GuideGroup guideGroup) { |
||||
if (guideGroup.isCompleteAll()) { |
||||
return GROUP_COMPLETE_ALL; |
||||
} else if (guideGroup.isCompleteSome()) { |
||||
return GROUP_COMPLETE_SOME; |
||||
} else { |
||||
return GROUP_COMPLETE_NONE; |
||||
} |
||||
} |
||||
|
||||
private UIButton createCompleteAllButton() { |
||||
UIButton button = new UIButton(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Complete_All"))); |
||||
button.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
GuideManager.getInstance().completeAll(); |
||||
resetScrollContent(); |
||||
} |
||||
}); |
||||
return button; |
||||
} |
||||
|
||||
private UIButton createCloseButton() { |
||||
UIButton button = new UIButton(Toolkit.i18nText(Toolkit.i18nText("Fine-Design_Guide_Manager_Dialog_Close"))); |
||||
button.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
setVisible(false); |
||||
} |
||||
}); |
||||
return button; |
||||
} |
||||
|
||||
private JPanel createActionsPane() { |
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(BorderFactory.createEmptyBorder(7, 10, 7, 10)); |
||||
container.add(createCompleteAllButton(), BorderLayout.WEST); |
||||
container.add(createCloseButton(), BorderLayout.EAST); |
||||
return container; |
||||
} |
||||
|
||||
private void resetScrollContent() { |
||||
scrollContent.removeAll(); |
||||
for (GuideVersion guideVersion : GuideManager.getInstance().getGuideVersionList()) { |
||||
scrollContent.add(createGuideVersionPane(guideVersion)); |
||||
} |
||||
revalidate(); |
||||
repaint(); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,98 @@
|
||||
package com.fr.design.mainframe.guide.utils; |
||||
|
||||
import javax.swing.JComponent; |
||||
import javax.swing.SwingUtilities; |
||||
import java.awt.AWTException; |
||||
import java.awt.AlphaComposite; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Container; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics2D; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
import java.awt.Robot; |
||||
import java.awt.image.BufferedImage; |
||||
|
||||
public class ScreenImage { |
||||
|
||||
public static BufferedImage createImage(JComponent component) { |
||||
return ScreenImage.createImage(component, getRegion(component)); |
||||
} |
||||
|
||||
public static BufferedImage createImage(JComponent component, Rectangle region) { |
||||
if (! component.isDisplayable()) { |
||||
Dimension d = component.getSize(); |
||||
|
||||
if (d.width == 0 || d.height == 0) { |
||||
d = component.getPreferredSize(); |
||||
component.setSize( d ); |
||||
} |
||||
|
||||
layoutComponent( component ); |
||||
} |
||||
|
||||
BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB); |
||||
Graphics2D g2d = image.createGraphics(); |
||||
|
||||
if (! component.isOpaque()) { |
||||
g2d.setColor( component.getBackground() ); |
||||
g2d.fillRect(region.x, region.y, region.width, region.height); |
||||
} |
||||
|
||||
g2d.translate(-region.x, -region.y); |
||||
component.print( g2d ); |
||||
g2d.dispose(); |
||||
return image; |
||||
} |
||||
|
||||
public static BufferedImage createImage(Component component) |
||||
throws AWTException { |
||||
Point p = new Point(0, 0); |
||||
SwingUtilities.convertPointToScreen(p, component); |
||||
Rectangle region = component.getBounds(); |
||||
region.x = p.x; |
||||
region.y = p.y; |
||||
return ScreenImage.createImage(region); |
||||
} |
||||
|
||||
public static BufferedImage createImageWithModal(JComponent component) { |
||||
Rectangle region = getRegion(component); |
||||
BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB); |
||||
Graphics2D g2d = image.createGraphics(); |
||||
g2d.drawImage(createImage(component), 0, 0, null); |
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); |
||||
g2d.setColor(Color.BLACK); |
||||
g2d.fillRect(0, 0, region.width, region.height); |
||||
g2d.dispose(); |
||||
return image; |
||||
} |
||||
|
||||
public static BufferedImage createImage(Rectangle region) |
||||
throws AWTException { |
||||
BufferedImage image = new Robot().createScreenCapture( region ); |
||||
return image; |
||||
} |
||||
|
||||
private static Rectangle getRegion(Component component) { |
||||
Dimension d = component.getSize(); |
||||
if (d.width == 0 || d.height == 0) { |
||||
d = component.getPreferredSize(); |
||||
component.setSize( d ); |
||||
} |
||||
return new Rectangle(0, 0, d.width, d.height); |
||||
} |
||||
|
||||
static void layoutComponent(Component component) { |
||||
synchronized (component.getTreeLock()) { |
||||
component.doLayout(); |
||||
|
||||
if (component instanceof Container) { |
||||
for (Component child : ((Container)component).getComponents()) { |
||||
layoutComponent(child); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 162 B |
After Width: | Height: | Size: 153 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 485 B |
After Width: | Height: | Size: 401 B |
After Width: | Height: | Size: 567 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,15 @@
|
||||
package com.fr.design.mainframe.share.ui.base; |
||||
|
||||
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock; |
||||
|
||||
import javax.swing.JPopupMenu; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/9/15 |
||||
*/ |
||||
public abstract class AbstractWidgetPopupPreviewPane<T> extends JPopupMenu { |
||||
|
||||
public abstract void populateBean(PreviewWidgetBlock<T> block); |
||||
} |
@ -0,0 +1,212 @@
|
||||
package com.fr.design.mainframe.share.ui.online; |
||||
|
||||
import com.fr.design.designer.IntervalConstants; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane; |
||||
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock; |
||||
import com.fr.form.share.bean.OnlineShareWidget; |
||||
import com.fr.general.FRFont; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JSeparator; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.Graphics; |
||||
import java.awt.GridBagConstraints; |
||||
import java.awt.GridBagLayout; |
||||
import java.awt.Image; |
||||
import java.awt.Toolkit; |
||||
|
||||
/** |
||||
* @author Starryi |
||||
* @version 1.0 |
||||
* Created by Starryi on 2021/9/14 |
||||
*/ |
||||
public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane<OnlineShareWidget> { |
||||
private static final int POPUP_WIDTH = 412; |
||||
private static final int POPUP_TOP_HEIGHT = 28; |
||||
private static final int POPUP_BOTTOM_HEIGHT = 54; |
||||
|
||||
private PreviewImagePane previewImagePane; |
||||
private UILabel versionLabel; |
||||
private UILabel downloadsLabel; |
||||
private UILabel priceLabel; |
||||
|
||||
private final JPanel suitableThemeNamePane; |
||||
private UILabel suitableThemeNameLabel; |
||||
|
||||
public OnlineWidgetPopupPreviewPane() { |
||||
setPreferredSize(new Dimension(POPUP_WIDTH, getPreferredSize().height)); |
||||
setLayout(new BorderLayout(0, 0)); |
||||
setOpaque(true); |
||||
setBackground(new Color(0xF0F0F1)); |
||||
|
||||
suitableThemeNamePane = createSuitableThemeNamePane(); |
||||
JPanel previewImagePane = createPreviewImagePane(); |
||||
JPanel widgetInfoPane = createWidgetInfoPane(); |
||||
|
||||
addComponents(suitableThemeNamePane, previewImagePane, widgetInfoPane); |
||||
} |
||||
|
||||
private JPanel createSuitableThemeNamePane() { |
||||
suitableThemeNameLabel = new UILabel(); |
||||
suitableThemeNameLabel.setOpaque(false); |
||||
suitableThemeNameLabel.setBackground(new Color(0xF5F5F7)); |
||||
suitableThemeNameLabel.setIcon(IOUtils.readIcon("/com/fr/design/icon/icon_predefined_style.png")); |
||||
suitableThemeNameLabel.setIconTextGap(IntervalConstants.INTERVAL_L6); |
||||
|
||||
JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
content.setPreferredSize(new Dimension(POPUP_WIDTH, POPUP_TOP_HEIGHT)); |
||||
content.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); |
||||
content.setOpaque(true); |
||||
content.setBackground(new Color(0xF5F5F7)); |
||||
content.add(suitableThemeNameLabel, BorderLayout.CENTER); |
||||
|
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.add(content, BorderLayout.CENTER); |
||||
|
||||
JSeparator separator = new JSeparator(); |
||||
separator.setPreferredSize(new Dimension(POPUP_WIDTH, 1)); |
||||
separator.setBackground(new Color(0xE8E8E9)); |
||||
container.add(separator, BorderLayout.SOUTH); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
private JPanel createPreviewImagePane() { |
||||
previewImagePane = new PreviewImagePane(); |
||||
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); |
||||
container.add(previewImagePane, BorderLayout.CENTER); |
||||
return container; |
||||
} |
||||
|
||||
private JPanel createWidgetInfoPane() { |
||||
versionLabel = new UILabel(); |
||||
versionLabel.setVerticalAlignment(SwingConstants.CENTER); |
||||
versionLabel.setFont(FRFont.getInstance(versionLabel.getFont()).deriveFont(12.0F)); |
||||
|
||||
downloadsLabel = new UILabel(); |
||||
downloadsLabel.setVerticalAlignment(SwingConstants.TOP); |
||||
downloadsLabel.setFont(FRFont.getInstance(downloadsLabel.getFont()).deriveFont(12.0F)); |
||||
|
||||
priceLabel = new UILabel(); |
||||
priceLabel.setVerticalAlignment(SwingConstants.CENTER); |
||||
priceLabel.setHorizontalAlignment(SwingConstants.RIGHT); |
||||
priceLabel.setFont(FRFont.getInstance(priceLabel.getFont()).deriveFont(14.0F)); |
||||
priceLabel.setForeground(new Color(0xE65251)); |
||||
|
||||
JPanel container = new JPanel(); |
||||
container.setPreferredSize(new Dimension(POPUP_WIDTH - 20, POPUP_BOTTOM_HEIGHT)); |
||||
container.setLayout(new GridBagLayout()); |
||||
container.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); |
||||
|
||||
GridBagConstraints constraints = new GridBagConstraints(); |
||||
constraints.fill = GridBagConstraints.BOTH; |
||||
|
||||
constraints.gridx = 0; |
||||
constraints.gridy = 0; |
||||
constraints.gridwidth = 1; |
||||
constraints.gridheight = 1; |
||||
constraints.weightx = 1; |
||||
constraints.weighty = 1; |
||||
container.add(versionLabel, constraints); |
||||
|
||||
constraints.gridx = 0; |
||||
constraints.gridy = 1; |
||||
constraints.gridwidth = 1; |
||||
constraints.gridheight = 1; |
||||
constraints.weightx = 1; |
||||
constraints.weighty = 1; |
||||
container.add(downloadsLabel, constraints); |
||||
|
||||
constraints.gridx = 1; |
||||
constraints.gridy = 0; |
||||
constraints.gridwidth = 1; |
||||
constraints.gridheight = 2; |
||||
constraints.weightx = 1; |
||||
constraints.weighty = 2; |
||||
container.add(priceLabel, constraints); |
||||
|
||||
return container; |
||||
} |
||||
|
||||
private void addComponents(JComponent... components) { |
||||
if (components == null) { |
||||
return; |
||||
} |
||||
JComponent container = this; |
||||
for (int i = 0; i < components.length; i++) { |
||||
JComponent component = components[i]; |
||||
if (component != null) { |
||||
container.add(component, BorderLayout.NORTH); |
||||
if (i < components.length - 1) { |
||||
JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
container.add(nextContainer, BorderLayout.CENTER); |
||||
container = nextContainer; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void populateBean(PreviewWidgetBlock<OnlineShareWidget> block) { |
||||
OnlineShareWidget widget = block.getWidget(); |
||||
OnlineShareWidget parentPackage = widget.getParentPackage(); |
||||
if (parentPackage != null && StringUtils.isNotEmpty(parentPackage.getThemeName())) { |
||||
suitableThemeNamePane.setVisible(true); |
||||
suitableThemeNameLabel.setText(parentPackage.getThemeName()); |
||||
} else { |
||||
suitableThemeNamePane.setVisible(false); |
||||
} |
||||
|
||||
String priceText = "¥" + widget.getPrice(); |
||||
if (widget.getPrice() <= 0) { |
||||
priceText = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Price_Free"); |
||||
} |
||||
priceLabel.setText(priceText); |
||||
|
||||
versionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Version") + ": " + widget.getDesignerVersion()); |
||||
downloadsLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Download_Times") + ": " + widget.getDownloadTimes()); |
||||
previewImagePane.setPreviewImage(block.getPreviewImage()); |
||||
|
||||
int height = (suitableThemeNamePane.isVisible() ? POPUP_TOP_HEIGHT : 0) + 10 + previewImagePane.getPreferredSize().height + POPUP_BOTTOM_HEIGHT; |
||||
setPreferredSize(new Dimension(POPUP_WIDTH, height)); |
||||
} |
||||
|
||||
private static class PreviewImagePane extends JPanel { |
||||
private static final Image DEFAULT_IMAGE = IOUtils.readImage("com/fr/base/images/share/component_error.png"); |
||||
private static final int PREVIEW_IMAGE_WIDTH = POPUP_WIDTH - 20; |
||||
private static final int STANDARD_DPI = 128; |
||||
|
||||
private Image previewImage; |
||||
|
||||
public void setPreviewImage(Image previewImage) { |
||||
this.previewImage = previewImage; |
||||
if (this.previewImage == null) { |
||||
this.previewImage = DEFAULT_IMAGE; |
||||
} |
||||
|
||||
int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); |
||||
int imageWidth = this.previewImage.getWidth(null); |
||||
int imageHeight = this.previewImage.getHeight(null); |
||||
|
||||
double imageAspectRatio = (double) imageWidth / imageHeight; |
||||
int width = (PREVIEW_IMAGE_WIDTH * dpi) / STANDARD_DPI; |
||||
int height = (int) (width / imageAspectRatio); |
||||
setPreferredSize(new Dimension(width, height)); |
||||
} |
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
g.drawImage(this.previewImage, 0, 0, getWidth(), getHeight(), null); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,19 @@
|
||||
package com.fr.design.mainframe.guide; |
||||
|
||||
public class GuideIds { |
||||
public static class GuideVersion { |
||||
public static final String V11_0_0 = "11.0.0"; |
||||
} |
||||
|
||||
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"; |
||||
} |
||||
} |
@ -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(GuideIds.GuideVersion.V11_0_0, new GuideGroup(GuideIds.GuideGroup.F01, Toolkit.i18nText("Fine-Design_Guide_Group_F01_Name"))); |
||||
GuideManager.getInstance().addGuideGroup(GuideIds.GuideVersion.V11_0_0, 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()); |
||||
} |
||||
} |
@ -0,0 +1,121 @@
|
||||
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.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 javax.swing.ImageIcon; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JPopupMenu; |
||||
import javax.swing.SwingUtilities; |
||||
import java.awt.Component; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
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() - designer.getHorizontalScaleValue(), 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); |
||||
} |
||||
|
||||
public static void openDialogWithoutModal(JDialog dialog) { |
||||
dialog.setModal(false); |
||||
dialog.setVisible(true); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,89 @@
|
||||
package com.fr.design.mainframe.guide.creator; |
||||
|
||||
import com.fr.design.actions.file.WebPreviewUtils; |
||||
import com.fr.design.designer.creator.XCreator; |
||||
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.BubbleTip; |
||||
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; |
||||
} |
||||
|
||||
public static GuideScene createSelectXCretorClickScene(String widgetName) { |
||||
ClickScene scene = new ClickScene(); |
||||
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() { |
||||
@Override |
||||
public boolean prepared() { |
||||
|
||||
XCreator xCreator = GuideCreateUtils.getXCreatorFormDesigner(widgetName); |
||||
scene.addClickTarget(GuideCreateUtils.getFormDesigner(), GuideCreateUtils.getXCreatorBoundsRelative2FormDesigner(xCreator), ClickScene.ClickType.LEFT); |
||||
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_Base_Tip_Select_Widget"), BubbleTip.Direction.BOTTOM); |
||||
return super.prepared(); |
||||
} |
||||
|
||||
@Override |
||||
public void onComplete() { |
||||
super.onComplete(); |
||||
FormDesigner designer = GuideCreateUtils.getFormDesigner(); |
||||
XCreator xCreator = GuideCreateUtils.getXCreatorFormDesigner(widgetName); |
||||
designer.getSelectionModel().reset(); |
||||
designer.getSelectionModel().selectACreator(xCreator); |
||||
} |
||||
}); |
||||
return scene; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -0,0 +1,243 @@
|
||||
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); |
||||
scene.addBubbleTip(Toolkit.i18nText("Fine-Design_Guide_Scene_F001001_Tip_Click_Confirm"), GuideTip.Direction.TOP); |
||||
} |
||||
return super.prepared(); |
||||
} |
||||
|
||||
@Override |
||||
public void onComplete() { |
||||
newFormPane.createLayoutForm(); |
||||
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(); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -0,0 +1,210 @@
|
||||
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(GuideSceneHelper.createFormDesignerBodyDisplayScene()) |
||||
.nextScene(GuideSceneHelper.createSelectXCretorClickScene("chart00")) |
||||
.nextScene(createScene5()) |
||||
.nextScene(GuideSceneHelper.createFormDesignerBodyDisplayScene()) |
||||
.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; |
||||
} |
||||
|
||||
@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() { |
||||
ClickScene scene = new ClickScene(); |
||||
final UIButtonGroup[] uiButtonGroup = new UIButtonGroup[1]; |
||||
scene.registerLifecycle(new GuideSceneLifecycleAdaptor() { |
||||
@Override |
||||
public boolean prepared() { |
||||
new Timer().schedule(new TimerTask() { |
||||
@Override |
||||
public void run() { |
||||
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 |
||||
); |
||||
scene.showScene(); |
||||
} |
||||
} |
||||
},1000); |
||||
return false; |
||||
} |
||||
|
||||
@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); |
||||
themeDialog.setVisible(true); |
||||
} |
||||
} |
@ -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) { |
||||
} |
||||
}); |
||||
|
||||
} |
||||
|
||||
} |