From 80c40ac4801dd4e44a154b7bbf69e87d6658d85f Mon Sep 17 00:00:00 2001
From: Daniel Grunwald <daniel@danielgrunwald.de>
Date: Tue, 2 Jun 2009 14:03:47 +0000
Subject: [PATCH] Fixed action="disable" conditions on WPF Menus. Allow AddIns
 to choose a free title for searches.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4205 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
---
 AddIns/ICSharpCode.SharpDevelop.addin           | 14 ++------------
 .../Engine/SearchReplaceInFilesManager.cs       |  4 +++-
 .../Project/Gui/DefaultSearchResult.cs          | 14 +++++++-------
 .../Project/Gui/SearchRootNode.cs               | 15 +++++----------
 .../Highlighting/Resources/CSharp-Mode.xshd     |  2 +-
 .../Src/Editor/Search/ISearchResultFactory.cs   |  2 +-
 .../Src/Editor/Search/SearchResultsPad.cs       | 14 +++++++-------
 .../FindReferencesAndRenameHelper.cs            |  4 ++--
 .../Menu/CoreMenuItem.cs                        | 11 ++++++++++-
 .../Menu/MenuService.cs                         | 17 +++++++++++------
 10 files changed, 49 insertions(+), 48 deletions(-)

diff --git a/AddIns/ICSharpCode.SharpDevelop.addin b/AddIns/ICSharpCode.SharpDevelop.addin
index a55d62fcd6..71d266ef5f 100644
--- a/AddIns/ICSharpCode.SharpDevelop.addin
+++ b/AddIns/ICSharpCode.SharpDevelop.addin
@@ -1370,17 +1370,7 @@
 		</Condition> <!-- end PROJECT menu -->
 		
 		<MenuItem id = "Build" label = "${res:XML.MainMenu.BuildMenu}" type="Menu">
-			<ComplexCondition action="Disable">
-				<Or>
-					<!--<And>
-						<Or>
-							<Condition name = "WindowActive" activewindow="ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.ITextEditorControlProvider"/>
-							<Condition name = "WindowActive" activewindow="ICSharpCode.FormsDesigner.FormsDesignerViewContent"/>
-						</Or>
-						<Condition name = "ActiveViewContentUntitled" activewindowuntitled="False"/>
-					</And>-->
-					<Condition name = "SolutionOpen"/>
-				</Or>
+			<Condition name = "SolutionOpen" action="Disable">
 				<MenuItem id       = "Build"
 				          label    = "${res:XML.MainMenu.BuildMenu.BuildSolution}"
 				          shortcut = "F8"
@@ -1431,7 +1421,7 @@
 				<MenuItem id = "EditConfigurations"
 				          label = "${res:XML.MainMenu.BuildMenu.EditConfigurationsPlatforms}"
 				          class = "ICSharpCode.SharpDevelop.Project.Commands.EditConfigurationsCommand"/>
-			</ComplexCondition>
+			</Condition>
 		</MenuItem> <!-- end BUILD menu -->
 		
 		<MenuItem id = "Debug" label = "${res:XML.MainMenu.DebugMenu}" type="Menu">
diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceInFilesManager.cs b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceInFilesManager.cs
index 81ebefd250..31a698e5eb 100644
--- a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceInFilesManager.cs
+++ b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceInFilesManager.cs
@@ -50,7 +50,9 @@ namespace SearchAndReplace
 		
 		public static void ShowSearchResults(string pattern, List<SearchResultMatch> results)
 		{
-			SearchResultsPad.Instance.ShowSearchResults(pattern, results);
+			string title = StringParser.Parse("${res:MainWindow.Windows.SearchResultPanel.OccurrencesOf}",
+			                                  new string[,] {{ "Pattern", pattern }});
+			SearchResultsPad.Instance.ShowSearchResults(title, results);
 			SearchResultsPad.Instance.BringToFront();
 		}
 		
diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Gui/DefaultSearchResult.cs b/src/AddIns/Misc/SearchAndReplace/Project/Gui/DefaultSearchResult.cs
index 93a0bb49cd..77513c6e13 100644
--- a/src/AddIns/Misc/SearchAndReplace/Project/Gui/DefaultSearchResult.cs
+++ b/src/AddIns/Misc/SearchAndReplace/Project/Gui/DefaultSearchResult.cs
@@ -24,19 +24,19 @@ namespace SearchAndReplace
 		IList<SearchResultMatch> matches;
 		SearchRootNode rootNode;
 		
-		public DefaultSearchResult(string pattern, IEnumerable<SearchResultMatch> matches)
+		public DefaultSearchResult(string title, IEnumerable<SearchResultMatch> matches)
 		{
-			if (pattern == null)
-				throw new ArgumentNullException("pattern");
+			if (title == null)
+				throw new ArgumentNullException("title");
 			if (matches == null)
 				throw new ArgumentNullException("matches");
 			this.matches = matches.ToArray();
-			rootNode = new SearchRootNode(pattern, this.matches);
+			rootNode = new SearchRootNode(title, this.matches);
 		}
 		
 		public string Text {
 			get {
-				return rootNode.GetPatternString() + " (" + SearchRootNode.GetOccurrencesString(rootNode.Occurrences) + ")";
+				return rootNode.Title + " (" + SearchRootNode.GetOccurrencesString(rootNode.Occurrences) + ")";
 			}
 		}
 		
@@ -59,9 +59,9 @@ namespace SearchAndReplace
 	
 	public class DefaultSearchResultFactory : ISearchResultFactory
 	{
-		public ISearchResult CreateSearchResult(string pattern, IEnumerable<SearchResultMatch> matches)
+		public ISearchResult CreateSearchResult(string title, IEnumerable<SearchResultMatch> matches)
 		{
-			return new DefaultSearchResult(pattern, matches);
+			return new DefaultSearchResult(title, matches);
 		}
 	}
 }
diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchRootNode.cs b/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchRootNode.cs
index 70e2c4baef..4ac40cab9e 100644
--- a/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchRootNode.cs
+++ b/src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchRootNode.cs
@@ -35,13 +35,14 @@ namespace SearchAndReplace
 			}
 		}
 		
-		string pattern;
 		IList<SearchResultNode> results;
 		int fileCount;
 		
-		public SearchRootNode(string pattern, IList<SearchResultMatch> results)
+		public string Title { get; private set; }
+		
+		public SearchRootNode(string title, IList<SearchResultMatch> results)
 		{
-			this.pattern = pattern;
+			this.Title = title;
 			this.results = results.Select(r => new SearchResultNode(r)).ToArray();
 			
 			fileCount = results.GroupBy(r => r.FileName, new FileNameComparer()).Count();
@@ -57,7 +58,7 @@ namespace SearchAndReplace
 		{
 			return new TextBlock {
 				Inlines = {
-					new Bold(new Run(GetPatternString())),
+					new Bold(new Run(this.Title)),
 					new Run(" (" + GetOccurrencesString(results.Count)
 					        + StringParser.Parse(" ${res:MainWindow.Windows.SearchResultPanel.In} ")
 					        + GetFileCountString(fileCount) + ")")
@@ -65,12 +66,6 @@ namespace SearchAndReplace
 			};
 		}
 		
-		public string GetPatternString()
-		{
-			return StringParser.Parse("${res:MainWindow.Windows.SearchResultPanel.OccurrencesOf}",
-			                          new string[,] {{ "Pattern", pattern }});
-		}
-		
 		public static string GetOccurrencesString(int count)
 		{
 			if (count == 1) {
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/CSharp-Mode.xshd b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/CSharp-Mode.xshd
index a1ca9a0a66..5f2f5458ab 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/CSharp-Mode.xshd
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/CSharp-Mode.xshd
@@ -9,7 +9,7 @@
 			<Word>TODO</Word>
 			<Word>FIXME</Word>
 		</Keywords>
-		<Keywords fontWeight="bold" foreground="#00EEE0E0">
+		<Keywords fontWeight="bold" foreground="#E0E000">
 			<Word>HACK</Word>
 			<Word>UNDONE</Word>
 		</Keywords>
diff --git a/src/Main/Base/Project/Src/Editor/Search/ISearchResultFactory.cs b/src/Main/Base/Project/Src/Editor/Search/ISearchResultFactory.cs
index 43c938a82e..5e64b11473 100644
--- a/src/Main/Base/Project/Src/Editor/Search/ISearchResultFactory.cs
+++ b/src/Main/Base/Project/Src/Editor/Search/ISearchResultFactory.cs
@@ -15,6 +15,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Search
 	/// </summary>
 	public interface ISearchResultFactory
 	{
-		ISearchResult CreateSearchResult(string pattern, IEnumerable<SearchResultMatch> matches);
+		ISearchResult CreateSearchResult(string title, IEnumerable<SearchResultMatch> matches);
 	}
 }
diff --git a/src/Main/Base/Project/Src/Editor/Search/SearchResultsPad.cs b/src/Main/Base/Project/Src/Editor/Search/SearchResultsPad.cs
index f17984863d..699303e68a 100644
--- a/src/Main/Base/Project/Src/Editor/Search/SearchResultsPad.cs
+++ b/src/Main/Base/Project/Src/Editor/Search/SearchResultsPad.cs
@@ -98,25 +98,25 @@ namespace ICSharpCode.SharpDevelop.Editor.Search
 			SearchResultsShown.RaiseEvent(this, EventArgs.Empty);
 		}
 		
-		public void ShowSearchResults(string pattern, IEnumerable<SearchResultMatch> matches)
+		public void ShowSearchResults(string title, IEnumerable<SearchResultMatch> matches)
 		{
-			ShowSearchResults(CreateSearchResult(pattern, matches));
+			ShowSearchResults(CreateSearchResult(title, matches));
 		}
 		
 		public event EventHandler SearchResultsShown;
 		
-		public static ISearchResult CreateSearchResult(string pattern, IEnumerable<SearchResultMatch> matches)
+		public static ISearchResult CreateSearchResult(string title, IEnumerable<SearchResultMatch> matches)
 		{
-			if (pattern == null)
-				throw new ArgumentNullException("pattern");
+			if (title == null)
+				throw new ArgumentNullException("title");
 			if (matches == null)
 				throw new ArgumentNullException("matches");
 			foreach (ISearchResultFactory factory in AddInTree.BuildItems<ISearchResultFactory>("/SharpDevelop/Pads/SearchResultPad/Factories", null)) {
-				ISearchResult result = factory.CreateSearchResult(pattern, matches);
+				ISearchResult result = factory.CreateSearchResult(title, matches);
 				if (result != null)
 					return result;
 			}
-			return new DummySearchResult { Text = pattern };
+			return new DummySearchResult { Text = title };
 		}
 		
 		sealed class DummySearchResult : ISearchResult
diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
index 8387564822..eafa6266a6 100644
--- a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
+++ b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
@@ -354,7 +354,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
 			}
 		}
 		
-		public static void ShowAsSearchResults(string pattern, List<Reference> list)
+		public static void ShowAsSearchResults(string title, List<Reference> list)
 		{
 			if (list == null) return;
 			List<SearchResultMatch> results = new List<SearchResultMatch>(list.Count);
@@ -362,7 +362,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
 				SearchResultMatch res = new SearchResultMatch(GetDocumentInformation(r.FileName), r.Offset, r.Length);
 				results.Add(res);
 			}
-			SearchResultsPad.Instance.ShowSearchResults(pattern, results);
+			SearchResultsPad.Instance.ShowSearchResults(title, results);
 			SearchResultsPad.Instance.BringToFront();
 		}
 		
diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
index e2642e0acd..da2ebd7a12 100644
--- a/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
@@ -21,6 +21,12 @@ namespace ICSharpCode.Core.Presentation
 		protected readonly Codon codon;
 		protected readonly object caller;
 		
