Create Source Editor in Android Studio Community Edition.

Hi,

I started a intellij plugin development and I want to create a source and designer editor in the plugin. Consider I am new to intellij plugin development, can anyone tell me How I can create an editor in intellij.

 

Thanks

Ishan Jain

19 comments

This is far from trivial task. What exactly do you want to achieve? You can look at existing "GUI" editors (Android, Swing GUI Builder) in IntelliJ Community/Android sources).

0

Thanks for reply.

I have created a custom source editor with custom language. But my real task is to create a html designer editor. How can I add a GUI in the editor like xml GUI editor of android. 

It would be great if you send me a link of the source where it exactly is created.

 

Thanks

Ishan Jain

0

See com.intellij.util.xml.ui.PerspectiveFileEditorProvider to provide additional tabs to switch from source to designer view. See com.intellij.android.designer.AndroidDesignerEditorProvider as reference for Android designer.

0

Thanks for reply.

I have tried the FileEditorProvider and also register it in the extension in plugin.xml. But when I create a file with the same extension as given in the source then it does not take that editor and instead the list of other editors which also doesnot contain my editor. I don't understand the exact problem.

 

Thanks

Ishan Jain

0

Could you share your sources? Otherwise it's impossible to diagnose what is happening here.

0
Thanks for reply.

import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
import com.intellij.ide.structureView.StructureViewBuilder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jdesktop.jdic.browser.WebBrowser;
import org.jdesktop.jdic.browser.WebBrowserEvent;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

/**
* Created by Admin on 3/16/2016.
*/
public class LangEditor implements FileEditor,
FileEditorManagerListener {
// private class XXXEditor implements FileEditor,
// FileEditorManagerListener, WebBrowserEventsHandler
// {
JPanel mainPanel, browserPanel;
org.jdesktop.jdic.browser.WebBrowser browser;
private final VirtualFile file;
private final Project project;

public LangEditor(Project project, VirtualFile file) {
this.file = file;
this.project = project;
mainPanel = new JPanel(new BorderLayout());

browserPanel = new JPanel(new BorderLayout());
try {
browser = new org.jdesktop.jdic.browser.WebBrowser();
} catch (Exception e) {
return;
}
browserPanel.add(browser, BorderLayout.CENTER);
//browser.setEventHandler(this);
mainPanel.add(browserPanel, BorderLayout.CENTER);
browserPanel.setBorder(BorderFactory.createEtchedBorder());


FileEditorManager.getInstance(project).addFileEditorManagerListener(this);
}



/**
* @return component which represents editor in the UI.
* <p>
* The method should never return <code>null</code>.
*/
public JComponent getComponent() {
return mainPanel;
}

/**
* Returns component to be focused when editor is opened. Method
* <p>
* should never return null.
*/
public JComponent getPreferredFocusedComponent() {
return mainPanel;
}

/**
* @return editor's name, a string that identifies editor among
* <p>
* other editors. For example, UI form might have two
* <p>
* editor: "GUI Designer"
* and "Text". So "GUI Designer" can be a name of one
* <p>
* editor and "Text"
* can be a name of other editor. The method should never
* <p>
* return null]]>.
*/
@NonNls
public String getName() {
return "Preview";
}

/**
* @return editor's internal state. Method should never return
* <p>
* null]]>.
*/
public FileEditorState getState(FileEditorStateLevel level) {
return LangEditorProvider.DummyFileEditorState.DUMMY;
}

/**
* Applies given state to the editor.
*
* @param state cannot be null
*/
public void setState(FileEditorState state) {
}

/**
* @return whether the editor's content is modified in comparision
* <p>
* with its file.
*/
public boolean isModified() {
return false;
}

/**
* @return whether the editor is valid or not. For some reasons
* <p>
* editor can become invalid. For example, text editor
* <p>
* becomes invalid when its file is deleted.
*/
public boolean isValid() {
return true;
}

/**
* This method is invoked each time when the editor is selected.
* <p>
* This can happen in two cases: editor is selected because the
* <p>
* selected file
* has been changed or editor for the selected file has been changed.
*/
public void selectNotify() {
}

private void reloadContent() {
FileDocumentManager fileDocManager =
FileDocumentManager.getInstance();
Document doc = fileDocManager.getDocument(file);
fileDocManager.saveDocument(doc);
try {
browser.setURL(new URL(file.getUrl()));
} catch (MalformedURLException e) {
}
}

/**
* This method is invoked each time when the editor is deselected.
*/
public void deselectNotify() {
}

/**
* Removes specified listener
*
* @param listener to be added
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
}

/**
* Adds specified listener
*
* @param listener to be removed
*/
public void removePropertyChangeListener(PropertyChangeListener
listener) {
}

/**
* @return highlighter object to perform background analysis and
* <p>
* highlighting activities.
* Return <code>null</code> if no background highlighting
* <p>
* activity necessary for this file editor.
*/
public BackgroundEditorHighlighter getBackgroundHighlighter() {
return null;
}

/**
* The method is optional. Currently is used only by find usages
* <p>
* subsystem
*
* @return the location of user focus. Typically it's a caret or
* <p>
* any other form of selection start.
*/
public FileEditorLocation getCurrentLocation() {
return null;
}

public StructureViewBuilder getStructureViewBuilder() {
return null;
}

/**
* write javadoc
*/
public void fileOpened(FileEditorManager source, VirtualFile file) {
}

/**
* write javadoc
*/
public void fileClosed(FileEditorManager source, VirtualFile file) {
}

/**
*
*/
public void selectionChanged(FileEditorManagerEvent event) {
if (
FileEditorManager.getInstance(project).getSelectedEditor(file) == this)
reloadContent();
}

@Override
public void dispose() {

}

@Nullable
@Override
public <T> T getUserData(@NotNull Key<T> key) {
return null;
}

@Override
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {

}
}



