package org.freeplane.plugin.script.addons; import java.awt.Component; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.freeplane.core.resources.ResourceController; import org.freeplane.core.ui.MenuBuilder; import org.freeplane.core.ui.components.UITools; import org.freeplane.core.util.FileUtils; import org.freeplane.core.util.FreeplaneIconUtils; import org.freeplane.core.util.LogUtils; import org.freeplane.core.util.TextUtils; import org.freeplane.features.map.MapModel; import org.freeplane.features.map.mindmapmode.MMapModel; import org.freeplane.features.mode.Controller; import org.freeplane.features.mode.ModeController; import org.freeplane.features.mode.mindmapmode.MModeController; import org.freeplane.features.url.mindmapmode.MFileManager; import org.freeplane.main.addons.AddOnProperties; import org.freeplane.main.addons.AddOnsController; import org.freeplane.plugin.script.ScriptingEngine; import org.freeplane.plugin.script.ScriptingPermissions; import com.jgoodies.forms.factories.DefaultComponentFactory; import com.jgoodies.forms.factories.FormFactory; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.RowSpec; @SuppressWarnings("serial") public class AddOnInstallerPanel extends JPanel { private ManageAddOnsPanel manageAddOnsPanel; private ManageAddOnsPanel manageThemesPanel; private JButton installButton; private JTextField urlField; public AddOnInstallerPanel(final ManageAddOnsPanel manageAddOnsPanel, ManageAddOnsPanel manageThemesPanel) { this.manageAddOnsPanel = manageAddOnsPanel; this.manageThemesPanel = manageThemesPanel; setLayout(new FormLayout(new ColumnSpec[] { ColumnSpec.decode("default:grow"),}, new RowSpec[] { FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.RELATED_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,})); // // Search // add(DefaultComponentFactory.getInstance().createSeparator(getTitleText("search")), "1, 2"); add(createVisitAddOnPageButton(), "1, 4, left, default"); add(Box.createVerticalStrut(20), "1, 6"); // // Install from known location // add(DefaultComponentFactory.getInstance().createSeparator(getTitleText("install.from.known.location")), "1, 7"); installButton = createInstallButton(); urlField = createUrlField(installButton); final JButton selectFile = createFileChooser(urlField); installButton.addActionListener(createInstallActionListener()); final Box box = Box.createHorizontalBox(); box.add(urlField); box.add(selectFile); add(box, "1, 9"); add(installButton, "1, 11, right, default"); // setBackground(Color.WHITE); } private static String getText(String key, Object... parameters) { return ManageAddOnsDialog.getText(key, parameters); } private static String getTitleText(final String key) { final String titleStyle = "<html><b><font size='+1'>"; return titleStyle + getText(key); } private JButton createVisitAddOnPageButton() { try { final String addOnsUriString = TextUtils.removeTranslateComment(TextUtils.getText("addons.site")); // parse the URI on creation of the dialog to test the URI syntax early final URI addOnsUri = new URI(addOnsUriString); return UITools.createHtmlLinkStyleButton(addOnsUri, getText("visit.addon.page")); } catch (URISyntaxException ex) { // bad translation? throw new RuntimeException(ex); } } private JButton createInstallButton() { final JButton installButton = new JButton(); MenuBuilder.setLabelAndMnemonic(installButton, getText("install")); installButton.setEnabled(false); // FIXME: get rid of that installButton.setMargin(new Insets(0, 25, 0, 25)); return installButton; } private ActionListener createInstallActionListener() { return new ActionListener() { public void actionPerformed(ActionEvent e) { final Controller controller = Controller.getCurrentController(); try { LogUtils.info("installing add-on from " + urlField.getText()); controller.getViewController().setWaitingCursor(true); final URL url = toURL(urlField.getText()); setStatusInfo(getText("status.installing")); final ModeController modeController = controller.getModeController(MModeController.MODENAME); final MFileManager fileManager = (MFileManager) MFileManager.getController(modeController); MapModel newMap = new MMapModel(); if (!fileManager.loadCatchExceptions(url, newMap)) { LogUtils.warn("can not load " + url); return; } controller.getModeController().getMapController().fireMapCreated(newMap); AddOnProperties addOn = (AddOnProperties) ScriptingEngine.executeScript(newMap.getRootNode(), getInstallScriptSource(), ScriptingPermissions.getPermissiveScriptingPermissions()); if (addOn != null) { setStatusInfo(getText("status.success", addOn.getName())); AddOnsController.getController().registerInstalledAddOn(addOn); final ManageAddOnsPanel managementPanel = addOn.isTheme() ? manageThemesPanel : manageAddOnsPanel; managementPanel.getTableModel().addAddOn(addOn); urlField.setText(""); ((JTabbedPane)getParent()).setSelectedComponent(managementPanel); selectLastAddOn(managementPanel); } } catch (Exception ex) { UITools.errorMessage(getText("error", ex.toString())); } finally { controller.getViewController().setWaitingCursor(false); } } private String getInstallScriptSource() throws IOException { final ResourceController resourceController = ResourceController.getResourceController(); final File scriptDir = new File(resourceController.getInstallationBaseDir(), "scripts"); final File installScript = new File(scriptDir, "installScriptAddOn.groovy"); if (!installScript.exists()) throw new RuntimeException("internal error: installer not found"); return FileUtils.slurpFile(installScript); } private URL toURL(String urlText) throws MalformedURLException { try { return new URL(urlText); } catch (Exception e2) { return new File(urlText).toURI().toURL(); } } }; } private void selectLastAddOn(JComponent managementPanel) { try { JTable table = findJTable(managementPanel); final int row = table.getModel().getRowCount() - 1; table.getSelectionModel().setSelectionInterval(row, row); } catch (Exception e) { LogUtils.warn("cannot select just installed add-on", e); } } private JTable findJTable(JComponent child) { for (Component component : child.getComponents()) { if (component instanceof JTable) { return (JTable) component; } else if (component instanceof JComponent) { final JTable findResult = findJTable((JComponent) component); if (findResult != null) return findResult; } } return null; } private JButton createFileChooser(final JTextField urlField) { final JButton selectFile = new JButton(getText("search.file"), FreeplaneIconUtils.createImageIconByResourceKey("OpenAction.icon")); final JFileChooser fileChooser = new JFileChooser(); selectFile.setToolTipText(getText("select.tooltip")); selectFile.setMaximumSize(UITools.MAX_BUTTON_DIMENSION); selectFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fileChooser.showOpenDialog(urlField); final File selectedFile = fileChooser.getSelectedFile(); if (selectedFile != null) urlField.setText(selectedFile.getAbsolutePath()); } }); return selectFile; } private JTextField createUrlField(final JButton install) { final JTextField urlField = new JTextField(); // urlField.setColumns(100); urlField.setToolTipText(getText("install.tooltip")); urlField.getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { updateImpl(e); } public void removeUpdate(DocumentEvent e) { updateImpl(e); } public void changedUpdate(DocumentEvent e) { updateImpl(e); } private void updateImpl(DocumentEvent e) { install.setEnabled(e.getDocument().getLength() > 0); } }); urlField.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_ENTER) { install.requestFocusInWindow(); install.doClick(); } } }); return urlField; } JButton getInstallButton() { return installButton; } JTextField getUrlField() { return urlField; } private static void setStatusInfo(final String message) { Controller.getCurrentController().getViewController().out(message); } }