diff options
author | Xavier Ducrohet <xav@android.com> | 2010-03-03 15:12:43 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-03-03 15:12:43 -0800 |
commit | 91ed8175993fb6eca29e5281bf3f7f5b7a3b3ded (patch) | |
tree | bc955a01f5e438e2c085e032706c9bb9cc5e7b4e | |
parent | b49601fcc218467515b028e81a7ddb53a52947d1 (diff) | |
parent | 45a70af18077db8d6822bad3a83e760e98ab5a1d (diff) | |
download | sdk-91ed8175993fb6eca29e5281bf3f7f5b7a3b3ded.zip sdk-91ed8175993fb6eca29e5281bf3f7f5b7a3b3ded.tar.gz sdk-91ed8175993fb6eca29e5281bf3f7f5b7a3b3ded.tar.bz2 |
Merge "ADT: reload layout when resources from libraries change."
4 files changed, 98 insertions, 22 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 index 19f12b7..50d6f8c 100644 --- 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 @@ -16,7 +16,9 @@ package com.android.ide.eclipse.adt.internal.editors.layout; +import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AndroidConstants; +import com.android.ide.eclipse.adt.internal.project.ProjectState; import com.android.ide.eclipse.adt.internal.resources.ResourceType; import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile; @@ -25,6 +27,7 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; 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.IResourceListener; +import com.android.ide.eclipse.adt.internal.sdk.Sdk; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarkerDelta; @@ -36,6 +39,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Map.Entry; /** @@ -54,7 +58,9 @@ public final class LayoutReloadMonitor { public final static class ChangeFlags { public boolean code = false; + /** any non-layout resource changes */ public boolean resources = false; + public boolean layout = false; public boolean rClass = false; public boolean localeList = false; @@ -75,9 +81,12 @@ public final class LayoutReloadMonitor { 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); + void reloadLayout(ChangeFlags flags, boolean libraryModified); } /** @@ -211,16 +220,20 @@ public final class LayoutReloadMonitor { */ public void resourceChangeEventEnd() { // for each IProject that was changed, we notify all the listeners. - synchronized (mListenerMap) { - for (Entry<IProject, ChangeFlags> project : mProjectFlags.entrySet()) { - List<ILayoutReloadListener> listeners = mListenerMap.get(project.getKey()); - - ChangeFlags flags = project.getValue(); - - if (listeners != null) { - for (ILayoutReloadListener listener : listeners) { - listener.reloadLayout(flags); - } + 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.getProject(project); + if (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); } } } @@ -228,6 +241,30 @@ public final class LayoutReloadMonitor { // 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"); + } + } + } + } + } }; /** @@ -266,15 +303,16 @@ public final class LayoutReloadMonitor { // it's unclear why but there has been cases of resTypes being empty! if (resTypes.length > 0) { - // files that generates > 1 types cannot be layout files. - if (resTypes.length > 1 || resTypes[0] != ResourceType.LAYOUT) { - // this is a resource change, that may require a layout redraw! - if (changeFlags == null) { - changeFlags = new ChangeFlags(); - mProjectFlags.put(project, changeFlags); - } + // this is a resource change, that may require a layout redraw! + if (changeFlags == null) { + changeFlags = new ChangeFlags(); + mProjectFlags.put(project, changeFlags); + } + if (resTypes[0] != ResourceType.LAYOUT) { changeFlags.resources = true; + } else { + changeFlags.layout = true; } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle1/GraphicalLayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle1/GraphicalLayoutEditor.java index 5a1f0e6..240d037 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle1/GraphicalLayoutEditor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle1/GraphicalLayoutEditor.java @@ -1136,7 +1136,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette /* * Called when the file changes triggered a redraw of the layout */ - public void reloadLayout(ChangeFlags flags) { + public void reloadLayout(ChangeFlags flags, boolean libraryChanged) { boolean recompute = false; if (flags.rClass) { @@ -1155,7 +1155,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette mParent.getDisplay().asyncExec(mLocaleUpdaterFromUiRunnable); } - if (flags.resources) { + if (flags.resources || (libraryChanged && flags.layout)) { recompute = true; // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java index 900fbc4..b328848 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java @@ -1159,7 +1159,7 @@ public class GraphicalEditorPart extends EditorPart implements IGraphicalLayoutE /* * Called when the file changes triggered a redraw of the layout */ - public void reloadLayout(ChangeFlags flags) { + public void reloadLayout(ChangeFlags flags, boolean libraryChanged) { boolean recompute = false; if (flags.rClass) { @@ -1187,7 +1187,9 @@ public class GraphicalEditorPart extends EditorPart implements IGraphicalLayoutE }); } - if (flags.resources) { + // if a resources was modified. + // also, if a layout in a library was modified. + if (flags.resources || (libraryChanged && flags.layout)) { recompute = true; // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java index b3d4347..4519350 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java @@ -68,6 +68,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.Map.Entry; /** @@ -627,6 +628,41 @@ public final class Sdk { return mLayoutDeviceManager; } + /** + * Returns a list of {@link ProjectState} representing projects depending, directly or + * indirectly on a given library project. + * @param project the library project. + * @return a possibly empty list of ProjectState. + */ + public static Set<ProjectState> getMainProjectsFor(IProject project) { + synchronized (sLock) { + // first get the project directly depending on this. + HashSet<ProjectState> list = new HashSet<ProjectState>(); + + // loop on all project and see if ProjectState.getLibrary returns a non null + // project. + for (Entry<IProject, ProjectState> entry : sProjectStateMap.entrySet()) { + if (project != entry.getKey()) { + LibraryState library = entry.getValue().getLibrary(project); + if (library != null) { + list.add(entry.getValue()); + } + } + } + + // now look for projects depending on the projects directly depending on the library. + HashSet<ProjectState> result = new HashSet<ProjectState>(list); + for (ProjectState p : list) { + if (p.isLibrary()) { + Set<ProjectState> set = getMainProjectsFor(p.getProject()); + result.addAll(set); + } + } + + return result; + } + } + private Sdk(SdkManager manager, AvdManager avdManager) { mManager = manager; mAvdManager = avdManager; |