1 package net.sourceforge.phpeclipse.phpeditor;
3 /**********************************************************************
4 Copyright (c) 2000, 2002 IBM Corp. and others.
5 All rights reserved. This program and the accompanying materials
6 are made available under the terms of the Common Public License v1.0
7 which accompanies this distribution, and is available at
8 http://www.eclipse.org/legal/cpl-v10.html
11 IBM Corporation - Initial implementation
12 Klaus Hartlage - www.eclipseproject.de
13 **********************************************************************/
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.Comparator;
18 import java.util.List;
20 import org.eclipse.jface.text.BadLocationException;
21 import org.eclipse.jface.text.BadPositionCategoryException;
22 import org.eclipse.jface.text.DefaultPositionUpdater;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IPositionUpdater;
25 import org.eclipse.jface.text.Position;
26 import org.eclipse.jface.viewers.ISelection;
27 import org.eclipse.jface.viewers.IStructuredSelection;
28 import org.eclipse.jface.viewers.ITreeContentProvider;
29 import org.eclipse.jface.viewers.LabelProvider;
30 import org.eclipse.jface.viewers.SelectionChangedEvent;
31 import org.eclipse.jface.viewers.TreeViewer;
32 import org.eclipse.jface.viewers.Viewer;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.ui.texteditor.IDocumentProvider;
36 import org.eclipse.ui.texteditor.ITextEditor;
37 import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
40 * A content outline page which always represents the functions of the
41 * connected PHPEditor.
43 public class PHPContentOutlinePage extends ContentOutlinePage {
48 protected static class Segment {
50 public Position position;
52 public Segment(String name, Position position) {
54 this.position = position;
57 public String toString() {
62 protected static class SegmentComparator implements Comparator {
63 public int compare(Object o1, Object o2) {
64 return ((Segment)o1).name.compareToIgnoreCase(((Segment)o2).name);
69 * Divides the editor's document into ten segments and provides elements for them.
71 protected class ContentProvider implements ITreeContentProvider {
73 protected final static String SEGMENTS = "__php_segments"; //$NON-NLS-1$
74 protected IPositionUpdater fPositionUpdater = new DefaultPositionUpdater(SEGMENTS);
75 protected List fContent = new ArrayList(10);
76 protected List fVariables = new ArrayList(100);
78 private String getIdentifier(String text, int firstIndex) {
81 int textLength = text.length();
82 StringBuffer identifier = new StringBuffer();
83 while (i < textLength) {
85 if (Character.isJavaIdentifierPart(c) || (c=='$')) {
87 } else if ( (i==firstIndex+1) && (c=='$')) {
90 return identifier.toString();
96 protected void parse(IDocument document) {
98 int lines = document.getNumberOfLines();
99 int increment = Math.max(Math.round((float) (lines / 10)), 10);
101 String text = document.get();
104 // lastIndex = text.indexOf("function ", lastIndex);
105 // while (lastIndex > 0) {
108 // i = lastIndex + 9;
109 // while ((i < text.length()) && Character.isJavaIdentifierPart(text.charAt(i))) {
112 // Position p = new Position(lastIndex, i - lastIndex);
113 // document.addPosition(SEGMENTS, p);
114 // fContent.add(new Segment(text.substring(lastIndex, i), p));
115 // // MessageFormat.format("function", new Object[] { new Integer(lastIndex)}), p)); //$NON-NLS-1$
116 // lastIndex = text.indexOf("function", lastIndex + 1);
117 // } catch (BadLocationException e) {
118 // } catch (BadPositionCategoryException e) {
123 boolean lineCommentMode = false;
124 boolean multiLineCommentMode = false;
125 boolean stringMode = false;
126 boolean functionMode = false;
131 int textLength = text.length() - 10;
132 while (i < textLength) {
133 c = text.charAt(i++);
135 lineCommentMode = false;
136 // read until end of line
137 } else if (c == '#') {
138 // read until end of line
139 lineCommentMode = true;
141 } else if (c == '/') {
142 c2 = text.charAt(i++);
144 lineCommentMode = true;
146 } else if (c2 == '*') {
147 multiLineCommentMode = true;
152 } else if (c == '*' && multiLineCommentMode) {
153 c2 = text.charAt(i++);
155 multiLineCommentMode = false;
160 } else if (c == '\\' && stringMode) {
161 c2 = text.charAt(i++);
167 } else if (c == '"') {
175 if (lineCommentMode || multiLineCommentMode || stringMode) {
179 if (functionMode && Character.isJavaIdentifierPart((char) c)) {
180 functionMode = false;
182 identifier = getIdentifier(text, lastIndex);
184 i += identifier.length()-1;
185 Position p = new Position(lastIndex, i - lastIndex);
186 document.addPosition(SEGMENTS, p);
187 fContent.add(new Segment(text.substring(lastIndex, i), p));
188 // MessageFormat.format("function", new Object[] { new Integer(lastIndex)}), p)); //$NON-NLS-1$
189 // lastIndex = text.indexOf("function", lastIndex + 1);
190 } catch (BadLocationException e) {
191 } catch (BadPositionCategoryException e) {
194 } else if (c == 'f') {
195 identifier = getIdentifier(text, i - 1);
196 if (identifier.equals("function")) {
200 } else if (c == '$') {
201 // get the variable name
202 identifier = getIdentifier(text, i - 1);
203 fVariables.add( identifier );
207 Collections.sort(fContent, new SegmentComparator());
208 Collections.sort(fVariables);
210 // for (int line = 0; line < lines; line += increment) {
212 // int length = increment;
213 // if (line + increment > lines)
214 // length = lines - line;
218 // int offset = document.getLineOffset(line);
219 // int end = document.getLineOffset(line + length);
220 // length = end - offset;
221 // Position p = new Position(offset, length);
222 // document.addPosition(SEGMENTS, p);
223 // fContent.add(new Segment(MessageFormat.format(PHPEditorMessages.getString("OutlinePage.segment.title_pattern"), new Object[] { new Integer(offset)}), p)); //$NON-NLS-1$
225 // } catch (BadPositionCategoryException x) {
226 // } catch (BadLocationException x) {
232 * @see IContentProvider#inputChanged(Viewer, Object, Object)
234 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
235 if (oldInput != null) {
236 IDocument document = fDocumentProvider.getDocument(oldInput);
237 if (document != null) {
239 document.removePositionCategory(SEGMENTS);
240 } catch (BadPositionCategoryException x) {
242 document.removePositionUpdater(fPositionUpdater);
249 if (newInput != null) {
250 IDocument document = fDocumentProvider.getDocument(newInput);
251 if (document != null) {
252 document.addPositionCategory(SEGMENTS);
253 document.addPositionUpdater(fPositionUpdater);
261 * @see IContentProvider#dispose
263 public void dispose() {
264 if (fContent != null) {
268 if (fVariables != null) {
275 * @see IContentProvider#isDeleted(Object)
277 public boolean isDeleted(Object element) {
282 * @see IStructuredContentProvider#getElements(Object)
284 public Object[] getElements(Object element) {
285 return fContent.toArray();
289 * returns all PHP variables
291 public Object[] getVariables() {
292 return fVariables.toArray();
295 * @see ITreeContentProvider#hasChildren(Object)
297 public boolean hasChildren(Object element) {
298 return element == fInput;
302 * @see ITreeContentProvider#getParent(Object)
304 public Object getParent(Object element) {
305 if (element instanceof Segment)
311 * @see ITreeContentProvider#getChildren(Object)
313 public Object[] getChildren(Object element) {
314 if (element == fInput)
315 return fContent.toArray();
316 return new Object[0];
320 protected Object fInput;
321 protected IDocumentProvider fDocumentProvider;
322 protected ITextEditor fTextEditor;
325 * Creates a content outline page using the given provider and the given editor.
327 public PHPContentOutlinePage(IDocumentProvider provider, ITextEditor editor) {
329 fDocumentProvider = provider;
330 fTextEditor = editor;
334 * Method declared on ContentOutlinePage
336 public void createControl(Composite parent) {
338 super.createControl(parent);
340 TreeViewer viewer = getTreeViewer();
341 viewer.setContentProvider(new ContentProvider());
342 viewer.setLabelProvider(new LabelProvider());
343 viewer.addSelectionChangedListener(this);
346 viewer.setInput(fInput);
350 * Method declared on ContentOutlinePage
352 public void selectionChanged(SelectionChangedEvent event) {
354 super.selectionChanged(event);
356 ISelection selection = event.getSelection();
357 if (selection.isEmpty())
358 fTextEditor.resetHighlightRange();
360 Segment segment = (Segment) ((IStructuredSelection) selection).getFirstElement();
361 int start = segment.position.getOffset();
362 int length = segment.position.getLength();
364 fTextEditor.setHighlightRange(start, length, true);
365 } catch (IllegalArgumentException x) {
366 fTextEditor.resetHighlightRange();
372 * Sets the input of the outline page
374 public void setInput(Object input) {
380 * Updates the outline page.
382 public void update() {
383 TreeViewer viewer = getTreeViewer();
385 if (viewer != null) {
386 Control control = viewer.getControl();
387 if (control != null && !control.isDisposed()) {
388 control.setRedraw(false);
389 viewer.setInput(fInput);
391 control.setRedraw(true);