/*
* $Id$
*
* Copyright (c) 2004-2005 by the TeXlapse Team.
* 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
*/
package net.sourceforge.texlipse.editor;
import java.util.ArrayList;
import net.sourceforge.texlipse.TexlipsePlugin;
import net.sourceforge.texlipse.model.TexDocumentModel;
import net.sourceforge.texlipse.outline.TexOutlinePage;
import net.sourceforge.texlipse.properties.TexlipseProperties;
import net.sourceforge.texlipse.treeview.views.TexOutlineTreeView;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.projection.ProjectionSupport;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.eclipse.ui.texteditor.TextOperationAction;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
/**
* The Latex editor.
*
* @author Oskar Ojala
* @author Taavi Hupponen
* @author Boris von Loesch
*/
public class TexEditor extends TextEditor {
public final static String TEX_PARTITIONING= "__tex_partitioning";
/** The editor's bracket matcher */
private TexPairMatcher fBracketMatcher = new TexPairMatcher("()[]{}");
private TexOutlinePage outlinePage;
private TexOutlineTreeView fullOutline;
private TexDocumentModel documentModel;
private TexCodeFolder folder;
private ProjectionSupport fProjectionSupport;
private BracketInserter fBracketInserter;
private TexlipseAnnotationUpdater fAnnotationUpdater;
/**
* Constructs a new editor.
*/
public TexEditor() {
super();
//setRangeIndicator(new DefaultRangeIndicator());
folder = new TexCodeFolder(this);
}
/**
* Create the part control.
*
* @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
public void createPartControl(Composite parent) {
super.createPartControl(parent);
// enable projection support (for code folder)
ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
fProjectionSupport = new ProjectionSupport(projectionViewer,
getAnnotationAccess(), getSharedColors());
fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error");
fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning");
fProjectionSupport.install();
if (TexlipsePlugin.getDefault().getPreferenceStore().getBoolean(TexlipseProperties.CODE_FOLDING)) {
projectionViewer.doOperation(ProjectionViewer.TOGGLE);
}
fAnnotationUpdater = new TexlipseAnnotationUpdater(this);
((IPostSelectionProvider) getSelectionProvider()).addPostSelectionChangedListener(
new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event) {
//Delete all StatuslineErrors after selection changes
documentModel.removeStatusLineErrorMessage();
}
});
// register documentModel as documentListener
// in initializeEditor this would cause NPE
this.getDocumentProvider().getDocument(getEditorInput()).addDocumentListener(this.documentModel);
this.documentModel.initializeModel();
this.documentModel.updateNow();
ISourceViewer sourceViewer = getSourceViewer();
if (sourceViewer instanceof ITextViewerExtension) {
if (fBracketInserter == null)
fBracketInserter = new BracketInserter(getSourceViewer(), this);
((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
}
}
/**
* Initialize TexDocumentModel and enable latex support in projects
* other than Latex Project.
*
* @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
*/
protected void initializeEditor() {
super.initializeEditor();
setEditorContextMenuId("net.sourceforge.texlipse.texEditorScope");
this.documentModel = new TexDocumentModel(this);
setSourceViewerConfiguration(new TexSourceViewerConfiguration(this));
// register a document provider to get latex support even in non-latex projects
if (getDocumentProvider() == null) {
setDocumentProvider(new TexDocumentProvider());
}
}
/**
* Create, configure and return the SourceViewer.
*
* @see org.eclipse.ui.texteditor.AbstractTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int)
*/
protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
ProjectionViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), true, styles);
getSourceViewerDecorationSupport(viewer);
return viewer;
}
/**
* @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#configureSourceViewerDecorationSupport(org.eclipse.ui.texteditor.SourceViewerDecorationSupport)
*/
protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
// copy the necessary values from plugin preferences instead of overwriting editor preferences
getPreferenceStore().setValue(TexlipseProperties.MATCHING_BRACKETS, TexlipsePlugin.getPreference(TexlipseProperties.MATCHING_BRACKETS));
getPreferenceStore().setValue(TexlipseProperties.MATCHING_BRACKETS_COLOR, TexlipsePlugin.getPreference(TexlipseProperties.MATCHING_BRACKETS_COLOR));
support.setCharacterPairMatcher(fBracketMatcher);
support.setMatchingCharacterPainterPreferenceKeys(TexlipseProperties.MATCHING_BRACKETS, TexlipseProperties.MATCHING_BRACKETS_COLOR);
super.configureSourceViewerDecorationSupport(support);
}
/**
* @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()
*/
protected void createActions() {
super.createActions();
IAction a = new TextOperationAction(TexlipsePlugin.getDefault().getResourceBundle(), "ContentAssistProposal.", this, ISourceViewer.CONTENTASSIST_PROPOSALS);
a.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
setAction("ContentAssistProposal", a);
}
/**
* @return The source viewer of this editor
*/
public ISourceViewer getViewer(){
return getSourceViewer();
}
/**
* Used by platform to get the OutlinePage and ProjectionSupport
* adapter.
*
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class required) {
if (IContentOutlinePage.class.equals(required)) {
if (this.outlinePage == null) {
this.outlinePage = new TexOutlinePage(this);
this.documentModel.updateOutline();
}
return outlinePage;
} else if (fProjectionSupport != null) {
Object adapter = fProjectionSupport.getAdapter(getSourceViewer(), required);
if (adapter != null)
return adapter;
}
return super.getAdapter(required);
}
/**
* @return The outline page associated with this editor
*/
public TexOutlinePage getOutlinePage() {
return this.outlinePage;
}
/**
* @return Returns the documentModel.
*/
public TexDocumentModel getDocumentModel() {
return documentModel;
}
/**
* @return the preference store of this editor
*/
public IPreferenceStore getPreferences() {
return getPreferenceStore();
}
/**
* Triggers parsing. If there is a way to determine whether the
* platform is currently being shut down, triggering of parsing in
* such a case could be skipped.
*
* @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
public void doSave(IProgressMonitor monitor) {
super.doSave(monitor);
this.documentModel.updateNow();
}
/**
* Updates the code folding of this editor.
*
* @param rootNodes The document tree that correspond to folds
* @param monitor A progress monitor for the job doing the update
*/
public void updateCodeFolder(ArrayList rootNodes, IProgressMonitor monitor) {
this.folder.update(rootNodes);
}
/**
* Triggers the model to be updated as soon as possible.
*
* Used by drag'n'drop and copy paste actions of the outline.
*/
public void updateModelNow() {
this.documentModel.updateNow();
}
/**
* Used by outline to determine whether drag'n'drop operations
* are permitted.
*
* @return true if current model is dirty
*/
public boolean isModelDirty() {
return this.documentModel.isDirty();
}
/**
* @see org.eclipse.ui.IWorkbenchPart#dispose()
*/
public void dispose() {
super.dispose();
}
// B----------------------------------- mmaus
/**
*
* @return the fullOutline view.
*/
public TexOutlineTreeView getFullOutline() {
return fullOutline;
}
/**
* register the full outline.
* @param view the view.
*/
public void registerFullOutline(TexOutlineTreeView view) {
boolean projectChange = false;
if (view == null || view.getEditor() == null) {
projectChange = true;
}
else if (view.getEditor().getEditorInput() instanceof IFileEditorInput) {
IFileEditorInput oldInput = (IFileEditorInput) view.getEditor().getEditorInput();
IProject newProject = getProject();
// Check whether the project changes
if (!oldInput.getFile().getProject().equals(newProject))
projectChange = true;
} else
projectChange = true;
this.fullOutline = view;
this.fullOutline.setEditor(this);
if (projectChange) {
//If the project changes we have to update the fulloutline
this.fullOutline.projectChanged();
this.documentModel.updateNow();
}
}
/**
* unregister the full outline if the view is closed.
* @param view the view.
*/
public void unregisterFullOutline(TexOutlineTreeView view) {
this.fullOutline = null;
}
public IDocument getTexDocument(){
return this.getDocumentProvider().getDocument(getEditorInput());
}
// E----------------------------------- mmaus
/**
* @return The project that belongs to the current file
* or null if it does not belong to any project
*/
public IProject getProject() {
IResource res = (IResource) getEditorInput().getAdapter(IResource.class);
if (res == null) return null;
else return res.getProject();
}
/**
* Initializes the key binding scopes of this editor.
*/
protected void initializeKeyBindingScopes() {
setKeyBindingScopes(new String[] { "org.eclipse.ui.textEditorScope", "net.sourceforge.texlipse.texEditorScope" }); //$NON-NLS-1$
}}