/** * Copyright 2014 * SMEdit https://github.com/StarMade/SMEdit * SMTools https://github.com/StarMade/SMTools * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. **/ package jo.sm.ui.act.plugin; import java.awt.Component; import java.awt.event.ActionEvent; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.swing.JFrame; import jo.sm.data.SparseMatrix; import jo.sm.data.StarMade; import jo.sm.logic.RunnableLogic; import jo.sm.logic.StarMadeLogic; import jo.sm.logic.utils.ConvertLogic; import jo.sm.mods.IBlocksPlugin; import jo.sm.mods.IPluginCallback; import jo.sm.mods.IRunnableWithProgress; import jo.sm.ship.data.Block; import jo.sm.ui.DlgError; import jo.sm.ui.RenderPanel; import jo.sm.ui.act.GenericAction; /** * @Auther Jo Jaquinta for SMEdit Classic - version 1.0 **/ @SuppressWarnings("serial") public class BlocksPluginAction extends GenericAction { private final IBlocksPlugin mPlugin; private final RenderPanel mPanel; public BlocksPluginAction(RenderPanel panel, IBlocksPlugin plugin) { mPanel = panel; mPlugin = plugin; String name = mPlugin.getName(); int o = name.indexOf('/'); if (o >= 0) { name = name.substring(o + 1); } setName(name); setToolTipText(mPlugin.getDescription()); } @Override public void actionPerformed(ActionEvent ev) { try { final Object params = mPlugin.newParameterBean(); loadProps(params); mPlugin.initParameterBean(StarMadeLogic.getModel(), params, StarMadeLogic.getInstance(), null); if (!getParams(params)) { return; } saveProps(params); IRunnableWithProgress t; t = new IRunnableWithProgress() { @Override public void run(IPluginCallback cb) { try { SparseMatrix<Block> original = StarMadeLogic.getModel(); mPanel.getUndoer().checkpoint(original); StarMade sm = StarMadeLogic.getInstance(); pluginInvoked(mPlugin, original, params, sm, cb); SparseMatrix<Block> modified = mPlugin.modify(original, params, sm, cb); if (!cb.isPleaseCancel()) { if (modified != null) { StarMadeLogic.setModel(modified); } else { mPanel.updateTiles(); } } if (((((PluginProgressDlg) cb).getErrorTitle() != null)) || (((PluginProgressDlg) cb).getErrorDescription() != null)) { ((PluginProgressDlg) cb).setPleaseCancel(true); // stop display if not yet auto-displayed StringBuilder description = new StringBuilder(); if (((PluginProgressDlg) cb).getErrorDescription() != null) { description.append("<hr/>").append(((PluginProgressDlg) cb).getErrorDescription()); } description.append(composeDescription(params)); DlgError.showError(getFrame(), ((PluginProgressDlg) cb).getErrorTitle(), description.toString(), ((PluginProgressDlg) cb).getError()); } else { } } catch (Throwable t) { DlgError.showError(getFrame(), "Error executing plugin", composeDescription(params), t); } } }; RunnableLogic.run(getFrame(), mPlugin.getName(), t); } catch (Throwable t) { DlgError.showError(getFrame(), "Error launching plugin", composeDescription(null), t); } } private String composeDescription(Object params) { StringBuilder html = new StringBuilder(); html.append("Plugin: <b>").append(mPlugin.getName()).append("</b><br/>"); if (params == null) { return html.toString(); } html.append("Arguments:<br/>"); html.append("<ul>"); try { BeanInfo info = Introspector.getBeanInfo(params.getClass()); for (PropertyDescriptor pd : info.getPropertyDescriptors()) { if ((pd.getReadMethod() == null) || (pd.getWriteMethod() == null)) { continue; } try { Object val = pd.getReadMethod().invoke(params); if (val != null) { html.append("<li>"); html.append(pd.getName()); html.append(" := <i>"); html.append(val.toString()); html.append("</i></li>"); } else { html.append("<li>"); html.append(pd.getName()); html.append(" := null</li>"); } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } } catch (IntrospectionException e) { e.printStackTrace(); } html.append("</ul>"); return html.toString(); } private void saveProps(Object params) { if (params == null) { return; } Properties props = StarMadeLogic.getProps(); String prefix = params.getClass().getName() + "$"; try { BeanInfo info = Introspector.getBeanInfo(params.getClass()); for (PropertyDescriptor pd : info.getPropertyDescriptors()) { if ((pd.getReadMethod() == null) || (pd.getWriteMethod() == null)) { continue; } try { Object val = pd.getReadMethod().invoke(params); if (val != null) { props.setProperty(prefix + pd.getName(), val.toString()); } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } } catch (IntrospectionException e) { e.printStackTrace(); } StarMadeLogic.saveProps(); } private void loadProps(Object params) { if (params == null) { return; } Properties props = StarMadeLogic.getProps(); String prefix = params.getClass().getName() + "$"; try { BeanInfo info = Introspector.getBeanInfo(params.getClass()); for (PropertyDescriptor pd : info.getPropertyDescriptors()) { if ((pd.getReadMethod() == null) || (pd.getWriteMethod() == null)) { continue; } if (!props.containsKey(prefix + pd.getName())) { continue; } String val = props.getProperty(prefix + pd.getName()); try { pd.getWriteMethod().invoke(params, ConvertLogic.toObject(val, pd.getPropertyType())); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } } catch (IntrospectionException e) { e.printStackTrace(); } } private boolean getParams(Object params) { if (params == null) { return true; } BeanEditDlg dlg = new BeanEditDlg(getFrame(), params); dlg.setVisible(true); params = dlg.getBean(); return params != null; } private JFrame getFrame() { for (Component c = mPanel; c != null; c = c.getParent()) { if (c instanceof JFrame) { return (JFrame) c; } } return null; } private static final List<IPluginInvocationListener> mListeners = new ArrayList<>(); public static void addPluginInvocationListener(IPluginInvocationListener listener) { mListeners.add(listener); } public static void removePluginInvocationListener(IPluginInvocationListener listener) { mListeners.remove(listener); } private void pluginInvoked(IBlocksPlugin plugin, SparseMatrix<Block> original, Object params, StarMade sm, IPluginCallback cb) { for (IPluginInvocationListener listener : mListeners.toArray(new IPluginInvocationListener[0])) { listener.pluginInvoked(plugin, original, params, sm, cb); } } }