/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2014 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.editors; import java.awt.Component; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyEditor; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.KeyStroke; import net.neilcsmith.praxis.core.ControlAddress; import net.neilcsmith.praxis.core.info.ArgumentInfo; import net.neilcsmith.praxis.core.types.PString; import net.neilcsmith.praxis.live.properties.EditorSupport; import net.neilcsmith.praxis.live.properties.PraxisProperty; import org.netbeans.api.actions.Openable; import org.openide.explorer.propertysheet.ExPropertyEditor; import org.openide.explorer.propertysheet.InplaceEditor; import static org.openide.explorer.propertysheet.InplaceEditor.COMMAND_FAILURE; import org.openide.explorer.propertysheet.PropertyEnv; import org.openide.explorer.propertysheet.PropertyModel; import org.openide.filesystems.FileChangeAdapter; import org.openide.filesystems.FileEvent; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataObject; import org.openide.util.Exceptions; /** * * @author Neil C Smith */ @SuppressWarnings("deprecation") class MimeTextEditor extends EditorSupport implements ExPropertyEditor, InplaceEditor.Factory { private final PraxisProperty property; private final String mime; private final String template; private final EditInitializer editInit; private final FileListener fileListener; private final String fileName; private final ArgumentInfo info; private PropertyEnv env; private FileObject file; private MimeTextEditor(PraxisProperty property, ArgumentInfo info, String mimetype) { this.property = property; this.mime = mimetype; this.template = info.getProperties().getString(ArgumentInfo.KEY_TEMPLATE, ""); this.editInit = new EditInitializer(); this.fileListener = new FileListener(); this.info = info; Object obj = property.getValue("address"); if (obj instanceof ControlAddress) { ControlAddress ad = (ControlAddress) obj; fileName = ad.getComponentAddress().getID() + "_" + ad.getID(); } else { fileName = property.getName(); } // property.setValue("canEditAsText", Boolean.FALSE); } @Override public void attachEnv(PropertyEnv env) { this.env = env; env.registerInplaceEditorFactory(this); } @Override public InplaceEditor getInplaceEditor() { return editInit; } public String getDisplayName() { return getClass().getSimpleName(); } @Override public void reset() { if (file == null) { return; } try { file.delete(); file = null; } catch (IOException ex) { Exceptions.printStackTrace(ex); } } private void openEditor() { try { if (file == null) { file = constructFile(); } DataObject dob = DataObject.find(file); Openable openable = dob.getLookup().lookup(Openable.class); if (openable != null) { openable.open(); } } catch (Exception ex) { } } private FileObject constructFile() throws Exception { FileSystem fs = FileUtil.createMemoryFileSystem(); FileObject f = fs.getRoot().createData(fileName, findFileExtension()); OutputStreamWriter writer = null; try { writer = new OutputStreamWriter(f.getOutputStream()); writer.append(constructFileContent()); } finally { if (writer != null) { writer.close(); } } f.setAttribute("argumentInfo", info); f.addFileChangeListener(fileListener); return f; } private String constructFileContent() { String s = property.getValue().toString(); if (s.trim().isEmpty()) { s = template; } return s; } private String findFileExtension() { if ("text/x-praxis-java".equals(mime)) { return "pxj"; } if ("text/x-praxis-script".equals(mime)) { return "pxs"; } if ("text/x-glsl-frag".equals(mime)) { return "frag"; } if ("text/x-glsl-vert".equals(mime)) { return "vert"; } return ""; } private void updateProperty() { if (file != null && property.isActiveEditor(this)) { try { property.setValue(PString.valueOf(file.asText())); } catch (Exception ex) { Exceptions.printStackTrace(ex); } } } class FileListener extends FileChangeAdapter { @Override public void fileChanged(final FileEvent fe) { if (EventQueue.isDispatchThread()) { if (fe.getFile() == file) { updateProperty(); } else { fe.getFile().removeFileChangeListener(this); } } else { EventQueue.invokeLater(new Runnable() { @Override public void run() { fileChanged(fe); } }); } } } class EditInitializer extends JComponent implements InplaceEditor { private JComponent cmp; private Object value; private PropertyEditor pe; private PropertyEnv env; private PropertyModel pm; private List<ActionListener> listeners; private EditInitializer() { this.listeners = new ArrayList<ActionListener>(); addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { initializeEditing(); } }); addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { initializeEditing(); } }); } @Override public void connect(PropertyEditor pe, PropertyEnv env) { this.pe = pe; this.env = env; value = pe.getValue(); } @Override public JComponent getComponent() { return this; } private void initializeEditing() { ActionEvent ev = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, COMMAND_FAILURE); for (ActionListener l : listeners.toArray(new ActionListener[0])) { l.actionPerformed(ev); } openEditor(); } @Override public void clear() { this.pe = null; this.env = null; this.value = null; } @Override public Object getValue() { return value; } @Override public void setValue(Object o) { } @Override public boolean supportsTextEntry() { return false; } @Override public void reset() { } @Override public void addActionListener(ActionListener al) { listeners.add(al); } @Override public void removeActionListener(ActionListener al) { listeners.remove(al); } @Override public KeyStroke[] getKeyStrokes() { return new KeyStroke[0]; } @Override public PropertyEditor getPropertyEditor() { return pe; } @Override public PropertyModel getPropertyModel() { return pm; } @Override public void setPropertyModel(PropertyModel pm) { this.pm = pm; } @Override public boolean isKnownComponent(Component c) { return false; } } }