一个插件实例 - 开发助手

功能:插件快捷重启、日志查询功能支持

plugin.xml

<extra-designer>
	<TitlePlaceProcessor class="v10.plugin.mate.MyTitleProcessor"/>
	<PluginManagerProvider class="v10.plugin.mate.MyPluginManager"/>
	<GlobalListenerProvider class="v10.plugin.mate.MyGlobalListenerProvider"/>
</extra-designer>

1、MyTitleProcessor - 日志查询支持

//设计器右上部分接口
public class MyTitleProcessor extends AbstractTitleProcessor {
	public MyTitleProcessor() {
	}
	@Override
	public void hold(Container container, Component loggerComponent, Component loginComponent) {
		if (loggerComponent instanceof LogMessageBar) {
			LogMessageBar logMessageBar = (LogMessageBar)loggerComponent;
			logMessageBar.addMouseListener(new MouseAdapter() {
				public void mouseClicked(MouseEvent event) {
					//右键清理日志
					if (event.getButton() == MouseEvent.BUTTON3) {
						PluginMate.clearLog();
					}
					JFrame frame = logMessageBar.getLogFrame();
					//日志窗口可设置大小
					frame.setResizable(true);
					DesignerLogHandler logHandler = DesignerLogHandler.getInstance();
					JPanel pane = (JPanel)logHandler.getLogHandlerArea();
					BorderLayout layout = (BorderLayout)pane.getLayout();
					UIScrollPane scrollPane = (UIScrollPane)layout.getLayoutComponent(BorderLayout.CENTER);
					JViewport viewPort = scrollPane.getViewport();
					JTextPane textPane = (JTextPane)viewPort.getView();
					LogHandlerBar logHandlerBar = (LogHandlerBar)logHandler.getCaption();
					String name = logHandlerBar.getComponent(0).getName();
					if (StringUtils.isEmpty(name) || !name.equals("PluginMateLogFinder")) {
						//添加搜索框
						UISearchTextField textField = new UISearchTextField(10);
						final StyledDocument styledDocument = textPane.getStyledDocument();
						//标记
						Style markedStyle = styledDocument.addStyle("markedStyle", null);
						StyleConstants.setBackground(markedStyle, Color.yellow);
						//取消标记
						Style unmarkedStyle = styledDocument.addStyle("unmarkedStyle", null);
						StyleConstants.setBackground(unmarkedStyle, Color.white);
						styledDocument.addDocumentListener(new DocumentAdapter() {
							@Override
							protected void textChanged(DocumentEvent documentEvent) {
								if (documentEvent.getType() == DocumentEvent.EventType.INSERT) {
									SwingUtilities.invokeLater(() -> find(styledDocument, textField.getText(), markedStyle, unmarkedStyle));
								}
							}
						});
						textField.registerChangeListener(() -> find(styledDocument, textField.getText(), markedStyle, unmarkedStyle));
						textField.setName("PluginMateLogFinder");
						logHandlerBar.add(textField, 0);
					}
				}
			});
		}
	}