import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.sun.deploy.security.DeployURLClassPathCallback;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

/**
* Created by Admin on 3/16/2016.
*/
public class LangEditorProvider implements ApplicationComponent,FileEditorProvider {

public void initComponent() {
}

public void disposeComponent() {
}

public String getComponentName() {
return "LangEditorProvider";
}

public boolean accept(Project project, VirtualFile file) {

return file.getFileType() == HiiFileType.INSTANCE;
}

public FileEditor createEditor(Project project, final VirtualFile file) {
return new LangEditor(project, file);
}

public void disposeEditor(FileEditor editor) {
}

@NotNull
@Override
public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) {
return DummyFileEditorState.DUMMY;

}

@Override
public void writeState(@NotNull FileEditorState state, @NotNull Project project, @NotNull Element targetElement) {

}

@NonNls
public String getEditorTypeId() {
return getComponentName();
}

public FileEditorPolicy getPolicy() {
return FileEditorPolicy.NONE;
}

public static class DummyFileEditorState implements FileEditorState {
public static final FileEditorState DUMMY = new DummyFileEditorState();

public boolean canBeMergedWith(FileEditorState otherState,
FileEditorStateLevel level) {
return false;
}
}

}

plugin.xml

<idea-plugin version="2">
<id>com.your.company.01.plugin.id</id>
<name>TestConcept2</name>
<version>1.0</version>
<vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>

<description><![CDATA[
Enter short description for your plugin here.<br>
<em>most HTML tags may be used</em>
]]></description>

<change-notes><![CDATA[
Add change notes here.<br>
<em>most HTML tags may be used</em>
]]>
</change-notes>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="141.0"/>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->

<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<fileEditorProvider implementation="LangEditorProvider"></fileEditorProvider>
<!--<fileTypeFactory implementation="HiiFileTypeFactory"></fileTypeFactory>-->
<!--<projectService serviceInterface="ViewsMetaManager"
serviceImplementation="ViewsMetaManager"/>-->
</extensions>

<actions>
<!-- Add your actions here -->
</actions>

</idea-plugin>


I have created the above editor and fileeditorprovider classes and register in plugin.xml.
0
import com.intellij.lang.Language;
import com.intellij.openapi.fileTypes.LanguageFileType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;

