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 {
44 private static final String ERROR = "error"; //$NON-NLS-1$
45 private static final String WARNING = "warning"; //$NON-NLS-1$
49 protected static class Segment {
51 public Position position;
53 public Segment(String name, Position position) {
55 this.position = position;
58 public String toString() {
63 protected static class SegmentComparator implements Comparator {
64 public int compare(Object o1, Object o2) {
65 return ((Segment) o1).name.compareToIgnoreCase(((Segment) o2).name);
70 * Divides the editor's document into ten segments and provides elements for them.
72 protected class ContentProvider implements ITreeContentProvider {
74 protected final static String SEGMENTS = "__php_segments"; //$NON-NLS-1$
75 protected IPositionUpdater fPositionUpdater = new DefaultPositionUpdater(SEGMENTS);
76 protected List fContent = new ArrayList(10);
77 protected List fVariables = new ArrayList(100);
79 private String getIdentifier(String text, int firstIndex) {
82 int textLength = text.length();
83 StringBuffer identifier = new StringBuffer();
84 while (i < textLength) {
86 if (Character.isJavaIdentifierPart(c) || (c == '$')) {
88 } else if ((i == firstIndex + 1) && (c == '$')) {
91 return identifier.toString();
97 protected void parse(IDocument document) {
99 int lines = document.getNumberOfLines();
100 int increment = Math.max(Math.round((float) (lines / 10)), 10);
102 String text = document.get();
105 // lastIndex = text.indexOf("function ", lastIndex);
106 // while (lastIndex > 0) {
109 // i = lastIndex + 9;
110 // while ((i < text.length()) && Character.isJavaIdentifierPart(text.charAt(i))) {
113 // Position p = new Position(lastIndex, i - lastIndex);
114 // document.addPosition(SEGMENTS, p);
115 // fContent.add(new Segment(text.substring(lastIndex, i), p));
116 // // MessageFormat.format("function", new Object[] { new Integer(lastIndex)}), p)); //$NON-NLS-1$
117 // lastIndex = text.indexOf("function", lastIndex + 1);
118 // } catch (BadLocationException e) {
119 // } catch (BadPositionCategoryException e) {
124 boolean lineCommentMode = false;
125 boolean multiLineCommentMode = false;
126 boolean stringMode = false;
127 boolean functionMode = false;
132 int textLength = text.length() - 10;
133 while (i < textLength) {
134 c = text.charAt(i++);
136 lineCommentMode = false;
137 // read until end of line
138 } else if (c == '#') {
139 // read until end of line
140 lineCommentMode = true;
142 } else if (c == '/') {
143 c2 = text.charAt(i++);
145 lineCommentMode = true;
147 } else if (c2 == '*') {
148 multiLineCommentMode = true;
153 } else if (c == '*' && multiLineCommentMode) {
154 c2 = text.charAt(i++);
156 multiLineCommentMode = false;
161 } else if (c == '\\' && stringMode) {
162 c2 = text.charAt(i++);
168 } else if (c == '"') {
176 if (lineCommentMode || multiLineCommentMode || stringMode) {
180 if (functionMode && Character.isJavaIdentifierPart((char) c)) {
181 functionMode = false;
183 identifier = getIdentifier(text, lastIndex);
185 i += identifier.length() - 1;
186 Position p = new Position(lastIndex, i - lastIndex);
187 document.addPosition(SEGMENTS, p);
188 fContent.add(new Segment(text.substring(lastIndex, i), p));
189 // MessageFormat.format("function", new Object[] { new Integer(lastIndex)}), p)); //$NON-NLS-1$
190 // lastIndex = text.indexOf("function", lastIndex + 1);
191 } catch (BadLocationException e) {
192 } catch (BadPositionCategoryException e) {
195 } else if (c == 'f') {
196 identifier = getIdentifier(text, i - 1);
197 if (identifier.equals("function")) {
201 } else if (c == '$') {
202 // get the variable name
203 identifier = getIdentifier(text, i - 1);
204 fVariables.add(identifier);
208 Collections.sort(fContent, new SegmentComparator());
209 Collections.sort(fVariables);
211 // for (int line = 0; line < lines; line += increment) {
213 // int length = increment;
214 // if (line + increment > lines)
215 // length = lines - line;
219 // int offset = document.getLineOffset(line);
220 // int end = document.getLineOffset(line + length);
221 // length = end - offset;
222 // Position p = new Position(offset, length);
223 // document.addPosition(SEGMENTS, p);
224 // fContent.add(new Segment(MessageFormat.format(PHPEditorMessages.getString("OutlinePage.segment.title_pattern"), new Object[] { new Integer(offset)}), p)); //$NON-NLS-1$
226 // } catch (BadPositionCategoryException x) {
227 // } catch (BadLocationException x) {
233 * @see IContentProvider#inputChanged(Viewer, Object, Object)
235 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
236 if (oldInput != null) {
237 IDocument document = fDocumentProvider.getDocument(oldInput);
238 if (document != null) {
240 document.removePositionCategory(SEGMENTS);
241 } catch (BadPositionCategoryException x) {
243 document.removePositionUpdater(fPositionUpdater);
250 if (newInput != null) {
251 IDocument document = fDocumentProvider.getDocument(newInput);
252 if (document != null) {
253 document.addPositionCategory(SEGMENTS);
254 document.addPositionUpdater(fPositionUpdater);
262 * @see IContentProvider#dispose
264 public void dispose() {
265 if (fContent != null) {
269 if (fVariables != null) {
276 * @see IContentProvider#isDeleted(Object)
278 public boolean isDeleted(Object element) {
283 * @see IStructuredContentProvider#getElements(Object)
285 public Object[] getElements(Object element) {
286 return fContent.toArray();
290 * returns all PHP variables
292 public Object[] getVariables() {
293 return fVariables.toArray();
296 * @see ITreeContentProvider#hasChildren(Object)
298 public boolean hasChildren(Object element) {
299 return element == fInput;
303 * @see ITreeContentProvider#getParent(Object)
305 public Object getParent(Object element) {
306 if (element instanceof Segment)
312 * @see ITreeContentProvider#getChildren(Object)
314 public Object[] getChildren(Object element) {
315 if (element == fInput)
316 return fContent.toArray();
317 return new Object[0];
321 protected Object fInput;
322 protected IDocumentProvider fDocumentProvider;
323 protected ITextEditor fTextEditor;
326 * Creates a content outline page using the given provider and the given editor.
328 public PHPContentOutlinePage(IDocumentProvider provider, ITextEditor editor) {
330 fDocumentProvider = provider;
331 fTextEditor = editor;
335 * Method declared on ContentOutlinePage
337 public void createControl(Composite parent) {
339 super.createControl(parent);
341 TreeViewer viewer = getTreeViewer();
342 viewer.setContentProvider(new ContentProvider());
343 viewer.setLabelProvider(new LabelProvider());
344 viewer.addSelectionChangedListener(this);
347 viewer.setInput(fInput);
351 * Method declared on ContentOutlinePage
353 public void selectionChanged(SelectionChangedEvent event) {
355 super.selectionChanged(event);
357 ISelection selection = event.getSelection();
358 if (selection.isEmpty())
359 fTextEditor.resetHighlightRange();
361 Segment segment = (Segment) ((IStructuredSelection) selection).getFirstElement();
362 int start = segment.position.getOffset();
363 int length = segment.position.getLength();
365 fTextEditor.setHighlightRange(start, length, true);
366 } catch (IllegalArgumentException x) {
367 fTextEditor.resetHighlightRange();
373 * Sets the input of the outline page
375 public void setInput(Object input) {
381 * Updates the outline page.
383 public void update() {
384 TreeViewer viewer = getTreeViewer();
386 if (viewer != null) {
387 Control control = viewer.getControl();
388 if (control != null && !control.isDisposed()) {
389 control.setRedraw(false);
390 viewer.setInput(fInput);
392 control.setRedraw(true);