blob: 2993ceb98d1483856982b31e034850b1b2222950 [file] [log] [blame]
package org.eclipse.photran.internal.ui.editor;
import org.eclipse.cdt.internal.ui.editor.CContentOutlinePage;
import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
import org.eclipse.cdt.internal.ui.editor.ICEditorActionDefinitionIds;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IWorkingCopyManager;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.rules.DefaultPartitioner;
import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.photran.internal.ui.actions.FortranCommentActions;
import org.eclipse.photran.internal.ui.preferences.FortranEditorPreferencePage;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
/**
* The Fortran text editor, including an inner class containing a coloring
* scheme.
*
* @author joverbey
* @author cheahcf
* @author nchen
*/
public class FortranFreeFormEditor extends AbstractFortranEditor {
public static final String EDITOR_ID = "org.eclipse.photran.internal.ui.Editor.FortranEditor";
private TabConverter tabConverter;
private Composite fMainComposite;
private static final int MAX_LINES_FOR_LEXER_BASED_SCANNER = 1000;
public FortranFreeFormEditor() {
super();
setSourceViewerConfiguration(new FortranSourceViewerConfiguration(this));
setRangeIndicator(new DefaultRangeIndicator());
// We must use the CUIPlugin's document provider in order for the
// working copy manager in setOutlinePageInput (below) to
// function correctly.
// setDocumentProvider(new EbnfDocumentProvider());
setDocumentProvider(CUIPlugin.getDefault().getDocumentProvider());
// So our Refactoring menu will appear
setEditorContextMenuId("#FortranEditorContext");
}
// Since we don't have our "own" document provider, we can't set up
// partitioning there... so we do it here instead
// TODO: dynamic change to
protected void doSetInput(IEditorInput input) throws CoreException {
super.doSetInput(input);
IDocument document = this.getDocumentProvider().getDocument(input);
if (document != null) {
linesOfCode = document.getNumberOfLines();
if (document.getNumberOfLines() > MAX_LINES_FOR_LEXER_BASED_SCANNER) {
RuleBasedPartitionScanner sScanner = new RuleBasedPartitionScanner();
IDocumentPartitioner partitioner = new DefaultPartitioner(
sScanner,
new String[] { FortranPartitionScanner.F90_STRING_CONSTANTS_PARTITION });
partitioner.connect(document);
document.setDocumentPartitioner(partitioner);
} else {
IDocumentPartitioner partitioner = new FortranPartitionScanner(
input.getName(), false);
partitioner.connect(document);
document.setDocumentPartitioner(partitioner);
}
configureTabConverter(); // prepare a new TabConverter for the
// document
}
}
// --- RESPOND TO PREFERENCE CHANGES ---//
/**
* Handles preference changes. Usually it is sufficient to use the
* superclass implementation. This time, we need to perform conversion and
* also change the tab width.
*/
protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
try {
if (getSourceViewer() == null
|| getSourceViewer().getTextWidget() == null)
return;
AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
if (asv != null) {
String property = event.getProperty();
if (FortranEditorPreferencePage.SPACES_FOR_TABS_PREF.equals(property)) {
asv.updateIndentationPrefixes();
if (FortranEditorPreferencePage.isTabConversionEnabled())
doTabConversion();
else
endTabConversion();
return;
}
if (FortranEditorPreferencePage.TAB_WIDTH_PREF.equals(property)) {
asv.updateIndentationPrefixes();
if (tabConverter != null)
tabConverter
.setNumberOfSpacesPerTab(FortranEditorPreferencePage
.getTabSize());
Object value = event.getNewValue();
if (value instanceof Integer) {
asv.getTextWidget().setTabs(
((Integer) value).intValue());
} else if (value instanceof String) {
asv.getTextWidget().setTabs(
Integer.parseInt((String) value));
}
return;
}
}
} finally {
super.handlePreferenceStoreChanged(event);
}
}
/**
* Creates a new tabCoverter for this editor that is currently opened in the
* workspace
*
*/
private void configureTabConverter() {
if (tabConverter != null) {
tabConverter.setLineTracker(new DefaultLineTracker());
}
}
/**
* Converts any new tabs that are entered into spaces
*
*/
private void doTabConversion() {
if (tabConverter == null) {
tabConverter = new TabConverter();
configureTabConverter();
tabConverter.setNumberOfSpacesPerTab(FortranEditorPreferencePage
.getTabSize());
AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
asv.addTextConverter(tabConverter);
asv.updateIndentationPrefixes();
}
}
/**
* Stops converting tabs that the user enters. Any previous tabs that were
* converted to spaces are left as they are.
*/
private void endTabConversion() {
if (tabConverter != null) {
AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
asv.removeTextConverter(tabConverter);
asv.updateIndentationPrefixes();
tabConverter = null;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
public void createPartControl(Composite parent) {
super.createPartControl(parent);
if (FortranEditorPreferencePage.isTabConversionEnabled())
doTabConversion();
Composite childComp = (Composite) ((Composite) parent.getChildren()[0])
.getChildren()[0];
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.verticalSpacing = 2;
childComp.setLayout(layout);
GridData data = new GridData(GridData.FILL_BOTH);
childComp.getChildren()[0].setLayoutData(data);
fMainComposite = childComp;
createHorizontalRuler(fMainComposite);
}
// --- EVERYTHING BELOW IS FOR OUTLINING ---//
public Object getAdapter(Class required) {
if (IContentOutlinePage.class.equals(required)) {
return getOutlinePage();
}
if (required == IShowInTargetList.class) {
return new IShowInTargetList() {
public String[] getShowInTargetIds() {
return new String[] { CUIPlugin.CVIEW_ID,
IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
}
};
}
return super.getAdapter(required);
}
protected CContentOutlinePage fOutlinePage;
private AbstractHorizontalRuler fHRuler;
/**
* Gets the outline page of the c-editor.
*
* @return Outline page.
*/
public CContentOutlinePage getOutlinePage() {
if (fOutlinePage == null) {
// CContentOutlinePage currently does nothing with its editor
// parameter,
// so we can pass in null rather than trying to convince it to use
// our
// editor (e.g., by subclassing CEditor).
fOutlinePage = new CContentOutlinePage(null);
fOutlinePage.addSelectionChangedListener(this);
}
setOutlinePageInput(fOutlinePage, getEditorInput());
return fOutlinePage;
}
/**
* Sets an input for the outline page.
*
* @param page
* Page to set the input.
* @param input
* Input to set.
*/
public static void setOutlinePageInput(CContentOutlinePage page,
IEditorInput input) {
if (page != null) {
IWorkingCopyManager manager = CUIPlugin.getDefault()
.getWorkingCopyManager();
page.setInput(manager.getWorkingCopy(input));
}
}
// --- TOGGLE COMMENTING SUPPORT
// ---------------------------------------------- //
/**
* cheahcf Required to intialize key bindings specified in plugin.xml
*/
protected void initializeKeyBindingScopes() {
setKeyBindingScopes(new String[] { "org.eclipse.photran.ui.FEditorScope" }); //$NON-NLS-1$
}
/**
* Create actions that will be registered with the editor.
*/
protected void createActions() {
super.createActions();
Action action = new FortranCommentActions(CEditorMessages
.getResourceBundle(), "AddBlockComment.", this); //$NON-NLS-1$
action
.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_BLOCK_COMMENT);
setAction("AddBlockComment", action); //$NON-NLS-1$
markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
markAsSelectionDependentAction("AddBlockComment", true); //$NON-NLS-1$
}
// --FOLDING
// SUPPORT----------------------------------------------------------------------------
// protected ProjectionSupport projectionSupport;
//
// protected ProjectionAnnotationModel annotationModel;
//
// public ProjectionAnnotationModel getAnnotationModel() {
// return annotationModel;
// }
//
// public void createPartControl(Composite parent) {
// super.createPartControl(parent);
//
// ProjectionViewer viewer = (ProjectionViewer) getSourceViewer();
//
// projectionSupport = new ProjectionSupport(viewer,
// getAnnotationAccess(), getSharedColors());
// projectionSupport.install();
//
// // turn projection mode on
// viewer.doOperation(ProjectionViewer.TOGGLE);
//
// annotationModel = viewer.getProjectionAnnotationModel();
// }
//
// protected ISourceViewer createSourceViewer(Composite parent,
// IVerticalRuler ruler, int styles) {
// ISourceViewer viewer = new ProjectionViewer(parent, ruler,
// getOverviewRuler(), isOverviewRulerVisible(), styles);
//
// // ensure decoration support has been created and configured.
// getSourceViewerDecorationSupport(viewer);
//
// return viewer;
// }
// -- ISelectionChangedListener implementation -----------------------------
/**
* @param mainComposite
* This creates the horizontal ruler and adds it to the top of the editor
*/
private void createHorizontalRuler(Composite mainComposite) {
GC gc = new GC(getSourceViewer().getTextWidget());
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.heightHint = gc.getFontMetrics().getHeight();
gc.dispose();
fHRuler = new FortranFreeFormHorizontalRuler(getVerticalRuler(), mainComposite);
fHRuler.setFont(getSourceViewer().getTextWidget().getFont());
fHRuler.setSourceViewer(getSourceViewer());
fHRuler.setLayoutData(data);
fHRuler.moveAbove(null);
}
}