+		/// <summary>
+		/// If true, UpdateStatus() sets the enabled flag.
+		/// Used for type=Menu, but not for type=MenuItem - for menu items, Enabled is controlled by the WPF ICommand.
+		/// </summary>
+		internal bool SetEnabled;
+		
 		public CoreMenuItem(Codon codon, object caller)
 		{
 			this.codon = codon;
@@ -45,10 +51,13 @@ namespace ICSharpCode.Core.Presentation
 		
 		public virtual void UpdateStatus()
 		{
-			if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
+			ConditionFailedAction result = codon.GetFailedAction(caller);
+			if (result == ConditionFailedAction.Exclude)
 				this.Visibility = Visibility.Collapsed;
 			else
 				this.Visibility = Visibility.Visible;
+			if (SetEnabled)
+				this.IsEnabled = result == ConditionFailedAction.Nothing;
 		}
 	}
 }
diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs
index 678fe72ca6..aa5c840c86 100644
--- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs
@@ -105,7 +105,7 @@ namespace ICSharpCode.Core.Presentation
 				ItemsSource = new object[1]
 			};
 			contextMenu.Opened += (sender, args) => {
-				contextMenu.ItemsSource = ExpandMenuBuilders(subItems);
+				contextMenu.ItemsSource = ExpandMenuBuilders(subItems, true);
 				args.Handled = true;
 			};
 			return contextMenu;
@@ -113,7 +113,8 @@ namespace ICSharpCode.Core.Presentation
 		
 		public static IList CreateMenuItems(UIElement inputBindingOwner, object owner, string addInTreePath)
 		{
-			return ExpandMenuBuilders(CreateUnexpandedMenuItems(inputBindingOwner, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false)));
+			IList items = CreateUnexpandedMenuItems(inputBindingOwner, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false));
+			return ExpandMenuBuilders(items, false);
 		}
 		
 		sealed class MenuItemBuilderPlaceholder
@@ -146,7 +147,7 @@ namespace ICSharpCode.Core.Presentation
 			return result;
 		}
 		
-		static IList ExpandMenuBuilders(ICollection input)
+		static IList ExpandMenuBuilders(ICollection input, bool addDummyEntryIfMenuEmpty)
 		{
 			ArrayList result = new ArrayList(input.Count);
 			foreach (object o in input) {
@@ -164,6 +165,9 @@ namespace ICSharpCode.Core.Presentation
 					}
 				}
 			}
+			if (addDummyEntryIfMenuEmpty && result.Count == 0) {
+				result.Add(new MenuItem { Header = "(empty menu)", IsEnabled = false });
+			}
 			return result;
 		}
 		
@@ -184,11 +188,12 @@ namespace ICSharpCode.Core.Presentation
 					return new MenuCommand(inputBindingOwner, codon, descriptor.Caller, createCommand);
 				case "Menu":
 					var item = new CoreMenuItem(codon, descriptor.Caller) {
-						ItemsSource = new object[1]
+						ItemsSource = new object[1],
+						SetEnabled = true
 					};
 					var subItems = CreateUnexpandedMenuItems(inputBindingOwner, descriptor.SubItems);
 					item.SubmenuOpened += (sender, args) => {
-						item.ItemsSource = ExpandMenuBuilders(subItems);
+						item.ItemsSource = ExpandMenuBuilders(subItems, true);
 						args.Handled = true;
 					};
 					return item;
@@ -198,7 +203,7 @@ namespace ICSharpCode.Core.Presentation
 						throw new NotSupportedException("Menu item builder " + codon.Properties["class"] + " does not implement IMenuItemBuilder");
 					return new MenuItemBuilderPlaceholder(builder, descriptor.Codon, descriptor.Caller);
 				default:
-					throw new System.NotSupportedException("unsupported menu item type : " + type);
+					throw new NotSupportedException("unsupported menu item type : " + type);
 			}
 		}