/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2011 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 3 for more details. * * You should have received a copy of the GNU General Public License version 3 * along with this work; if not, see http://www.gnu.org/licenses/ * * * Please visit http://neilcsmith.net if you need additional information or * have any questions. */ package net.neilcsmith.praxis.live.pxr.wizard; import java.awt.Component; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.logging.Logger; import javax.swing.JComponent; import javax.swing.event.ChangeListener; import net.neilcsmith.praxis.core.CallArguments; import net.neilcsmith.praxis.core.ComponentType; import net.neilcsmith.praxis.live.core.api.Callback; import net.neilcsmith.praxis.live.project.api.ExecutionLevel; import net.neilcsmith.praxis.live.project.api.PraxisProject; import net.neilcsmith.praxis.live.project.api.PraxisProjectProperties; import net.neilcsmith.praxis.live.pxr.PXRDataObject; import net.neilcsmith.praxis.live.pxr.PXRFileHandler; import org.netbeans.api.project.Project; import org.netbeans.spi.project.ui.templates.support.Templates; import org.openide.WizardDescriptor; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataObject; import org.openide.util.Exceptions; public final class PXRWizardIterator implements WizardDescriptor.InstantiatingIterator { final static Logger LOG = Logger.getLogger(PXRWizardIterator.class.getName()); public final static String PROP_PXR_ID = "PXR.id"; public final static String PROP_PXR_FILE = "PXR.file"; public final static String PROP_PXR_TYPE = "PXR.type"; public final static String PROP_PXR_BUILD = "PXR.build"; public final static String PROP_PXR_AUTOSTART = "PXR.autostart"; private int index; private WizardDescriptor wizard; private WizardDescriptor.Panel[] panels; private ComponentType rootType; public PXRWizardIterator() { LOG.fine("Creating PXRWizardIterator"); } /** * Initialize panels representing individual wizard's steps and sets * various properties for them influencing wizard appearance. */ private WizardDescriptor.Panel[] getPanels() { if (panels == null) { panels = new WizardDescriptor.Panel[] { new PXRWizardPanel1(rootType) }; // @TODO - this seems to break Templates.getTargetFolder() ??? // String[] steps = createSteps(); // for (int i = 0; i < panels.length; i++) { // Component c = panels[i].getComponent(); // if (steps[i] == null) { // // Default step name to component name of panel. Mainly // // useful for getting the name of the target chooser to // // appear in the list of steps. // steps[i] = c.getName(); // } // if (c instanceof JComponent) { // assume Swing components // JComponent jc = (JComponent) c; // // Sets step number of a component // // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*: // jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); // // Sets steps names for a panel // jc.putClientProperty("WizardPanel_contentData", steps); // // Turn on subtitle creation on each step // jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); // // Show steps on the left side with the image on the background // jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE); // // Turn on numbering of all steps // jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE); // } // } } return panels; } @Override public Set instantiate() throws IOException { Object obj = wizard.getProperty(PROP_PXR_ID); String id; if (obj instanceof String) { id = (String) obj; } else { throw new IOException("No id in wizard"); } obj = wizard.getProperty(PROP_PXR_FILE); File file; if (obj instanceof File) { file = (File) obj; } else { throw new IOException("No file in wizard"); } if (file.exists()) { throw new IOException("File already exists"); } obj = wizard.getProperty(PROP_PXR_TYPE); ComponentType type; if (obj instanceof ComponentType) { type = (ComponentType) obj; } else { throw new IOException("No type in wizard"); } boolean build = false; obj = wizard.getProperty(PROP_PXR_BUILD); if (obj instanceof Boolean) { build = ((Boolean) obj).booleanValue(); } boolean autostart = false; obj = wizard.getProperty(PROP_PXR_AUTOSTART); if (obj instanceof Boolean) { autostart = ((Boolean) obj).booleanValue(); } FileObject fileObj = FileUtil.createData(file); writeFile(fileObj, id, type, autostart); Project project = Templates.getProject(wizard); if (project != null) { FileObject autostarter = writeAutostartFile(project, id); PraxisProjectProperties props = project.getLookup().lookup(PraxisProjectProperties.class); if (props != null) { props.addProjectFile(ExecutionLevel.BUILD, fileObj); if (autostart) { props.addProjectFile(ExecutionLevel.RUN, autostarter); } } if (build) { buildFile(project, fileObj); } } else { LOG.warning("No project found for wizard"); } return Collections.singleton(fileObj); } private void writeFile(FileObject file, String id, ComponentType type, boolean autostart) throws IOException { StringBuilder code = new StringBuilder(); code.append("@ /").append(id).append(" ").append(type).append(" {\n"); // code.append(" ").append("#%autostart ").append(autostart).append("\n"); code.append("}"); Writer writer = null; try { writer = new OutputStreamWriter(file.getOutputStream()); writer.append(code); } finally { if (writer != null) { writer.close(); } } } private FileObject writeAutostartFile(Project base, String id) throws IOException { FileObject configDir = base.getProjectDirectory().getFileObject("config"); if (configDir == null) { configDir = base.getProjectDirectory().createFolder("config"); } String fileName = id + "_autostart"; FileObject autostarter = configDir.getFileObject(fileName); if (autostarter == null) { autostarter = configDir.createData(fileName); } String code = "/" + id + ".start"; Writer writer = null; try { writer = new OutputStreamWriter(autostarter.getOutputStream()); writer.append(code); } finally { if (writer != null) { writer.close(); } } return autostarter; } private void buildFile(Project base, FileObject file) { PraxisProject project = base.getLookup().lookup(PraxisProject.class); try { DataObject dob = DataObject.find(file); if (dob instanceof PXRDataObject) { new PXRFileHandler(project, (PXRDataObject) dob).process(new Callback() { @Override public void onReturn(CallArguments args) { } @Override public void onError(CallArguments args) { } }); } } catch (Exception ex) { Exceptions.printStackTrace(ex); } } @Override public void initialize(WizardDescriptor wizard) { this.wizard = wizard; FileObject template = Templates.getTemplate(wizard); Object typeAttr = template.getAttribute("rootType"); if (typeAttr != null) { try { rootType = ComponentType.create(typeAttr.toString()); } catch (Exception ex) { // do nothing } } } @Override public void uninitialize(WizardDescriptor wizard) { panels = null; } @Override public WizardDescriptor.Panel current() { return getPanels()[index]; } @Override public String name() { return index + 1 + ". from " + getPanels().length; } @Override public boolean hasNext() { return index < getPanels().length - 1; } @Override public boolean hasPrevious() { return index > 0; } @Override public void nextPanel() { if (!hasNext()) { throw new NoSuchElementException(); } index++; } @Override public void previousPanel() { if (!hasPrevious()) { throw new NoSuchElementException(); } index--; } // If nothing unusual changes in the middle of the wizard, simply: @Override public void addChangeListener(ChangeListener l) { } @Override public void removeChangeListener(ChangeListener l) { } // If something changes dynamically (besides moving between panels), e.g. // the number of panels changes in response to user input, then uncomment // the following and call when needed: fireChangeEvent(); /* private Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0 public final void addChangeListener(ChangeListener l) { synchronized (listeners) { listeners.add(l); } } public final void removeChangeListener(ChangeListener l) { synchronized (listeners) { listeners.remove(l); } } protected final void fireChangeEvent() { Iterator<ChangeListener> it; synchronized (listeners) { it = new HashSet<ChangeListener>(listeners).iterator(); } ChangeEvent ev = new ChangeEvent(this); while (it.hasNext()) { it.next().stateChanged(ev); } } */ // You could safely ignore this method. Is is here to keep steps which were // there before this wizard was instantiated. It should be better handled // by NetBeans Wizard API itself rather than needed to be implemented by a // client code. private String[] createSteps() { String[] beforeSteps = null; Object prop = wizard.getProperty("WizardPanel_contentData"); if (prop != null && prop instanceof String[]) { beforeSteps = (String[]) prop; } if (beforeSteps == null) { beforeSteps = new String[0]; } String[] res = new String[(beforeSteps.length - 1) + panels.length]; for (int i = 0; i < res.length; i++) { if (i < (beforeSteps.length - 1)) { res[i] = beforeSteps[i]; } else { res[i] = panels[i - beforeSteps.length + 1].getComponent().getName(); } } return res; } }