	private void find(StyledDocument styledDocument, String target, Style markedStyle, Style unmarkedStyle) {
		styledDocument.setCharacterAttributes(0, styledDocument.getLength(), unmarkedStyle, false);
		if (target.length() == 0) {
			return;
		}
		try {
			String text = styledDocument.getText(0, styledDocument.getLength());
			int p = text.indexOf(target);
			while (p >= 0) {
				styledDocument.setCharacterAttributes(p, target.length(), markedStyle, false);
				p = text.indexOf(target, p + 1);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

2、MyPluginManager - 快捷启动插件选择

//插件管理接口
public class MyPluginManager extends AbstractPluginManagerProvider {
	@Override
	public UpdateAction pluginManagerAction() {
		return new PluginManagerAction() {
			@Override
			public void actionPerformed(ActionEvent e) {
				super.actionPerformed(e);
				if (Arch.getArch() != Arch.ARM && !OperatingSystem.isLinux() && !SupportOSImpl.MACOS_WEB_PLUGIN_MANAGEMENT.support()) {
					if (!ServerPreferenceConfig.getInstance().isUseOptimizedUPM() && !SupportOSImpl.MACOS_NEW_PLUGIN_MANAGEMENT.support() && !DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter()) {
						oldShop();
					} else {
						newShop();
					}
				}
			}
		};
	}

	@SuppressWarnings("deprecation")
	//JavaFX模式
	private void oldShop() {
		if (!PluginWebBridge.getHelper().isCustomTitleBar()) {
			return;
		}
		Platform.runLater(() -> {
			Iterator<Window> i = Window.impl_getWindows();
			while (i.hasNext()) {
				final Window w = i.next();
				final Scene scene = w.getScene();
				if (scene != null) {
					BorderPane pane = (BorderPane)scene.getRoot();
					WebView webView = (WebView)pane.getCenter();
					if (webView != null) {
						WebEngine webEngine = webView.getEngine();
						netscape.javascript.JSObject jsObject = (netscape.javascript.JSObject)webEngine.executeScript("window");
						//js、java桥梁
						jsObject.setMember("PluginMateWebBridge", PluginMate.getInstance());
						if (webEngine.getLoadWorker().getState() == Worker.State.SUCCEEDED) {
							org.w3c.dom.Document doc = webEngine.getDocument();
							org.w3c.dom.Element styleNode = doc.createElement("style");
							org.w3c.dom.Text styleContent = doc.createTextNode(getResource("old_shop.css"));
							styleNode.appendChild(styleContent);
							doc.getDocumentElement().getElementsByTagName("head").item(0).appendChild(styleNode);
							webEngine.executeScript(getResource("old_shop.js"));
						} else {
							ChangeListener<Worker.State> changeListener = (observable, oldValue, newValue) -> {
								if (newValue == Worker.State.SUCCEEDED) {
									org.w3c.dom.Document doc = webEngine.getDocument();
									org.w3c.dom.Element styleNode = doc.createElement("style");
									org.w3c.dom.Text styleContent = doc.createTextNode(getResource("old_shop.css"));
									styleNode.appendChild(styleContent);
									doc.getDocumentElement().getElementsByTagName("head").item(0).appendChild(styleNode);
									webEngine.executeScript(getResource("old_shop.js"));
								}
							};
							webEngine.getLoadWorker().stateProperty().addListener(changeListener);
						}
					}
				}
			}
		});
	}
	//jxbrowser模式
	private void newShop() {
		SwingUtilities.invokeLater(() -> {
			UpmShowDialog dialog = (UpmShowDialog)UpmFinder.getDialog();
			if (dialog != null) {
				Container pane = dialog.getRootPane().getContentPane();
				BorderLayout borderLayout = (BorderLayout)pane.getLayout();
				UpmShowPane upmShowPane = (UpmShowPane)borderLayout.getLayoutComponent(BorderLayout.CENTER);
				borderLayout = (BorderLayout)upmShowPane.getLayout();
				NewModernUIPane<?> modernUIPane = (NewModernUIPane<?>)borderLayout.getLayoutComponent(BorderLayout.CENTER);
				borderLayout = (BorderLayout)modernUIPane.getLayout();
				BrowserView browserView = (BrowserView)borderLayout.getLayoutComponent(BorderLayout.CENTER);
				Browser browser = browserView.getBrowser();
				CountDownLatch latch = new CountDownLatch(1);
				Subscription frameLoadFinished = browser.navigation().on(FrameLoadFinished.class, (event) -> {
					if (event.frame().isMain()) {
						browser.mainFrame().ifPresent(frame -> {
							frame.document().ifPresent(document -> document.documentElement().flatMap(element -> element.findElementByTagName("head")).ifPresent(head -> {
								com.teamdev.jxbrowser.dom.Element styleNode = document.createElement("style");
								com.teamdev.jxbrowser.dom.Node styleContent = document.createTextNode(getResource("new_shop.css"));
								styleNode.appendChild(styleContent);
								head.appendChild(styleNode);
							}));
							com.teamdev.jxbrowser.js.JsObject jsObject = frame.executeJavaScript("window");
							if (jsObject != null) {
								//js、java桥梁
								jsObject.putProperty("PluginMateWebBridge", PluginMate.getInstance());
							}
							frame.executeJavaScript(getResource("new_shop.js"));
						});
						latch.countDown();
					}
				});
				try {
					if (!latch.await(5, TimeUnit.SECONDS)) {
						throw new TimeoutException("Failed to execute task within 10 seconds.");
					}
				} catch (InterruptedException ex) {
					Thread.currentThread().interrupt();
					ex.printStackTrace();
				} finally {
					frameLoadFinished.unsubscribe();
				}
			}
		});
	}
}
//old_shop.js - jQuery模式
! function() {
	var button = $("<button class=\"shortcut-plugin-btn\" disabled=\"disabled\">快捷</button>")
	.appendTo(".sideView .installed-btn-group .pull-left").end()
	.on("click", function() {
		if (Store.Installed.selectPlugin && Store.Installed.selectPlugin.id && window.PluginMateWebBridge) {
			//设置快捷插件
			if (Store.Installed.selectPlugin.id == window.PluginMateWebBridge.getPluginId()) {
				window.PluginMateWebBridge.setPluginId("");
			} else {
				window.PluginMateWebBridge.setPluginId(Store.Installed.selectPlugin.id);
			}
			Store.Installed.showInstalledPlugin();
		}
		return false;
	});
	//监听控件选择动作
	Store.Installed = new Proxy(Store.Installed, {
		set: function(target, key, value) {
			target[key] = value
			if (key == 'selectPlugin') {
				if (value.id === undefined) {
					button.attr("disabled", "disabled")
				} else {
					button.removeAttr("disabled")
				}
			}
		}
	});
	//设置快捷插件状态
	Store.Render.window_show = new Proxy(Store.Render.window_show, {
		apply: function(target, thisArg, argumentsList) {
			var res = Reflect.apply(target, thisArg, argumentsList);
			if (window.PluginMateWebBridge) {
				var shortcutPluginID = window.PluginMateWebBridge.getPluginId();
				if(shortcutPluginID != "") {
					var svg = "<svg>";
					svg += "<polygon points=\"0,2 2,4 2,0\" style=\"fill: #cf8c2f;\"/>";
					svg += "<polygon points=\"0,2 0,25 21,46 44,46\" style=\"fill: #faaa39;\"/>";
					svg += "<polygon points=\"44,46 46,44 42,44\" style=\"fill: #cf8c2f;\"/>";
					svg += "</svg>";
					var $mark = $("<div class=\"shortcut-plugin-marked\"></div>").append(svg).append("<div class=\"mark-text\"></div>");
					$("#" + shortcutPluginID.replace(/\./g, "-")).append($mark);
				}
			}
			return res;
		}
	});
} ();
//new_shop.js - BI模式
! function() {
	if (!window.PluginMateWebBridge) {
		return;
	}
	BI.config("bi.button", function(obj) {
		if (obj.text == BI.i18nText("Dec-Upm_Shop_Store_Update-ALL")) {
			obj.minWidth = 60;
		} else if (obj.text == BI.i18nText("Dec-Upm_Shop_Store_Update_From_Local")) {
			obj.minWidth = 67;
		} else if (obj.text == BI.i18nText("Dec-Upm_Shop_Store_Disabled") || obj.text == BI.i18nText("Dec-Upm_Shop_Store_Delete")) {
			obj.minWidth = 36;
			obj.textWidth = 36;
		}
	});
	BI.shortcut("shortcut.plugin.marked", BI.inherit(BI.Widget, {
		props: {
			invisible: true
		},
		render: function() {
			return {
				type: "bi.absolute",
				cls: "shortcut-plugin-marked",
				items: [{
					el: {
						type: "bi.layout",
						cls: "mark-text"
					},
					bottom: 19,
					left: 8
				}]
			}
		},
		beforeCreate: function() {
			var svg = "<svg>";
			svg += "<polygon points=\"0,2 2,4 2,0\" style=\"fill: #cf8c2f;\" />";
			svg += "<polygon points=\"0,2 0,21 25,46 44,46\" style=\"fill: #faaa39;\" />";
			svg += "<polygon points=\"44,46 46,44 42,44\" style=\"fill: #cf8c2f;\" />";
			svg += "</svg>";
			this.element.append(svg);
		}
	}));
	BI.config("bi.left_right_vertical_adapt", function(obj) {
		if (obj.items && obj.items.left && obj.items.left.length == 2) {
			if (obj.items.left[0].text == BI.i18nText("Dec-Upm_Shop_Store_Disabled")) {
				//监听插件选择状态
				BI.model("shortcut-plugin-model", BI.inherit(Fix.Model, {
					context: ["pluginSelected", "installedPlugins"],
					computed: {
						selectedPlugin: function() {
							var e = this;
							return BI.find(this.model.installedPlugins, (function(t, i) {
								return i.id === e.model.pluginSelected
							}))
						}
					},
					actions: {
						showInstalledPlugins: function() {
							var e = this;
							if (window.PluginHelper) {
								window.PluginHelper.getInstalledPlugins(function(t) {
									e.model.installedPlugins = JSON.parse(t);
								});
							} else if (window.parent.Dec) {
								window.parent.Dec.reqGet("/v10/plugin/installation", "getInstalledPlugins",
								function(t) {
									e.model.installedPlugins = t.data
								});
							} else {
								$("#store").empty();
								BI.createWidget({
									type: "dec.upm.plugin.shop",
									element: "#store"
								});
							}
						}
					}
				}));
				BI.shortcut("shortcut.plugin.button", BI.inherit(BI.Button, {
					props: {
						text: "快捷",
						minWidth: 36,
						textWidth: 36,
						height: 30,
						disabled: true,
						level: "warning",
						css: {
							marginLeft: 5
						},
						handler: function() {
							var self = this;
							if (this.model.pluginSelected == window.PluginMateWebBridge.getPluginId()) {
								window.PluginMateWebBridge.setPluginId("");
							} else {
								window.PluginMateWebBridge.setPluginId(this.model.pluginSelected);
							}
							this.store.showInstalledPlugins();
						}
					},
					_store: function() {
						return BI.Models.getModel("shortcut-plugin-model");
					},
					watch: {
						pluginSelected: function(e) {
							if (BI.isEmpty(e)) {
								this.setEnable(false);
							} else {
								this.setEnable(true);
							}
						}
					}
				}));
				obj.items.left.push({
					type: "shortcut.plugin.button"
				});
			}
		}
	});

	BI.config("bi.bubble_combo", function(obj) {
		var shortcutPluginID = window.PluginMateWebBridge.getPluginId();
		if (BI.isEmpty(shortcutPluginID)) {
			return;
		}
		obj.trigger = "click-hover";
		if (obj.element && obj.element.options) {
			if (obj.element.options.baseCls == "dec-upm-plguin-conponents-plugin" && obj.element.options.isInstalled) {
				if (shortcutPluginID == obj.element.options.id) {
					obj.el.items[0].items[0].items.push({
						el: {
							type: "shortcut.plugin.marked",
							invisible: false
						},
						left: 0,
						bottom: 0 - obj.el.items[0].items[1].height
					});
				}
			}
		}
	});

	$("#store").empty();
	BI.createWidget({
		type: "dec.upm.plugin.shop",
		element: "#store"
	});
} ();

3、MyGlobalListenerProvider - 快捷启动

//快捷键接口
public class MyGlobalListenerProvider extends AbstractGlobalListenerProvider {
	@Override
	public AWTEventListener listener() {
		return event -> {
			if (event instanceof KeyEvent) {
				KeyEvent keyEvent = (KeyEvent) event;
				if (keyEvent.isControlDown() && keyEvent.paramString().contains("KEY_RELEASED")) {
					if (keyEvent.getKeyCode() == KeyEvent.VK_1) {
						PluginMate.clearLog();
						PluginMate.restartPlugin();
					} else if (keyEvent.getKeyCode() == KeyEvent.VK_2) {
						PluginMate.restartPlugin();
					} else if (keyEvent.getKeyCode() == KeyEvent.VK_3) {
						PluginMate.reinstallPlugin();
					}
				}
			}
		};
	}
}

4、PluginMate - 具体处理

//继承数据库记录类
public class PluginMate extends DefaultConfiguration {
	private PluginMate() {
	}

	//数据库字段名
	@Identifier("shortcutPluginID")
	private final Conf<String> shortcutPluginID = Holders.simple("");

	public static PluginMate getInstance() {
		return ConfigContext.getConfigInstance(PluginMate.class);
	}

	public String getPluginId() {
		return shortcutPluginID.get();
	}

	public void setPluginId(String pluginId) {
		shortcutPluginID.set(pluginId);
	}

	//清理日志功能
	public static void clearLog() {
		DesignerLogHandler logHandler = DesignerLogHandler.getInstance();
		JPanel pane = (JPanel)logHandler.getLogHandlerArea();
		for (Component c : pane.getComponents()) {
			if (c instanceof UIScrollPane) {
				UIScrollPane scrollPane = (UIScrollPane)c;
				for (Component cc : scrollPane.getComponents()) {
					if (cc instanceof JViewport) {
						JViewport viewport = (JViewport)cc;
						JTextPane textPane = (JTextPane)viewport.getView();
						textPane.setText("");
						break;
					}
				}
				break;
			}
		}
		((LogHandlerBar)logHandler.getCaption()).clearMessage();
	}

	//重启插件
	public static void restartPlugin() {
		String pluginId = getInstance().getPluginId();
		if (StringUtils.isEmpty(pluginId)) {
			showAlert("请选择快捷启动插件");
			return;
		}

		final PluginController controller = PluginManager.getController();

		final PluginMarker pluginMarker = PluginUtils.getInstalledPluginMarkerByID(pluginId);
		if (pluginMarker == null) {
			showAlert("插件不存在");
			return;
		}
		PluginContext context = PluginManager.getContext(pluginMarker);

		ProgressDialog dialog = new ProgressDialog(DesignerContext.getDesignerFrame());
		dialog.setProgressValue(0);
		dialog.setVisible(true);

		if (context.isRunning()) {
			dialog.updateLoadingText("停止...");
			dialog.setProgressMaximum(2);
			controller.forbid(pluginMarker, pluginTaskResult -> {
				dialog.updateLoadingText("启动...");
				wait4(200);
				dialog.setProgressValue(1);
				controller.enable(pluginMarker, pluginTaskResult1 -> {
					dialog.updateLoadingText("重启完成");
					dialog.setProgressValue(2);
					wait4(600);
					dialog.dispose();
				});
			});
		} else {
			dialog.updateLoadingText("启动...");
			dialog.setProgressMaximum(1);
			controller.enable(pluginMarker, pluginTaskResult -> {
				dialog.updateLoadingText("重启完成");
				dialog.setProgressValue(1);
				wait4(600);
				dialog.dispose();
			});
		}
	}
	//重新安装插件
	public static void reinstallPlugin() {
		String pluginId = getInstance().getPluginId();
		if (StringUtils.isEmpty(pluginId)) {
			showAlert("请选择快捷启动插件");
			return;
		}

		final PluginController controller = PluginManager.getController();

		final PluginMarker pluginMarker = PluginUtils.getInstalledPluginMarkerByID(pluginId);
		if (pluginMarker == null) {
			showAlert("插件不存在");
			return;
		}
		PluginContext context = PluginManager.getContext(pluginMarker);

		File installation = getInstallation(context);
		if (installation == null) {
			showAlert("安装包不存在");
			return;
		}

		ProgressDialog dialog = new ProgressDialog(DesignerContext.getDesignerFrame());
		dialog.setProgressValue(0);
		dialog.setVisible(true);

		if (context.isRunning()) {
			dialog.updateLoadingText("停止...");
			dialog.setProgressMaximum(3);
			controller.forbid(pluginMarker, pluginTaskResult1 -> {
				dialog.updateLoadingText("卸载...");
				dialog.setProgressValue(1);
				wait4(200);
				controller.uninstall(pluginMarker, true, pluginTaskResult2 -> {
					dialog.updateLoadingText("安装...");
					dialog.setProgressValue(2);
					wait4(200);
					controller.install(installation, new ProgressCallback() {
						@Override
						public void updateProgress(String s, double v) {
						}

						@Override
						public void done(PluginTaskResult pluginTaskResult1) {
							dialog.updateLoadingText("安装完成");
							dialog.setProgressValue(3);
							wait4(600);
							dialog.dispose();
						}
					});
				});
			});
		} else {
			dialog.updateLoadingText("卸载...");
			dialog.setProgressMaximum(2);
			controller.uninstall(pluginMarker, true, pluginTaskResult1 -> {
				dialog.updateLoadingText("安装...");
				dialog.setProgressValue(1);
				wait4(200);
				controller.install(installation, new ProgressCallback() {
					@Override
					public void updateProgress(String s, double v) {
					}

					@Override
					public void done(PluginTaskResult pluginTaskResult1) {
						dialog.updateLoadingText("安装完成");
						dialog.setProgressValue(2);
						wait4(600);
						dialog.dispose();
					}
				});
			});
		}
	}

	private static @Nullable File getInstallation(PluginContext context) {
		if (context.getClassPaths().size() == 0) {
			return null;
		}
		File dir = new File(context.getClassPaths().get(0).getPath()).getParentFile();
		String pluginDirName = dir.getName();
		File install1 = new File(dir.getAbsolutePath() + "/plugin_installation.zip");
		File install2 = new File(dir.getParentFile().getAbsolutePath() + "/installation_zips/" + pluginDirName + "/plugin_installation.zip");
		File install;
		if (install1.exists()) {
			if (install2.exists()) {
				install = install1.lastModified() >= install2.lastModified() ? install1 : install2;
			} else {
				install = install1;
			}
		} else if (install2.exists()) {
			install = install2;
		} else {
			return null;
		}
		return install;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值