4
// Lluis Sanchez Gual <lluis@novell.com>
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
// of this software and associated documentation files (the "Software"), to deal
10
// in the Software without restriction, including without limitation the rights
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
// copies of the Software, and to permit persons to whom the Software is
13
// furnished to do so, subject to the following conditions:
15
// The above copyright notice and this permission notice shall be included in
16
// all copies or substantial portions of the Software.
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30
using System.Collections;
31
using System.Collections.Generic;
32
using System.Collections.ObjectModel;
34
using MonoDevelop.Projects;
35
using MonoDevelop.Core;
36
using MonoDevelop.Core.Assemblies;
37
using MonoDevelop.Core.Serialization;
38
using MonoDevelop.Projects.CodeGeneration;
39
using MonoDevelop.Ide.Gui.Dialogs;
40
using MonoDevelop.Ide.Gui.Content;
41
using System.Runtime.CompilerServices;
42
using MonoDevelop.Core.Instrumentation;
43
using MonoDevelop.Ide.Gui;
44
using MonoDevelop.Ide.Projects;
46
namespace MonoDevelop.Ide
48
public class RootWorkspace: IBuildTarget, IWorkspaceObject
50
WorkspaceItemCollection items;
51
// IParserDatabase parserDatabase;
52
string activeConfiguration;
53
bool useDefaultRuntime;
55
ProjectFileEventHandler fileAddedToProjectHandler;
56
ProjectFileEventHandler fileRemovedFromProjectHandler;
57
ProjectFileRenamedEventHandler fileRenamedInProjectHandler;
58
ProjectFileEventHandler fileChangedInProjectHandler;
59
ProjectFileEventHandler filePropertyChangedInProjectHandler;
60
ProjectReferenceEventHandler referenceAddedToProjectHandler;
61
ProjectReferenceEventHandler referenceRemovedFromProjectHandler;
62
SolutionItemChangeEventHandler itemAddedToSolutionHandler;
63
SolutionItemChangeEventHandler itemRemovedFromSolutionHandler;
64
EventHandler<WorkspaceItemChangeEventArgs> descendantItemAddedHandler;
65
EventHandler<WorkspaceItemChangeEventArgs> descendantItemRemovedHandler;
66
EventHandler configurationsChanged;
68
internal RootWorkspace ()
70
fileAddedToProjectHandler = (ProjectFileEventHandler) DispatchService.GuiDispatch (new ProjectFileEventHandler (NotifyFileAddedToProject));
71
fileRemovedFromProjectHandler = (ProjectFileEventHandler) DispatchService.GuiDispatch (new ProjectFileEventHandler (NotifyFileRemovedFromProject));
72
fileRenamedInProjectHandler = (ProjectFileRenamedEventHandler) DispatchService.GuiDispatch (new ProjectFileRenamedEventHandler (NotifyFileRenamedInProject));
73
fileChangedInProjectHandler = (ProjectFileEventHandler) DispatchService.GuiDispatch (new ProjectFileEventHandler (NotifyFileChangedInProject));
74
filePropertyChangedInProjectHandler = (ProjectFileEventHandler) DispatchService.GuiDispatch (new ProjectFileEventHandler (NotifyFilePropertyChangedInProject));
75
referenceAddedToProjectHandler = (ProjectReferenceEventHandler) DispatchService.GuiDispatch (new ProjectReferenceEventHandler (NotifyReferenceAddedToProject));
76
referenceRemovedFromProjectHandler = (ProjectReferenceEventHandler) DispatchService.GuiDispatch (new ProjectReferenceEventHandler (NotifyReferenceRemovedFromProject));
78
itemAddedToSolutionHandler = (SolutionItemChangeEventHandler) DispatchService.GuiDispatch (new SolutionItemChangeEventHandler (NotifyItemAddedToSolution));
79
itemRemovedFromSolutionHandler = (SolutionItemChangeEventHandler) DispatchService.GuiDispatch (new SolutionItemChangeEventHandler (NotifyItemRemovedFromSolution));
81
descendantItemAddedHandler = (EventHandler<WorkspaceItemChangeEventArgs>) DispatchService.GuiDispatch (new EventHandler<WorkspaceItemChangeEventArgs> (NotifyDescendantItemAdded));
82
descendantItemRemovedHandler = (EventHandler<WorkspaceItemChangeEventArgs>) DispatchService.GuiDispatch (new EventHandler<WorkspaceItemChangeEventArgs> (NotifyDescendantItemRemoved));
83
configurationsChanged = (EventHandler) DispatchService.GuiDispatch (new EventHandler (NotifyConfigurationsChanged));
85
FileService.FileRemoved += (EventHandler<FileEventArgs>) DispatchService.GuiDispatch (new EventHandler<FileEventArgs> (CheckFileRemove));
86
FileService.FileRenamed += (EventHandler<FileCopyEventArgs>) DispatchService.GuiDispatch (new EventHandler<FileCopyEventArgs> (CheckFileRename));
88
// Set the initial active runtime
89
UseDefaultRuntime = true;
90
IdeApp.Preferences.DefaultTargetRuntimeChanged += delegate {
91
// If the default runtime changes and current active is default, update it
92
if (UseDefaultRuntime) {
93
Runtime.SystemAssemblyService.DefaultRuntime = IdeApp.Preferences.DefaultTargetRuntime;
94
useDefaultRuntime = true;
98
//FIXME: disabled OnRunProjectChecks timeout because it churns disk, wastes power on laptop. Need better solution.
99
//GLib.Timeout.Add (2000, OnRunProjectChecks);
102
public WorkspaceItemCollection Items {
105
items = new RootWorkspaceItemCollection (this);
110
public IParserDatabase ParserDatabase {
112
if (parserDatabase == null) {
113
parserDatabase = Services.ParserService.CreateParserDatabase ();
114
parserDatabase.TrackFileChanges = true;
115
parserDatabase.ParseProgressMonitorFactory = new ParseProgressMonitorFactory ();
117
return parserDatabase;
121
public string ActiveConfigurationId {
123
return activeConfiguration;
126
if (activeConfiguration != value) {
127
activeConfiguration = value;
128
if (ActiveConfigurationChanged != null)
129
ActiveConfigurationChanged (this, EventArgs.Empty);
134
public ConfigurationSelector ActiveConfiguration {
135
get { return new SolutionConfigurationSelector (activeConfiguration); }
138
public TargetRuntime ActiveRuntime {
140
return Runtime.SystemAssemblyService.DefaultRuntime;
143
useDefaultRuntime = false;
144
Runtime.SystemAssemblyService.DefaultRuntime = value;
148
public bool UseDefaultRuntime {
149
get { return useDefaultRuntime; }
151
if (useDefaultRuntime != value) {
152
useDefaultRuntime = value;
154
Runtime.SystemAssemblyService.DefaultRuntime = IdeApp.Preferences.DefaultTargetRuntime;
160
get { return Items.Count > 0; }
163
public CodeRefactorer GetCodeRefactorer (Solution solution)
165
CodeRefactorer refactorer = new CodeRefactorer (solution);
166
refactorer.TextFileProvider = new OpenDocumentFileProvider ();
170
IDictionary IExtendedDataItem.ExtendedProperties {
172
throw new NotSupportedException ("Root namespace can't have extended properties.");
176
string IWorkspaceObject.Name {
178
return "MonoDevelop Workspace";
181
throw new NotSupportedException ("Can't change the name of the root workspace.");
185
public FilePath BaseDirectory {
187
return IdeApp.ProjectOperations.ProjectsDefaultPath;
191
FilePath IWorkspaceObject.BaseDirectory {
193
return BaseDirectory;
196
throw new NotSupportedException ();
200
FilePath IWorkspaceObject.ItemDirectory {
202
return BaseDirectory;
206
public AuthorInformation GetAuthorInformation (SolutionItem item)
209
return GetAuthorInformation (item.ParentSolution);
210
return AuthorInformation.Default;
213
public AuthorInformation GetAuthorInformation (Solution solution)
215
if (solution == null)
216
return AuthorInformation.Default;
217
AuthorInformation info = solution.UserProperties.GetValue<AuthorInformation> ("AuthorInfo");
218
return info ?? AuthorInformation.Default;
221
#region Model queries
223
public SolutionEntityItem FindSolutionItem (string fileName)
225
foreach (WorkspaceItem it in Items) {
226
SolutionEntityItem si = it.FindSolutionItem (fileName);
233
public ReadOnlyCollection<SolutionItem> GetAllSolutionItems ()
235
return GetAllSolutionItems<SolutionItem> ();
238
public virtual ReadOnlyCollection<T> GetAllSolutionItems<T> () where T: SolutionItem
240
List<T> list = new List<T> ();
241
foreach (WorkspaceItem it in Items) {
242
list.AddRange (it.GetAllSolutionItems<T> ());
244
return list.AsReadOnly ();
247
public ReadOnlyCollection<Project> GetAllProjects ()
249
return GetAllSolutionItems<Project> ();
252
public ReadOnlyCollection<Solution> GetAllSolutions ()
254
return GetAllItems<Solution> ();
257
public ReadOnlyCollection<T> GetAllItems<T> () where T:WorkspaceItem
259
List<T> list = new List<T> ();
260
foreach (WorkspaceItem it in Items)
261
GetAllItems<T> (list, it);
262
return list.AsReadOnly ();
265
void GetAllItems<T> (List<T> list, WorkspaceItem item) where T: WorkspaceItem
270
if (item is Workspace) {
271
foreach (WorkspaceItem citem in ((Workspace)item).Items)
272
GetAllItems<T> (list, citem);
276
public Project GetProjectContainingFile (string fileName)
278
foreach (WorkspaceItem it in Items) {
279
Project p = it.GetProjectContainingFile (fileName);
288
#region Build and run operations
292
IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true);
295
monitor.ReportSuccess (GettextCatalog.GetString ("Workspace saved."));
296
} catch (Exception ex) {
297
monitor.ReportError (GettextCatalog.GetString ("Save failed."), ex);
303
public IAsyncOperation Build ()
305
return IdeApp.ProjectOperations.Build (this);
310
IdeApp.ProjectOperations.Clean (this);
313
public IAsyncOperation Execute ()
315
if (IdeApp.ProjectOperations.CurrentSelectedSolution != null)
316
return IdeApp.ProjectOperations.Execute (IdeApp.ProjectOperations.CurrentSelectedSolution);
318
MessageService.ShowError (GettextCatalog.GetString ("No solution has been selected"), GettextCatalog.GetString ("The solution to be executed must be selected in the solution pad."));
323
public bool CanExecute ()
325
if (IdeApp.ProjectOperations.CurrentSelectedSolution != null)
326
return IdeApp.ProjectOperations.CanExecute (IdeApp.ProjectOperations.CurrentSelectedSolution);
332
bool IBuildTarget.CanExecute (ExecutionContext context, ConfigurationSelector configuration)
334
if (IdeApp.ProjectOperations.CurrentSelectedSolution != null)
335
return IdeApp.ProjectOperations.CurrentSelectedSolution.CanExecute (context, configuration);
341
public void Dispose ()
345
public void Save (IProgressMonitor monitor)
347
monitor.BeginTask (GettextCatalog.GetString ("Saving Workspace..."), Items.Count);
348
foreach (WorkspaceItem it in Items) {
355
BuildResult IBuildTarget.RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration)
357
BuildResult result = null;
358
foreach (WorkspaceItem it in Items) {
359
BuildResult res = it.RunTarget (monitor, target, configuration);
362
result = new BuildResult ();
369
public void Execute (MonoDevelop.Core.IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configuration)
371
Solution sol = IdeApp.ProjectOperations.CurrentSelectedSolution;
373
ReadOnlyCollection<Solution> sols = GetAllSolutions ();
378
sol.Execute (monitor, context, configuration);
380
throw new UserException (GettextCatalog.GetString ("No solution has been selected."));
383
public bool NeedsBuilding ()
385
return NeedsBuilding (IdeApp.Workspace.ActiveConfiguration) || IsDirtyFileInCombine;
388
public bool NeedsBuilding (ConfigurationSelector configuration)
390
foreach (WorkspaceItem it in Items) {
391
if (it.NeedsBuilding (configuration))
397
public void SetNeedsBuilding (bool needsBuilding, ConfigurationSelector configuration)
399
foreach (WorkspaceItem it in Items)
400
it.SetNeedsBuilding (needsBuilding, configuration);
403
bool IsDirtyFileInCombine {
405
foreach (Project projectEntry in GetAllProjects()) {
406
foreach (ProjectFile fInfo in projectEntry.Files) {
407
foreach (Document doc in IdeApp.Workbench.Documents) {
408
if (doc.IsDirty && doc.FileName == fInfo.FilePath) {
418
public ReadOnlyCollection<string> GetConfigurations ()
420
List<string> configs = new List<string> ();
421
foreach (WorkspaceItem it in Items) {
422
foreach (string conf in it.GetConfigurations ()) {
423
if (!configs.Contains (conf))
427
return configs.AsReadOnly ();
431
#region Opening and closing
433
public void SavePreferences ()
435
foreach (WorkspaceItem it in Items)
436
SavePreferences (it);
444
public bool Close (bool saveWorkspacePreferencies)
446
return Close (saveWorkspacePreferencies, true);
449
internal bool Close (bool saveWorkspacePreferencies, bool closeProjectFiles)
451
if (Items.Count > 0) {
453
// Request permission for unloading the items
454
foreach (WorkspaceItem it in new List<WorkspaceItem> (Items)) {
455
if (!RequestItemUnload (it))
459
if (saveWorkspacePreferencies)
462
if (closeProjectFiles) {
463
Document[] docs = new Document[IdeApp.Workbench.Documents.Count];
464
IdeApp.Workbench.Documents.CopyTo (docs, 0);
465
foreach (Document doc in docs) {
466
if (doc.HasProject) {
473
foreach (WorkspaceItem it in new List<WorkspaceItem> (Items)) {
477
} catch (Exception ex) {
478
MessageService.ShowException (ex, GettextCatalog.GetString ("Could not close solution '{0}'.", it.Name));
485
public void CloseWorkspaceItem (WorkspaceItem item)
487
if (!Items.Contains (item))
488
throw new InvalidOperationException ("Only top level items can be closed.");
490
if (RequestItemUnload (item))
494
public bool RequestItemUnload (IBuildTarget item)
496
if (ItemUnloading != null) {
498
ItemUnloadingEventArgs args = new ItemUnloadingEventArgs (item);
499
ItemUnloading (this, args);
501
} catch (Exception ex) {
502
LoggingService.LogError ("Exception in ItemUnloading.", ex);
508
public IAsyncOperation OpenWorkspaceItem (string filename)
510
return OpenWorkspaceItem (filename, true);
513
public IAsyncOperation OpenWorkspaceItem (string filename, bool closeCurrent)
515
return OpenWorkspaceItem (filename, closeCurrent, true);
518
public IAsyncOperation OpenWorkspaceItem (string filename, bool closeCurrent, bool loadPreferences)
522
return MonoDevelop.Core.ProgressMonitoring.NullAsyncOperation.Failure;
525
if (filename.StartsWith ("file://"))
526
filename = new Uri(filename).LocalPath;
528
IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetLoadProgressMonitor (true);
530
DispatchService.BackgroundDispatch (delegate {
531
BackgroundLoadWorkspace (monitor, filename, loadPreferences);
533
return monitor.AsyncOperation;
536
void ReattachDocumentProjects (IEnumerable<string> closedDocs)
538
foreach (Document doc in IdeApp.Workbench.Documents) {
539
if (doc.Project == null && doc.IsFile) {
540
Project p = GetProjectContainingFile (doc.FileName);
545
if (closedDocs != null) {
546
foreach (string doc in closedDocs) {
547
IdeApp.Workbench.OpenDocument (doc, false);
552
void BackgroundLoadWorkspace (IProgressMonitor monitor, string filename, bool loadPreferences)
554
WorkspaceItem item = null;
555
ITimeTracker timer = Counters.OpenWorkspaceItemTimer.BeginTiming ();
558
if (!File.Exists (filename)) {
559
monitor.ReportError (GettextCatalog.GetString ("File not found: {0}", filename), null);
564
if (!Services.ProjectService.IsWorkspaceItemFile (filename)) {
565
if (!Services.ProjectService.IsSolutionItemFile (filename)) {
566
monitor.ReportError (GettextCatalog.GetString ("File is not a project or solution: {0}", filename), null);
571
// It is a project, not a solution. Try to create a dummy solution and add the project to it
573
timer.Trace ("Getting wrapper solution");
574
item = IdeApp.Services.ProjectService.GetWrapperSolution (monitor, filename);
578
timer.Trace ("Reading item");
579
item = Services.ProjectService.ReadWorkspaceItem (monitor, filename);
580
if (monitor.IsCancelRequested) {
586
timer.Trace ("Registering to recent list");
587
IdeApp.Workbench.RecentOpen.AddLastProject (item.FileName, item.Name);
589
timer.Trace ("Adding to items list");
592
timer.Trace ("Searching for new files");
593
SearchForNewFiles ();
595
} catch (Exception ex) {
596
monitor.ReportError ("Load operation failed.", ex);
598
// Don't use 'finally' to dispose the monitor, since it has to be disposed later
604
Gtk.Application.Invoke (delegate {
607
if (Items.Count == 1 && loadPreferences) {
608
timer.Trace ("Restoring workspace preferences");
609
RestoreWorkspacePreferences (item);
611
timer.Trace ("Reattaching documents");
612
ReattachDocumentProjects (null);
613
monitor.ReportSuccess (GettextCatalog.GetString ("Solution loaded."));
621
void SearchForNewFiles ()
623
foreach (Project p in GetAllProjects()) {
624
if (p.NewFileSearch != NewFileSearch.None)
630
void SearchNewFiles (Project project)
632
List<string> newFiles = new List<string> ();
633
string[] collection = Directory.GetFiles (project.BaseDirectory, "*", SearchOption.AllDirectories);
635
HashSet<string> projectFiles = new HashSet<string> ();
636
foreach (string file in project.GetItemFiles (true))
637
projectFiles.Add (file);
639
foreach (string sfile in collection) {
640
if (projectFiles.Contains (Path.GetFullPath (sfile)))
642
if (IdeApp.Services.ProjectService.IsSolutionItemFile (sfile) || IdeApp.Services.ProjectService.IsWorkspaceItemFile (sfile))
644
string extension = Path.GetExtension(sfile).ToUpper();
645
string file = Path.GetFileName (sfile);
647
if (extension != ".SCC" && // source safe control files -- Svante Lidmans
648
extension != ".DLL" &&
649
extension != ".PDB" &&
650
extension != ".EXE" &&
651
extension != ".CMBX" &&
652
extension != ".PRJX" &&
653
extension != ".SWP" &&
654
extension != ".MDSX" &&
655
extension != ".MDS" &&
656
extension != ".MDP" &&
657
extension != ".PIDB" &&
658
extension != ".PIDB-JOURNAL" &&
659
!file.EndsWith ("make.sh") &&
660
!file.EndsWith ("~") &&
661
!file.StartsWith (".") &&
662
!(Path.GetDirectoryName(sfile).IndexOf("CVS") != -1) &&
663
!(Path.GetDirectoryName(sfile).IndexOf(".svn") != -1) &&
664
!(Path.GetDirectoryName(sfile).IndexOf(Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar) != -1) &&
665
!file.StartsWith ("Makefile") &&
666
!Path.GetDirectoryName(file).EndsWith("ProjectDocumentation")) {
672
if (newFiles.Count > 0) {
673
if (project.NewFileSearch == NewFileSearch.OnLoadAutoInsert) {
674
foreach (string file in newFiles) {
675
project.AddFile (file);
678
DispatchService.GuiDispatch (
679
delegate (object state) {
680
NewFilesMessage message = (NewFilesMessage) state;
681
var includeNewFilesDialog = new IncludeNewFilesDialog (message.Project);
682
includeNewFilesDialog.AddFiles (message.NewFiles);
683
MessageService.ShowCustomDialog (includeNewFilesDialog, IdeApp.Workbench.RootWindow);
685
new NewFilesMessage (project, newFiles)
691
private class NewFilesMessage
693
public Project Project;
694
public List<string> NewFiles;
695
public NewFilesMessage (Project p, List<string> newFiles)
698
this.NewFiles = newFiles;
702
void RestoreWorkspacePreferences (WorkspaceItem item)
704
// Restore local configuration data
707
WorkspaceUserData data = item.UserProperties.GetValue<WorkspaceUserData> ("MonoDevelop.Ide.Workspace");
709
ActiveConfigurationId = data.ActiveConfiguration;
710
if (string.IsNullOrEmpty (data.ActiveRuntime))
711
UseDefaultRuntime = true;
713
TargetRuntime tr = Runtime.SystemAssemblyService.GetTargetRuntime (data.ActiveRuntime);
717
UseDefaultRuntime = true;
721
catch (Exception ex) {
722
LoggingService.LogError ("Exception while loading user solution preferences.", ex);
725
// Allow add-ins to restore preferences
727
if (LoadingUserPreferences != null) {
728
UserPreferencesEventArgs args = new UserPreferencesEventArgs (item, item.UserProperties);
730
LoadingUserPreferences (this, args);
731
} catch (Exception ex) {
732
LoggingService.LogError ("Exception in LoadingUserPreferences.", ex);
737
public void SavePreferences (WorkspaceItem item)
739
// Local configuration info
741
WorkspaceUserData data = new WorkspaceUserData ();
742
data.ActiveConfiguration = ActiveConfigurationId;
743
data.ActiveRuntime = UseDefaultRuntime ? null : ActiveRuntime.Id;
744
item.UserProperties.SetValue ("MonoDevelop.Ide.Workspace", data);
746
// Allow add-ins to fill-up data
748
if (StoringUserPreferences != null) {
749
UserPreferencesEventArgs args = new UserPreferencesEventArgs (item, item.UserProperties);
751
StoringUserPreferences (this, args);
752
} catch (Exception ex) {
753
LoggingService.LogError ("Exception in UserPreferencesRequested.", ex);
759
item.SaveUserProperties ();
762
bool OnRunProjectChecks ()
764
// If any project has been modified, reload it
765
foreach (WorkspaceItem it in new List<WorkspaceItem> (Items))
766
OnCheckWorkspaceItem (it);
770
void OnCheckWorkspaceItem (WorkspaceItem item)
772
if (item.NeedsReload) {
773
IEnumerable<string> closedDocs;
774
if (AllowReload (item.GetAllProjects (), out closedDocs)) {
775
if (item.ParentWorkspace == null) {
776
string file = item.FileName;
778
CloseWorkspaceItem (item);
779
OpenWorkspaceItem (file, false);
782
using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetSaveProgressMonitor (true)) {
783
item.ParentWorkspace.ReloadItem (m, item);
784
ReattachDocumentProjects (closedDocs);
790
item.NeedsReload = false;
793
if (item is Workspace) {
794
Workspace ws = (Workspace) item;
795
List<WorkspaceItem> items = new List<WorkspaceItem> (ws.Items);
796
foreach (WorkspaceItem it in items)
797
OnCheckWorkspaceItem (it);
799
else if (item is Solution) {
800
Solution sol = (Solution) item;
801
OnCheckProject (sol.RootFolder);
805
void OnCheckProject (SolutionItem entry)
807
if (entry.NeedsReload) {
808
IEnumerable projects = null;
809
if (entry is Project) {
810
projects = new Project [] { (Project) entry };
811
} else if (entry is SolutionFolder) {
812
projects = ((SolutionFolder)entry).GetAllProjects ();
815
IEnumerable<string> closedDocs;
817
if (AllowReload (projects, out closedDocs)) {
818
using (IProgressMonitor m = IdeApp.Workbench.ProgressMonitors.GetLoadProgressMonitor (true)) {
819
// Root folders never need to reload
820
entry.ParentFolder.ReloadItem (m, entry);
821
ReattachDocumentProjects (closedDocs);
825
entry.NeedsReload = false;
828
if (entry is SolutionFolder) {
829
ArrayList ens = new ArrayList ();
830
foreach (SolutionItem ce in ((SolutionFolder)entry).Items)
832
foreach (SolutionItem ce in ens)
837
// bool AllowReload (IEnumerable projects)
839
// IEnumerable<string> closedDocs;
840
// return AllowReload (projects, out closedDocs);
843
bool AllowReload (IEnumerable projects, out IEnumerable<string> closedDocs)
847
if (projects == null)
850
List<Document> docs = new List<Document> ();
851
foreach (Project p in projects) {
852
docs.AddRange (GetOpenDocuments (p, false));
858
// Find a common project reload capability
860
bool hasUnsaved = false;
861
bool hasNoFiles = false;
862
ProjectReloadCapability prc = ProjectReloadCapability.Full;
863
foreach (Document doc in docs) {
868
ISupportsProjectReload pr = doc.GetContent<ISupportsProjectReload> ();
870
ProjectReloadCapability c = pr.ProjectReloadCapability;
871
if ((int) c < (int) prc)
875
prc = ProjectReloadCapability.None;
881
case ProjectReloadCapability.None:
882
if (hasNoFiles && hasUnsaved)
883
msg = GettextCatalog.GetString ("WARNING: Some documents may need to be closed, and unsaved data will be lost. You will be asked to save the unsaved documents.");
885
msg = GettextCatalog.GetString ("WARNING: Some documents may need to be reloaded or closed, and unsaved data will be lost. You will be asked to save the unsaved documents.");
887
msg = GettextCatalog.GetString ("WARNING: Some files may need to be reloaded, and unsaved data will be lost. You will be asked to save the unsaved files.");
889
goto case ProjectReloadCapability.UnsavedData;
892
case ProjectReloadCapability.UnsavedData:
893
msg = GettextCatalog.GetString ("Some files may need to be reloaded, and editing status for those files (such as the undo queue) will be lost.");
897
if (!MessageService.Confirm (GettextCatalog.GetString ("The project '{0}' has been modified by an external application. Do you want to reload it?", docs[0].Project.Name), msg, AlertButton.Reload))
901
List<string> closed = new List<string> ();
903
foreach (Document doc in docs) {
906
ISupportsProjectReload pr = doc.GetContent<ISupportsProjectReload> ();
908
doc.SetProject (null);
910
FilePath file = doc.IsFile ? doc.FileName : FilePath.Null;
911
EventHandler saved = delegate {
919
else if (!file.IsNullOrEmpty && File.Exists (file))
931
internal List<Document> GetOpenDocuments (Project project, bool modifiedOnly)
933
List<Document> docs = new List<Document> ();
934
foreach (Document doc in IdeApp.Workbench.Documents) {
935
if (doc.Project == project && (!modifiedOnly || doc.IsDirty)) {
945
#region Event handling
947
internal void NotifyItemAdded (WorkspaceItem item)
949
if (DispatchService.IsGuiThread)
950
NotifyItemAddedGui (item);
952
Gtk.Application.Invoke (delegate {
953
NotifyItemAddedGui (item);
957
void NotifyItemAddedGui (WorkspaceItem item)
960
// Mono.Profiler.RuntimeControls.EnableProfiler ();
961
MonoDevelop.Projects.Dom.Parser.ProjectDomService.Load (item);
962
// Mono.Profiler.RuntimeControls.DisableProfiler ();
963
// Console.WriteLine ("PARSE LOAD: " + (DateTime.Now - t).TotalMilliseconds);
964
} catch (Exception ex) {
965
LoggingService.LogError ("Could not load parser database.", ex);
968
Workspace ws = item as Workspace;
970
ws.DescendantItemAdded += descendantItemAddedHandler;
971
ws.DescendantItemRemoved += descendantItemRemovedHandler;
973
item.ConfigurationsChanged += configurationsChanged;
975
WorkspaceItemEventArgs args = new WorkspaceItemEventArgs (item);
976
NotifyDescendantItemAdded (this, args);
977
NotifyConfigurationsChanged (null, args);
979
if (WorkspaceItemOpened != null)
980
WorkspaceItemOpened (this, args);
981
if (Items.Count == 1) {
982
IdeApp.Workbench.CurrentLayout = "Solution";
983
if (FirstWorkspaceItemOpened != null)
984
FirstWorkspaceItemOpened (this, args);
988
internal void NotifyItemRemoved (WorkspaceItem item)
990
if (DispatchService.IsGuiThread)
991
NotifyItemRemovedGui (item);
993
Gtk.Application.Invoke (delegate {
994
NotifyItemRemovedGui (item);
998
internal void NotifyItemRemovedGui (WorkspaceItem item)
1000
Workspace ws = item as Workspace;
1002
ws.DescendantItemAdded -= descendantItemAddedHandler;
1003
ws.DescendantItemRemoved -= descendantItemRemovedHandler;
1005
item.ConfigurationsChanged -= configurationsChanged;
1007
if (Items.Count == 0) {
1008
IdeApp.Workbench.CurrentLayout = "Default";
1009
if (LastWorkspaceItemClosed != null)
1010
LastWorkspaceItemClosed (this, EventArgs.Empty);
1013
WorkspaceItemEventArgs args = new WorkspaceItemEventArgs (item);
1014
NotifyConfigurationsChanged (null, args);
1016
if (WorkspaceItemClosed != null)
1017
WorkspaceItemClosed (this, args);
1019
MonoDevelop.Projects.Dom.Parser.ProjectDomService.Unload (item);
1020
// ParserDatabase.Unload (item);
1022
NotifyDescendantItemRemoved (this, args);
1025
void SubscribeSolution (Solution sol)
1027
sol.FileAddedToProject += fileAddedToProjectHandler;
1028
sol.FileRemovedFromProject += fileRemovedFromProjectHandler;
1029
sol.FileRenamedInProject += fileRenamedInProjectHandler;
1030
sol.FileChangedInProject += fileChangedInProjectHandler;
1031
sol.FilePropertyChangedInProject += filePropertyChangedInProjectHandler;
1032
sol.ReferenceAddedToProject += referenceAddedToProjectHandler;
1033
sol.ReferenceRemovedFromProject += referenceRemovedFromProjectHandler;
1034
sol.SolutionItemAdded += itemAddedToSolutionHandler;
1035
sol.SolutionItemRemoved += itemRemovedFromSolutionHandler;
1038
void UnsubscribeSolution (Solution solution)
1040
solution.FileAddedToProject -= fileAddedToProjectHandler;
1041
solution.FileRemovedFromProject -= fileRemovedFromProjectHandler;
1042
solution.FileRenamedInProject -= fileRenamedInProjectHandler;
1043
solution.FileChangedInProject -= fileChangedInProjectHandler;
1044
solution.FilePropertyChangedInProject -= filePropertyChangedInProjectHandler;
1045
solution.ReferenceAddedToProject -= referenceAddedToProjectHandler;
1046
solution.ReferenceRemovedFromProject -= referenceRemovedFromProjectHandler;
1047
solution.SolutionItemAdded -= itemAddedToSolutionHandler;
1048
solution.SolutionItemRemoved -= itemRemovedFromSolutionHandler;
1051
void NotifyConfigurationsChanged (object s, EventArgs a)
1053
if (ConfigurationsChanged != null)
1054
ConfigurationsChanged (this, a);
1057
void NotifyFileRemovedFromProject (object sender, ProjectFileEventArgs e)
1059
if (FileRemovedFromProject != null) {
1060
FileRemovedFromProject(this, e);
1064
void NotifyFileAddedToProject (object sender, ProjectFileEventArgs e)
1066
if (FileAddedToProject != null) {
1067
FileAddedToProject (this, e);
1071
internal void NotifyFileRenamedInProject (object sender, ProjectFileRenamedEventArgs e)
1073
if (FileRenamedInProject != null) {
1074
FileRenamedInProject (this, e);
1078
internal void NotifyFileChangedInProject (object sender, ProjectFileEventArgs e)
1080
if (FileChangedInProject != null) {
1081
FileChangedInProject (this, e);
1085
internal void NotifyFilePropertyChangedInProject (object sender, ProjectFileEventArgs e)
1087
if (FilePropertyChangedInProject != null) {
1088
FilePropertyChangedInProject (this, e);
1092
internal void NotifyReferenceAddedToProject (object sender, ProjectReferenceEventArgs e)
1094
if (ReferenceAddedToProject != null) {
1095
ReferenceAddedToProject (this, e);
1099
internal void NotifyReferenceRemovedFromProject (object sender, ProjectReferenceEventArgs e)
1101
if (ReferenceRemovedFromProject != null) {
1102
ReferenceRemovedFromProject (this, e);
1106
void NotifyItemAddedToSolution (object sender, SolutionItemEventArgs args)
1108
// Delay the notification of this event to ensure that the new project is properly
1109
// registered in the parser database when it is fired
1111
Gtk.Application.Invoke (delegate {
1112
if (ItemAddedToSolution != null)
1113
ItemAddedToSolution (sender, args);
1117
void NotifyItemRemovedFromSolution (object sender, SolutionItemEventArgs args)
1119
NotifyItemRemovedFromSolutionRec (sender, args.SolutionItem, args.Solution);
1122
void NotifyItemRemovedFromSolutionRec (object sender, SolutionItem e, Solution sol)
1124
if (e == IdeApp.ProjectOperations.CurrentSelectedSolutionItem)
1125
IdeApp.ProjectOperations.CurrentSelectedSolutionItem = null;
1127
if (e is SolutionFolder) {
1128
foreach (SolutionItem ce in ((SolutionFolder)e).Items)
1129
NotifyItemRemovedFromSolutionRec (sender, ce, sol);
1131
if (ItemRemovedFromSolution != null)
1132
ItemRemovedFromSolution (sender, new SolutionItemEventArgs (e, sol));
1135
void NotifyDescendantItemAdded (object s, WorkspaceItemEventArgs args)
1137
// If a top level item has been moved to a child item, remove it from
1139
if (s != this && Items.Contains (args.Item))
1140
Items.Remove (args.Item);
1141
foreach (WorkspaceItem item in args.Item.GetAllItems ()) {
1142
if (item is Solution)
1143
SubscribeSolution ((Solution)item);
1144
OnItemLoaded (item);
1148
void NotifyDescendantItemRemoved (object s, WorkspaceItemEventArgs args)
1150
foreach (WorkspaceItem item in args.Item.GetAllItems ()) {
1151
OnItemUnloaded (item);
1152
if (item is Solution)
1153
UnsubscribeSolution ((Solution)item);
1157
void OnItemLoaded (WorkspaceItem item)
1160
if (WorkspaceItemLoaded != null)
1161
WorkspaceItemLoaded (this, new WorkspaceItemEventArgs (item));
1162
if (item is Solution && SolutionLoaded != null)
1163
SolutionLoaded (this, new SolutionEventArgs ((Solution)item));
1164
} catch (Exception ex) {
1165
LoggingService.LogError ("Error in SolutionOpened event.", ex);
1169
void OnItemUnloaded (WorkspaceItem item)
1172
if (WorkspaceItemUnloaded != null)
1173
WorkspaceItemUnloaded (this, new WorkspaceItemEventArgs (item));
1174
if (item is Solution && SolutionUnloaded != null)
1175
SolutionUnloaded (this, new SolutionEventArgs ((Solution)item));
1176
} catch (Exception ex) {
1177
LoggingService.LogError ("Error in SolutionClosed event.", ex);
1181
void CheckFileRemove(object sender, FileEventArgs e)
1183
foreach (Solution sol in GetAllSolutions ())
1184
sol.RootFolder.RemoveFileFromProjects (e.FileName);
1187
void CheckFileRename(object sender, FileCopyEventArgs e)
1189
foreach (Solution sol in GetAllSolutions ())
1190
sol.RootFolder.RenameFileInProjects (e.SourceFile, e.TargetFile);
1195
#region Event declaration
1197
public event ProjectFileEventHandler FileRemovedFromProject;
1198
public event ProjectFileEventHandler FileAddedToProject;
1199
public event ProjectFileEventHandler FileChangedInProject;
1200
public event ProjectFileEventHandler FilePropertyChangedInProject;
1201
public event ProjectFileRenamedEventHandler FileRenamedInProject;
1203
public event EventHandler<SolutionEventArgs> SolutionLoaded;
1204
public event EventHandler<SolutionEventArgs> SolutionUnloaded;
1205
public event EventHandler<WorkspaceItemEventArgs> FirstWorkspaceItemOpened;
1206
public event EventHandler LastWorkspaceItemClosed;
1207
public event EventHandler<WorkspaceItemEventArgs> WorkspaceItemLoaded;
1208
public event EventHandler<WorkspaceItemEventArgs> WorkspaceItemUnloaded;
1209
public event EventHandler<WorkspaceItemEventArgs> WorkspaceItemOpened;
1210
public event EventHandler<WorkspaceItemEventArgs> WorkspaceItemClosed;
1211
public event EventHandler<UserPreferencesEventArgs> StoringUserPreferences;
1212
public event EventHandler<UserPreferencesEventArgs> LoadingUserPreferences;
1213
public event EventHandler<ItemUnloadingEventArgs> ItemUnloading;
1215
public event EventHandler<SolutionEventArgs> CurrentSelectedSolutionChanged;
1217
public event ProjectReferenceEventHandler ReferenceAddedToProject;
1218
public event ProjectReferenceEventHandler ReferenceRemovedFromProject;
1220
// Fired just before an entry is added to a combine
1221
public event SolutionItemEventHandler ItemAddedToSolution;
1222
public event SolutionItemEventHandler ItemRemovedFromSolution;
1224
public event EventHandler ActiveConfigurationChanged;
1225
public event EventHandler ConfigurationsChanged;
1227
public event EventHandler RuntimesChanged {
1228
add { Runtime.SystemAssemblyService.RuntimesChanged += value; }
1229
remove { Runtime.SystemAssemblyService.RuntimesChanged -= value; }
1232
public event EventHandler ActiveRuntimeChanged {
1233
add { Runtime.SystemAssemblyService.DefaultRuntimeChanged += value; }
1234
remove { Runtime.SystemAssemblyService.DefaultRuntimeChanged -= value; }
1239
class RootWorkspaceItemCollection: WorkspaceItemCollection
1241
RootWorkspace parent;
1243
public RootWorkspaceItemCollection (RootWorkspace parent)
1245
this.parent = parent;
1248
protected override void ClearItems ()
1250
if (parent != null) {
1251
List<WorkspaceItem> items = new List<WorkspaceItem> (this);
1252
foreach (WorkspaceItem it in items)
1253
parent.NotifyItemRemoved (it);
1259
protected override void InsertItem (int index, WorkspaceItem item)
1261
base.InsertItem (index, item);
1263
parent.NotifyItemAdded (item);
1266
protected override void RemoveItem (int index)
1268
WorkspaceItem item = this [index];
1269
base.RemoveItem (index);
1271
parent.NotifyItemRemoved (item);
1274
protected override void SetItem (int index, WorkspaceItem item)
1276
WorkspaceItem oldItem = this [index];
1277
base.SetItem (index, item);
1278
if (parent != null) {
1279
parent.NotifyItemRemoved (oldItem);
1280
parent.NotifyItemAdded (item);
1285
public class UserPreferencesEventArgs: WorkspaceItemEventArgs
1287
PropertyBag properties;
1289
public PropertyBag Properties {
1295
public UserPreferencesEventArgs (WorkspaceItem item, PropertyBag properties): base (item)
1297
this.properties = properties;
1301
[DataItem ("Workspace")]
1302
class WorkspaceUserData
1305
public string ActiveConfiguration;
1307
public string ActiveRuntime;
1310
public class ItemUnloadingEventArgs: EventArgs
1314
public bool Cancel { get; set; }
1316
public IBuildTarget Item {
1322
public ItemUnloadingEventArgs (IBuildTarget item)
1329
namespace Mono.Profiler {
1330
public class RuntimeControls {
1332
[MethodImplAttribute(MethodImplOptions.InternalCall)]
1333
public static extern void TakeHeapSnapshot ();
1335
[MethodImplAttribute(MethodImplOptions.InternalCall)]
1336
public static extern void EnableProfiler ();
1338
[MethodImplAttribute(MethodImplOptions.InternalCall)]
1339
public static extern void DisableProfiler ();