RecentProjectManager -> applicationService

This commit is contained in:
Gregory.Shrago
2014-01-17 18:43:51 +04:00
parent 2d6afbec6e
commit c69719b357
10 changed files with 129 additions and 124 deletions
@@ -21,7 +21,6 @@ import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -34,8 +33,8 @@ import org.jetbrains.annotations.NotNull;
)}
)
public class RecentProjectsManager extends RecentProjectsManagerBase {
public RecentProjectsManager(final ProjectManager projectManager, final MessageBus messageBus) {
super(projectManager, messageBus);
public RecentProjectsManager(MessageBus messageBus) {
super(messageBus);
}
protected String getProjectPath(@NotNull Project project) {
@@ -20,7 +20,6 @@ import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.platform.ModuleAttachProcessor;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -37,8 +36,8 @@ import org.jetbrains.annotations.NotNull;
)}
)
public class RecentDirectoryProjectsManagerEx extends RecentDirectoryProjectsManager {
public RecentDirectoryProjectsManagerEx(ProjectManager projectManager, MessageBus messageBus) {
super(projectManager, messageBus);
public RecentDirectoryProjectsManagerEx(MessageBus messageBus) {
super(messageBus);
}
@NotNull
@@ -20,7 +20,6 @@ import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -42,8 +41,8 @@ import org.jetbrains.annotations.Nullable;
)}
)
public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase {
public RecentDirectoryProjectsManager(ProjectManager projectManager, MessageBus messageBus) {
super(projectManager, messageBus);
public RecentDirectoryProjectsManager(MessageBus messageBus) {
super(messageBus);
}
@Nullable
@@ -21,9 +21,11 @@ import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerAdapter;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
@@ -33,6 +35,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.impl.SystemDock;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -44,16 +47,35 @@ import java.util.*;
/**
* @author yole
*/
public abstract class RecentProjectsManagerBase implements PersistentStateComponent<RecentProjectsManagerBase.State> {
public abstract class RecentProjectsManagerBase implements ProjectManagerListener, PersistentStateComponent<RecentProjectsManagerBase.State> {
public static RecentProjectsManagerBase getInstance() {
return ApplicationManager.getApplication().getComponent(RecentProjectsManagerBase.class);
return ServiceManager.getService(RecentProjectsManagerBase.class);
}
public static class State {
public List<String> recentPaths = new ArrayList<String>();
public List<String> openPaths = new ArrayList<String>();
public Map<String, String> names = new HashMap<String, String>();
public List<String> recentPaths = ContainerUtil.newArrayList();
public List<String> openPaths = ContainerUtil.newArrayList();
public Map<String, String> names = ContainerUtil.newLinkedHashMap();
public String lastPath;
void validateRecentProjects() {
//noinspection StatementWithEmptyBody
while (recentPaths.remove(null)) ;
Collection<String> displayNames = names.values();
//noinspection StatementWithEmptyBody
while (displayNames.remove("")) ;
while (recentPaths.size() > Registry.intValue("ide.max.recent.projects")) {
int index = recentPaths.size() - 1;
names.remove(recentPaths.get(index));
recentPaths.remove(index);
}
}
void removePath(String path) {
recentPaths.remove(path);
names.remove(path);
}
}
private final Object myStateLock = new Object();
@@ -61,14 +83,13 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
private final Map<String, String> myNameCache = Collections.synchronizedMap(new HashMap<String, String>());
public RecentProjectsManagerBase(ProjectManager projectManager, MessageBus messageBus) {
projectManager.addProjectManagerListener(new MyProjectManagerListener());
protected RecentProjectsManagerBase(MessageBus messageBus) {
messageBus.connect().subscribe(AppLifecycleListener.TOPIC, new MyAppLifecycleListener());
}
public State getState() {
synchronized (myStateLock) {
validateRecentProjects();
myState.validateRecentProjects();
return myState;
}
}
@@ -88,37 +109,16 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
}
}
private void validateRecentProjects() {
synchronized (myStateLock) {
for (Iterator i = myState.recentPaths.iterator(); i.hasNext();) {
String s = (String)i.next();
if (s == null) {
i.remove();
}
}
while (myState.recentPaths.size() > Registry.intValue("ide.max.recent.projects")) {
final int index = myState.recentPaths.size() - 1;
myState.names.remove(myState.recentPaths.get(index));
myState.recentPaths.remove(index);
}
}
}
public void removePath(final String path) {
if (path == null) return;
synchronized (myStateLock) {
if (SystemInfo.isFileSystemCaseSensitive) {
myState.recentPaths.remove(path);
myState.names.remove(path);
myState.removePath(path);
}
else {
Iterator<String> i = myState.recentPaths.iterator();
while (i.hasNext()) {
String p = i.next();
for (String p : ArrayUtil.toStringArray(myState.recentPaths)) {
if (path.equalsIgnoreCase(p)) {
myState.names.remove(p);
i.remove();
myState.removePath(path);
}
}
}
@@ -137,13 +137,16 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
if (openProjects.length == 0) {
myState.lastPath = null;
myState.openPaths = Collections.emptyList();
} else {
}
else {
myState.lastPath = getProjectPath(openProjects[openProjects.length - 1]);
myState.openPaths = new ArrayList<String>();
myState.openPaths = ContainerUtil.newArrayList();
for (Project openProject : openProjects) {
final String path = getProjectPath(openProject);
ContainerUtil.addIfNotNull(myState.openPaths, path);
myState.names.put(path, getProjectDisplayName(openProject));
String path = getProjectPath(openProject);
if (path != null) {
myState.openPaths.add(path);
myState.names.put(path, getProjectDisplayName(openProject));
}
}
}
}
@@ -157,17 +160,11 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
private Set<String> getDuplicateProjectNames(Set<String> openedPaths, Set<String> recentPaths) {
Set<String> names = ContainerUtil.newHashSet();
Set<String> duplicates = ContainerUtil.newHashSet();
for (String path : openedPaths) {
for (String path : ContainerUtil.concat(openedPaths, recentPaths)) {
if (!names.add(getProjectName(path))) {
duplicates.add(path);
}
}
for (String path : recentPaths) {
if (!names.add(getProjectName(path))) {
duplicates.add(path);
}
}
return duplicates;
}
@@ -177,17 +174,17 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
* @return
*/
public AnAction[] getRecentProjectsActions(boolean addClearListItem) {
validateRecentProjects();
final Set<String> paths;
synchronized (myStateLock) {
myState.validateRecentProjects();
paths = ContainerUtil.newLinkedHashSet(myState.recentPaths);
}
final Set<String> openedPaths = ContainerUtil.newHashSet();
for (Project openProject : ProjectManager.getInstance().getOpenProjects()) {
ContainerUtil.addIfNotNull(openedPaths, getProjectPath(openProject));
}
final LinkedHashSet<String> paths;
synchronized (myStateLock) {
paths = ContainerUtil.newLinkedHashSet(myState.recentPaths);
}
paths.remove(null);
paths.removeAll(openedPaths);
@@ -220,7 +217,7 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
list.add(action);
}
if (addClearListItem) {
AnAction clearListAction = new AnAction(IdeBundle.message("action.clear.list")) {
AnAction clearListAction = new DumbAwareAction(IdeBundle.message("action.clear.list")) {
public void actionPerformed(AnActionEvent e) {
final int rc = Messages.showOkCancelDialog(e.getData(CommonDataKeys.PROJECT),
"Would you like to clear the list of recent projects?",
@@ -261,34 +258,35 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
return file.exists() && (!file.isDirectory() || new File(file, Project.DIRECTORY_STORE_FOLDER).exists());
}
private class MyProjectManagerListener extends ProjectManagerAdapter {
public void projectOpened(final Project project) {
if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
String path = getProjectPath(project);
public void projectOpened(final Project project) {
String path = getProjectPath(project);
if (path != null) {
markPathRecent(path);
}
SystemDock.updateMenu();
}
@Override
public final boolean canCloseProject(Project project) {
return true;
}
@Override
public void projectClosing(Project project) {
synchronized (myStateLock) {
myState.names.put(getProjectPath(project), getProjectDisplayName(project));
}
}
public void projectClosed(final Project project) {
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length > 0) {
String path = getProjectPath(openProjects[openProjects.length - 1]);
if (path != null) {
markPathRecent(path);
}
SystemDock.updateMenu();
}
@Override
public void projectClosing(Project project) {
synchronized (myStateLock) {
myState.names.put(getProjectPath(project), getProjectDisplayName(project));
}
}
public void projectClosed(final Project project) {
if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length > 0) {
String path = getProjectPath(openProjects[openProjects.length - 1]);
if (path != null) {
markPathRecent(path);
}
}
SystemDock.updateMenu();
}
SystemDock.updateMenu();
}
@NotNull
@@ -330,35 +328,46 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon
}
}
protected boolean willReopenProjectOnStart() {
return GeneralSettings.getInstance().isReopenLastProject() && getLastProjectPath() != null;
}
protected void doReopenLastProject() {
GeneralSettings generalSettings = GeneralSettings.getInstance();
if (generalSettings.isReopenLastProject()) {
Collection<String> openPaths;
synchronized (myStateLock) {
openPaths = ContainerUtil.newLinkedHashSet(myState.openPaths);
}
if (!openPaths.isEmpty()) {
for (String openPath : openPaths) {
if (isValidProjectPath(openPath)) {
doOpenProject(openPath, null, true);
}
}
}
else {
String lastProjectPath = getLastProjectPath();
if (lastProjectPath != null) {
if (isValidProjectPath(lastProjectPath)) doOpenProject(lastProjectPath, null, false);
}
}
}
}
private class MyAppLifecycleListener extends AppLifecycleListener.Adapter {
public void appFrameCreated(final String[] commandLineArgs, @NotNull final Ref<Boolean> willOpenProject) {
if (GeneralSettings.getInstance().isReopenLastProject() && getLastProjectPath() != null) {
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
ProjectManager.getInstance().addProjectManagerListener(RecentProjectsManagerBase.this);
}
if (willReopenProjectOnStart()) {
willOpenProject.set(Boolean.TRUE);
}
}
public void appStarting(final Project projectFromCommandLine) {
public void appStarting(Project projectFromCommandLine) {
if (projectFromCommandLine != null) return;
GeneralSettings generalSettings = GeneralSettings.getInstance();
if (generalSettings.isReopenLastProject()) {
List<String> openPaths;
synchronized (myStateLock) {
openPaths = ContainerUtil.newArrayList(myState.openPaths);
}
if (!openPaths.isEmpty()) {
for (String openPath : openPaths) {
if (isValidProjectPath(openPath)) {
doOpenProject(openPath, null, true);
}
}
}
else {
String lastProjectPath = getLastProjectPath();
if (lastProjectPath != null) {
if (isValidProjectPath(lastProjectPath)) doOpenProject(lastProjectPath, null, false);
}
}
}
doReopenLastProject();
}
public void projectFrameClosed() {
@@ -19,6 +19,7 @@ import com.intellij.CommonBundle;
import com.intellij.conversion.ConversionResult;
import com.intellij.conversion.ConversionService;
import com.intellij.ide.AppLifecycleListener;
import com.intellij.ide.RecentProjectsManagerBase;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.notification.NotificationsManager;
@@ -58,6 +59,7 @@ import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
@@ -118,7 +120,10 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
return array;
}
public ProjectManagerImpl(VirtualFileManager virtualFileManager, ProgressManager progressManager) {
/** @noinspection UnusedParameters*/
public ProjectManagerImpl(VirtualFileManager virtualFileManager,
RecentProjectsManagerBase recentProjectsManager,
ProgressManager progressManager) {
myProgressManager = progressManager;
Application app = ApplicationManager.getApplication();
MessageBus messageBus = app.getMessageBus();
@@ -291,7 +296,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
@NotNull String filePath,
boolean isDefault,
boolean isOptimiseTestLoadSpeed) {
return isDefault ? new DefaultProject(this, "", isOptimiseTestLoadSpeed, projectName)
return isDefault ? new DefaultProject(this, "", isOptimiseTestLoadSpeed, ObjectUtils.assertNotNull(projectName))
: new ProjectImpl(this, new File(filePath).getAbsolutePath(), isOptimiseTestLoadSpeed, projectName);
}
@@ -22,6 +22,9 @@
<xi:include href="/META-INF/VcsExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
<xi:include href="/META-INF/LangExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
<applicationService serviceInterface="com.intellij.ide.RecentProjectsManagerBase"
serviceImplementation="com.intellij.ide.RecentDirectoryProjectsManagerEx"/>
<applicationService serviceInterface="com.intellij.packageDependencies.DependenciesVisitorFactory"
serviceImplementation="com.intellij.packageDependencies.DependenciesVisitorFactory"/>
<applicationService serviceInterface="com.intellij.openapi.projectRoots.ProjectJdkTable"
@@ -18,6 +18,9 @@
<xi:include href="/META-INF/PlatformExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
<xi:include href="/META-INF/VcsExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
<applicationService serviceInterface="com.intellij.ide.RecentProjectsManagerBase"
serviceImplementation="com.intellij.ide.RecentDirectoryProjectsManager"/>
<applicationService serviceInterface="com.intellij.codeStyle.CodeStyleFacade"
serviceImplementation="com.intellij.codeStyle.DefaultCodeStyleFacade"/>
@@ -15,10 +15,6 @@
<interface-class>com.intellij.openapi.project.impl.ProjectStoreClassProvider</interface-class>
<implementation-class>com.intellij.openapi.components.impl.stores.PlatformProjectStoreClassProvider</implementation-class>
</component>
<component>
<interface-class>com.intellij.ide.RecentProjectsManagerBase</interface-class>
<implementation-class>com.intellij.ide.RecentDirectoryProjectsManager</implementation-class>
</component>
</application-components>
<project-components>
<component>
@@ -53,7 +49,7 @@
<component>
<implementation-class>com.intellij.platform.PlatformVcsDetector</implementation-class>
<headless-implementation-class></headless-implementation-class>
<headless-implementation-class/>
</component>
</project-components>
@@ -15,10 +15,6 @@
<interface-class>com.intellij.openapi.project.impl.ProjectStoreClassProvider</interface-class>
<implementation-class>com.intellij.openapi.components.impl.stores.PlatformLangProjectStoreClassProvider</implementation-class>
</component>
<component>
<interface-class>com.intellij.ide.RecentProjectsManagerBase</interface-class>
<implementation-class>com.intellij.ide.RecentDirectoryProjectsManagerEx</implementation-class>
</component>
</application-components>
<project-components>
<component>
+3 -7
View File
@@ -10,13 +10,6 @@
<xi:include href="/componentSets/IdeaComponents.xml" xpointer="xpointer(/components/*)"/>
<xi:include href="/idea/RichPlatformActions.xml" xpointer="xpointer(/component/*)"/>
<application-components>
<component>
<interface-class>com.intellij.ide.RecentProjectsManagerBase</interface-class>
<implementation-class>com.intellij.ide.RecentProjectsManager</implementation-class>
</component>
</application-components>
<project-components>
<component>
<implementation-class>com.intellij.framework.detection.impl.FrameworkDetectionManager</implementation-class>
@@ -133,6 +126,9 @@
<compiler implementation="com.intellij.packaging.impl.compiler.ArtifactsCompiler" id="artifactsCompiler"/>
<gotoRelatedProvider implementation="com.intellij.testIntegration.GotoTestRelatedProvider"/>
<applicationService serviceInterface="com.intellij.ide.RecentProjectsManagerBase"
serviceImplementation="com.intellij.ide.RecentProjectsManager"/>
<applicationService serviceInterface="com.intellij.util.descriptors.ConfigFileFactory"
serviceImplementation="com.intellij.util.descriptors.impl.ConfigFileFactoryImpl"/>