/**
* Created by Admin on 3/16/2016.
*/
public class HiiFileType extends LanguageFileType{

public static final HiiFileType INSTANCE = new HiiFileType(HiiLanguage.INSTANCE);

/**
* Creates a language file type for the specified language.
*
* @param language The language used in the files of the type.
*/
private HiiFileType(@NotNull Language language) {
super(language);
}

@NotNull
@Override
public String getName() {
return "Ext File";
}

@NotNull
@Override
public String getDescription() {
return "Ext File Description";
}

@NotNull
@Override
public String getDefaultExtension() {
return "ext";
}

@Nullable
@Override
public Icon getIcon() {
return HiiIcons.FILE;
}
}



import com.intellij.openapi.fileTypes.FileTypeConsumer;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import org.jetbrains.annotations.NotNull;

/**
* Created by Admin on 3/16/2016.
*/
public class HiiFileTypeFactory extends FileTypeFactory{

@Override
public void createFileTypes(@NotNull FileTypeConsumer consumer) {
consumer.consume(HiiFileType.INSTANCE, "ext");
}
}



import com.intellij.openapi.util.IconLoader;

import javax.swing.*;

/**
* Created by Admin on 3/16/2016.
*/
public class HiiIcons {

public static final Icon FILE = IconLoader.getIcon("/icons/jar-gray.png");
}



import com.intellij.lang.Language;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

/**
* Created by Admin on 3/16/2016.
*/
public class HiiLanguage extends Language{

public static HiiLanguage INSTANCE = new HiiLanguage("ExtLang");

private HiiLanguage(@NotNull @NonNls String ID) {
super(ID);
}
}



plugin.xml

<idea-plugin version="2">
<id>com.your.company.01.plugin.id</id>
<name>TestConcept2</name>
<version>1.0</version>
<vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>

<description><![CDATA[
Enter short description for your plugin here.<br>
<em>most HTML tags may be used</em>
]]></description>

<change-notes><![CDATA[
Add change notes here.<br>
<em>most HTML tags may be used</em>
]]>
</change-notes>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="141.0"/>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->

<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<fileEditorProvider implementation="LangEditorProvider"></fileEditorProvider>
<!--<fileTypeFactory implementation="HiiFileTypeFactory"></fileTypeFactory>-->
<projectService serviceInterface="ViewsMetaManager"
serviceImplementation="ViewsMetaManager"/>
</extensions>

<actions>
<!-- Add your actions here -->
</actions>

</idea-plugin>



above are the language classes
0

AFAIU LangEditor does not implement com.intellij.openapi.fileEditor.FileEditorProvider or any of its inheritors. Thus the Extension Point will be ignored. If it still doesn't work, please provide a Github URL or ZIP of project.

0

Thanks for reply.

In the following method of LangEditorProvider class I am returning LangEditor.

 

public FileEditor createEditor(Project project, final VirtualFile file) {
return new LangEditor(project, file);
}

I have also added the source code on github:

https://bitbucket.org/ishan_jain/testintellijconcept/src/38b60e7b115ce5c8c3da1243ca026669263d3c32?at=new_branch 
0

It can't match your "ext" filetype because the registration of <fileTypeFactory> assigning your custom filetype is commented out in plugin.xml. After this it works for me.

 

 

0

Thanks for reply.

 

No I have already commented out that, I have just commented in this post. Did you see the UI in the editor, the browser which I have added to the editor?

0

Because I only see the text editor.

0

I'm referring to the code in your repository you linked above. Please try to debug into accept() method and see if filetype is correctly associated with your file. And verify there is no other association via IDE settings.

0

Thank you very much for the reply. I have also seen the UI in the editor. 

Earlier it was not showing it because I have also created another project which was giving errors. 

So I reinstalled the ide and created new project. Can you also tell me one more thing that if I have created another plugin project and run it, then again run another plugin project then how can I remove the earlier cached plugins. 

It also does not show in the settings window with plugin tab.

0

I see, clear out the sandbox directory configured in SDKs->IJ SDK->"Sandbox Home"

0

Hi,

Can I add New <AppName> Project in the file->New->New <App Name> Project option in the menu bar.

Thanks

0

Yes, you can add any Action to group NewProjectOrModuleGroup for generic setup or use EP com.intellij.projectImport.ProjectImportProvider to re-use "Import from existing sources" logic.

0

Hi,

Can someone provide the ".bnf" grammar file for javascript or ecmascript?

 

Thanks

0

Please sign in to leave a comment.