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