Skip to content

Commit ab5fcbf

Browse files
committed
newui: 初步实现插件项目创建工具
1 parent 6c054dd commit ab5fcbf

14 files changed

Lines changed: 328 additions & 22 deletions

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@
5555
<artifactId>xcore</artifactId>
5656
<version>0.0.4-SNAPSHOT</version>
5757
</dependency>
58+
<dependency>
59+
<groupId>org.projectlombok</groupId>
60+
<artifactId>lombok</artifactId>
61+
<version>1.18.6</version>
62+
<scope>provided</scope>
63+
</dependency>
5864
<!-- dom4j 需要的依赖 -->
5965
<dependency>
6066
<groupId>jaxen</groupId>

src/main/java/com/xwintop/xJavaFxTool/newui/NewLauncherController.java

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,29 @@
1212
import com.xwintop.xcore.javafx.dialog.FxAlerts;
1313
import com.xwintop.xcore.javafx.dialog.FxDialog;
1414
import com.xwintop.xcore.util.javafx.JavaFxViewUtil;
15+
import java.awt.Desktop;
16+
import java.io.File;
17+
import java.io.IOException;
18+
import java.net.URI;
19+
import java.util.ArrayList;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.ResourceBundle;
1524
import javafx.beans.Observable;
1625
import javafx.fxml.FXMLLoader;
1726
import javafx.scene.Parent;
27+
import javafx.scene.control.ButtonType;
28+
import javafx.scene.control.CheckMenuItem;
29+
import javafx.scene.control.ContextMenu;
30+
import javafx.scene.control.Hyperlink;
31+
import javafx.scene.control.TabPane;
1832
import javafx.scene.control.TextField;
19-
import javafx.scene.control.*;
2033
import javafx.scene.layout.VBox;
2134
import javafx.scene.web.WebView;
2235
import lombok.extern.slf4j.Slf4j;
2336
import org.apache.commons.lang3.StringUtils;
2437

