[Pydev-cvs] org.python.pydev/src/org/python/pydev/editor/codefolding PyEditProjection.java,NONE,1.1
Brought to you by:
fabioz
From: Fabio Z. <fa...@us...> - 2004-07-19 17:59:51
|
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/codefolding In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13181/src/org/python/pydev/editor/codefolding Added Files: PyEditProjection.java PyProjectionAnnotation.java CodeFoldingSetter.java Log Message: Code folding capabilities added. --- NEW FILE: PyEditProjection.java --- /* * Created on Jul 19, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codefolding; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; 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.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.editors.text.TextEditor; import org.python.pydev.parser.IParserListener; /** * @author Fabio Zadrozny * * The code below has been implemented after the following build notes: * * http://download2.eclipse.org/downloads/drops/S-3.0M9-200405211200/buildnotes/buildnotes_text.html */ public abstract class PyEditProjection extends TextEditor implements IParserListener { private ProjectionSupport fProjectionSupport; /* * (non-Javadoc) * * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, * org.eclipse.jface.text.source.IVerticalRuler, int) */ protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { return new ProjectionViewer(parent, ruler, getOverviewRuler(), true, styles); } public void createPartControl(Composite parent) { super.createPartControl(parent); try { 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 .setHoverControlCreator(new IInformationControlCreator() { public IInformationControl createInformationControl( Shell shell) { return new DefaultInformationControl(shell); } }); fProjectionSupport.install(); if (isFoldingEnabled()) projectionViewer.doOperation(ProjectionViewer.TOGGLE); } catch (Exception e) { e.printStackTrace(); } } /** * @return */ private boolean isFoldingEnabled() { // TODO Auto-generated method stub return true; } public Object getAdapter(Class required) { if (fProjectionSupport != null) { Object adapter = fProjectionSupport.getAdapter(getSourceViewer(), required); if (adapter != null) return adapter; } return super.getAdapter(required); } } --- NEW FILE: PyProjectionAnnotation.java --- /* * Created on Jul 19, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codefolding; import org.eclipse.jface.text.source.projection.ProjectionAnnotation; import org.python.pydev.editor.model.AbstractNode; /** * This class was created so that we can check if some annotation reappears * (if this happens, we don't want to delete it). * * @author Fabio Zadrozny */ public class PyProjectionAnnotation extends ProjectionAnnotation{ public AbstractNode node; public PyProjectionAnnotation(AbstractNode node){ this.node = node; } /** * @param node2 * @return */ public boolean appearsSame(AbstractNode node2) { if(node2.getClass().equals(node.getClass()) == false) return false; if(getCompleteName(node2).equals(getCompleteName(node)) == false) return false; return true; } /** * @param node2 */ private String getCompleteName(AbstractNode node2) { String ret = node2.getName(); while(node2.getParent() != null){ ret = node2.getParent().getName() + "."+ ret; node2 = node2.getParent(); } return ret; } } --- NEW FILE: CodeFoldingSetter.java --- /* * Created on Jul 19, 2004 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codefolding; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.projection.ProjectionAnnotation; import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; import org.eclipse.ui.editors.text.TextEditor; import org.python.pydev.editor.model.AbstractNode; import org.python.pydev.editor.model.ClassNode; import org.python.pydev.editor.model.FunctionNode; import org.python.pydev.editor.model.IModelListener; import org.python.pydev.editor.model.ModelUtils; /** * @author Fabio Zadrozny * * This class is used to set the code folding markers. */ public class CodeFoldingSetter implements IModelListener { private TextEditor editor; public CodeFoldingSetter(TextEditor editor) { this.editor = editor; } /* * (non-Javadoc) * * @see org.python.pydev.editor.model.IModelListener#modelChanged(org.python.pydev.editor.model.AbstractNode) */ public void modelChanged(AbstractNode root) { IAnnotationModel model = (IAnnotationModel) editor .getAdapter(ProjectionAnnotationModel.class); try{ if (model != null) { ArrayList collapsed = new ArrayList(); //put annotations in array list. Iterator iter = model.getAnnotationIterator(); while ( iter != null && iter.hasNext()) { PyProjectionAnnotation element = (PyProjectionAnnotation) iter.next(); collapsed.add(element); } //(re) insert annotations. AbstractNode current = ModelUtils.getNextNode(root); while (current != null) { if (current instanceof FunctionNode || current instanceof ClassNode) { addFoldingMark(current, model, collapsed); } current = ModelUtils.getNextNode(current); } //remove the annotations that have not been reinserted. for (Iterator it = collapsed.iterator(); it.hasNext();) { PyProjectionAnnotation element = (PyProjectionAnnotation) it.next(); model.removeAnnotation(element); } } }catch (Exception e) { e.printStackTrace(); } } /** * @param node * @param model * @throws BadLocationException */ private void addFoldingMark(AbstractNode node, IAnnotationModel model, ArrayList collapsed) throws BadLocationException { int start = node.getStart().line; int end = start; int size = node.getChildren().size(); if(size > 0){ end = ((AbstractNode)node.getChildren().get(size-1)).getScope().getEnd().line+1; }else{ throw new BadLocationException("Invalid location"); } try { IDocument document = editor.getDocumentProvider().getDocument( editor.getEditorInput()); int offset = document.getLineOffset(start); int endOffset = document.getLineOffset(end); Position position = new Position(offset, endOffset - offset); model.addAnnotation(getAnnotationToAdd(position, node, model, collapsed), position); } catch (BadLocationException x) { x.printStackTrace(); } } /** * We have to be careful not to remove collapsed annotations because if this happens, * previous code folding is not correct. * * @param position * @param node * @param model * @param collapsed * @return */ private ProjectionAnnotation getAnnotationToAdd(Position position, AbstractNode node, IAnnotationModel model, ArrayList collapsed){ for (Iterator iter = collapsed.iterator(); iter.hasNext();) { PyProjectionAnnotation element = (PyProjectionAnnotation) iter.next(); if (element.appearsSame(node)){ collapsed.remove(element); //after getting it, remove it, so we don't accidentally get it again. return element; } } return new PyProjectionAnnotation(node ); } } |