1 package com
.intellij
.ide
;
3 import com
.intellij
.ide
.impl
.ProjectUtil
;
4 import com
.intellij
.openapi
.actionSystem
.AnAction
;
5 import com
.intellij
.openapi
.actionSystem
.AnActionEvent
;
6 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
7 import com
.intellij
.openapi
.actionSystem
.Separator
;
8 import com
.intellij
.openapi
.application
.ApplicationManager
;
9 import com
.intellij
.openapi
.components
.PersistentStateComponent
;
10 import com
.intellij
.openapi
.project
.Project
;
11 import com
.intellij
.openapi
.project
.ProjectManager
;
12 import com
.intellij
.openapi
.project
.ProjectManagerAdapter
;
13 import com
.intellij
.openapi
.util
.Ref
;
14 import com
.intellij
.openapi
.util
.SystemInfo
;
15 import com
.intellij
.util
.ArrayUtil
;
16 import com
.intellij
.util
.messages
.MessageBus
;
17 import org
.jetbrains
.annotations
.NotNull
;
18 import org
.jetbrains
.annotations
.Nullable
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Iterator
;
23 import java
.util
.List
;
28 public abstract class RecentProjectsManagerBase
implements PersistentStateComponent
<RecentProjectsManagerBase
.State
> {
29 public static RecentProjectsManagerBase
getInstance() {
30 return ApplicationManager
.getApplication().getComponent(RecentProjectsManagerBase
.class);
33 public static class State
{
34 public List
<String
> recentPaths
= new ArrayList
<String
>();
35 public String lastPath
;
38 protected State myState
= new State();
40 private static final int MAX_RECENT_PROJECTS
= 15;
42 public RecentProjectsManagerBase(ProjectManager projectManager
, MessageBus messageBus
) {
43 projectManager
.addProjectManagerListener(new MyProjectManagerListener());
44 messageBus
.connect().subscribe(AppLifecycleListener
.TOPIC
, new MyAppLifecycleListener());
47 public State
getState() {
48 validateRecentProjects();
52 public void loadState(final State state
) {
54 if (myState
.lastPath
!= null && !new File(myState
.lastPath
).exists()) {
55 myState
.lastPath
= null;
57 if (myState
.lastPath
!= null) {
58 File lastFile
= new File(myState
.lastPath
);
59 if (lastFile
.isDirectory() && !new File(lastFile
, ProjectUtil
.DIRECTORY_BASED_PROJECT_DIR
).exists()) {
60 myState
.lastPath
= null;
65 private void validateRecentProjects() {
66 for (Iterator i
= myState
.recentPaths
.iterator(); i
.hasNext();) {
67 String s
= (String
)i
.next();
68 if (s
== null || !(new File(s
).exists())) {
72 while (myState
.recentPaths
.size() > MAX_RECENT_PROJECTS
) {
73 myState
.recentPaths
.remove(myState
.recentPaths
.size() - 1);
77 private void removePath(final String path
) {
78 if (SystemInfo
.isFileSystemCaseSensitive
) {
79 myState
.recentPaths
.remove(path
);
82 Iterator
<String
> i
= myState
.recentPaths
.iterator();
85 if (path
.equalsIgnoreCase(p
)) {
92 public String
getLastProjectPath() {
93 return myState
.lastPath
;
96 public void updateLastProjectPath() {
97 Project
[] openProjects
= ProjectManager
.getInstance().getOpenProjects();
98 if (openProjects
.length
== 0) {
99 myState
.lastPath
= null;
101 myState
.lastPath
= getProjectPath(openProjects
[openProjects
.length
- 1]);
106 * @param addClearListItem - used for detecting whether the "Clear List" action should be added
107 * to the end of the returned list of actions
110 public AnAction
[] getRecentProjectsActions(boolean addClearListItem
) {
111 validateRecentProjects();
113 Project
[] openProjects
= ProjectManager
.getInstance().getOpenProjects();
115 ArrayList
<AnAction
> actions
= new ArrayList
<AnAction
>();
116 outer
: for (String recentPath
: myState
.recentPaths
) {
118 for (Project openProject
: openProjects
) {
119 if (recentPath
.equals(getProjectPath(openProject
))) {
124 actions
.add(new ReopenProjectAction(recentPath
));
128 if (actions
.size() == 0) {
129 return new AnAction
[0];
132 ArrayList
<AnAction
> list
= new ArrayList
<AnAction
>();
133 for (AnAction action
: actions
) {
136 if (addClearListItem
) {
137 AnAction clearListAction
= new AnAction(IdeBundle
.message("action.clear.list")) {
138 public void actionPerformed(AnActionEvent e
) {
139 myState
.recentPaths
.clear();
142 list
.add(Separator
.getInstance());
143 list
.add(clearListAction
);
146 return list
.toArray(new AnAction
[list
.size()]);
149 public String
[] getRecentProjectPaths() {
150 validateRecentProjects();
151 return ArrayUtil
.toStringArray(myState
.recentPaths
);
155 protected abstract String
getProjectPath(Project project
);
157 protected abstract void doOpenProject(String projectPath
, Project projectToClose
);
159 private class MyProjectManagerListener
extends ProjectManagerAdapter
{
160 public void projectOpened(final Project project
) {
161 String path
= getProjectPath(project
);
162 myState
.lastPath
= path
;
164 myState
.recentPaths
.add(0, path
);
167 public void projectClosed(final Project project
) {
168 Project
[] openProjects
= ProjectManager
.getInstance().getOpenProjects();
169 if (openProjects
.length
> 0) {
170 String path
= getProjectPath(openProjects
[openProjects
.length
- 1]);
172 myState
.lastPath
= path
;
174 myState
.recentPaths
.add(0, path
);
180 private class ReopenProjectAction
extends AnAction
{
181 private final String myProjectPath
;
183 public ReopenProjectAction(String projectPath
) {
184 myProjectPath
= projectPath
;
185 getTemplatePresentation().setText(projectPath
, false);
188 public void actionPerformed(AnActionEvent e
) {
189 doOpenProject(myProjectPath
, PlatformDataKeys
.PROJECT
.getData(e
.getDataContext()));
193 private class MyAppLifecycleListener
extends AppLifecycleListener
.Adapter
{
194 public void appFrameCreated(final String
[] commandLineArgs
, @NotNull final Ref
<Boolean
> willOpenProject
) {
195 if (GeneralSettings
.getInstance().isReopenLastProject() && getLastProjectPath() != null) {
196 willOpenProject
.set(Boolean
.TRUE
);
200 public void appStarting(final Project projectFromCommandLine
) {
201 if (projectFromCommandLine
!= null) return;
202 GeneralSettings generalSettings
= GeneralSettings
.getInstance();
203 if (generalSettings
.isReopenLastProject()) {
204 String lastProjectPath
= getLastProjectPath();
205 if (lastProjectPath
!= null) {
206 doOpenProject(lastProjectPath
, null);
211 public void projectFrameClosed() {
212 updateLastProjectPath();
215 public void projectOpenFailed() {
216 updateLastProjectPath();