Tet for Bugs item #690938
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPContentOutlinePage.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
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
9
10 Contributors:
11     IBM Corporation - Initial implementation
12     Klaus Hartlage - www.eclipseproject.de
13 **********************************************************************/
14
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.Comparator;
18 import java.util.List;
19 import java.util.TreeSet;
20
21 import net.sourceforge.phpdt.internal.compiler.parser.PHPOutlineInfo;
22 import net.sourceforge.phpdt.internal.compiler.parser.Parser;
23 import net.sourceforge.phpdt.internal.compiler.parser.PHPSegment;
24 import net.sourceforge.phpdt.internal.compiler.parser.PHPSegmentWithChildren;
25 import net.sourceforge.phpdt.internal.ui.viewsupport.ImageDescriptorRegistry;
26 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
27
28 import org.eclipse.jface.resource.ImageDescriptor;
29 import org.eclipse.jface.text.BadPositionCategoryException;
30 import org.eclipse.jface.text.DefaultPositionUpdater;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IPositionUpdater;
33 import org.eclipse.jface.viewers.ISelection;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.jface.viewers.ITreeContentProvider;
36 import org.eclipse.jface.viewers.LabelProvider;
37 import org.eclipse.jface.viewers.SelectionChangedEvent;
38 import org.eclipse.jface.viewers.TreeViewer;
39 import org.eclipse.jface.viewers.Viewer;
40 import org.eclipse.swt.graphics.Image;
41 import org.eclipse.swt.widgets.Composite;
42 import org.eclipse.swt.widgets.Control;
43 import org.eclipse.ui.texteditor.IDocumentProvider;
44 import org.eclipse.ui.texteditor.ITextEditor;
45 import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
46
47 /**
48  * A content outline page which always represents the functions of the
49  * connected PHPEditor.
50  */
51 public class PHPContentOutlinePage extends ContentOutlinePage {
52   private static final String ERROR = "error"; //$NON-NLS-1$
53   private static final String WARNING = "warning"; //$NON-NLS-1$
54
55   protected static class SegmentComparator implements Comparator {
56     public int compare(Object o1, Object o2) {
57       if (o1 instanceof PHPSegmentWithChildren && !(o2 instanceof PHPSegmentWithChildren)) {
58         return 1;
59       }
60       if (o2 instanceof PHPSegmentWithChildren && !(o1 instanceof PHPSegmentWithChildren)) {
61         return -1;
62       }
63       return ((PHPSegment) o1).toString().compareToIgnoreCase(((PHPSegment) o2).toString());
64     }
65   }
66
67   /**
68    * Divides the editor's document into ten segments and provides elements for them.
69    */
70   protected class ContentProvider implements ITreeContentProvider {
71
72     protected final static String SEGMENTS = "__php_segments"; //$NON-NLS-1$
73     protected IPositionUpdater fPositionUpdater = new DefaultPositionUpdater(SEGMENTS);
74     protected List fContent = new ArrayList(10);
75     protected TreeSet fVariables = new TreeSet();
76
77     //    private String getIdentifier(String text, int firstIndex) {
78     //      int i = firstIndex;
79     //      char c;
80     //      int textLength = text.length();
81     //      StringBuffer identifier = new StringBuffer();
82     //      while (i < textLength) {
83     //        c = text.charAt(i++);
84     //        if (Character.isJavaIdentifierPart(c) || (c == '$')) {
85     //          identifier.append(c);
86     //        } else if ((i == firstIndex + 1) && (c == '$')) {
87     //          identifier.append(c);
88     //        } else {
89     //          return identifier.toString();
90     //        }
91     //      }
92     //      return null;
93     //    }
94
95     protected void parse(IDocument document) {
96
97       //      int lines = document.getNumberOfLines();
98       //      int increment = Math.max(Math.round((float) (lines / 10)), 10);
99
100       String name;
101       int index;
102       String text = document.get();
103       Parser parser = new Parser(null);
104
105       PHPOutlineInfo outlineInfo = parser.parseInfo(fInput, text);
106       fVariables = outlineInfo.getVariables();
107
108       PHPSegmentWithChildren declarations = outlineInfo.getDeclarations();
109       PHPSegment temp;
110       for (int i = 0; i < declarations.size(); i++) {
111         temp = declarations.get(i);
112         fContent.add(temp);
113       }
114       Collections.sort(fContent, new SegmentComparator());
115
116     }
117
118     /*
119      * @see IContentProvider#inputChanged(Viewer, Object, Object)
120      */
121     public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
122       if (oldInput != null) {
123         IDocument document = fDocumentProvider.getDocument(oldInput);
124         if (document != null) {
125           try {
126             document.removePositionCategory(SEGMENTS);
127           } catch (BadPositionCategoryException x) {
128           }
129           document.removePositionUpdater(fPositionUpdater);
130         }
131       }
132
133       fContent.clear();
134       fVariables.clear();
135
136       if (newInput != null) {
137         IDocument document = fDocumentProvider.getDocument(newInput);
138         if (document != null) {
139           document.addPositionCategory(SEGMENTS);
140           document.addPositionUpdater(fPositionUpdater);
141
142           parse(document);
143         }
144       }
145     }
146
147     /*
148      * @see IContentProvider#dispose
149      */
150     public void dispose() {
151       if (fContent != null) {
152         fContent.clear();
153         fContent = null;
154       }
155       if (fVariables != null) {
156         fVariables.clear();
157         fVariables = null;
158       }
159     }
160
161     /*
162      * @see IContentProvider#isDeleted(Object)
163      */
164     public boolean isDeleted(Object element) {
165       return false;
166     }
167
168     /**
169      * returns all PHP variables
170      */
171     public Object[] getVariables() {
172       return fVariables.toArray();
173     }
174
175     /*
176      * @see IStructuredContentProvider#getElements(Object)
177      */
178     public Object[] getElements(Object element) {
179       return fContent.toArray();
180     }
181
182     /*
183      * @see ITreeContentProvider#hasChildren(Object)
184      */
185     public boolean hasChildren(Object element) {
186       if (element instanceof PHPSegmentWithChildren) {
187         return !((PHPSegmentWithChildren) element).getList().isEmpty();
188       }
189       return element == fInput;
190     }
191
192     /*
193      * @see ITreeContentProvider#getParent(Object)
194      */
195     public Object getParent(Object element) {
196       if (element instanceof PHPSegment) {
197         return ((PHPSegment) element).getParent();
198       }
199       return null;
200     }
201
202     /*
203      * @see ITreeContentProvider#getChildren(Object)
204      */
205     public Object[] getChildren(Object element) {
206       if (element == fInput)
207         return fContent.toArray();
208       if (element instanceof PHPSegmentWithChildren)
209         return ((PHPSegmentWithChildren) element).getList().toArray();
210       return new Object[0];
211     }
212   };
213
214   protected class OutlineLabelProvider extends LabelProvider {
215     private ImageDescriptorRegistry fRegistry;
216
217     public OutlineLabelProvider() {
218       fRegistry = PHPeclipsePlugin.getImageDescriptorRegistry();
219       ;
220     }
221     /**
222     * The <code>LabelProvider</code> implementation of this 
223     * <code>ILabelProvider</code> method returns <code>null</code>. Subclasses may 
224     * override.
225     */
226     public Image getImage(Object element) {
227       if (element instanceof PHPSegment) {
228         ImageDescriptor descriptor = ((PHPSegment) element).getImage();
229         return fRegistry.get(descriptor);
230       }
231       return null;
232     }
233   }
234
235   protected Object fInput;
236   protected IDocumentProvider fDocumentProvider;
237   protected ITextEditor fTextEditor;
238   protected PHPEditor fEditor;
239   protected ContentProvider contentProvider;
240
241   /**
242    * Creates a content outline page using the given provider and the given editor.
243    */
244   public PHPContentOutlinePage(IDocumentProvider provider, ITextEditor editor) {
245     super();
246     contentProvider = null;
247     fDocumentProvider = provider;
248     fTextEditor = editor;
249     if (editor instanceof PHPEditor)
250       fEditor = (PHPEditor) editor;
251   }
252
253   /* (non-Javadoc)
254    * Method declared on ContentOutlinePage
255    */
256   public void createControl(Composite parent) {
257
258     super.createControl(parent);
259
260     TreeViewer viewer = getTreeViewer();
261
262     contentProvider = new ContentProvider();
263     viewer.setContentProvider(contentProvider);
264     viewer.setLabelProvider(new OutlineLabelProvider());
265
266     viewer.addSelectionChangedListener(this);
267
268     if (fInput != null)
269       viewer.setInput(fInput);
270   }
271
272   /* (non-Javadoc)
273    * Method declared on ContentOutlinePage
274    */
275   public void selectionChanged(SelectionChangedEvent event) {
276
277     super.selectionChanged(event);
278
279     ISelection selection = event.getSelection();
280     if (selection.isEmpty())
281       fTextEditor.resetHighlightRange();
282     else {
283       PHPSegment segment = (PHPSegment) ((IStructuredSelection) selection).getFirstElement();
284       int start = segment.getPosition().getOffset();
285       int length = segment.getPosition().getLength();
286       try {
287         fTextEditor.setHighlightRange(start, length, true);
288       } catch (IllegalArgumentException x) {
289         fTextEditor.resetHighlightRange();
290       }
291     }
292   }
293
294   /**
295    * Sets the input of the outline page
296    */
297   public void setInput(Object input) {
298     fInput = input;
299     update();
300   }
301
302   /**
303    * Updates the outline page.
304    */
305   public void update() {
306     TreeViewer viewer = getTreeViewer();
307
308     if (viewer != null) {
309       Control control = viewer.getControl();
310       if (control != null && !control.isDisposed()) {
311         control.setRedraw(false);
312         viewer.setInput(fInput);
313         viewer.expandAll();
314         control.setRedraw(true);
315       }
316     }
317   }
318   
319   public Object[] getVariables() {
320     if (contentProvider != null) {
321       return contentProvider.getVariables();
322     }
323     return null;
324   }
325   //  public ContentProvider getContentProvider() {
326   //    return contentProvider;
327   //  }
328
329 }