25-
import java.awt.*;
26-
import java.io.IOException;
27-
import java.net.URI;
28-
import java.util.List;
29-
import java.util.*;
30-
3138
@Slf4j
3239
public class NewLauncherController {
3340

@@ -46,15 +53,14 @@ public class NewLauncherController {
4653
private ContextMenu itemContextMenu;
4754

4855
// 实现搜索用
49-
private List<PluginItemController> pluginItemControllers = new ArrayList<>();
56+
private final List<PluginItemController> pluginItemControllers = new ArrayList<>();
5057

5158
public void initialize() {
5259
NewLauncherService.getInstance().setController(this);
5360
txtSearch.textProperty().addListener(this::onSearchKeywordChanged);
5461
initContextMenu();
5562
loadPlugins(); // 加载插件列表到界面上
5663
startWebView.getEngine().load(IndexController.QQ_URL); // 额外再打开一个反馈页面,可关闭
57-
lnkCreatePlugin.setVisible(Boolean.parseBoolean(System.getProperty("create", "false")));
5864
}
5965

6066
private void initContextMenu() {
@@ -176,10 +182,14 @@ public void openPluginCreator() {
176182
dialog
177183
.setButtonHandler(ButtonType.OK, (actionEvent, stage) -> {
178184
if (controller.isStartCreation()) {
179-
PluginProjectInfo info = controller.getPluginProjectInfo();
180-
CreatePluginProjectService.getInstance().createProject(info);
181-
FxAlerts.info("创建成功", "项目 '" + info.getArtifactId() + "' 已经创建完毕。");
182-
// todo open directory
185+
try {
186+
PluginProjectInfo info = controller.getPluginProjectInfo();
187+
CreatePluginProjectService.getInstance().createProject(info);
188+
FxAlerts.info("创建成功", "项目 '" + info.getArtifactId() + "' 已经创建完毕。");
189+
Desktop.getDesktop().open(new File(info.getLocation()));
190+
} catch (IOException e) {
191+
FxAlerts.error("打开目标文件夹失败", e);
192+
}
183193
}
184194
stage.close();
185195
})

src/main/java/com/xwintop/xJavaFxTool/newui/PluginCreatorController.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.xwintop.xJavaFxTool.newui.creator.PluginProjectInfo;
44
import com.xwintop.xcore.util.javafx.FileChooserUtil;
5+
import java.io.File;
6+
import java.net.MalformedURLException;
57
import javafx.scene.Node;
68
import javafx.scene.control.Label;
79
import javafx.scene.control.TextField;
@@ -10,9 +12,6 @@
1012
import javafx.scene.layout.StackPane;
1113
import javafx.stage.FileChooser;
1214

13-
import java.io.File;
14-
import java.net.MalformedURLException;
15-
1615
public class PluginCreatorController {
1716

1817
public static final String WELCOME = "你想创建自己的插件项目吗?\n\n"
@@ -39,6 +38,8 @@ public class PluginCreatorController {
3938

4039
public TextField txtPluginName;
4140

41+
public TextField txtPluginTitle;
42+
4243
private boolean startCreation;
4344

4445
private void showStack(int index) {
@@ -89,6 +90,7 @@ public PluginProjectInfo getPluginProjectInfo() {
8990
pluginProjectInfo.setArtifactId(this.txtArtifactId.getText());
9091
pluginProjectInfo.setVersion(this.txtVersion.getText());
9192
pluginProjectInfo.setPluginName(this.txtPluginName.getText());
93+
pluginProjectInfo.setPluginTitle(this.txtPluginTitle.getText());
9294
pluginProjectInfo.setPluginLogo(this.imgPluginLogo.getImage());
9395
return pluginProjectInfo;
9496
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,94 @@
11
package com.xwintop.xJavaFxTool.newui.creator;
22

3+
import static com.xwintop.xJavaFxTool.utils.ResourceBundleUtils.toNativeAscii;
4+
5+
import com.xwintop.xJavaFxTool.utils.ResourceUtils;
6+
import com.xwintop.xcore.javafx.dialog.FxAlerts;
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.nio.charset.Charset;
10+
import java.nio.charset.StandardCharsets;
11+
import java.nio.file.Files;
12+
import java.nio.file.Path;
13+
import java.nio.file.Paths;
14+
import org.apache.commons.io.FileUtils;
15+
316
public class CreatePluginProjectService {
417

518
private static final CreatePluginProjectService INSTANCE = new CreatePluginProjectService();
619

20+
public static final Charset CHARSET = StandardCharsets.UTF_8;
21+
722
public static CreatePluginProjectService getInstance() {
823
return INSTANCE;
924
}
1025

1126
public void createProject(PluginProjectInfo pluginProjectInfo) {
27+
try {
28+
FileUtils.forceMkdir(new File(pluginProjectInfo.getLocation()));
29+
savePom(pluginProjectInfo);
30+
saveConfiguration(pluginProjectInfo);
31+
saveResourceBundle(pluginProjectInfo);
32+
saveFxml(pluginProjectInfo);
33+
saveControllerClass(pluginProjectInfo);
34+
saveMainClass(pluginProjectInfo);
35+
} catch (Exception e) {
36+
FxAlerts.error("创建失败", e);
37+
}
38+
}
39+
40+
private void saveMainClass(PluginProjectInfo info) throws Exception {
41+
String java = ResourceUtils.readResource("/plugin-template/PLUGIN_NAMEMain.java", CHARSET);
42+
java = java
43+
.replace("[PACKAGE]", info.getPackageName())
44+
.replace("[PLUGIN_NAME]", info.getPluginName())
45+
.replace("[CLASS_NAME]", info.getMainClass());
46+
String javaPath = "src/main/java/" + info.getMainFullClass().replace(".", "/") + ".java";
47+
writeFile(Paths.get(info.getLocation(), javaPath), java);
48+
}
49+
50+
private void saveControllerClass(PluginProjectInfo info) throws Exception {
51+
String java = ResourceUtils.readResource("/plugin-template/PLUGIN_NAMEController.java", CHARSET);
52+
java = java
53+
.replace("[PACKAGE]", info.getPackageName())
54+
.replace("[CLASS_NAME]", info.getControllerClass());
55+
String javaPath = "src/main/java/" + info.getControllerFullClass().replace(".", "/") + ".java";
56+
writeFile(Paths.get(info.getLocation(), javaPath), java);
57+
}
58+
59+
private void saveFxml(PluginProjectInfo info) throws Exception {
60+
String fxml = ResourceUtils.readResource("/plugin-template/PLUGIN_NAME.fxml", CHARSET);
61+
fxml = fxml
62+
.replace("[CONTROLLER]", info.getControllerFullClass())
63+
.replace("[PLUGIN_NAME]", info.getPluginName());
64+
String resourceBundlePath = "src/main/resources/fxml/" + info.getPluginName() + ".fxml";
65+
writeFile(Paths.get(info.getLocation(), resourceBundlePath), fxml);
66+
}
67+
68+
private void saveResourceBundle(PluginProjectInfo info) throws Exception {
69+
String resourceBundle = ResourceUtils.readResource("/plugin-template/PLUGIN_NAME.properties", CHARSET);
70+
resourceBundle = resourceBundle.replace("[TITLE]", toNativeAscii(info.getPluginTitle(), false, true));
71+
String resourceBundlePath = "src/main/resources/locale/" + info.getPluginName() + ".properties";
72+
writeFile(Paths.get(info.getLocation(), resourceBundlePath), resourceBundle);
73+
}
74+
75+
private void saveConfiguration(PluginProjectInfo info) throws Exception {
76+
String config = ResourceUtils.readResource("/plugin-template/toolFxmlLoaderConfiguration.xml", CHARSET);
77+
config = config.replace("[PLUGIN_NAME]", info.getPluginName());
78+
writeFile(Paths.get(info.getLocation(), "src/main/resources/config/toolFxmlLoaderConfiguration.xml"), config);
79+
}
80+
81+
private void savePom(PluginProjectInfo info) throws Exception {
82+
String pom = ResourceUtils.readResource("/plugin-template/pom.xml", CHARSET);
83+
pom = pom
84+
.replace("[GROUPID]", info.getGroupId())
85+
.replace("[ARTIFACTID]", info.getArtifactId())
86+
.replace("[VERSION]", info.getVersion());
87+
Files.write(Paths.get(info.getLocation(), "pom.xml"), pom.getBytes(CHARSET));
88+
}
1289

90+
private void writeFile(Path path, String fileContent) throws IOException {
91+
FileUtils.forceMkdirParent(path.toFile());
92+
Files.write(path, fileContent.getBytes(CHARSET));
1393
}
1494
}

src/main/java/com/xwintop/xJavaFxTool/newui/creator/PluginProjectInfo.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,40 @@ public class PluginProjectInfo {
1616

1717
private String pluginName;
1818

19+
private String pluginTitle;
20+
1921
private Image pluginLogo;
22+
23+
//////////////////////////////////////////////////////////////
24+
25+
public String getPackageName() {
26+
return groupId + "." + toClassName(artifactId).toLowerCase();
27+
}
28+
29+
public String getControllerClass() {
30+
return toClassName(artifactId) + "Controller";
31+
}
32+
33+
public String getControllerFullClass() {
34+
return getPackageName() + "." + getControllerClass();
35+
}
36+
37+
public String getMainClass() {
38+
return toClassName(artifactId) + "Main";
39+
}
40+
41+
public String getMainFullClass() {
42+
return getPackageName() + "." + getMainClass();
43+
}
44+
45+
private String toClassName(String hyphens) {
46+
StringBuilder sb = new StringBuilder();
47+
for (String s : hyphens.split("-")) {
48+
sb.append(Character.toUpperCase(s.charAt(0)));
49+
if (s.length() > 1) {
50+
sb.append(s.substring(1).toLowerCase());
51+
}
52+
}
53+
return sb.toString();
54+
}
2055
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.xwintop.xJavaFxTool.utils;
2+
3+
public class ResourceBundleUtils {
4+
5+
/**
6+
* 参考 {@link java.util.Properties} 的 saveConvert() 方法
7+
*/
8+
public static String toNativeAscii(String theString,
9+
boolean escapeSpace,
10+
boolean escapeUnicode) {
11+
int len = theString.length();
12+
int bufLen = len * 2;
13+
if (bufLen < 0) {
14+
bufLen = Integer.MAX_VALUE;
15+
}
16+
StringBuilder outBuffer = new StringBuilder(bufLen);
17+
18+
for(int x=0; x<len; x++) {
19+
char aChar = theString.charAt(x);
20+
// Handle common case first, selecting largest block that
21+
// avoids the specials below
22+
if ((aChar > 61) && (aChar < 127)) {
23+
if (aChar == '\\') {
24+
outBuffer.append('\\'); outBuffer.append('\\');
25+
continue;
26+
}
27+
outBuffer.append(aChar);
28+
continue;
29+
}
30+
switch(aChar) {
31+
case ' ':
32+
if (x == 0 || escapeSpace)
33+
outBuffer.append('\\');
34+
outBuffer.append(' ');
35+
break;
36+
case '\t':outBuffer.append('\\'); outBuffer.append('t');
37+
break;
38+
case '\n':outBuffer.append('\\'); outBuffer.append('n');
39+
break;
40+
case '\r':outBuffer.append('\\'); outBuffer.append('r');
41+
break;
42+
case '\f':outBuffer.append('\\'); outBuffer.append('f');
43+
break;
44+
case '=': // Fall through
45+
case ':': // Fall through
46+
case '#': // Fall through
47+
case '!':
48+
outBuffer.append('\\'); outBuffer.append(aChar);
49+
break;
50+
default:
51+
if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode ) {
52+
outBuffer.append('\\');
53+
outBuffer.append('u');
54+
outBuffer.append(toHex((aChar >> 12) & 0xF));
55+
outBuffer.append(toHex((aChar >> 8) & 0xF));
56+
outBuffer.append(toHex((aChar >> 4) & 0xF));
57+
outBuffer.append(toHex( aChar & 0xF));
58+
} else {
59+
outBuffer.append(aChar);
60+
}
61+
}
62+
}
63+
return outBuffer.toString();
64+
}
65+
66+
/**
67+
* Convert a nibble to a hex character
68+
* @param nibble the nibble to convert.
69+
*/
70+
private static char toHex(int nibble) {
71+
return hexDigit[(nibble & 0xF)];
72+
}
73+
74+
/** A table of hex digits */
75+
private static final char[] hexDigit = {
76+
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
77+
};
78+
79+
}

src/main/java/com/xwintop/xJavaFxTool/utils/ResourceUtils.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package com.xwintop.xJavaFxTool.utils;
22

3+
import java.io.IOException;
4+
import java.net.URISyntaxException;
35
import java.net.URL;
6+
import java.nio.charset.Charset;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.nio.file.Paths;
410
import org.apache.commons.lang.StringUtils;
511

612
public class ResourceUtils {
@@ -16,4 +22,9 @@ public static URL getResource(String... candidates) {
1622
}
1723
return null;
1824
}
25+
26+
public static String readResource(String resource, Charset charset) throws URISyntaxException, IOException {
27+
Path path = Paths.get(ResourceUtils.class.getResource(resource).toURI());
28+
return new String(Files.readAllBytes(path), charset);
29+
}
1930
}

0 commit comments

Comments
 (0)