完善插件逻辑
This commit is contained in:
parent
0fffcb6828
commit
e505f2a6ce
@ -2,6 +2,7 @@ package org.jcnc.jnotepad.app.manager;
|
||||
|
||||
import atlantafx.base.theme.PrimerLight;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
@ -14,10 +15,12 @@ import org.jcnc.jnotepad.controller.ResourceController;
|
||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.RootManager;
|
||||
import org.jcnc.jnotepad.views.manager.SidebarToolBarManager;
|
||||
import org.jcnc.jnotepad.views.manager.TopMenuBarManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -31,6 +34,7 @@ import java.util.concurrent.ExecutorService;
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class ApplicationManager {
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
private static final ApplicationManager INSTANCE = new ApplicationManager();
|
||||
/**
|
||||
* 线程池
|
||||
@ -180,4 +184,9 @@ public class ApplicationManager {
|
||||
public void setPrimaryStage(Stage primaryStage) {
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
|
||||
public void stopApplication() {
|
||||
Platform.exit();
|
||||
// application.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@ package org.jcnc.jnotepad.model.entity;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.jcnc.jnotepad.plugin.interfaces.Plugin;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 插件信息
|
||||
*
|
||||
@ -241,4 +243,37 @@ public class PluginDescriptor {
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name, version, enabled, author, category, icon, size, description, detailedIntroduction, log, pluginUrl, mainClass, assetFolder, readMe, score, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PluginDescriptor other = (PluginDescriptor) obj;
|
||||
return Objects.equals(id, other.id) &&
|
||||
Objects.equals(name, other.name) &&
|
||||
Objects.equals(version, other.version) &&
|
||||
enabled == other.enabled &&
|
||||
Objects.equals(author, other.author) &&
|
||||
Objects.equals(category, other.category) &&
|
||||
Objects.equals(icon, other.icon) &&
|
||||
Objects.equals(size, other.size) &&
|
||||
Objects.equals(description, other.description) &&
|
||||
Objects.equals(detailedIntroduction, other.detailedIntroduction) &&
|
||||
Objects.equals(log, other.log) &&
|
||||
Objects.equals(pluginUrl, other.pluginUrl) &&
|
||||
Objects.equals(mainClass, other.mainClass) &&
|
||||
Objects.equals(assetFolder, other.assetFolder) &&
|
||||
Objects.equals(readMe, other.readMe) &&
|
||||
Objects.equals(score, other.score) &&
|
||||
Objects.equals(plugin, other.plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
package org.jcnc.jnotepad.plugin.manager;
|
||||
|
||||
import org.jcnc.jnotepad.app.manager.ApplicationManager;
|
||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
@ -67,29 +69,34 @@ public class PluginManager {
|
||||
*/
|
||||
public void unloadPlugin(PluginDescriptor pluginDescriptor) {
|
||||
// 删除集合中的插件信息
|
||||
pluginDescriptors.remove(pluginDescriptor);
|
||||
PluginConfigController instance = PluginConfigController.getInstance();
|
||||
instance.getConfig().getPlugins().remove(pluginDescriptor);
|
||||
// 刷新配置
|
||||
instance.writeConfig();
|
||||
// 删除本地插件jar包
|
||||
Path plungsPath = instance.getPlungsPath();
|
||||
try (Stream<Path> pathStream = Files.walk(plungsPath)) {
|
||||
pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> {
|
||||
try {
|
||||
File pluginJar = new File(path.toString());
|
||||
PluginDescriptor temp = readPlugin(pluginJar);
|
||||
if ((temp.getName() + temp.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
||||
Files.delete(pluginJar.toPath());
|
||||
ThreadPoolManager.getThreadPool().submit(() -> {
|
||||
// 移除插件管理类中的插件描述类
|
||||
pluginDescriptors.remove(pluginDescriptor);
|
||||
// 移除插件配置文件类中的插件描述类
|
||||
PluginConfigController instance = PluginConfigController.getInstance();
|
||||
instance.getConfig().getPlugins().remove(pluginDescriptor);
|
||||
|
||||
// 刷新配置
|
||||
instance.writeConfig();
|
||||
// 删除本地插件jar包
|
||||
Path plungsPath = instance.getPlungsPath();
|
||||
try (Stream<Path> pathStream = Files.walk(plungsPath)) {
|
||||
pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> {
|
||||
try {
|
||||
File pluginJar = new File(path.toString());
|
||||
PluginDescriptor temp = readPlugin(pluginJar);
|
||||
if ((temp.getName() + temp.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
||||
Files.delete(pluginJar.toPath());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
ThreadPoolManager.threadContSelfSubtracting();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
ThreadPoolManager.threadContSelfSubtracting();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,10 +173,6 @@ public class PluginManager {
|
||||
return temporaryPluginDescriptors;
|
||||
}
|
||||
|
||||
public void setTemporaryPluginDescriptors(List<PluginDescriptor> temporaryPluginDescriptors) {
|
||||
this.temporaryPluginDescriptors = temporaryPluginDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用插件
|
||||
*
|
||||
@ -183,15 +186,28 @@ public class PluginManager {
|
||||
* 保存插件设置并退出
|
||||
*/
|
||||
public void saveAndExitSettings() {
|
||||
pluginDescriptors = temporaryPluginDescriptors;
|
||||
settingsChange();
|
||||
clearTemporarySettings();
|
||||
}
|
||||
|
||||
private void settingsChange() {
|
||||
boolean equals = temporaryPluginDescriptors.equals(pluginDescriptors);
|
||||
if (!equals) {
|
||||
pluginDescriptors = temporaryPluginDescriptors;
|
||||
PopUpUtil.questionAlert("更改", "程序与插件更新", "请重启程序以应用插件中的更改!",
|
||||
appDialog -> {
|
||||
appDialog.close();
|
||||
// 执行关闭操作
|
||||
ApplicationManager.getInstance().stopApplication();
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存插件设置但不退出
|
||||
*/
|
||||
public void saveNotExitSettings() {
|
||||
pluginDescriptors = temporaryPluginDescriptors;
|
||||
settingsChange();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -7,6 +7,7 @@ import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.ui.dialog.interfaces.DialogButtonAction;
|
||||
|
||||
/**
|
||||
* 应用对话框
|
||||
@ -53,8 +54,8 @@ public class AppDialog extends Stage {
|
||||
// 自定义文本
|
||||
Label customTextLabel = new Label(builder.getCustomText());
|
||||
|
||||
Button confirmButton = createButton(builder.getLeftBtnText(), builder.getLeftBtnAction()::handleAction);
|
||||
Button cancelButton = createButton(builder.getRightBtnText(), builder.getRightBtnAction()::handleAction);
|
||||
Button confirmButton = createButton(builder.getLeftBtnText(), builder.getLeftBtnAction());
|
||||
Button cancelButton = createButton(builder.getRightBtnText(), builder.getRightBtnAction());
|
||||
|
||||
HBox hBox = new HBox(builder.getHBoxSpacing(), confirmButton, cancelButton);
|
||||
hBox.setAlignment(builder.getHboxPos());
|
||||
@ -75,9 +76,9 @@ public class AppDialog extends Stage {
|
||||
* @param action 按钮点击时的操作
|
||||
* @return Button 按钮控件
|
||||
*/
|
||||
private Button createButton(String text, Runnable action) {
|
||||
private Button createButton(String text, DialogButtonAction action) {
|
||||
Button button = new Button(text);
|
||||
button.setOnAction(e -> action.run());
|
||||
button.setOnAction(e -> action.handleAction(this));
|
||||
return button;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.model.enums.DialogType;
|
||||
import org.jcnc.jnotepad.ui.dialog.interfaces.DialogButtonAction;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
@ -24,9 +25,9 @@ public class AppDialogBuilder {
|
||||
private double height = 150;
|
||||
private FontIcon icon;
|
||||
|
||||
private DialogButtonAction leftBtnAction = () -> appDialog.close();
|
||||
private DialogButtonAction leftBtnAction = Stage::close;
|
||||
|
||||
private DialogButtonAction rightBtnAction = () -> appDialog.close();
|
||||
private DialogButtonAction rightBtnAction = Stage::close;
|
||||
|
||||
private String leftBtnText = "确定";
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package org.jcnc.jnotepad.ui.dialog.interfaces;
|
||||
|
||||
import org.jcnc.jnotepad.ui.dialog.AppDialog;
|
||||
|
||||
/**
|
||||
* 对话框按钮点击事件接口
|
||||
*
|
||||
@ -8,10 +10,10 @@ package org.jcnc.jnotepad.ui.dialog.interfaces;
|
||||
public interface DialogButtonAction {
|
||||
/**
|
||||
* 处理按钮的操作。子类必须实现此方法以定义按钮的行为
|
||||
*
|
||||
* @param appDialog 对话框
|
||||
* @apiNote
|
||||
* @since 2023/9/3 22:53
|
||||
*/
|
||||
|
||||
void handleAction();
|
||||
void handleAction(AppDialog appDialog);
|
||||
}
|
||||
|
||||
@ -26,8 +26,11 @@ import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.ui.dialog.AppDialog;
|
||||
import org.jcnc.jnotepad.ui.dialog.interfaces.DialogButtonAction;
|
||||
import org.jcnc.jnotepad.ui.module.CustomSetButton;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
@ -149,6 +152,10 @@ public class PluginManagementPane extends BorderPane {
|
||||
bottomBox.setAlignment(Pos.CENTER_RIGHT);
|
||||
bottomBox.setStyle("-fx-background-color: rgba(43,43,43,0.12);");
|
||||
bottomBox.setPadding(new Insets(7, 15, 7, 0));
|
||||
Button applicationButton = new Button(" 应用 ");
|
||||
applicationButton.getStyleClass().addAll(Styles.SMALL);
|
||||
applicationButton.setOnAction(event -> pluginManager.saveNotExitSettings());
|
||||
|
||||
Button confirmButton = new Button(" 确认 ");
|
||||
confirmButton.setTextFill(Color.WHITE);
|
||||
confirmButton.getStyleClass().addAll(Styles.SMALL);
|
||||
@ -168,9 +175,7 @@ public class PluginManagementPane extends BorderPane {
|
||||
stage.close();
|
||||
});
|
||||
cancelButton.getStyleClass().addAll(Styles.SMALL);
|
||||
Button applicationButton = new Button(" 应用 ");
|
||||
applicationButton.getStyleClass().addAll(Styles.SMALL);
|
||||
applicationButton.setOnAction(event -> pluginManager.saveNotExitSettings());
|
||||
|
||||
bottomBox.getChildren().addAll(confirmButton, cancelButton, applicationButton);
|
||||
|
||||
this.setBottom(bottomBox);
|
||||
@ -228,11 +233,11 @@ public class PluginManagementPane extends BorderPane {
|
||||
tile.setAction(toggleSwitch);
|
||||
tile.setActionHandler(() -> {
|
||||
customSplitPane.setRightContent(tileContentMap.get(tile));
|
||||
logger.info("点击了" + tile);
|
||||
logger.info("点击了{}", tile);
|
||||
});
|
||||
|
||||
// 创建专属的customSplitPane内容
|
||||
var content = createCustomSplitPaneContent(pluginDescriptor, toggleSwitch);
|
||||
var content = createCustomSplitPaneContent(pluginDescriptor, toggleSwitch, tile);
|
||||
|
||||
// 将内容与Tile关联起来
|
||||
tileContentMap.put(tile, content);
|
||||
@ -245,7 +250,7 @@ public class PluginManagementPane extends BorderPane {
|
||||
*
|
||||
* @return 创建的CustomSplitPane内容
|
||||
*/
|
||||
private Node createCustomSplitPaneContent(PluginDescriptor pluginDescriptor, ToggleSwitch toggleSwitch) {
|
||||
private Node createCustomSplitPaneContent(PluginDescriptor pluginDescriptor, ToggleSwitch toggleSwitch, Tile tile) {
|
||||
VBox content = new VBox(8);
|
||||
content.setPadding(new Insets(10));
|
||||
var titleLabel = new Text(pluginDescriptor.getName());
|
||||
@ -258,17 +263,30 @@ public class PluginManagementPane extends BorderPane {
|
||||
|
||||
|
||||
var uninstallItem = new MenuItem("卸载");
|
||||
|
||||
var state = new SplitMenuButton(uninstallItem);
|
||||
toggleSwitch.setSelected(pluginDescriptor.isEnabled());
|
||||
BooleanProperty booleanProperty = toggleSwitch.selectedProperty();
|
||||
state.textProperty().bind(Bindings.when(booleanProperty).then("禁用").otherwise("启用"));
|
||||
|
||||
uninstallItem.setOnAction(event -> PopUpUtil.warningAlert("卸载", "确定要卸载" + pluginDescriptor.getName() + "吗?", "此操作无法撤销!", new DialogButtonAction() {
|
||||
@Override
|
||||
public void handleAction(AppDialog dialog) {
|
||||
pluginManager.unloadPlugin(pluginDescriptor);
|
||||
state.setDisable(true);
|
||||
toggleSwitch.setDisable(true);
|
||||
dialog.close();
|
||||
}
|
||||
}, null));
|
||||
state.getStyleClass().addAll(Styles.ACCENT);
|
||||
state.setPrefWidth(80);
|
||||
toggleSwitch.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if (Boolean.TRUE.equals(newValue)) {
|
||||
pluginManager.enablePlugIn(pluginDescriptor);
|
||||
customSplitPane.setRightContent(tileContentMap.get(tile));
|
||||
} else {
|
||||
pluginManager.disablePlugIn(pluginDescriptor);
|
||||
customSplitPane.setRightContent(tileContentMap.get(tile));
|
||||
}
|
||||
});
|
||||
state.setOnAction(event -> {
|
||||
|
||||
@ -357,6 +357,4 @@ public class TopMenuBarManager {
|
||||
});
|
||||
topMenu.add(menu);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user