Allowing changing encoding on per-file. diff --git a/openide.loaders/src/org/netbeans/modules/openide/loaders/PerFileEncodingQueryImplementation.java b/openide.loaders/src/org/netbeans/modules/openide/loaders/PerFileEncodingQueryImplementation.java new file mode 100644 --- /dev/null +++ b/openide.loaders/src/org/netbeans/modules/openide/loaders/PerFileEncodingQueryImplementation.java @@ -0,0 +1,78 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, 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-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.openide.loaders; + +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.logging.Logger; +import org.netbeans.spi.queries.FileEncodingQueryImplementation; +import org.openide.filesystems.FileObject; + +/** + * This provides a higher priority query on text encoding. + * + *

In order to keep it work, make sure other service implementation has a lower + * position than this one.

+ * + * @author LAO Zhongcheng + */ +@org.openide.util.lookup.ServiceProvider(service=org.netbeans.spi.queries.FileEncodingQueryImplementation.class, position=10) +public class PerFileEncodingQueryImplementation extends FileEncodingQueryImplementation { + + private static final Logger LOG = Logger.getLogger(PerFileEncodingQueryImplementation.class.getName()); + + /** Name of text encoding property. Allows to change per-file text encoding. */ + private static final String PROP_TEXT_ENCODING = "textEncoding"; // NOI18N + + @Override + public Charset getEncoding(FileObject file) { + String overridenEncoding = (String) file.getAttribute(PROP_TEXT_ENCODING); + if (overridenEncoding != null) { + try { + return Charset.forName(overridenEncoding); + } catch (UnsupportedCharsetException ex) { + LOG.warning("Invalid charset: " + overridenEncoding); + } + } + + return null; + } + +} diff --git a/openide.loaders/src/org/openide/loaders/Bundle.properties b/openide.loaders/src/org/openide/loaders/Bundle.properties --- a/openide.loaders/src/org/openide/loaders/Bundle.properties +++ b/openide.loaders/src/org/openide/loaders/Bundle.properties @@ -90,6 +90,9 @@ PROP_extension=Extension HINT_extension=Primary file extension. ERROR_extension=Cannot change extension. File is modified. +PROP_textEncoding=Text Encoding +HINT_textEncoding=Text encoding of the primary file. (Only applies to the text editor. This will not effect the build.) +ERROR_textEncoding=Cannot change text encoding. The specified encoding {0} is invalid on current Java platform. # name of set with sorting options PROP_sorting=Sorting diff --git a/openide.loaders/src/org/openide/loaders/DataNode.java b/openide.loaders/src/org/openide/loaders/DataNode.java --- a/openide.loaders/src/org/openide/loaders/DataNode.java +++ b/openide.loaders/src/org/openide/loaders/DataNode.java @@ -46,13 +46,18 @@ import java.beans.*; import java.io.*; import java.lang.reflect.InvocationTargetException; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.text.MessageFormat; import java.util.*; import javax.swing.Action; +import org.netbeans.api.queries.FileEncodingQuery; import org.netbeans.modules.openide.loaders.UIException; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.filesystems.*; import org.openide.nodes.*; +import org.openide.text.DataEditorSupport; import org.openide.util.*; import org.openide.util.actions.SystemAction; import org.openide.util.datatransfer.ExTransferable; @@ -78,6 +83,9 @@ /** Name of extension property. Allows to change extension. */ private static final String PROP_EXTENSION = "extension"; // NOI18N + /** Name of text encoding property. Allows to change per-file text encoding. */ + private static final String PROP_TEXT_ENCODING = "textEncoding"; // NOI18N + /** Create a data node with the given children set for the given data object. * @param obj object to work with * @param ch children container for the node @@ -468,6 +476,7 @@ ss.put(new AllFilesProperty()); ss.put(new SizeProperty()); ss.put(new LastModifiedProperty()); + ss.put(new TextEncodingProperty()); } // Fix for IZ#120560 - Refactor of resources node in project view throws ISE exception if ( fo.isFolder() ){ @@ -602,6 +611,69 @@ } } + /** + * A property with text encoding of this object. It allows to change the per-file text encoding (#27444). + */ + private final class TextEncodingProperty extends PropertySupport.ReadWrite { + + public TextEncodingProperty() { + super(PROP_TEXT_ENCODING, String.class, + DataObject.getString("PROP_textEncoding"), DataObject.getString("HINT_textEncoding")); //NOI18N + } + + @Override + public boolean canWrite() { + return obj.isRenameAllowed(); + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + Charset charset = FileEncodingQuery.getEncoding(obj.getPrimaryFile()); + return charset.name(); + } + + @Override + public void setValue(String newEncoding) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + try { + Charset newCharset = Charset.forName(newEncoding); + newEncoding = newCharset.name(); + if (getValue().equals(newEncoding)) { + return; + } + } catch (UnsupportedCharsetException ex) { + String message = DataObject.getString("ERROR_textEncoding"); //NOI18N + DialogDisplayer.getDefault().notify( + new NotifyDescriptor.Message(MessageFormat.format(message, new Object[]{newEncoding}))); + return; + } + try { + DataEditorSupport editor = obj.getLookup().lookup(DataEditorSupport.class); + FileObject prim = obj.getPrimaryFile(); + + if (obj.isModified() && editor.close() == false) { + return; + } + + FileLock lock = prim.lock(); + try { + prim.setAttribute(PROP_TEXT_ENCODING, newEncoding); + + } finally { + lock.releaseLock(); + } + + if (editor.isDocumentLoaded()) { + editor.reload(); + } else { + editor.open(); + } + + } catch (IOException ioe) { + Exceptions.printStackTrace(ioe); + } + } + } + /** Copy this node to the clipboard. * * @return {@link org.openide.util.datatransfer.ExTransferable.Single} with one copy flavor @@ -1176,6 +1248,4 @@ } } - - } diff --git a/openide.loaders/src/org/openide/text/DataEditorSupport.java b/openide.loaders/src/org/openide/text/DataEditorSupport.java --- a/openide.loaders/src/org/openide/text/DataEditorSupport.java +++ b/openide.loaders/src/org/openide/text/DataEditorSupport.java @@ -95,6 +95,7 @@ import org.openide.util.Mutex; import org.openide.util.NbBundle; import org.openide.util.Parameters; +import org.openide.util.Task; import org.openide.util.WeakListeners; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.InstanceContent; @@ -1204,5 +1205,12 @@ return obj != null && getClass() == obj.getClass(); } } + + /** + * Reloads the document synchronously. + */ + public void reload() { + super.reloadDocument().waitFinished(); + } }