• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.adt.internal.ui;
18 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.AndroidConstants;
21 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResourceItem;
22 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
23 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
24 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
25 import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IResourceEventListener;
26 import com.android.ide.eclipse.adt.io.IFileWrapper;
27 import com.android.sdklib.io.IAbstractFile;
28 
29 import org.eclipse.core.resources.IFile;
30 import org.eclipse.core.resources.IProject;
31 import org.eclipse.core.resources.IResource;
32 import org.eclipse.core.runtime.CoreException;
33 import org.eclipse.core.runtime.IAdaptable;
34 import org.eclipse.jdt.core.IJavaElement;
35 import org.eclipse.jdt.core.IJavaProject;
36 import org.eclipse.jface.preference.IPreferenceStore;
37 import org.eclipse.jface.viewers.DoubleClickEvent;
38 import org.eclipse.jface.viewers.IDoubleClickListener;
39 import org.eclipse.jface.viewers.ISelection;
40 import org.eclipse.jface.viewers.IStructuredSelection;
41 import org.eclipse.jface.viewers.TreeViewer;
42 import org.eclipse.swt.SWT;
43 import org.eclipse.swt.SWTException;
44 import org.eclipse.swt.events.ControlEvent;
45 import org.eclipse.swt.events.ControlListener;
46 import org.eclipse.swt.layout.GridData;
47 import org.eclipse.swt.widgets.Composite;
48 import org.eclipse.swt.widgets.Tree;
49 import org.eclipse.swt.widgets.TreeColumn;
50 import org.eclipse.ui.IEditorInput;
51 import org.eclipse.ui.IEditorPart;
52 import org.eclipse.ui.IFileEditorInput;
53 import org.eclipse.ui.ISelectionListener;
54 import org.eclipse.ui.IWorkbenchPage;
55 import org.eclipse.ui.IWorkbenchPart;
56 import org.eclipse.ui.PartInitException;
57 import org.eclipse.ui.ide.IDE;
58 import org.eclipse.ui.part.ViewPart;
59 
60 import java.util.Iterator;
61 
62 /**
63  * Resource Explorer View.
64  * <p/>
65  * This contains a basic Tree view, and uses a TreeViewer to handle the data.
66  * <p/>
67  * The view listener to change in selection in the workbench, and update to show the resource
68  * of the project of the current selected item (either item in the package explorer, or of the
69  * current editor).
70  *
71  * @see ResourceContentProvider
72  */
73 public class ResourceExplorerView extends ViewPart implements ISelectionListener,
74         IResourceEventListener {
75 
76     // Note: keep using the obsolete AndroidConstants.EDITORS_NAMESPACE (which used
77     // to be the Editors Plugin ID) to keep existing preferences functional.
78     private final static String PREFS_COLUMN_RES =
79         AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col1"; //$NON-NLS-1$
80     private final static String PREFS_COLUMN_2 =
81         AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col2"; //$NON-NLS-1$
82 
83     private Tree mTree;
84     private TreeViewer mTreeViewer;
85 
86     private IProject mCurrentProject;
87 
ResourceExplorerView()88     public ResourceExplorerView() {
89     }
90 
91     @Override
createPartControl(Composite parent)92     public void createPartControl(Composite parent) {
93         mTree = new Tree(parent, SWT.SINGLE | SWT.VIRTUAL);
94         mTree.setLayoutData(new GridData(GridData.FILL_BOTH));
95         mTree.setHeaderVisible(true);
96         mTree.setLinesVisible(true);
97 
98         final IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
99 
100         // create 2 columns. The main one with the resources, and an "info" column.
101         createTreeColumn(mTree, "Resources", SWT.LEFT,
102                 "abcdefghijklmnopqrstuvwxz", -1, PREFS_COLUMN_RES, store); //$NON-NLS-1$
103         createTreeColumn(mTree, "Info", SWT.LEFT,
104                 "0123456789", -1, PREFS_COLUMN_2, store); //$NON-NLS-1$
105 
106         // create the jface wrapper
107         mTreeViewer = new TreeViewer(mTree);
108 
109         mTreeViewer.setContentProvider(new ResourceContentProvider(true /* fullLevels */));
110         mTreeViewer.setLabelProvider(new ResourceLabelProvider());
111 
112         // listen to selection change in the workbench.
113         IWorkbenchPage page = getSite().getPage();
114 
115         page.addSelectionListener(this);
116 
117         // init with current selection
118         selectionChanged(getSite().getPart(), page.getSelection());
119 
120         // add support for double click.
121         mTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
122             public void doubleClick(DoubleClickEvent event) {
123                 ISelection sel = event.getSelection();
124 
125                 if (sel instanceof IStructuredSelection) {
126                     IStructuredSelection selection = (IStructuredSelection) sel;
127 
128                     if (selection.size() == 1) {
129                         Object element = selection.getFirstElement();
130 
131                         // if it's a resourceFile, we directly open it.
132                         if (element instanceof ResourceFile) {
133                             try {
134                                 IAbstractFile iAbstractFile = ((ResourceFile)element).getFile();
135                                 if (iAbstractFile instanceof IFileWrapper) {
136                                     IDE.openEditor(getSite().getWorkbenchWindow().getActivePage(),
137                                             ((IFileWrapper)iAbstractFile).getIFile());
138                                 }
139                             } catch (PartInitException e) {
140                             }
141                         } else if (element instanceof ProjectResourceItem) {
142                             // if it's a ResourceItem, we open the first file, but only if
143                             // there's no alternate files.
144                             ProjectResourceItem item = (ProjectResourceItem)element;
145 
146                             if (item.isEditableDirectly()) {
147                                 ResourceFile[] files = item.getSourceFileArray();
148                                 if (files[0] != null) {
149                                     try {
150                                         IAbstractFile iAbstractFile = files[0].getFile();
151                                         if (iAbstractFile instanceof IFileWrapper) {
152                                             IDE.openEditor(
153                                                     getSite().getWorkbenchWindow().getActivePage(),
154                                                     ((IFileWrapper)iAbstractFile).getIFile());
155                                         }
156                                     } catch (PartInitException e) {
157                                     }
158                                 }
159                             }
160                         }
161                     }
162                 }
163             }
164         });
165 
166         // set up the resource manager to send us resource change notification
167         AdtPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
168     }
169 
170     @Override
dispose()171     public void dispose() {
172         AdtPlugin.getDefault().getResourceMonitor().removeResourceEventListener(this);
173 
174         super.dispose();
175     }
176 
177     @Override
setFocus()178     public void setFocus() {
179         mTree.setFocus();
180     }
181 
182     /**
183      * Processes a new selection.
184      */
selectionChanged(IWorkbenchPart part, ISelection selection)185     public void selectionChanged(IWorkbenchPart part, ISelection selection) {
186         // first we test if the part is an editor.
187         if (part instanceof IEditorPart) {
188             // if it is, we check if it's a file editor.
189             IEditorInput input = ((IEditorPart)part).getEditorInput();
190 
191             if (input instanceof IFileEditorInput) {
192                 // from the file editor we can get the IFile object, and from it, the IProject.
193                 IFile file = ((IFileEditorInput)input).getFile();
194 
195                 // get the file project
196                 IProject project = file.getProject();
197 
198                 handleProjectSelection(project);
199             }
200         } else if (selection instanceof IStructuredSelection) {
201             // if it's not an editor, we look for structured selection.
202             for (Iterator<?> it = ((IStructuredSelection) selection).iterator();
203                     it.hasNext();) {
204                 Object element = it.next();
205                 IProject project = null;
206 
207                 // if we are in the navigator or package explorer, the selection could contain a
208                 // IResource object.
209                 if (element instanceof IResource) {
210                     project = ((IResource) element).getProject();
211                 } else if (element instanceof IJavaElement) {
212                     // if we are in the package explorer on a java element, we handle that too.
213                     IJavaElement javaElement = (IJavaElement)element;
214                     IJavaProject javaProject = javaElement.getJavaProject();
215                     if (javaProject != null) {
216                         project = javaProject.getProject();
217                     }
218                 } else if (element instanceof IAdaptable) {
219                     // finally we try to get a project object from IAdaptable.
220                     project = (IProject) ((IAdaptable) element)
221                             .getAdapter(IProject.class);
222                 }
223 
224                 // if we found a project, handle it, and return.
225                 if (project != null) {
226                     if (handleProjectSelection(project)) {
227                         return;
228                     }
229                 }
230             }
231         }
232     }
233 
234     /**
235      * Handles a project selection.
236      * @param project the new selected project
237      * @return true if the project could be processed.
238      */
handleProjectSelection(IProject project)239     private boolean handleProjectSelection(IProject project) {
240         try {
241             // if it's an android project, then we get its resources, and feed them
242             // to the tree viewer.
243             if (project.hasNature(AndroidConstants.NATURE_DEFAULT)) {
244                 if (mCurrentProject != project) {
245                     ProjectResources projRes = ResourceManager.getInstance().getProjectResources(
246                             project);
247                     if (projRes != null) {
248                         mTreeViewer.setInput(projRes);
249                         mCurrentProject = project;
250                         return true;
251                     }
252                 }
253             }
254         } catch (CoreException e) {
255         }
256 
257         return false;
258     }
259 
260     /**
261      * Create a TreeColumn with the specified parameters. If a
262      * <code>PreferenceStore</code> object and a preference entry name String
263      * object are provided then the column will listen to change in its width
264      * and update the preference store accordingly.
265      *
266      * @param parent The Table parent object
267      * @param header The header string
268      * @param style The column style
269      * @param sample_text A sample text to figure out column width if preference
270      *            value is missing
271      * @param fixedSize a fixed size. If != -1 the column is non resizable
272      * @param pref_name The preference entry name for column width
273      * @param prefs The preference store
274      */
createTreeColumn(Tree parent, String header, int style, String sample_text, int fixedSize, final String pref_name, final IPreferenceStore prefs)275     public void createTreeColumn(Tree parent, String header, int style,
276             String sample_text, int fixedSize, final String pref_name,
277             final IPreferenceStore prefs) {
278 
279         // create the column
280         TreeColumn col = new TreeColumn(parent, style);
281 
282         if (fixedSize != -1) {
283             col.setWidth(fixedSize);
284             col.setResizable(false);
285         } else {
286             // if there is no pref store or the entry is missing, we use the sample
287             // text and pack the column.
288             // Otherwise we just read the width from the prefs and apply it.
289             if (prefs == null || prefs.contains(pref_name) == false) {
290                 col.setText(sample_text);
291                 col.pack();
292 
293                 // init the prefs store with the current value
294                 if (prefs != null) {
295                     prefs.setValue(pref_name, col.getWidth());
296                 }
297             } else {
298                 col.setWidth(prefs.getInt(pref_name));
299             }
300 
301             // if there is a pref store and a pref entry name, then we setup a
302             // listener to catch column resize to put the new width value into the store.
303             if (prefs != null && pref_name != null) {
304                 col.addControlListener(new ControlListener() {
305                     public void controlMoved(ControlEvent e) {
306                     }
307 
308                     public void controlResized(ControlEvent e) {
309                         // get the new width
310                         int w = ((TreeColumn)e.widget).getWidth();
311 
312                         // store in pref store
313                         prefs.setValue(pref_name, w);
314                     }
315                 });
316             }
317         }
318 
319         // set the header
320         col.setText(header);
321     }
322 
323     /**
324      * Processes a start in a resource event change.
325      */
resourceChangeEventStart()326     public void resourceChangeEventStart() {
327         // pass
328     }
329 
330     /**
331      * Processes the end of a resource change event.
332      */
resourceChangeEventEnd()333     public void resourceChangeEventEnd() {
334         try {
335             mTree.getDisplay().asyncExec(new Runnable() {
336                 public void run() {
337                     if (mTree.isDisposed() == false) {
338                         mTreeViewer.refresh();
339                     }
340                 }
341             });
342         } catch (SWTException e) {
343             // display is disposed. nothing to do.
344         }
345     }
346 }
347