最近在开发EclipsePlug, 开发一个SQL代码编辑器, 所以就写一篇文章. 希望对大家有帮助. 让大家少走弯路. (代码可能不能运行, 但关键部分都有). 因为代码比较多. 所以可能不能一次性上传完成. 毕竟我还要修改, 空话不多说. 直接上代码.
首先是Editor类, 我取名为SQLEditor, 继承TextEditor:
package com.test.editors;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.TextEditor;
import com.zdk.platform.studio.dbassistant.codeassistent.ColorManager;
import com.zdk.platform.studio.dbassistant.codeassistent.SQLConfiguration;
import com.zdk.platform.studio.dbassistant.codeassistent.SQLDocumentProvider;
/**
* 类说明: SQL语句编辑器.
* @author xiao天__
*
*/
public class SQLEditor extends TextEditor {
/**editorID**/
public static String ID = "com.test.SQLEditor";
private ColorManager colorManager;
private SQLConfiguration configuration;
public SQLEditor() {
super();
configuration = new SQLConfiguration();
setSourceViewerConfiguration(configuration);
setDocumentProvider(new SQLDocumentProvider());
}
/**
* 方法说明: 设置字体.
*/
public void initFont() {
FontData fontData = new FontData("Consolas", 11, SWT.NORMAL);
Font font = new Font(getEditorSite().getShell().getDisplay(), fontData);
this.getSourceViewer().getTextWidget().setFont(font);
}
public void dispose() {
if(colorManager != null) {
colorManager.dispose();
}
super.dispose();
}
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
initFont();
}
}
如果大家使用的是有文件的方式. 就可以直接配置Plug-in.xml文件方式来打开SQLEditor, 而小天__使用的是不需要文件的方式来打开SQLEditor, 主要是项目需要, 所以这里给大家写两种方式:
方式一:
Plug-in.xml:
<plugin>
<extension
point="org.eclipse.ui.editors">
<editor
name="SQL编辑器"
extensions="xml"
icon="icons/sample.gif"
contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
class="com.test.SQLEditor"
id="com.test.SQLEditor">
</editor>
</extension>
</plugin>
方式二:
Plug-in.xml的配置都是一样的, 因为没有文件. 所以我们必须要构建一个Input对象:
SQLEditorInput:
package com.test.editors;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
public class SQLEditorInput implements IStorageEditorInput {
/**显示名称**/
private String name;
/**正文**/
private String content = "";
/**存储器**/
public IStorage storage;
public SQLEditorInput(String name) {
this.name = name;
storage = new IStorage() {
@Override
public Object getAdapter(Class adapter) {
return null;
}
@Override
public boolean isReadOnly() {
return isReadOnly;
}
@Override
public String getName() {
return SQLEditorInput.this.name;
}
@Override
public IPath getFullPath() {
return null;
}
@Override
public InputStream getContents() throws CoreException {
return new ByteArrayInputStream(content.getBytes());
}
};
}
public SQLEditorInput(String name, IStorage is) {
this.name = name;
this.storage = is;
}
@Override
public boolean exists() {
return true;
}
@Override
public ImageDescriptor getImageDescriptor() {
return null;
}
@Override
public String getName() {
return name;
}
@Override
public IPersistableElement getPersistable() {
return null;
}
@Override
public String getToolTipText() {
return "SQL编辑器";
}
@Override
public Object getAdapter(Class adapter) {
return null;
}
@Override
public IStorage getStorage() throws CoreException {
return storage;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof SQLEditorInput){
SQLEditorInput newDbEditorInput = (SQLEditorInput)obj;
if(this.name.equals(newDbEditorInput.getName())) {
return true;
}
}
return false;
}
}
这个方法可以写在工具栏的事件里. 右键菜单里. 这个就看需求了.
public void openView() {
SQLEditorInput input = new SQLEditorInput("新建查询");
try {
page.openEditor(input, "com.test.SQLEditor");
} catch (PartInitException e) {
e.printStackTrace();
}
}
SQLConfiguration类:
package com.zdk.platform.studio.dbassistant.codeassistent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.formatter.ContentFormatter;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import com.zdk.platform.studio.dbassistant.codeassistent.assistent.SQLContentAssistent;
public class SQLConfiguration extends SourceViewerConfiguration {
private SQLContentAssistent assistent;
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
PresentationReconciler reconciler = new PresentationReconciler();
DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new SQLPartitionScanner());
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
return reconciler;
}
@Override
public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
ContentFormatter formatter = new ContentFormatter();
formatter.setFormattingStrategy(new SQLFormattingStrategy(), IDocument.DEFAULT_CONTENT_TYPE);
formatter.enablePartitionAwareFormatting(true);
return formatter;
}
/**
* 设置自动提示.
*/
@Override
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
ContentAssistant contentAssistent = new ContentAssistant();
assistent = new SQLContentAssistent();
contentAssistent.setContentAssistProcessor(assistent, IDocument.DEFAULT_CONTENT_TYPE);
contentAssistent.enableAutoActivation(true);
contentAssistent.setAutoActivationDelay(200);
return contentAssistent;
}
public DBConfig getDbConfig() {
return dbConfig;
}
}
package com.zdk.platform.studio.dbassistant.codeassistent;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.ui.editors.text.FileDocumentProvider;
public class SQLDocumentProvider extends FileDocumentProvider {
protected IDocument createDocument(Object element) throws CoreException {
IDocument document = super.createDocument(element);
if (document != null) {
IDocumentPartitioner partitioner =
new FastPartitioner(
new SQLPartitionScanner(),
new String[] { });
partitioner.connect(document);
document.setDocumentPartitioner(partitioner);
}
return document;
}
}
代码高亮部分:
ColorManager类:
package com.zdk.platform.studio.dbassistant.codeassistent;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
/**
* 类说明: 颜色管理类.
* @author 小天__
*
*/
public class ColorManager {
/**注释颜色**/
public static final RGB COLOR_COMMENT = new RGB(0, 128, 0);
/**关键字颜色**/
public static final RGB COLOR_KEYWORD = new RGB(128, 0, 0);
/**普通文本颜色**/
public static final RGB COLOR_TEXT = new RGB(0, 0, 0);
protected static Map fColorTable = new HashMap(10);
public void dispose() {
Iterator e = fColorTable.values().iterator();
while (e.hasNext())
((Color) e.next()).dispose();
}
public static Color getColor(RGB rgb) {
Color color = (Color) fColorTable.get(rgb);
if (color == null) {
color = new Color(Display.getCurrent(), rgb);
fColorTable.put(rgb, color);
}
return color;
}
}
SQLPartitionScanner:
package com.test.codeassistent;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.EndOfLineRule;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
import org.eclipse.jface.text.rules.SingleLineRule;
import org.eclipse.jface.text.rules.Token;
import com.test.rule.KeyWordDetector;
import com.test.rule.KeyWordRule;
public class SQLPartitionScanner extends RuleBasedPartitionScanner {
private TextAttribute keywordAttr = new TextAttribute(ColorManager.getColor(ColorManager.COLOR_KEYWORD));
public SQLPartitionScanner() {
IPredicateRule[] rules = new IPredicateRule[1];
rules[0] = new KeyWordRule(new KeyWordDetector(), new Token(keywordAttr));
setPredicateRules(rules);
}
}
package com.zdk.platform.studio.dbassistant.codeassistent.rule;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.IWordDetector;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.WordRule;
import com.test.SQLPartitionScanner;
public class KeyWordRule extends WordRule implements IPredicateRule {
private StringBuffer fBuffer= new StringBuffer();
private boolean fIgnoreCase= false;
/**关键字**/
public String keywords = "insert,update,delete,select";
public KeyWordRule(IWordDetector detector, IToken defaultToken) {
super(detector, new Token(SQLPartitionScanner.textAttr));
//增加关键字
String[] keywordArray = keywords.split(",");
for (int i = 0; i < keywordArray.length; i++) {
String keywrod = keywordArray[i];
addWord(keywrod, defaultToken);
}
}
public IToken evaluate(ICharacterScanner scanner) {
int c= scanner.read();
if (c != ICharacterScanner.EOF && fDetector.isWordStart((char) c)) {
if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) {
fBuffer.setLength(0);
do {
fBuffer.append((char) c);
c= scanner.read();
} while (c != ICharacterScanner.EOF && fDetector.isWordPart((char) c));
scanner.unread();
String buffer= fBuffer.toString();
if (fIgnoreCase) {
buffer = buffer.toLowerCase();
}
IToken token= (IToken)fWords.get(buffer);
if (token != null) {
return token;
}
if (fDefaultToken.isUndefined()) {
unreadBuffer(scanner);
}
return fDefaultToken;
}
}
scanner.unread();
return Token.UNDEFINED;
}
@Override
public IToken getSuccessToken() {
return Token.UNDEFINED;
}
@Override
public IToken evaluate(ICharacterScanner scanner, boolean resume) {
return this.fDefaultToken;
}
}
package com.zdk.platform.studio.dbassistant.codeassistent.rule;
/*******************************************************************************
* Copyright (c) 2000 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* QNX Software System
*******************************************************************************/
import org.eclipse.jface.text.rules.IWordDetector;
/**
* A C aware word detector.
*/
public class KeyWordDetector implements IWordDetector {
/**
* @see IWordDetector#isWordIdentifierStart
*/
public boolean isWordStart(char c) {
if(64 < c && c < 123 || c == '=') { //大写字母A-Z, 小写字母a-z;
return true;
}
return false;
}
/**
* @see IWordDetector#isWordIdentifierPart
*/
public boolean isWordPart(char c) {
if(64 < c && c < 123 || c == '=') { //大写字母A-Z, 小写字母a-z;
return true;
}
return false;
}
}
SQLContentAssistent:
package com.test.assistent;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import com.zdk.platform.studio.pojo.DBConfig;
public class SQLContentAssistent implements IContentAssistProcessor {
/**提示集合**/
public List<IAssistentContent> assistentContentList = new ArrayList<IAssistentContent>();
/**开始位置**/
public int startIndex = 0;
/**当前文档**/
public IDocument doc;
/**数据连接对象**/
private DBConfig dbConfig;
/**
* 构造方法: 添加提示种类.
*/
public SQLContentAssistent() {
super();
assistentContentList.add(new KeywordAssistentData());
}
@Override
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
this.doc = viewer.getDocument();
List list = new KeywordAssistentData().getAssistentData(this.doc, offset);
return (CompletionProposal[]) list.toArray(new CompletionProposal[list.size()]);
}
@Override
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
// TODO 自动生成的方法存根
return null;
}
/**
* 设置何时激活
*/
@Override
public char[] getCompletionProposalAutoActivationCharacters() {
return new char[] {'.'};
}
@Override
public char[] getContextInformationAutoActivationCharacters() {
return null;
}
@Override
public String getErrorMessage() {
// TODO 自动生成的方法存根
return null;
}
@Override
public IContextInformationValidator getContextInformationValidator() {
// TODO 自动生成的方法存根
return null;
}
/**
* 方法说明: 获取提示前面的字符串.
* @param doc
* @param offest
* @return
*/
public String getFrontText(IDocument doc, int offest) {
StringBuffer buf = new StringBuffer();
while(true) { //循环添加关键字.
try {
char c = doc.getChar(--offest);
startIndex = offest;
if(Character.isWhitespace(c)) {
startIndex++;
break;
}
if(c == ';' || c == '(' || c == ')' || c == '{' || c == '}' || c == ',') { //结束符号.
startIndex++;
break;
}
buf.append(c);
} catch (BadLocationException e) {
break;
}
}
return buf.reverse().toString();
}
}
package com.test.assistent;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import com.zdk.platform.studio.dbassistant.codeassistent.Contents;
/**
* 类说明: 关键字提示数据类.
* @author Administrator
*
*/
public class KeywordAssistentData implements IAssistentContent {
private int start = 0;
@Override
public List<CompletionProposal> getAssistentData(IDocument doc, int offset) {
String str = getFrontText(doc, offset);
List<CompletionProposal> list = new ArrayList<CompletionProposal>();
//用正则匹配.
Pattern p = null;
Matcher m = null;
for (int i = 0; i < Contents.KEY_WORD_ARRAY.length; i++) {
String keyWord = Contents.KEY_WORD_ARRAY[i];
p = Pattern.compile("(^" + str + ")", Pattern.CASE_INSENSITIVE);
m = p.matcher(keyWord);
if(m.find()) {
String insert = Contents.KEY_WORD_ARRAY[i];
//创建替换类容. insert:替换文本, offset:替换其实位置.
//0:替换结束位置.偏移量, insert.length:替换完成后.光标位置偏移量.
CompletionProposal proposal = new CompletionProposal(insert, start, offset - start, insert.length());
list.add(proposal);
}
}
return list;
}
/**
* 方法说明: 获取提示前面的字符串.
* @param doc
* @param offest
* @return
*/
public String getFrontText(IDocument doc, int offest) {
StringBuffer buf = new StringBuffer();
while(true) { //循环添加关键字.
try {
char c = doc.getChar(--offest);
start = offest;
if(Character.isWhitespace(c)) {
start++;
break;
}
if(c == ';' || c == '(' || c == ')' || c == '{' || c == '}' || c == ',') { //结束符号.
start++;
break;
}
buf.append(c);
} catch (BadLocationException e) {
break;
}
}
return buf.reverse().toString();
}
}
以上就是大部分代码了.