# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: D:\projects\nb.saveas_int # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: openide/nodes/src/org/openide/cookies/SaveAsCookie.java *** D:\projects\nb.saveas_int\openide\nodes\src\org\openide\cookies\SaveAsCookie.java No Base Revision --- D:\projects\nb.saveas_int\openide\nodes\src\org\openide\cookies\SaveAsCookie.java Locally New *************** *** 1,0 **** --- 1,37 ---- + /* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + package org.openide.cookies; + + import java.io.IOException; + import org.openide.nodes.Node; + + + /** + * The cookie to save document under a different file name and/or extension. + * + * @since 7.1 + * @author S. Aubrecht + */ + public interface SaveAsCookie extends Node.Cookie { + /** + * Invoke the save operation. + * @throws IOException if the object could not be saved + */ + public void saveAs() throws IOException; + } Index: openide/loaders/src/org/openide/text/DataEditorSupport.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\text\DataEditorSupport.java Base (1.39) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\text\DataEditorSupport.java Locally Modified (Based On 1.39) *************** *** 26,40 **** --- 26,45 ---- import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; + import javax.swing.JFileChooser; import javax.swing.text.*; + import org.netbeans.modules.openide.loaders.DataObjectAccessor; import org.netbeans.modules.openide.loaders.UIException; import org.openide.*; + import org.openide.cookies.OpenCookie; + import org.openide.cookies.SaveAsCookie; import org.openide.filesystems.*; import org.openide.loaders.*; import org.openide.nodes.*; import org.openide.util.*; import org.openide.util.lookup.*; import org.openide.windows.CloneableOpenSupport; + import org.openide.windows.WindowManager; /** * Support for associating an editor and a Swing {@link Document} to a data object. *************** *** 319,324 **** --- 324,503 ---- return (DataObject)l.getLookup ().lookup (DataObject.class); } + /** + * Save the document under a new file name and/or extension. + * @throws java.io.IOException If the operation failed + * @since 6.2 + */ + public void saveAs() throws IOException { + if( env instanceof Env ) { + + File newFile = getNewFileName(); + if( null == newFile ) { + return; + } + + FileObject newFolder = FileUtil.toFileObject( newFile.getParentFile() ); + FileObject newFileObject = FileUtil.toFileObject( newFile ); + //ask the user for a new file name to save to + String newFilename = getFileName( newFile ); + String newExtension = FileUtil.getExtension( newFile.getName() ); + + DataObject currentDob = getDataObject(); + DataObject newDob = null; + if( !currentDob.isModified() || null == getDocument() ) { + //the document is not modified on disk, we copy/rename the file + DataFolder df = DataFolder.findFolder( newFolder ); + if( null != newFileObject ) { + //remove the target file if it already exists + newFileObject.delete(); + } + + newDob = DataObjectAccessor.DEFAULT.copyRename( currentDob, df, newFilename, newExtension ); + } else { + //the document is modified in editor, we need to save the editor kit instead + if( null == newFileObject ) { + //make sure the target file exists + newFileObject = newFolder.createData( newFilename, newExtension ); + } + + saveDocumentAs( newFileObject.getOutputStream() ); + currentDob.setModified( false ); + newDob = DataObject.find( newFileObject ); + } + + if( null != newDob ) { + //TODO open the document at the position of the original document when #94607 is implemented + OpenCookie c = newDob.getCookie( OpenCookie.class ); + if( null != c ) { + //close the original document + close( false ); + //open the new one + c.open(); + } + } + } + } + + + /** + * Save the document to a new file. + * @param output + * @exception IOException on I/O error + */ + private void saveDocumentAs( final OutputStream output ) throws IOException { + + final StyledDocument myDoc = getDocument(); + + // save the document as a reader + class SaveAsWriter implements Runnable { + private IOException ex; + + public void run() { + try { + OutputStream os = null; + + try { + os = new BufferedOutputStream( output ); + saveFromKitToStream( myDoc, os ); + + os.close(); // performs firing + os = null; + + } catch( BadLocationException ex ) { + ERR.log( Level.INFO, null, ex ); + } finally { + if (os != null) { // try to close if not yet done + os.close(); + } + } + } catch (IOException e) { + this.ex = e; + } + } + + public void after() throws IOException { + if (ex != null) { + throw ex; + } + } + } + + SaveAsWriter saveAsWriter = new SaveAsWriter(); + myDoc.render(saveAsWriter); + saveAsWriter.after(); + } + + /** + * Save the document to given stream + * @param myDoc + * @param os + * @throws IOException + * @throws BadLocationException + */ + private void saveFromKitToStream( StyledDocument myDoc, OutputStream os ) throws IOException, BadLocationException { + // Note: there's no new kit getting created, the method actually caches + // previously created kit and has just a funny name + final EditorKit kit = createEditorKit(); + + saveFromKitToStream( myDoc, kit, os ); + } + + /** + * Show file 'save as' dialog window to ask user for a new file name. + * @return File selected by the user or null if no file was selected. + */ + private File getNewFileName() { + File newFile = null; + FileObject currentFileObject = ((Env)env).getFile(); + if( null != currentFileObject ) + newFile = FileUtil.toFile( currentFileObject ); + + JFileChooser chooser = new JFileChooser(); + chooser.setDialogTitle( NbBundle.getMessage(DataObject.class, "LBL_SaveAsTitle" ) ); //NOI18N + chooser.setMultiSelectionEnabled( false ); + if( null != newFile ) + chooser.setSelectedFile( newFile ); + File origFile = newFile; + if( JFileChooser.APPROVE_OPTION != chooser.showSaveDialog( WindowManager.getDefault().getMainWindow() ) ) { + return null; + } + newFile = chooser.getSelectedFile(); + if( null == newFile || newFile.equals( origFile ) ) + return null; + + //create target folder if necessary + File targetFolder = newFile.getParentFile(); + if( !targetFolder.exists() ) + targetFolder.mkdirs(); + FileObject targetFileObjectFolder = FileUtil.toFileObject( targetFolder ); + if( null == targetFileObjectFolder ) { + NotifyDescriptor error = new NotifyDescriptor( + NbBundle.getMessage(DataObject.class, "MSG_CannotCreateTargetFolder"), //NOI18N + NbBundle.getMessage(DataObject.class, "LBL_SaveAsTitle"), //NOI18N + NotifyDescriptor.DEFAULT_OPTION, + NotifyDescriptor.ERROR_MESSAGE, + new Object[] {NotifyDescriptor.OK_OPTION}, + NotifyDescriptor.OK_OPTION ); + DialogDisplayer.getDefault().notify( error ); + return null; + } + return newFile; + } + + /** + * Get the name part without the extension of the given file + * @param file + * @return name part of the given file + */ + private static String getFileName( File file ) { + String fileName = file.getName(); + int index = fileName.lastIndexOf( '.' ); + if( index > 0 ) + return fileName.substring( 0, index ); + return fileName; + } + /** Environment that connects the data object and the CloneableEditorSupport. */ public static abstract class Env extends OpenSupport.Env implements CloneableEditorSupport.Env { *************** *** 344,350 **** --- 523,535 ---- */ public Env (DataObject obj) { super (obj); + if( obj instanceof MultiDataObject ) { + //add SaveAsCookie implementation + if (obj.getCookie( SaveAsCookie.class ) == null ) { + getCookieSet( (MultiDataObject)obj).add( new SaveAsCookieImpl() ); } + } + } /** Getter for the file to work on. * @return the file *************** *** 584,589 **** --- 769,798 ---- ois.defaultReadObject (); warned = true; } + + // UGLY + private static java.lang.reflect.Method getCookieSetMethod = null; + private static final org.openide.nodes.CookieSet getCookieSet( MultiDataObject obj ) { + try { + if (getCookieSetMethod == null) { + getCookieSetMethod = MultiDataObject.class.getDeclaredMethod ("getCookieSet", new Class[] { }); // NOI18N + getCookieSetMethod.setAccessible (true); + } + return (org.openide.nodes.CookieSet) getCookieSetMethod.invoke (obj, new Object[] { }); + } catch (Exception e) { + ERR.log( Level.INFO, null, e ); + return new org.openide.nodes.CookieSet (); + } + } + + private class SaveAsCookieImpl implements SaveAsCookie { + public void saveAs() throws IOException { + CloneableOpenSupport cos = Env.super.findCloneableOpenSupport(); + if (cos instanceof DataEditorSupport) { + ((DataEditorSupport)cos).saveAs(); + } + } + } } // end of Env /** Listener on file object that notifies the Env object Index: openide/nodes/manifest.mf *** D:\projects\nb.saveas_int\openide\nodes\manifest.mf Base (1.8) --- D:\projects\nb.saveas_int\openide\nodes\manifest.mf Locally Modified (Based On 1.8) Index: openide/loaders/src/org/openide/loaders/Bundle.properties *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\Bundle.properties Base (1.19) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\Bundle.properties Locally Modified (Based On 1.19) *************** *** 305,307 **** --- 305,312 ---- This file appears to contain binary data. \ Are you sure you want to open it in the text editor? MSG_BinaryFileWarning=Binary File Detected + + CTL_SaveAsAction=Sa&ve As + MSG_SaveAsFailed=Save As action failed. + LBL_SaveAsTitle=Save As + MSG_CannotCreateTargetFolder=Cannot create the target folder. Index: openide/loaders/src/org/openide/loaders/MultiDataObject.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\MultiDataObject.java Base (1.27) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\MultiDataObject.java Locally Modified (Based On 1.27) *************** *** 712,717 **** --- 712,728 ---- } } + @Override + protected DataObject handleCopyRename(DataFolder df, String name, String ext) throws IOException { + if( getLoader() instanceof UniFileLoader ) { + //allow the operation for single file DataObjects + FileObject fo = getPrimaryEntry().copyRename (df.getPrimaryFile (), name, ext); + return DataObject.find( fo ); + } + + throw new IOException( "SaveAs operation not supported for this file type." ); + } + /** Set the set of cookies. * To the provided cookie set a listener is attached, * and any change to the set is propagated by *************** *** 1089,1094 **** --- 1100,1118 ---- */ public abstract FileObject createFromTemplate (FileObject f, String name) throws IOException; + /** + * Called when the entry is to be copied and renamed. + * @param f the folder to create this entry in + * @param name new file name + * @param ext new file extension + * @return the copied and renamed FileObject, never null + * @exception IOException when the operation fails + * @since 6.2 + */ + public FileObject copyRename (FileObject f, String name, String ext) throws IOException { + throw new IOException( "Unsupported operation" ); + } + /** Try to lock this file entry. * @return the lock if the operation was successful; otherwise null * @throws IOException if the lock could not be taken Index: openide/loaders/manifest.mf *** D:\projects\nb.saveas_int\openide\loaders\manifest.mf Base (1.30) --- D:\projects\nb.saveas_int\openide\loaders\manifest.mf Locally Modified (Based On 1.30) *************** *** 1,5 **** Manifest-Version: 1.0 OpenIDE-Module: org.openide.loaders ! OpenIDE-Module-Specification-Version: 6.1 OpenIDE-Module-Localizing-Bundle: org/openide/loaders/Bundle.properties --- 1,5 ---- Manifest-Version: 1.0 OpenIDE-Module: org.openide.loaders ! OpenIDE-Module-Specification-Version: 6.2 OpenIDE-Module-Localizing-Bundle: org/openide/loaders/Bundle.properties Index: openide/loaders/src/org/openide/loaders/OperationEvent.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\OperationEvent.java Base (1.6) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\OperationEvent.java Locally Modified (Based On 1.6) *************** *** 21,27 **** import java.util.EventObject; - import org.openide.util.Lookup; import org.openide.filesystems.FileObject; /** Event that describes operations taken on --- 21,26 ---- *************** *** 31,37 **** */ public class OperationEvent extends EventObject { /** package private numbering of methods */ ! static final int COPY = 1, MOVE = 2, DELETE = 3, RENAME = 4, SHADOW = 5, TEMPL = 6, CREATE = 7; /** data object */ private DataObject obj; --- 30,36 ---- */ public class OperationEvent extends EventObject { /** package private numbering of methods */ ! static final int COPY = 1, MOVE = 2, DELETE = 3, RENAME = 4, SHADOW = 5, TEMPL = 6, CREATE = 7, COPY_RENAME = 8; /** data object */ private DataObject obj; *************** *** 149,155 **** --- 148,187 ---- sb.append(orig); } } + + /** + * Notification of a copy+rename action of a data object. + * @since 6.2 + */ + public static final class CopyRename extends OperationEvent { + /** original data object */ + private DataObject orig; + + static final long serialVersionUID =-1L; + /** @param obj renamed object + * @param orig original object + */ + CopyRename (DataObject obj, DataObject orig) { + super (obj); + this.orig = orig; } + + + /** Get the original data object. + * @return the data object + */ + public DataObject getOriginalDataObject () { + return orig; + } + + + final void writeDebug(StringBuffer sb) { + sb.append(" originalobj: "); + sb.append(orig); + } + } + } Index: openide/loaders/src/org/openide/loaders/DataObjectAccessorImpl.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DataObjectAccessorImpl.java No Base Revision --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DataObjectAccessorImpl.java Locally New *************** *** 1,0 **** --- 1,37 ---- + /* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + + + package org.openide.loaders; + + import java.io.IOException; + import org.netbeans.modules.openide.loaders.DataObjectAccessor; + + /** + * API trampoline to access package private methods in DataObject class. + * @since 6.2 + * @author S. Aubrecht + */ + final class DataObjectAccessorImpl extends DataObjectAccessor { + + public DataObject copyRename( DataObject dob, DataFolder f, String name, String ext ) throws IOException { + return dob.copyRename( f, name, ext ); + } + + } Index: openide/loaders/src/org/openide/loaders/DataLoaderPool.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DataLoaderPool.java Base (1.31) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DataLoaderPool.java Locally Modified (Based On 1.31) *************** *** 212,217 **** --- 212,220 ---- case OperationEvent.CREATE: l.operationPostCreate (ev); break; + case OperationEvent.COPY_RENAME: + l.operationCopyRename ((OperationEvent.CopyRename)ev); + break; } } } Index: core/ui/src/org/netbeans/core/ui/resources/layer.xml *** D:\projects\nb.saveas_int\core\ui\src\org\netbeans\core\ui\resources\layer.xml Base (1.118) --- D:\projects\nb.saveas_int\core\ui\src\org\netbeans\core\ui\resources\layer.xml Locally Modified (Based On 1.118) *************** *** 61,66 **** --- 61,67 ---- + *************** *** 113,119 **** ! --- 114,122 ---- ! ! ! Index: openide/loaders/src/org/openide/loaders/DataObject.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DataObject.java Base (1.34) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DataObject.java Locally Modified (Based On 1.34) *************** *** 27,32 **** --- 27,33 ---- import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.event.*; + import org.netbeans.modules.openide.loaders.DataObjectAccessor; import org.openide.filesystems.*; import org.openide.nodes.*; import org.openide.util.*; *************** *** 114,119 **** --- 115,124 ---- /** default logger for whole package */ static final Logger LOG = Logger.getLogger("org.openide.loaders"); // NOI18N + static { + DataObjectAccessor.DEFAULT = new DataObjectAccessorImpl(); + } + /** Create a new data object. * * @param pf primary file object for this data object *************** *** 528,533 **** --- 533,570 ---- */ protected abstract DataObject handleCopy (DataFolder f) throws IOException; + /** Copy this object to a folder under a different name and file extension. + * The copy of the object is required to be deletable and movable. + *

