diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java | 375 |
1 files changed, 0 insertions, 375 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java deleted file mode 100644 index 4e4429dc8..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.editors.layout; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.resources.ResourceFile; -import com.android.ide.common.resources.ResourceFolder; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IResourceEventListener; -import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; -import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager.IResourceListener; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceType; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.runtime.CoreException; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * Monitor for file changes that could trigger a layout redraw, or a UI update - */ -public final class LayoutReloadMonitor { - - // singleton, enforced by private constructor. - private final static LayoutReloadMonitor sThis = new LayoutReloadMonitor(); - - /** - * Map of listeners by IProject. - */ - private final Map<IProject, List<ILayoutReloadListener>> mListenerMap = - new HashMap<IProject, List<ILayoutReloadListener>>(); - - public final static class ChangeFlags { - public boolean code = false; - /** any non-layout resource changes */ - public boolean resources = false; - public boolean rClass = false; - public boolean localeList = false; - public boolean manifest = false; - - boolean isAllTrue() { - return code && resources && rClass && localeList && manifest; - } - } - - /** - * List of projects having received a resource change. - */ - private final Map<IProject, ChangeFlags> mProjectFlags = new HashMap<IProject, ChangeFlags>(); - - /** - * Classes which implement this interface provide a method to respond to resource changes - * triggering a layout redraw - */ - public interface ILayoutReloadListener { - /** - * Sent when the layout needs to be redrawn - * - * @param flags a {@link ChangeFlags} object indicating what type of resource changed. - * @param libraryModified <code>true</code> if the changeFlags are not for the project - * associated with the listener, but instead correspond to a library. - */ - void reloadLayout(ChangeFlags flags, boolean libraryModified); - } - - /** - * Returns the single instance of {@link LayoutReloadMonitor}. - */ - public static LayoutReloadMonitor getMonitor() { - return sThis; - } - - private LayoutReloadMonitor() { - // listen to resource changes. Used for non-layout resource (trigger a redraw), or - // any resource folder (trigger a locale list refresh) - ResourceManager.getInstance().addListener(mResourceListener); - - // also listen for .class file changed in case the layout has custom view classes. - GlobalProjectMonitor monitor = GlobalProjectMonitor.getMonitor(); - monitor.addFileListener(mFileListener, - IResourceDelta.ADDED | IResourceDelta.CHANGED | IResourceDelta.REMOVED); - - monitor.addResourceEventListener(mResourceEventListener); - } - - /** - * Adds a listener for a given {@link IProject}. - * @param project - * @param listener - */ - public void addListener(IProject project, ILayoutReloadListener listener) { - synchronized (mListenerMap) { - List<ILayoutReloadListener> list = mListenerMap.get(project); - if (list == null) { - list = new ArrayList<ILayoutReloadListener>(); - mListenerMap.put(project, list); - } - - list.add(listener); - } - } - - /** - * Removes a listener for a given {@link IProject}. - */ - public void removeListener(IProject project, ILayoutReloadListener listener) { - synchronized (mListenerMap) { - List<ILayoutReloadListener> list = mListenerMap.get(project); - if (list != null) { - list.remove(listener); - } - } - } - - /** - * Removes a listener, no matter which {@link IProject} it was associated with. - */ - public void removeListener(ILayoutReloadListener listener) { - synchronized (mListenerMap) { - - for (List<ILayoutReloadListener> list : mListenerMap.values()) { - Iterator<ILayoutReloadListener> it = list.iterator(); - while (it.hasNext()) { - ILayoutReloadListener i = it.next(); - if (i == listener) { - it.remove(); - } - } - } - } - } - - /** - * Implementation of the {@link IFileListener} as an internal class so that the methods - * do not appear in the public API of {@link LayoutReloadMonitor}. - * - * This is only to detect code and manifest change. Resource changes (located in res/) - * is done through {@link #mResourceListener}. - */ - private IFileListener mFileListener = new IFileListener() { - /* - * Callback for IFileListener. Called when a file changed. - * This records the changes for each project, but does not notify listeners. - */ - @Override - public void fileChanged(@NonNull IFile file, @NonNull IMarkerDelta[] markerDeltas, - int kind, @Nullable String extension, int flags, boolean isAndroidProject) { - // This listener only cares about .class files and AndroidManifest.xml files - if (!(SdkConstants.EXT_CLASS.equals(extension) - || SdkConstants.EXT_XML.equals(extension) - && SdkConstants.FN_ANDROID_MANIFEST_XML.equals(file.getName()))) { - return; - } - - // get the file's project - IProject project = file.getProject(); - - if (isAndroidProject) { - // project is an Android project, it's the one being affected - // directly by its own file change. - processFileChanged(file, project, extension); - } else { - // check the projects depending on it, if they are Android project, update them. - IProject[] referencingProjects = project.getReferencingProjects(); - - for (IProject p : referencingProjects) { - try { - boolean hasAndroidNature = p.hasNature(AdtConstants.NATURE_DEFAULT); - if (hasAndroidNature) { - // the changed project is a dependency on an Android project, - // update the main project. - processFileChanged(file, p, extension); - } - } catch (CoreException e) { - // do nothing if the nature cannot be queried. - } - } - } - } - - /** - * Processes a file change for a given project which may or may not be the file's project. - * @param file the changed file - * @param project the project impacted by the file change. - */ - private void processFileChanged(IFile file, IProject project, String extension) { - // if this project has already been marked as modified, we do nothing. - ChangeFlags changeFlags = mProjectFlags.get(project); - if (changeFlags != null && changeFlags.isAllTrue()) { - return; - } - - // here we only care about code change (so change for .class files). - // Resource changes is handled by the IResourceListener. - if (SdkConstants.EXT_CLASS.equals(extension)) { - if (file.getName().matches("R[\\$\\.](.*)")) { - // this is a R change! - if (changeFlags == null) { - changeFlags = new ChangeFlags(); - mProjectFlags.put(project, changeFlags); - } - - changeFlags.rClass = true; - } else { - // this is a code change! - if (changeFlags == null) { - changeFlags = new ChangeFlags(); - mProjectFlags.put(project, changeFlags); - } - - changeFlags.code = true; - } - } else if (SdkConstants.FN_ANDROID_MANIFEST_XML.equals(file.getName()) && - file.getParent().equals(project)) { - // this is a manifest change! - if (changeFlags == null) { - changeFlags = new ChangeFlags(); - mProjectFlags.put(project, changeFlags); - } - - changeFlags.manifest = true; - } - } - }; - - /** - * Implementation of the {@link IResourceEventListener} as an internal class so that the methods - * do not appear in the public API of {@link LayoutReloadMonitor}. - */ - private IResourceEventListener mResourceEventListener = new IResourceEventListener() { - /* - * Callback for ResourceMonitor.IResourceEventListener. Called at the beginning of a - * resource change event. This is called once, while fileChanged can be - * called several times. - * - */ - @Override - public void resourceChangeEventStart() { - // nothing to be done here, it all happens in the resourceChangeEventEnd - } - - /* - * Callback for ResourceMonitor.IResourceEventListener. Called at the end of a resource - * change event. This is where we notify the listeners. - */ - @Override - public void resourceChangeEventEnd() { - // for each IProject that was changed, we notify all the listeners. - for (Entry<IProject, ChangeFlags> entry : mProjectFlags.entrySet()) { - IProject project = entry.getKey(); - - // notify the project itself. - notifyForProject(project, entry.getValue(), false); - - // check if the project is a library, and if it is search for what other - // project depends on this one (directly or not) - ProjectState state = Sdk.getProjectState(project); - if (state != null && state.isLibrary()) { - Set<ProjectState> mainProjects = Sdk.getMainProjectsFor(project); - for (ProjectState mainProject : mainProjects) { - // always give the changeflag of the modified project. - notifyForProject(mainProject.getProject(), entry.getValue(), true); - } - } - } - - // empty the list. - mProjectFlags.clear(); - } - - /** - * Notifies the listeners for a given project. - * @param project the project for which the listeners must be notified - * @param flags the change flags to pass to the listener - * @param libraryChanged a flag indicating if the change flags are for the give project, - * or if they are for a library dependency. - */ - private void notifyForProject(IProject project, ChangeFlags flags, - boolean libraryChanged) { - synchronized (mListenerMap) { - List<ILayoutReloadListener> listeners = mListenerMap.get(project); - - if (listeners != null) { - for (ILayoutReloadListener listener : listeners) { - try { - listener.reloadLayout(flags, libraryChanged); - } catch (Throwable t) { - AdtPlugin.log(t, "Failed to call ILayoutReloadListener.reloadLayout"); - } - } - } - } - } - }; - - /** - * Implementation of the {@link IResourceListener} as an internal class so that the methods - * do not appear in the public API of {@link LayoutReloadMonitor}. - */ - private IResourceListener mResourceListener = new IResourceListener() { - - @Override - public void folderChanged(IProject project, ResourceFolder folder, int eventType) { - // if this project has already been marked as modified, we do nothing. - ChangeFlags changeFlags = mProjectFlags.get(project); - if (changeFlags != null && changeFlags.isAllTrue()) { - return; - } - - // this means a new resource folder was added or removed, which can impact the - // locale list. - if (changeFlags == null) { - changeFlags = new ChangeFlags(); - mProjectFlags.put(project, changeFlags); - } - - changeFlags.localeList = true; - } - - @Override - public void fileChanged(IProject project, ResourceFile file, int eventType) { - // if this project has already been marked as modified, we do nothing. - ChangeFlags changeFlags = mProjectFlags.get(project); - if (changeFlags != null && changeFlags.isAllTrue()) { - return; - } - - // now check that the file is *NOT* a layout file (those automatically trigger a layout - // reload and we don't want to do it twice.) - Collection<ResourceType> resTypes = file.getResourceTypes(); - - // it's unclear why but there has been cases of resTypes being empty! - if (resTypes.size() > 0) { - // this is a resource change, that may require a layout redraw! - if (changeFlags == null) { - changeFlags = new ChangeFlags(); - mProjectFlags.put(project, changeFlags); - } - - changeFlags.resources = true; - } - } - }; -} |