Eclipse插件开发:插入代码的灰色背景提前消失问题求解
解决Eclipse插件中插入代码的灰色背景提前消失问题
直接通过StyledText.setStyleRange()设置的背景色会被Eclipse文本编辑器的自动样式刷新机制覆盖——编辑器会定期重新计算语法高亮等样式,手动设置的StyleRange会被清除,导致背景在Tab键按下前就消失。
解决方案
需要利用Eclipse文本框架的PresentationReconciler来管理临时样式,它能和编辑器的样式更新流程兼容,避免手动设置的样式被冲掉。具体步骤:
- 为目标文本编辑器注册一个临时的
IPresentationRepairer,专门处理插入代码的背景样式 - 在Tab或Esc触发时,移除这个临时修复器,恢复默认样式
修改后的代码示例
public class InsertCodeHandler extends AbstractHandler { private static final String CODE_TO_INSERT = "public static void main"; private boolean codeInserted = false; private int insertOffset; private TemporaryStyleRepairer tempRepairer; private PresentationReconciler originalReconciler; @Override public Object execute(ExecutionEvent event) throws ExecutionException { IEditorPart editorPart = HandlerUtil.getActiveEditor(event); if (editorPart instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editorPart; IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); ITextViewer textViewer = textEditor.getAdapter(ITextViewer.class); insertOffset = textViewer.getTextWidget().getCaretOffset(); try { // 插入代码 document.replace(insertOffset, 0, CODE_TO_INSERT); codeInserted = true; StyledText styledText = textViewer.getTextWidget(); Display display = styledText.getDisplay(); Color greyBg = display.getSystemColor(SWT.COLOR_GRAY); // 创建临时样式修复器 tempRepairer = new TemporaryStyleRepairer(greyBg, insertOffset, CODE_TO_INSERT.length()); // 获取编辑器原有的PresentationReconciler originalReconciler = textViewer.getPresentationReconciler(); // 替换为包含临时修复器的Reconciler PresentationReconciler tempReconciler = new PresentationReconciler(); // 复制原有修复器的设置 tempReconciler.setDocumentPartitioning(originalReconciler.getDocumentPartitioning()); for (Iterator<?> it = originalReconciler.getRepairers().entrySet().iterator(); it.hasNext(); ) { Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next(); tempReconciler.setRepairer((IPresentationRepairer) entry.getValue(), (String) entry.getKey()); } // 添加临时修复器到默认分区(可根据实际分区调整) tempReconciler.setRepairer(tempRepairer, IDocument.DEFAULT_CONTENT_TYPE); textViewer.setPresentationReconciler(tempReconciler); // 注册按键监听器 styledText.addVerifyKeyListener(new VerifyKeyListener() { @Override public void verifyKey(VerifyEvent e) { if (e.keyCode == SWT.TAB && codeInserted) { // 恢复原有的PresentationReconciler textViewer.setPresentationReconciler(originalReconciler); // 移动光标到插入代码末尾 styledText.setSelection(insertOffset + CODE_TO_INSERT.length()); e.doit = false; codeInserted = false; } else if (e.keyCode == SWT.ESC && codeInserted) { try { // 删除插入的代码 document.replace(insertOffset, CODE_TO_INSERT.length(), ""); // 恢复原样式 textViewer.setPresentationReconciler(originalReconciler); codeInserted = false; } catch (BadLocationException ex) { ex.printStackTrace(); } } } }); } catch (BadLocationException e) { e.printStackTrace(); } } return null; } // 自定义临时样式修复器 private static class TemporaryStyleRepairer implements IPresentationRepairer { private final Color bgColor; private final int startOffset; private final int length; public TemporaryStyleRepairer(Color bgColor, int startOffset, int length) { this.bgColor = bgColor; this.startOffset = startOffset; this.length = length; } @Override public void createPresentation(TextPresentation presentation, int offset, int length) { // 只在目标区域应用背景色 int overlapStart = Math.max(offset, startOffset); int overlapEnd = Math.min(offset + length, startOffset + this.length); if (overlapStart < overlapEnd) { StyleRange styleRange = new StyleRange(overlapStart, overlapEnd - overlapStart, null, bgColor); presentation.addStyleRange(styleRange); } } } }
关键改动说明
- 使用
PresentationReconciler管理样式:替代直接操作StyledText,让临时样式和编辑器的原生样式更新流程兼容 - 自定义
TemporaryStyleRepairer:仅在插入代码的区域应用灰色背景,不影响其他内容的样式 - 按键触发时恢复原
PresentationReconciler:移除临时样式,回到编辑器默认的样式状态
内容的提问来源于stack exchange,提问作者jasvik
相关产品推荐
相关产品推荐

