mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Scheme exporter API and IDEA-90075 (Export Codestyle as XML File)
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.application.options.codeStyle;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.fileChooser.FileSaverDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileSaverDialog;
|
||||
import com.intellij.openapi.options.SchemeExporter;
|
||||
import com.intellij.openapi.options.SchemeExporterEP;
|
||||
import com.intellij.openapi.options.SchemeExporterException;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWrapper;
|
||||
import com.intellij.psi.codeStyle.CodeStyleScheme;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
class CodeStyleSchemeExporterUI {
|
||||
@NotNull private final Component myParentComponent;
|
||||
@NotNull private final CodeStyleScheme myScheme;
|
||||
@NotNull private final StatusCallback myStatusCallback;
|
||||
|
||||
CodeStyleSchemeExporterUI(@NotNull Component parentComponent, @NotNull CodeStyleScheme scheme, @NotNull StatusCallback statusCallback) {
|
||||
myParentComponent = parentComponent;
|
||||
myScheme = scheme;
|
||||
myStatusCallback = statusCallback;
|
||||
}
|
||||
|
||||
void export() {
|
||||
ListPopup popup = JBPopupFactory.getInstance().createListPopup(
|
||||
new BaseListPopupStep<String>(ApplicationBundle.message("code.style.scheme.exporter.ui.export.as.title"), enumExporters()) {
|
||||
@Override
|
||||
public PopupStep onChosen(final String selectedValue, boolean finalChoice) {
|
||||
return doFinalStep(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
exportSchemeUsing(selectedValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
popup.showInCenterOf(myParentComponent);
|
||||
}
|
||||
|
||||
private static String[] enumExporters() {
|
||||
List<String> names = new ArrayList<String>();
|
||||
Collection<SchemeExporterEP<CodeStyleScheme>> extensions = SchemeExporterEP.getExtensions(CodeStyleScheme.class);
|
||||
for (SchemeExporterEP<CodeStyleScheme> extension : extensions) {
|
||||
names.add(extension.name);
|
||||
}
|
||||
return ArrayUtil.toStringArray(names);
|
||||
}
|
||||
|
||||
private void exportSchemeUsing(@NotNull String exporterName) {
|
||||
SchemeExporter<CodeStyleScheme> exporter = SchemeExporterEP.getExporter(exporterName, CodeStyleScheme.class);
|
||||
if (exporter != null) {
|
||||
String ext = exporter.getExtension();
|
||||
FileSaverDialog saver =
|
||||
FileChooserFactory.getInstance()
|
||||
.createSaveFileDialog(new FileSaverDescriptor(
|
||||
ApplicationBundle.message("code.style.scheme.exporter.ui.file.chooser.title"),
|
||||
ApplicationBundle.message("code.style.scheme.exporter.ui.file.chooser.message"),
|
||||
ext), myParentComponent);
|
||||
VirtualFileWrapper target = saver.save(null, getFileNameSuggestion() + "." + ext);
|
||||
if (target != null) {
|
||||
VirtualFile targetFile = target.getVirtualFile(true);
|
||||
if (targetFile != null) {
|
||||
try {
|
||||
exporter.exportScheme(myScheme, targetFile);
|
||||
myStatusCallback
|
||||
.showMessage(ApplicationBundle.message("code.style.scheme.exporter.ui.code.style.exported.message", myScheme.getName(),
|
||||
targetFile.getPresentableUrl()), MessageType.INFO);
|
||||
}
|
||||
catch (SchemeExporterException e) {
|
||||
myStatusCallback.showMessage(e.getMessage(), MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myStatusCallback.showMessage(ApplicationBundle.message("code.style.scheme.exporter.ui.cannot.write.message"), MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getFileNameSuggestion() {
|
||||
return myScheme.getName();
|
||||
}
|
||||
|
||||
interface StatusCallback {
|
||||
void showMessage(@NotNull String message, @NotNull MessageType messageType);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -75,7 +75,7 @@
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Export..."/>
|
||||
<text value="E&xport..."/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="816ef" class="javax.swing.JButton" binding="myImportButton" default-binding="true">
|
||||
|
||||
+22
-4
@@ -22,10 +22,7 @@ import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDialog;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.options.SchemeFactory;
|
||||
import com.intellij.openapi.options.SchemeImportException;
|
||||
import com.intellij.openapi.options.SchemeImporter;
|
||||
import com.intellij.openapi.options.SchemeImporterEP;
|
||||
import com.intellij.openapi.options.*;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
@@ -128,6 +125,19 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper {
|
||||
});
|
||||
}
|
||||
|
||||
if (SchemeExporterEP.getExtensions(CodeStyleScheme.class).isEmpty()) {
|
||||
myExportButton.setVisible(false);
|
||||
}
|
||||
else {
|
||||
myExportButton.setVisible(true);
|
||||
myExportButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
exportSelectedScheme();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -453,4 +463,12 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private void exportSelectedScheme() {
|
||||
new CodeStyleSchemeExporterUI(myExportButton, getSelectedScheme(), new CodeStyleSchemeExporterUI.StatusCallback() {
|
||||
@Override
|
||||
public void showMessage(@NotNull String message, @NotNull MessageType messageType) {
|
||||
showStatus(myExportButton, message, messageType);
|
||||
}
|
||||
}).export();
|
||||
}
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.impl.source.codeStyle;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.options.SchemeExporter;
|
||||
import com.intellij.openapi.options.SchemeExporterException;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleScheme;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.output.Format;
|
||||
import org.jdom.output.XMLOutputter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
/**
|
||||
* Exports (copies) a code style scheme to an external file as is.
|
||||
*
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
public class CodeStyleSchemeCopyExporter implements SchemeExporter<CodeStyleScheme> {
|
||||
@Override
|
||||
public void exportScheme(@NotNull final CodeStyleScheme scheme, @NotNull final VirtualFile targetFile) throws SchemeExporterException {
|
||||
assert scheme instanceof CodeStyleSchemeImpl;
|
||||
try {
|
||||
final Element root = schemeToDom((CodeStyleSchemeImpl)scheme);
|
||||
ApplicationManager.getApplication().runWriteAction(new ThrowableComputable<Boolean, IOException>() {
|
||||
@Override
|
||||
public Boolean compute() throws IOException {
|
||||
writeToFile(targetFile, root);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new SchemeExporterException("Export failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "xml";
|
||||
}
|
||||
|
||||
private static Element schemeToDom(@NotNull CodeStyleSchemeImpl scheme) throws WriteExternalException {
|
||||
Element newElement = new Element("code_scheme");
|
||||
newElement.setAttribute("name", scheme.getName());
|
||||
scheme.writeExternal(newElement);
|
||||
return newElement;
|
||||
}
|
||||
|
||||
private void writeToFile(@NotNull VirtualFile file, @NotNull Element element) throws IOException {
|
||||
OutputStream targetStream = file.getOutputStream(this);
|
||||
try {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(targetStream);
|
||||
Format format = Format.getPrettyFormat();
|
||||
format.setLineSeparator("\n");
|
||||
new XMLOutputter(format).output(element, writer);
|
||||
}
|
||||
finally {
|
||||
targetStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.options;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Base interface to export a scheme.
|
||||
*
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
public interface SchemeExporter <T extends Scheme> {
|
||||
/**
|
||||
* Writes a scheme to existing <code>targetFile</code>. An implementor may use <code>targetFile.getOutputStream()</code> method to
|
||||
* obtain a stream to write to.
|
||||
*
|
||||
* @param scheme The scheme to export.
|
||||
* @param targetFile The target virtual file.
|
||||
* @throws SchemeExporterException
|
||||
*/
|
||||
void exportScheme(@NotNull T scheme, @NotNull VirtualFile targetFile) throws SchemeExporterException;
|
||||
|
||||
/**
|
||||
* @return Target file extension without a dot, for example "xml".
|
||||
*/
|
||||
String getExtension();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.options;
|
||||
|
||||
/**
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
public class SchemeExporterException extends Exception {
|
||||
public SchemeExporterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.options;
|
||||
|
||||
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.util.LazyInstance;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extension point for schemes exporters.
|
||||
*
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
public class SchemeExporterEP <S extends Scheme> extends AbstractExtensionPointBean {
|
||||
public static final ExtensionPointName<SchemeExporterEP> EP_NAME = ExtensionPointName.create("com.intellij.schemeExporter");
|
||||
|
||||
@Attribute("name")
|
||||
public String name;
|
||||
|
||||
@Attribute("schemeClass")
|
||||
public String schemeClass;
|
||||
|
||||
@Attribute("implementationClass")
|
||||
public String implementationClass;
|
||||
|
||||
private final LazyInstance<SchemeExporter<S>> myExporterInstance = new LazyInstance<SchemeExporter<S>>() {
|
||||
@Override
|
||||
protected Class<SchemeExporter<S>> getInstanceClass() throws ClassNotFoundException {
|
||||
return findClass(implementationClass);
|
||||
}
|
||||
};
|
||||
|
||||
public SchemeExporter<S> getInstance() {
|
||||
return myExporterInstance.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds extensions supporting the given <code>schemeClass</code>
|
||||
* @param schemeClass The class of the scheme to search extensions for.
|
||||
* @return A collection of exporters capable of exporting schemes of the given class. An empty collection is returned if there are
|
||||
* no matching exporters.
|
||||
*/
|
||||
@NotNull
|
||||
public static <S extends Scheme> Collection<SchemeExporterEP<S>> getExtensions(Class<S> schemeClass) {
|
||||
List<SchemeExporterEP<S>> exporters = new ArrayList<SchemeExporterEP<S>>();
|
||||
for (SchemeExporterEP<?> exporterEP : EP_NAME.getExtensions()) {
|
||||
if (schemeClass.getName().equals(exporterEP.schemeClass)) {
|
||||
//noinspection unchecked
|
||||
exporters.add((SchemeExporterEP<S>)exporterEP);
|
||||
}
|
||||
}
|
||||
return exporters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an exporter for the given name and scheme class. It is allowed for exporters to have the same name but different scheme classes.
|
||||
* @param name The exporter name as defined in plug-in configuration.
|
||||
* @param schemeClass The scheme class the exporter has to support.
|
||||
* @return The found exporter or null if there are no exporters for the given name and scheme class.
|
||||
*/
|
||||
@Nullable
|
||||
public static <S extends Scheme> SchemeExporter<S> getExporter(@NotNull String name, Class<S> schemeClass) {
|
||||
for (SchemeExporterEP<S> exporterEP : getExtensions(schemeClass)) {
|
||||
if (name.equals(exporterEP.name)) {
|
||||
return exporterEP.getInstance();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -506,6 +506,11 @@ message.code.style.scheme.already.exists=Scheme {0} already exists. Overwrite se
|
||||
code.style.scheme.import.unnamed=Unnamed
|
||||
message.code.style.scheme.import.success={0} settings were imported to {1} scheme.{2}
|
||||
message.code.style.scheme.import.failure={0} import failed with error message: {1}
|
||||
code.style.scheme.exporter.ui.export.as.title=Export As
|
||||
code.style.scheme.exporter.ui.file.chooser.title=Target File
|
||||
code.style.scheme.exporter.ui.file.chooser.message=Export to
|
||||
code.style.scheme.exporter.ui.code.style.exported.message={0} code style exported to {1}
|
||||
code.style.scheme.exporter.ui.cannot.write.message=Cannot write to selected file/location.
|
||||
|
||||
label.name=Name:
|
||||
error.scheme.must.have.a.name=Scheme must have a name
|
||||
|
||||
@@ -928,6 +928,11 @@
|
||||
<smartPointerElementInfoFactory implementation="com.intellij.psi.impl.smartPointers.AnchorElementInfoFactory"/>
|
||||
<codeInsight.lineMarkerProvider language="" implementationClass="com.intellij.execution.lineMarker.RunLineMarkerProvider"/>
|
||||
<projectService serviceImplementation="com.intellij.execution.TestStateStorage"/>
|
||||
|
||||
<schemeExporter
|
||||
name="Code Style XML File"
|
||||
schemeClass="com.intellij.psi.codeStyle.CodeStyleScheme"
|
||||
implementationClass="com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeCopyExporter"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
|
||||
@@ -219,6 +219,11 @@
|
||||
<with attribute="implementationClass" implements="com.intellij.openapi.options.SchemeImporter"/>
|
||||
</extensionPoint>
|
||||
|
||||
<extensionPoint name="schemeExporter" beanClass="com.intellij.openapi.options.SchemeExporterEP">
|
||||
<with attribute="schemeClass" implements="com.intellij.openapi.options.Scheme"/>
|
||||
<with attribute="implementationClass" implements="com.intellij.openapi.options.SchemeExporter"/>
|
||||
</extensionPoint>
|
||||
|
||||
<extensionPoint qualifiedName="org.jetbrains.urlOpener" interface="com.intellij.ide.browsers.UrlOpener"/>
|
||||
<extensionPoint name="tipAndTrick" beanClass="com.intellij.ide.util.TipAndTrickBean"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user