diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
index bbd1bd8c3a..8b67c9d3b0 100755
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
@@ -32,6 +32,7 @@
+
@@ -473,14 +474,14 @@
-
+
-
+
+
+
+
+
diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index bcedbeeb4f..4209301749 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -340,6 +340,9 @@
+
+
+
@@ -913,6 +916,7 @@
False
+
diff --git a/src/Main/Base/Project/Src/Project/AbstractProject.cs b/src/Main/Base/Project/Src/Project/AbstractProject.cs
index 66b0cfbd30..87ac8655c7 100644
--- a/src/Main/Base/Project/Src/Project/AbstractProject.cs
+++ b/src/Main/Base/Project/Src/Project/AbstractProject.cs
@@ -305,7 +305,7 @@ namespace ICSharpCode.SharpDevelop.Project
[Browsable(false)]
public virtual ICollection AvailableFileItemTypes {
get {
- return ItemType.DefaultFileItems;
+ return GetOrCreateBehavior().AvailableFileItemTypes;
}
}
@@ -386,7 +386,7 @@ namespace ICSharpCode.SharpDevelop.Project
[Browsable(false)]
public virtual bool IsStartable {
get {
- return false;
+ return GetOrCreateBehavior().IsStartable;
}
}
@@ -399,18 +399,7 @@ namespace ICSharpCode.SharpDevelop.Project
public virtual void Start(bool withDebugging)
{
- ProcessStartInfo psi;
- try {
- psi = CreateStartInfo();
- } catch (ProjectStartException ex) {
- MessageService.ShowError(ex.Message);
- return;
- }
- if (withDebugging) {
- DebuggerService.CurrentDebugger.Start(psi);
- } else {
- DebuggerService.CurrentDebugger.StartWithoutDebugging(psi);
- }
+ GetOrCreateBehavior().Start(withDebugging);
}
///
@@ -421,7 +410,7 @@ namespace ICSharpCode.SharpDevelop.Project
/// Note: this can be a ProcessStartInfo with a URL as filename!
public virtual ProcessStartInfo CreateStartInfo()
{
- throw new NotSupportedException();
+ return GetOrCreateBehavior().CreateStartInfo();
}
///
@@ -481,7 +470,7 @@ namespace ICSharpCode.SharpDevelop.Project
///
public virtual ProjectItem CreateProjectItem(IProjectItemBackendStore item)
{
- return new UnknownProjectItem(this, item);
+ return GetOrCreateBehavior().CreateProjectItem(item);
}
#region Dirty
@@ -513,7 +502,7 @@ namespace ICSharpCode.SharpDevelop.Project
///
public virtual ItemType GetDefaultItemType(string fileName)
{
- return ItemType.None;
+ return GetOrCreateBehavior().GetDefaultItemType(fileName);
}
[Browsable(false)]
@@ -611,6 +600,7 @@ namespace ICSharpCode.SharpDevelop.Project
public virtual void ProjectCreationComplete()
{
+ GetOrCreateBehavior().ProjectCreationComplete();
}
public virtual XElement LoadProjectExtensions(string name)
@@ -626,5 +616,19 @@ namespace ICSharpCode.SharpDevelop.Project
public Properties ProjectSpecificProperties {
get; protected set;
}
+
+ protected virtual ProjectBehavior CreateDefaultBehavior()
+ {
+ return new DefaultProjectBehavior(this);
+ }
+
+ protected ProjectBehavior projectBehavior;
+
+ protected virtual ProjectBehavior GetOrCreateBehavior()
+ {
+ if (projectBehavior == null)
+ projectBehavior = ProjectBehaviorService.LoadBehaviorsForProject(this, CreateDefaultBehavior());
+ return projectBehavior;
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehavior.cs b/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehavior.cs
new file mode 100644
index 0000000000..ec23507b81
--- /dev/null
+++ b/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehavior.cs
@@ -0,0 +1,144 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Debugging;
+
+namespace ICSharpCode.SharpDevelop.Project
+{
+ public abstract class ProjectBehavior
+ {
+ ProjectBehavior next;
+ protected IProject Project { get; private set; }
+
+ public ProjectBehavior(IProject project, ProjectBehavior next = null)
+ {
+ if (project == null)
+ throw new ArgumentNullException("project");
+ this.Project = project;
+ this.next = next;
+ }
+
+ internal void SetProject(IProject project)
+ {
+ if (project == null)
+ throw new ArgumentNullException("project");
+ this.Project = project;
+ }
+
+ internal void SetNext(ProjectBehavior next)
+ {
+ if (next == null)
+ throw new ArgumentNullException("next");
+ this.next = next;
+ }
+
+ public virtual bool IsStartable {
+ get {
+ if (this.next != null)
+ return next.IsStartable;
+ return false;
+ }
+ }
+
+ public virtual void Start(bool withDebugging)
+ {
+ if (this.next != null)
+ next.Start(withDebugging);
+ }
+
+ public virtual ProcessStartInfo CreateStartInfo()
+ {
+ if (this.next != null)
+ return next.CreateStartInfo();
+ return null;
+ }
+
+ public virtual ItemType GetDefaultItemType(string fileName)
+ {
+ if (this.next != null)
+ return next.GetDefaultItemType(fileName);
+ return default(ItemType);
+ }
+
+ public virtual ProjectItem CreateProjectItem(IProjectItemBackendStore item)
+ {
+ if (this.next != null)
+ return next.CreateProjectItem(item);
+ return null;
+ }
+
+ public virtual ICollection AvailableFileItemTypes {
+ get {
+ if (this.next != null)
+ return next.AvailableFileItemTypes;
+ return null;
+ }
+ }
+
+ public virtual void ProjectCreationComplete()
+ {
+ if (this.next != null)
+ next.ProjectCreationComplete();
+ }
+ }
+
+ sealed class DefaultProjectBehavior : ProjectBehavior
+ {
+ public DefaultProjectBehavior(IProject project)
+ : base(project)
+ {
+ }
+
+ public override bool IsStartable {
+ get { return false; }
+ }
+
+ public override void Start(bool withDebugging)
+ {
+ ProcessStartInfo psi;
+ try {
+ if (!(Project is AbstractProject))
+ return;
+ psi = ((AbstractProject)Project).CreateStartInfo();
+ } catch (ProjectStartException ex) {
+ MessageService.ShowError(ex.Message);
+ return;
+ }
+ if (withDebugging) {
+ DebuggerService.CurrentDebugger.Start(psi);
+ } else {
+ DebuggerService.CurrentDebugger.StartWithoutDebugging(psi);
+ }
+ }
+
+ public override ProcessStartInfo CreateStartInfo()
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ItemType GetDefaultItemType(string fileName)
+ {
+ return ItemType.None;
+ }
+
+ public override ProjectItem CreateProjectItem(IProjectItemBackendStore item)
+ {
+ return new UnknownProjectItem(Project, item);
+ }
+
+ public override ICollection AvailableFileItemTypes {
+ get { return ItemType.DefaultFileItems; }
+ }
+
+ public override void ProjectCreationComplete()
+ {
+
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehaviorService.cs b/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehaviorService.cs
new file mode 100644
index 0000000000..37c4f48b89
--- /dev/null
+++ b/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehaviorService.cs
@@ -0,0 +1,32 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using ICSharpCode.Core;
+
+namespace ICSharpCode.SharpDevelop.Project
+{
+ public static class ProjectBehaviorService
+ {
+ const string AddInPath = "/SharpDevelop/Workbench/ProjectBehaviors";
+
+ public static ProjectBehavior LoadBehaviorsForProject(IProject project, ProjectBehavior defaultBehavior)
+ {
+ List behaviors = AddInTree.BuildItems(AddInPath, project, false);
+ ProjectBehavior first = null, current = null;
+ foreach (var behavior in behaviors) {
+ behavior.SetProject(project);
+ if (first == null)
+ first = behavior;
+ else
+ current.SetNext(behavior);
+ current = behavior;
+ }
+ if (current == null)
+ return defaultBehavior;
+ current.SetNext(defaultBehavior);
+ return first;
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehaviorSupportedConditionEvaluator.cs b/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehaviorSupportedConditionEvaluator.cs
new file mode 100644
index 0000000000..722ada79b3
--- /dev/null
+++ b/src/Main/Base/Project/Src/Project/Behaviors/ProjectBehaviorSupportedConditionEvaluator.cs
@@ -0,0 +1,47 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.Core;
+
+namespace ICSharpCode.SharpDevelop.Project
+{
+ public class ProjectBehaviorSupportedConditionEvaluator : IConditionEvaluator
+ {
+ public bool IsValid(object owner, Condition condition)
+ {
+ Guid conditionGuid;
+ if (!Guid.TryParse(condition.Properties["guid"], out conditionGuid))
+ return true;
+
+ string guidString;
+ if (owner is IProject)
+ guidString = FindGuidInProject((IProject)owner);
+ else if (ProjectService.CurrentProject != null)
+ guidString = FindGuidInProject(ProjectService.CurrentProject);
+ else
+ return false;
+
+ Guid result;
+ foreach (string guid in guidString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) {
+ if (Guid.TryParse(guid, out result) && conditionGuid == result)
+ return true;
+ }
+
+ return false;
+ }
+
+ string FindGuidInProject(IProject project)
+ {
+ if (project is MSBuildBasedProject) {
+ string guid = ((MSBuildBasedProject)project).GetEvaluatedProperty("ProjectTypeGuids");
+ if (!string.IsNullOrEmpty(guid))
+ return guid;
+ }
+
+ return project.TypeGuid;
+ }
+ }
+}