An event is fired, and atomicity is implemented. + * @param f the folder to copy the object to + * @exception IOException if something went wrong + * @return the new object + */ + final DataObject copyRename (final DataFolder f, final String name, final String ext) throws IOException { + final DataObject[] result = new DataObject[1]; + invokeAtomicAction (f.getPrimaryFile (), new FileSystem.AtomicAction () { + public void run () throws IOException { + result[0] = handleCopyRename (f, name, ext); + } + }, null); + fireOperationEvent ( + new OperationEvent.CopyRename (result[0], this), OperationEvent.COPY_RENAME + ); + return result[0]; + } + /** + * Copy and rename this object to a folder (implemented by subclasses). + * @param f target folder + * @param name new file name + * @param ext new file extension + * @return the new data object + * @exception IOException if an error occures or the file cannot be copied/renamed + * @since 6.2 + */ + protected DataObject handleCopyRename (DataFolder f, String name, String ext) throws IOException { + throw new IOException( "Unsupported operation" ); //NOI18N + } + /** Delete this object. *

Events are fired and atomicity is implemented. * @exception IOException if an error occures Index: openide/loaders/src/org/openide/loaders/ShadowChangeAdapter.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\ShadowChangeAdapter.java Base (1.5) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\ShadowChangeAdapter.java Locally Modified (Based On 1.5) *************** *** 21,27 **** import java.util.EventObject; - import org.openide.util.Lookup; import org.openide.filesystems.*; /** Adapter for listening on changes of fileobjects and refreshing data --- 21,26 ---- *************** *** 103,109 **** --- 102,118 ---- checkBrokenDataShadows(ev); } + /** + * Object has been successfully copied and renamed. + * @param ev event describing the action + * @since 6.2 + */ + public void operationCopyRename(OperationEvent.CopyRename ev) { + checkDataShadows(ev); + checkBrokenDataShadows(ev); } + } Index: openide/loaders/src/org/netbeans/modules/openide/loaders/DataObjectAccessor.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\netbeans\modules\openide\loaders\DataObjectAccessor.java No Base Revision --- D:\projects\nb.saveas_int\openide\loaders\src\org\netbeans\modules\openide\loaders\DataObjectAccessor.java Locally New *************** *** 1,0 **** --- 1,49 ---- + /* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + package org.netbeans.modules.openide.loaders; + + import java.io.IOException; + import org.openide.loaders.DataFolder; + import org.openide.loaders.DataObject; + + /** + * API trampoline to access package private methods in DataObject class. + * + * @since 6.2 + * @author S. Aubrecht + */ + public abstract class DataObjectAccessor { + + public static DataObjectAccessor DEFAULT; + + static { + // invokes static initializer of Item.class + // that will assign value to the DEFAULT field above + Class c = DataObject.class; + try { + Class.forName(c.getName(), true, c.getClassLoader()); + } catch (ClassNotFoundException ex) { + assert false : ex; + } + // assert DEFAULT != null : "The DEFAULT field must be initialized"; + } + + public abstract DataObject copyRename( DataObject dob, DataFolder f, String name, String ext ) throws IOException; + + } Index: form/src/org/netbeans/modules/form/FormDataObject.java *** D:\projects\nb.saveas_int\form\src\org\netbeans\modules\form\FormDataObject.java Base (1.49) --- D:\projects\nb.saveas_int\form\src\org\netbeans\modules\form\FormDataObject.java Locally Modified (Based On 1.49) *************** *** 20,28 **** --- 20,31 ---- package org.netbeans.modules.form; + import java.io.IOException; import org.openide.cookies.EditCookie; import org.openide.cookies.OpenCookie; import org.openide.filesystems.FileObject; + import org.openide.loaders.DataFolder; + import org.openide.loaders.DataObject; import org.openide.loaders.DataObjectExistsException; import org.openide.loaders.FileEntry; import org.openide.loaders.MultiDataObject; *************** *** 149,155 **** --- 152,165 ---- is.defaultReadObject(); } + @Override + protected DataObject handleCopyRename(DataFolder df, String name, String ext) throws IOException { + FileObject fo = getPrimaryEntry().copyRename (df.getPrimaryFile (), name, ext); + return DataObject.find( fo ); } + + } Index: openide/nodes/nbproject/project.properties *** D:\projects\nb.saveas_int\openide\nodes\nbproject\project.properties Base (1.10) --- D:\projects\nb.saveas_int\openide\nodes\nbproject\project.properties Locally Modified (Based On 1.10) *************** *** 22,25 **** javadoc.arch=${basedir}/../arch/arch-openide-nodes.xml javadoc.apichanges=${basedir}/apichanges.xml ! spec.version.base=7.0 --- 22,25 ---- javadoc.arch=${basedir}/../arch/arch-openide-nodes.xml javadoc.apichanges=${basedir}/apichanges.xml ! spec.version.base=7.1 Index: openide/loaders/src/org/openide/loaders/DefaultDataObject.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DefaultDataObject.java Base (1.12) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\DefaultDataObject.java Locally Modified (Based On 1.12) *************** *** 127,132 **** --- 127,138 ---- return super.handleCreateFromTemplate (df, name); } + @Override + protected DataObject handleCopyRename(DataFolder df, String name, String ext) throws IOException { + FileObject fo = getPrimaryEntry ().copyRename (df.getPrimaryFile (), name, ext); + return DataObject.find( fo ); + } + /** Either opens the in text editor or asks user questions. */ public void open() { Index: openide/loaders/src/org/openide/loaders/OperationAdapter.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\OperationAdapter.java Base (1.3) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\OperationAdapter.java Locally Modified (Based On 1.3) *************** *** 51,57 **** --- 51,62 ---- /* Empty implementation */ public void operationCreateFromTemplate (OperationEvent.Copy ev) { } + + /* Empty implementation */ + public void operationCopyRename (OperationEvent.CopyRename ev) { } + } Index: java/source/src/org/netbeans/modules/java/JavaDataObject.java *** D:\projects\nb.saveas_int\java\source\src\org\netbeans\modules\java\JavaDataObject.java Base (1.3) --- D:\projects\nb.saveas_int\java\source\src\org\netbeans\modules\java\JavaDataObject.java Locally Modified (Based On 1.3) *************** *** 36,41 **** --- 36,43 ---- import org.openide.cookies.SaveCookie; import org.openide.filesystems.FileLock; import org.openide.filesystems.FileObject; + import org.openide.loaders.DataFolder; + import org.openide.loaders.DataObject; import org.openide.loaders.DataObjectExistsException; import org.openide.loaders.MultiDataObject; import org.openide.loaders.MultiFileLoader; *************** *** 65,70 **** --- 67,80 ---- return super.getCookie(type); } + protected DataObject handleCopyRename(DataFolder df, String name, String ext) throws IOException { + String originalName = getName(); + FileObject fo = getPrimaryEntry ().copyRename (df.getPrimaryFile (), name, ext); + DataObject dob = DataObject.find( fo ); + //TODO invoke refactoring here + return dob; + } + private synchronized JavaEditorSupport createJavaEditorSupport () { if (jes == null) { jes = new JavaEditorSupport (this); Index: openide/loaders/src/org/openide/loaders/FileEntry.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\FileEntry.java Base (1.5) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\FileEntry.java Locally Modified (Based On 1.5) *************** *** 51,56 **** --- 51,62 ---- return fo.copy (f, newName, fo.getExt ()); } + @Override + public FileObject copyRename(FileObject f, String name, String ext) throws IOException { + FileObject fo = getFile(); + return fo.copy (f, name, ext); + } + /* Renames underlying fileobject. This implementation return the * same file. * Index: openide/loaders/src/org/openide/loaders/OperationListener.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\OperationListener.java Base (1.3) --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\loaders\OperationListener.java Locally Modified (Based On 1.3) *************** *** 64,67 **** --- 64,74 ---- * @param ev event describing the action */ public void operationCreateFromTemplate (OperationEvent.Copy ev); + + /** + * Object has been successfully copied and renamed. + * @param ev event describing the action + * @since 6.2 + */ + public void operationCopyRename (OperationEvent.CopyRename ev); } Index: openide/loaders/src/org/openide/actions/SaveAsAction.java *** D:\projects\nb.saveas_int\openide\loaders\src\org\openide\actions\SaveAsAction.java No Base Revision --- D:\projects\nb.saveas_int\openide\loaders\src\org\openide\actions\SaveAsAction.java Locally New *************** *** 1,0 **** --- 1,85 ---- + /* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + package org.openide.actions; + + import java.io.IOException; + import java.util.logging.Level; + import java.util.logging.Logger; + import org.openide.cookies.SaveAsCookie; + import org.openide.loaders.DataObject; + import org.openide.nodes.Node; + import org.openide.util.HelpCtx; + import org.openide.util.NbBundle; + import org.openide.util.actions.NodeAction; + import org.openide.windows.TopComponent; + import org.openide.windows.WindowManager; + + /** + * Action to save document under a different file name and/or extension. + * The action is enabled for editor windows only. + * + * @since 6.2 + * @author S. Aubrecht + */ + public final class SaveAsAction extends NodeAction { + + @Override + protected void initialize() { + super.initialize(); + putValue("noIconInMenu", Boolean.TRUE); //NOI18N + //TODO add listener to topcomponent.registry? + } + + @Override + protected void performAction(Node[] activatedNodes) { + SaveAsCookie c = (SaveAsCookie) activatedNodes[0].getCookie(SaveAsCookie.class); + try { + c.saveAs(); + } catch( IOException ioE ) { + Logger.getLogger( SaveAsAction.class.getName() ).log( Level.WARNING, + NbBundle.getMessage(DataObject.class, "MSG_SaveAsFailed"), ioE ); //NOI18N + } + } + + @Override + protected boolean enable(Node[] activatedNodes) { + TopComponent tc = TopComponent.getRegistry().getActivated(); + return null != activatedNodes + && activatedNodes.length > 0 + && null != activatedNodes[0].getCookie( SaveAsCookie.class ) + && null == tc + && WindowManager.getDefault().isEditorTopComponent( tc ); + } + + @Override + public String getName() { + return NbBundle.getMessage(DataObject.class, "CTL_SaveAsAction"); //NOI18N + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + } +