Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Enable Templates in a Custom Editor

DZone's Guide to

How to Enable Templates in a Custom Editor

· Java Zone
Free Resource

Try Okta to add social login, MFA, and OpenID Connect support to your Java app in minutes. Create a free developer account today and never build auth again.

The template feature is one of the most used features in Eclipse editors, providing auto-completion for the code syntax. When you type “for” in the Java editor and hit Ctrl + space you get the custom assist proposal for the completion of the  for loop. It saves the developer's time and also makes the editor more user interactive. If you are interested in creating template for your custom editor then the following steps are helpful for you.

Steps for Enabling the Template Feature

Step1:

You need to extend the extension point org.eclipse.ui.preferencePages and you have to add the template preference page.

<page category=”cat” class=”com.xyz.ABCTemplatePreferencePage” id=”TemplateID” name=”Templates”> 
</page>
public class CustomTemplatePreferencePage extends TemplatePreferencePage implements IWorkbenchPreferencePage {

public CustomTemplatePreferencePage() {
try {
setPreferenceStore(Activator.getDefault().getPreferenceStore());
setTemplateStore(CustomTemplateManager.getInstance().getTemplateStore());
setContextTypeRegistry(CustomTemplateManager.getInstance().getContextTypeRegistry());
} catch(Exception ex){
ex.printStackTrace();
}
}

protected boolean isShowFormatterSetting() {
return false;
}

public boolean performOk() {
boolean ok = super.performOk();
Activator.getDefault().savePluginPreferences();
return ok;
}

}

Step 2:
Define the context for your template. For this you need to extend the extension point called org.eclipse.ui.editors.templates

<contextType class=”com.xyz.CustomTemplateContextType” id=”editorType” name=”Test”>
</contextType>

<include file=”templates/default-templates.xml” translations=”templates/default-templates.xml”>
</include>

 

The include property is used for loading the default templates form the xml file Its loaded only once for the lifecycle of your workspace or when u click on restore default from your preference page.

public class CustomTemplateContextType extends 
org.eclipse.jface.text.templates.TemplateContextType {

public static final String CONTEXT_TYPE
= Activator.getDefault().getPluginId() + ".preference.contextType.Custom";


public CustomTemplateContextType() {
addResolver(new GlobalTemplateVariables.Cursor());
addResolver(new GlobalTemplateVariables.WordSelection());
addResolver(new GlobalTemplateVariables.LineSelection());
}

}

Step 3:
For adding the additional information to your template you need to extend the TemplateProposal class and override the method name called getAdditionalProposalInfo.

public class CustomTemplateCompletionProposal extends TemplateProposal{
private final Template fTemplate;
private final TemplateContext fContext;
private final Image fImage;
private final IRegion fRegion;
private int fRelevance;
private String fDisplayString;



public CustomTemplateCompletionProposal(Template template,
TemplateContext context, IRegion region, Image image, int relevance) {
super(template, context, region, image, relevance);
fTemplate=template;
fContext = context;
fImage=image;
fRegion=region;
fRelevance=relevance;
fDisplayString=null;
}

@Override

public String getAdditionalProposalInfo() {
return StringUtils.convertToHTMLContent(fTemplate.getPattern());

}

}

 

Step 4: Define a template manager class for managing the processes

public class CustomTemplateManager {
private static final String CUSTOM_TEMPLATES_KEY
= Activator.getDefault().getPluginId() + ".customtemplates";
private static CustomTemplateManager instance;
private TemplateStore fStore;
private ContributionContextTypeRegistry fRegistry;
private TemplatePersistenceData[] templateData;
private CustomTemplateManager(){}

public static CustomTemplateManager getInstance(){
if(instance==null){
instance = new CustomTemplateManager();
}
return instance;
}

public TemplateStore getTemplateStore(){

if (fStore == null){
fStore = new ContributionTemplateStore(getContextTypeRegistry(),
Activator.getDefault().getPreferenceStore(), CUSTOM_TEMPLATES_KEY);
try {
fStore.load();
} catch (IOException e){
e.printStackTrace();

}
}
return fStore;
}



public ContextTypeRegistry getContextTypeRegistry(){
if (fRegistry == null){
fRegistry = new ContributionContextTypeRegistry();
}
fRegistry.addContextType(CustomTemplateContextType.CONTEXT_TYPE);
return fRegistry;
}

public IPreferenceStore getPreferenceStore(){
return Activator.getDefault().getPreferenceStore();
}

public void savePluginPreferences(){
Activator.getDefault().savePluginPreferences();
}

}

