You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
16 KiB
514 lines
16 KiB
// <file> |
|
// <copyright see="prj:///doc/copyright.txt"/> |
|
// <license see="prj:///doc/license.txt"/> |
|
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> |
|
// <version>$Revision$</version> |
|
// </file> |
|
|
|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using System.Diagnostics; |
|
using System.Threading; |
|
using System.Windows; |
|
using System.Windows.Input; |
|
using System.Windows.Controls; |
|
|
|
using ICSharpCode.Core; |
|
using ICSharpCode.Core.Presentation; |
|
using ICSharpCode.SharpDevelop.Gui; |
|
using ICSharpCode.SharpDevelop.Internal.ExternalTool; |
|
using ICSharpCode.SharpDevelop.Project; |
|
using ICSharpCode.SharpDevelop.Util; |
|
|
|
namespace ICSharpCode.SharpDevelop.Commands |
|
{ |
|
public class NavigationHistoryMenuBuilder : IMenuItemBuilder |
|
{ |
|
// TODO: refactor BuildSubmenu to add a choice between flat and perfile, eventually per class/method sorting of the list |
|
|
|
/*ToolStripItem[] BuildMenuFlat(ICollection<INavigationPoint> points, int additionalItems) |
|
{ |
|
ToolStripItem[] items = new ToolStripItem[points.Count+additionalItems]; |
|
MenuCommand cmd = null; |
|
INavigationPoint p = null; |
|
List<INavigationPoint> list = new List<INavigationPoint>(points); |
|
|
|
int n = points.Count-1; // the last point |
|
int i = 0; |
|
while (i<points.Count) { |
|
p = list[n-i]; |
|
cmd = new MenuCommand(p.Description, new EventHandler(NavigateTo)); |
|
cmd.Tag = p; |
|
// if (p == NavigationService.CurrentPosition) { |
|
// cmd.Text = "*** "+cmd.Text; |
|
// } |
|
items[i++] = cmd; |
|
} |
|
return items; |
|
}*/ |
|
List<FrameworkElement> BuildMenuByFile(ICollection<INavigationPoint> points) |
|
{ |
|
List<FrameworkElement> items = new List<FrameworkElement>(); |
|
Dictionary<string, List<INavigationPoint>> files = |
|
new Dictionary<string, List<INavigationPoint>>(); |
|
List<string> fileNames = new List<string>(); |
|
|
|
foreach (INavigationPoint p in points) { |
|
if (p.FileName==null) { |
|
throw new ApplicationException("should not get here!"); |
|
} |
|
if (!fileNames.Contains(p.FileName)) { |
|
fileNames.Add(p.FileName); |
|
files.Add(p.FileName, new List<INavigationPoint>()); |
|
} |
|
if (!files[p.FileName].Contains(p)) { |
|
files[p.FileName].Add(p); |
|
} |
|
} |
|
|
|
fileNames.Sort(); |
|
|
|
MenuItem containerItem = null; |
|
MenuItem cmd = null; |
|
|
|
foreach (string fname in fileNames) { |
|
|
|
// create a menu bucket |
|
containerItem = new MenuItem(); |
|
containerItem.Header = System.IO.Path.GetFileName(fname); |
|
containerItem.ToolTip = fname; |
|
|
|
// sort and populate the bucket's contents |
|
// files[fname].Sort(); |
|
foreach(INavigationPoint p in files[fname]) { |
|
cmd = new MenuItem(); |
|
cmd.Header = p.Description; |
|
cmd.Click += NavigateTo; |
|
cmd.Tag = p; |
|
containerItem.Items.Add(cmd); |
|
} |
|
|
|
// if there's only one nested item, add it |
|
// to the result directly, ignoring the bucket |
|
// if (containerItem.DropDownItems.Count==1) { |
|
// items[i] = containerItem.DropDownItems[0]; |
|
// items[i].Text = ((INavigationPoint)items[i].Tag).FullDescription; |
|
// i++; |
|
// } else { |
|
// // add the bucket to the result |
|
// items[i++] = containerItem; |
|
// } |
|
// add the bucket to the result |
|
items.Add(containerItem); |
|
} |
|
|
|
return items; |
|
} |
|
|
|
public ICollection BuildItems(Codon codon, object owner) |
|
{ |
|
if (NavigationService.CanNavigateBack || NavigationService.CanNavigateForwards) { |
|
ICollection<INavigationPoint> points = NavigationService.Points; |
|
|
|
//ToolStripItem[] items = BuildMenuFlat(points, numberOfAdditionalItems); |
|
var result = BuildMenuByFile(points); |
|
|
|
// additional item 1 |
|
result.Add(new Separator()); |
|
|
|
// additional item 2 |
|
MenuItem clearHistory = new MenuItem(); |
|
clearHistory.Header = StringParser.Parse("${res:XML.MainMenu.Navigation.ClearHistory}"); |
|
clearHistory.Click += delegate { NavigationService.ClearHistory(); }; |
|
result.Add(clearHistory); |
|
|
|
return result; |
|
} |
|
|
|
// default is to disable the dropdown feature... |
|
return null; |
|
} |
|
|
|
public void NavigateTo(object sender, EventArgs e) |
|
{ |
|
MenuItem item = (MenuItem)sender; |
|
NavigationService.Go((INavigationPoint)item.Tag); |
|
} |
|
} |
|
|
|
public class RecentFilesMenuBuilder : IMenuItemBuilder |
|
{ |
|
public ICollection BuildItems(Codon codon, object owner) |
|
{ |
|
RecentOpen recentOpen = FileService.RecentOpen; |
|
|
|
if (recentOpen.RecentFile.Count > 0) { |
|
var items = new System.Windows.Controls.MenuItem[recentOpen.RecentFile.Count]; |
|
|
|
for (int i = 0; i < recentOpen.RecentFile.Count; ++i) { |
|
// variable inside loop, so that anonymous method refers to correct recent file |
|
string recentFile = recentOpen.RecentFile[i]; |
|
string accelaratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10) + " " : ""; |
|
items[i] = new System.Windows.Controls.MenuItem() { |
|
Header = accelaratorKeyPrefix + recentFile |
|
}; |
|
items[i].Click += delegate { |
|
FileService.OpenFile(recentFile); |
|
}; |
|
} |
|
return items; |
|
} else { |
|
return new [] { new System.Windows.Controls.MenuItem { |
|
Header = StringParser.Parse("${res:Dialog.Componnents.RichMenuItem.NoRecentFilesString}"), |
|
IsEnabled = false |
|
} }; |
|
} |
|
} |
|
} |
|
|
|
public class RecentProjectsMenuBuilder : IMenuItemBuilder |
|
{ |
|
public ICollection BuildItems(Codon codon, object owner) |
|
{ |
|
RecentOpen recentOpen = FileService.RecentOpen; |
|
|
|
if (recentOpen.RecentProject.Count > 0) { |
|
var items = new System.Windows.Controls.MenuItem[recentOpen.RecentProject.Count]; |
|
|
|
for (int i = 0; i < recentOpen.RecentProject.Count; ++i) { |
|
// variable inside loop, so that anonymous method refers to correct recent file |
|
string recentProject = recentOpen.RecentProject[i]; |
|
string accelaratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10) + " " : ""; |
|
items[i] = new System.Windows.Controls.MenuItem() { |
|
Header = accelaratorKeyPrefix + recentProject |
|
}; |
|
items[i].Click += delegate { |
|
ProjectService.LoadSolution(recentProject); |
|
}; |
|
} |
|
return items; |
|
} else { |
|
return new [] { new System.Windows.Controls.MenuItem { |
|
Header = StringParser.Parse("${res:Dialog.Componnents.RichMenuItem.NoRecentProjectsString}"), |
|
IsEnabled = false |
|
} }; |
|
} |
|
} |
|
} |
|
|
|
public class ToolMenuBuilder : IMenuItemBuilder |
|
{ |
|
public ICollection BuildItems(Codon codon, object owner) |
|
{ |
|
var items = new System.Windows.Controls.MenuItem[ToolLoader.Tool.Count]; |
|
for (int i = 0; i < ToolLoader.Tool.Count; ++i) { |
|
ExternalTool tool = ToolLoader.Tool[i]; |
|
items[i] = new System.Windows.Controls.MenuItem { |
|
Header = tool.ToString() |
|
}; |
|
items[i].Click += delegate { RunTool(tool); }; |
|
} |
|
return items; |
|
} |
|
|
|
void RunTool(ExternalTool tool) |
|
{ |
|
// Set these to somewhat useful values in case StingParser.Parse() passes when being called on one of them. |
|
string command = tool.Command; |
|
string args = tool.Arguments; |
|
|
|
// This needs it's own try/catch because if parsing these messages fail, the catch block after |
|
// the second try would also throw because MessageService.ShowError() calls StringParser.Parse() |
|
try { |
|
command = StringParser.Parse(tool.Command); |
|
args = StringParser.Parse(tool.Arguments); |
|
} catch (Exception ex) { |
|
MessageService.ShowError("${res:XML.MainMenu.ToolMenu.ExternalTools.ExecutionFailed} '" + ex.Message); |
|
return; |
|
} |
|
|
|
if (tool.PromptForArguments) { |
|
args = MessageService.ShowInputBox(tool.MenuCommand, "${res:XML.MainMenu.ToolMenu.ExternalTools.EnterArguments}", args); |
|
if (args == null) |
|
return; |
|
} |
|
|
|
try { |
|
if (tool.UseOutputPad) { |
|
ProcessRunner processRunner = new ProcessRunner(); |
|
processRunner.LogStandardOutputAndError = false; |
|
processRunner.ProcessExited += ProcessExitEvent; |
|
processRunner.OutputLineReceived += process_OutputLineReceived; |
|
processRunner.ErrorLineReceived += process_OutputLineReceived; |
|
processRunner.WorkingDirectory = StringParser.Parse(tool.InitialDirectory); |
|
if (args == null || args.Length == 0 || args.Trim('"', ' ').Length == 0) { |
|
processRunner.Start(command); |
|
} else { |
|
processRunner.Start(command, args); |
|
} |
|
} else { |
|
ProcessStartInfo startinfo; |
|
if (args == null || args.Length == 0 || args.Trim('"', ' ').Length == 0) { |
|
startinfo = new ProcessStartInfo(command); |
|
} else { |
|
startinfo = new ProcessStartInfo(command, args); |
|
} |
|
startinfo.WorkingDirectory = StringParser.Parse(tool.InitialDirectory); |
|
Process process = new Process(); |
|
process.StartInfo = startinfo; |
|
process.Start(); |
|
} |
|
} catch (Exception ex) { |
|
MessageService.ShowError("${res:XML.MainMenu.ToolMenu.ExternalTools.ExecutionFailed} '" + command + " " + args + "'\n" + ex.Message); |
|
} |
|
} |
|
|
|
void ProcessExitEvent(object sender, EventArgs e) |
|
{ |
|
WorkbenchSingleton.SafeThreadAsyncCall( |
|
delegate { |
|
ProcessRunner p = (ProcessRunner)sender; |
|
TaskService.BuildMessageViewCategory.AppendLine(StringParser.Parse("${res:XML.MainMenu.ToolMenu.ExternalTools.ExitedWithCode} " + p.ExitCode)); |
|
p.Dispose(); |
|
}); |
|
} |
|
|
|
void process_OutputLineReceived(object sender, LineReceivedEventArgs e) |
|
{ |
|
TaskService.BuildMessageViewCategory.AppendLine(e.Line); |
|
} |
|
} |
|
|
|
public class OpenContentsMenuBuilder : IMenuItemBuilder |
|
{ |
|
public ICollection BuildItems(Codon codon, object owner) |
|
{ |
|
int windowCount = WorkbenchSingleton.Workbench.WorkbenchWindowCollection.Count; |
|
if (windowCount == 0) { |
|
return new object[] {}; |
|
} |
|
var items = new object[windowCount + 1]; |
|
items[0] = new System.Windows.Controls.Separator(); |
|
for (int i = 0; i < windowCount; ++i) { |
|
IWorkbenchWindow window = WorkbenchSingleton.Workbench.WorkbenchWindowCollection[i]; |
|
var item = new System.Windows.Controls.MenuItem() { |
|
IsChecked = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow == window, |
|
IsCheckable = true, |
|
Header = StringParser.Parse(window.Title) |
|
}; |
|
item.Click += delegate { |
|
window.SelectWindow(); |
|
}; |
|
items[i + 1] = item; |
|
} |
|
return items; |
|
} |
|
} |
|
|
|
// public class IncludeFilesBuilder : ISubmenuBuilder |
|
// { |
|
// public ProjectBrowserView browser; |
|
// |
|
// MyMenuItem includeInCompileItem; |
|
// MyMenuItem includeInDeployItem; |
|
// |
|
// class MyMenuItem : MenuCheckBox |
|
// { |
|
// IncludeFilesBuilder builder; |
|
// |
|
// public MyMenuItem(IncludeFilesBuilder builder, string name, EventHandler handler) : base(null, null, name) |
|
// { |
|
// base.Click += handler; |
|
// this.builder = builder; |
|
// } |
|
// |
|
// public override void UpdateStatus() |
|
// { |
|
// base.UpdateStatus(); |
|
// if (builder == null) { |
|
// return; |
|
// } |
|
// AbstractBrowserNode node = builder.browser.SelectedNode as AbstractBrowserNode; |
|
// |
|
// if (node == null) { |
|
// return; |
|
// } |
|
// |
|
// ProjectFile finfo = node.UserData as ProjectFile; |
|
// if (finfo == null) { |
|
// builder.includeInCompileItem.Enabled = builder.includeInCompileItem.Enabled = false; |
|
// } else { |
|
// if (!builder.includeInCompileItem.Enabled) { |
|
// builder.includeInCompileItem.Enabled = builder.includeInCompileItem.Enabled = true; |
|
// } |
|
// builder.includeInCompileItem.Checked = finfo.BuildAction == BuildAction.Compile; |
|
// builder.includeInDeployItem.Checked = !node.Project.DeployInformation.IsFileExcluded(finfo.Name); |
|
// } |
|
// } |
|
// } |
|
// |
|
// public ToolStripItem[] BuildSubmenu(Codon codon, object owner) |
|
// { |
|
// browser = (ProjectBrowserView)owner; |
|
// includeInCompileItem = new MyMenuItem(this, "${res:ProjectComponent.ContextMenu.IncludeMenu.InCompile}", new EventHandler(ChangeCompileInclude)); |
|
// includeInDeployItem = new MyMenuItem(this, "${res:ProjectComponent.ContextMenu.IncludeMenu.InDeploy}", new EventHandler(ChangeDeployInclude)); |
|
// |
|
// return new ToolStripItem[] { |
|
// includeInCompileItem, |
|
// includeInDeployItem |
|
// }; |
|
// |
|
// } |
|
// void ChangeCompileInclude(object sender, EventArgs e) |
|
// { |
|
// AbstractBrowserNode node = browser.SelectedNode as AbstractBrowserNode; |
|
// |
|
// if (node == null) { |
|
// return; |
|
// } |
|
// |
|
// ProjectFile finfo = node.UserData as ProjectFile; |
|
// if (finfo != null) { |
|
// if (finfo.BuildAction == BuildAction.Compile) { |
|
// finfo.BuildAction = BuildAction.Nothing; |
|
// } else { |
|
// finfo.BuildAction = BuildAction.Compile; |
|
// } |
|
// } |
|
// |
|
// ProjectService.SaveCombine(); |
|
// } |
|
// |
|
// void ChangeDeployInclude(object sender, EventArgs e) |
|
// { |
|
// AbstractBrowserNode node = browser.SelectedNode as AbstractBrowserNode; |
|
// |
|
// if (node == null) { |
|
// return; |
|
// } |
|
// |
|
// ProjectFile finfo = node.UserData as ProjectFile; |
|
// if (finfo != null) { |
|
// if (node.Project.DeployInformation.IsFileExcluded(finfo.Name)) { |
|
// node.Project.DeployInformation.RemoveExcludedFile(finfo.Name); |
|
// } else { |
|
// node.Project.DeployInformation.AddExcludedFile(finfo.Name); |
|
// } |
|
// } |
|
// |
|
// ProjectService.SaveCombine(); |
|
// } |
|
// } |
|
|
|
public class ToolsViewMenuBuilder : ViewMenuBuilder |
|
{ |
|
protected override string Category { |
|
get { |
|
return "Tools"; |
|
} |
|
} |
|
} |
|
|
|
public class MainViewMenuBuilder : ViewMenuBuilder |
|
{ |
|
protected override string Category { |
|
get { |
|
return "Main"; |
|
} |
|
} |
|
} |
|
|
|
public class DebugViewMenuBuilder : ViewMenuBuilder |
|
{ |
|
protected override string Category { |
|
get { |
|
return "Debugger"; |
|
} |
|
} |
|
} |
|
|
|
public abstract class ViewMenuBuilder : IMenuItemBuilder |
|
{ |
|
class BringPadToFrontCommand : System.Windows.Input.ICommand |
|
{ |
|
PadDescriptor padDescriptor; |
|
|
|
public BringPadToFrontCommand(PadDescriptor padDescriptor) |
|
{ |
|
this.padDescriptor = padDescriptor; |
|
} |
|
|
|
public event EventHandler CanExecuteChanged { add {} remove {} } |
|
|
|
public void Execute(object parameter) |
|
{ |
|
padDescriptor.BringPadToFront(); |
|
} |
|
|
|
public bool CanExecute(object parameter) |
|
{ |
|
return true; |
|
} |
|
} |
|
|
|
protected abstract string Category { |
|
get; |
|
} |
|
|
|
public List<string> bindingsAssigned = new List<string>(); |
|
|
|
public ICollection BuildItems(Codon codon, object owner) |
|
{ |
|
ArrayList list = new ArrayList(); |
|
foreach (PadDescriptor padContent in WorkbenchSingleton.Workbench.PadContentCollection) { |
|
if (padContent.Category == Category) { |
|
var item = new System.Windows.Controls.MenuItem(); |
|
item.Header = ICSharpCode.Core.Presentation.MenuService.ConvertLabel(StringParser.Parse(padContent.Title)); |
|
if (!string.IsNullOrEmpty(padContent.Icon)) { |
|
item.Icon = PresentationResourceService.GetPixelSnappedImage(padContent.Icon); |
|
} |
|
|
|
var routedCommandName = "SDViewCommands.ShowView_" + padContent.Class; |
|
var routedCommandText = "Show view " + MenuService.ConvertLabel(StringParser.Parse(padContent.Title)); |
|
|
|
// TODO: fix this hack |
|
if(!bindingsAssigned.Contains(routedCommandName)) { |
|
// Dynamicaly create routed UI command to loaded pad and bindings for it |
|
CommandsRegistry.RegisterRoutedUICommand(routedCommandName, routedCommandText); |
|
CommandsRegistry.LoadCommand(routedCommandName, new BringPadToFrontCommand(padContent)); |
|
CommandsRegistry.RegisterCommandBinding(CommandsRegistry.DefaultContext, null, routedCommandName, routedCommandName, null, false); |
|
|
|
// If pad have shortcut specified add input binding |
|
if (!string.IsNullOrEmpty(padContent.Shortcut)) { |
|
var gestures = (InputGestureCollection)new InputGestureCollectionConverter().ConvertFromString(padContent.Shortcut); |
|
foreach(InputGesture gesture in gestures) { |
|
CommandsRegistry.RegisterInputBinding(CommandsRegistry.DefaultContext, null, routedCommandName, gesture); |
|
} |
|
} |
|
|
|
bindingsAssigned.Add(routedCommandName); |
|
} |
|
|
|
CommandsRegistry.InvokeCommandBindingUpdateHandlers(CommandsRegistry.DefaultContext, null); |
|
CommandsRegistry.InvokeInputBindingUpdateHandlers(CommandsRegistry.DefaultContext, null); |
|
|
|
item.InputGestureText = padContent.Shortcut; |
|
item.Command = CommandsRegistry.GetRoutedUICommand(routedCommandName); |
|
|
|
// item.Command = new BringPadToFrontCommand(padContent); |
|
// if (!string.IsNullOrEmpty(padContent.Shortcut)) { |
|
// var kg = Core.Presentation.MenuService.ParseShortcut(padContent.Shortcut); |
|
// WorkbenchSingleton.MainWindow.InputBindings.Add( |
|
// new System.Windows.Input.InputBinding(item.Command, kg) |
|
// ); |
|
// item.InputGestureText = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); |
|
// } |
|
|
|
list.Add(item); |
|
} |
|
} |
|
return list; |
|
} |
|
} |
|
}
|
|
|