Step 5: Now you have to define the logic of template completion process. For this you need to extend the TemplateCompletionProcessor provided by the Eclipse API and you have to write your custom logic.

public class CustomTemplateAssistProcessor extends TemplateCompletionProcessor{
@Override
protected String extractPrefix(ITextViewer viewer, int offset) {
int i= offset;
IDocument document= viewer.getDocument();
if (i > document.getLength())
return "";
try {
while (i > 0) {
char ch= document.getChar(i - 1);
if (!Character.isJavaIdentifierPart(ch))
break;
i--;
}
if(i>0){
int j=i;
if(document.getChar(j-1)=='<')
i--;
}
return document.get(i, offset - i);
} catch (BadLocationException e) {
return "";
}
}

protected Template[] getTemplates(String contextTypeId) {
CustomTemplateManager manager = CustomTemplateManager.getInstance();
return manager.getTemplateStore().getTemplates();
}

protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
CustomTemplateManager manager = CustomTemplateManager.getInstance();
return manager.getContextTypeRegistry().getContextType(CustomTemplateContextType.CONTEXT_TYPE);
}

protected Image getImage(Template template) {
return Activator.getDefault().getImageRegistry().get(Activator.ICON_TEMPLATE);
}

public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
ITextSelection selection= (ITextSelection) viewer.getSelectionProvider().getSelection();
// adjust offset to end of normalized selection
if (selection.getOffset() == offset)
offset= selection.getOffset() + selection.getLength();
String prefix= extractPrefix(viewer, offset);
Region region= new Region(offset - prefix.length(), prefix.length());
TemplateContext context= createContext(viewer, region);
if (context == null)
return new ICompletionProposal[0];
context.setVariable("selection", selection.getText()); // name of the selection variables {line, word_selection //$NON-NLS-1$
Template[] templates= getTemplates(context.getContextType().getId());
List<ICompletionProposal> matches= new ArrayList<ICompletionProposal>();
for (int i= 0; i < templates.length; i++) {
Template template= templates[i];
try {
context.getContextType().validate(template.getPattern());
} catch (TemplateException e) {
continue;
}
if(!prefix.equals("") &&prefix.charAt(0)=='<')
prefix=prefix.substring(1);
if (!prefix.equals("")&&(template.getName().startsWith(prefix) &&
template.matches(prefix, context.getContextType().getId())))
matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
}
return matches.toArray(new ICompletionProposal[matches.size()]);
}

}

Step 6: Now you have to modify your content assist processor class so that you can add the template proposal in the list of code completion assist processor. For this you need to extend CustomTemplateAssistProcessor and call its super.computeCompletionProposals to retrieve the template list.

public class CustomContentAssistProcessor extends CustomTemplateAssistProcessor {
private CustomEditor editor;
this.editor = editor;
public boolean enableTemplate(){
return true;
}

public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
int offset) {
ICompletionProposal[] completionProposals = null;
IEditorInput editorInput = editor.getEditorInput();
String text = viewer.getTextWidget().getText();
List<Object> modList = new ArrayList<Object>();
if(enableTemplate()){
ICompletionProposal[] templates = super.computeCompletionProposals(viewer, offset);
if(templates!=null){
for(int i=0;i<templates.length;i){
modList.add(templates[i]);
}

}
if(completionProposals!=null){
for(int i=0;i<completionProposals.length;i){
modList.add(completionProposals[i]);
}
}
}

if(modList.size()>0)
return (ICompletionProposal[])modList.toArray(new ICompletionProposal[modList.size()]);

return completionProposals;
}

Now you can run the application and this will enable the template feature for your editor.

 

 

SocialTwist Tell-a-Friend
View Rajesh profile on LinkedIn

Build and launch faster with Okta’s user management API. Register today for the free forever developer edition!

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}