Browse Source

Worked on SD2-1054: Opening a file with different editor

Still missing: "Set as default"

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2646 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 18 years ago
parent
commit
b8e587a202
  1. 8
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 145
      src/Main/Base/Project/Src/Gui/Dialogs/AddOpenWithEntryDialog.Designer.cs
  3. 75
      src/Main/Base/Project/Src/Gui/Dialogs/AddOpenWithEntryDialog.cs
  4. 5
      src/Main/Base/Project/Src/Gui/Dialogs/OpenWithDialog.Designer.cs
  5. 41
      src/Main/Base/Project/Src/Gui/Dialogs/OpenWithDialog.cs
  6. 120
      src/Main/Base/Project/Src/Gui/Dialogs/OpenWithDialog.resx
  7. 4
      src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ExternalToolPanel.cs
  8. 4
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/DefaultFileNodeCommands.cs
  9. 10
      src/Main/Base/Project/Src/Gui/Pads/ToolsPad.cs
  10. 1
      src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs
  11. 77
      src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingDescriptor.cs
  12. 67
      src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs
  13. 116
      src/Main/Base/Project/Src/Services/DisplayBinding/ExternalProcessDisplayBinding.cs

8
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -59,6 +59,10 @@ @@ -59,6 +59,10 @@
<Compile Include="Src\Gui\AbstractViewContentWithoutFile.cs" />
<Compile Include="Src\Gui\BrowserDisplayBinding\BrowserDisplayBinding.cs" />
<Compile Include="Src\Gui\Components\SideBar\TextEditorSideBar.cs" />
<Compile Include="Src\Gui\Dialogs\AddOpenWithEntryDialog.cs" />
<Compile Include="Src\Gui\Dialogs\AddOpenWithEntryDialog.Designer.cs">
<DependentUpon>AddOpenWithEntryDialog.cs</DependentUpon>
</Compile>
<Compile Include="Src\Gui\Dialogs\OpenWithDialog.cs" />
<Compile Include="Src\Gui\Dialogs\OpenWithDialog.Designer.cs">
<DependentUpon>OpenWithDialog.cs</DependentUpon>
@ -83,6 +87,7 @@ @@ -83,6 +87,7 @@
<Compile Include="Src\Project\ProjectPropertyChangedEventArgs.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmarkEventArgs.cs" />
<Compile Include="Src\Services\DisplayBinding\ExternalProcessDisplayBinding.cs" />
<Compile Include="Src\Services\DisplayBinding\ISecondaryDisplayBinding.cs" />
<Compile Include="Src\Services\File\OpenedFile.cs" />
<Compile Include="Src\Services\File\RecentOpen.cs" />
@ -691,9 +696,6 @@ @@ -691,9 +696,6 @@
<Compile Include="Src\TextEditor\Gui\Editor\IncrementalSearch.cs" />
<EmbeddedResource Include="Resources\IncrementalSearchCursor.cur" />
<EmbeddedResource Include="Resources\ReverseIncrementalSearchCursor.cur" />
<EmbeddedResource Include="Src\Gui\Dialogs\OpenWithDialog.resx">
<DependentUpon>OpenWithDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Src\TextEditor\SearchAndReplace\Gui\AsynchronousWaitDialog.resx">
<DependentUpon>AsynchronousWaitDialog.cs</DependentUpon>
</EmbeddedResource>

145
src/Main/Base/Project/Src/Gui/Dialogs/AddOpenWithEntryDialog.Designer.cs generated

@ -0,0 +1,145 @@ @@ -0,0 +1,145 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
namespace ICSharpCode.SharpDevelop.Gui
{
partial class AddOpenWithEntryDialog
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.programNameTextBox = new System.Windows.Forms.TextBox();
this.browseForProgramButton = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.displayNameTextBox = new System.Windows.Forms.TextBox();
this.okButton = new System.Windows.Forms.Button();
this.cancelButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(12, 18);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(100, 23);
this.label1.TabIndex = 0;
this.label1.Text = "&Program name:";
//
// programNameTextBox
//
this.programNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.programNameTextBox.Location = new System.Drawing.Point(118, 15);
this.programNameTextBox.Name = "programNameTextBox";
this.programNameTextBox.Size = new System.Drawing.Size(250, 20);
this.programNameTextBox.TabIndex = 1;
this.programNameTextBox.TextChanged += new System.EventHandler(this.ProgramNameTextBoxTextChanged);
//
// browseForProgramButton
//
this.browseForProgramButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.browseForProgramButton.Location = new System.Drawing.Point(374, 13);
this.browseForProgramButton.Name = "browseForProgramButton";
this.browseForProgramButton.Size = new System.Drawing.Size(28, 23);
this.browseForProgramButton.TabIndex = 2;
this.browseForProgramButton.Text = "...";
this.browseForProgramButton.UseVisualStyleBackColor = true;
this.browseForProgramButton.Click += new System.EventHandler(this.BrowseForProgramButtonClick);
//
// label2
//
this.label2.Location = new System.Drawing.Point(12, 50);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(100, 23);
this.label2.TabIndex = 3;
this.label2.Text = "&Display name:";
//
// displayNameTextBox
//
this.displayNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.displayNameTextBox.Location = new System.Drawing.Point(118, 47);
this.displayNameTextBox.Name = "displayNameTextBox";
this.displayNameTextBox.Size = new System.Drawing.Size(284, 20);
this.displayNameTextBox.TabIndex = 4;
this.displayNameTextBox.TextChanged += new System.EventHandler(this.DisplayNameTextBoxTextChanged);
//
// okButton
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
this.okButton.Enabled = false;
this.okButton.Location = new System.Drawing.Point(246, 73);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 5;
this.okButton.Text = "${res:Global.OKButtonText}";
this.okButton.UseVisualStyleBackColor = true;
//
// cancelButton
//
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(327, 73);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 23);
this.cancelButton.TabIndex = 6;
this.cancelButton.Text = "${res:Global.CancelButtonText}";
this.cancelButton.UseVisualStyleBackColor = true;
//
// AddOpenWithEntryDialog
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(414, 106);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.okButton);
this.Controls.Add(this.displayNameTextBox);
this.Controls.Add(this.label2);
this.Controls.Add(this.browseForProgramButton);
this.Controls.Add(this.programNameTextBox);
this.Controls.Add(this.label1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AddOpenWithEntryDialog";
this.Text = "Add program";
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.TextBox displayNameTextBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button browseForProgramButton;
private System.Windows.Forms.TextBox programNameTextBox;
private System.Windows.Forms.Label label1;
}
}

75
src/Main/Base/Project/Src/Gui/Dialogs/AddOpenWithEntryDialog.cs

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui
{
/// <summary>
/// This dialog is used to add a new program to the open with dialog.
/// </summary>
public partial class AddOpenWithEntryDialog : Form
{
public AddOpenWithEntryDialog()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
this.DialogResult = DialogResult.Cancel;
foreach (Control ctl in this.Controls) {
ctl.Text = StringParser.Parse(ctl.Text);
}
}
public string ProgramName {
get { return programNameTextBox.Text; }
}
public string DisplayName {
get { return displayNameTextBox.Text; }
}
bool userEditedDisplayName;
void BrowseForProgramButtonClick(object sender, EventArgs e)
{
using (OpenFileDialog dlg = new OpenFileDialog()) {
dlg.Filter = StringParser.Parse(OptionPanels.ExternalToolPane.ExecutableFilesFilter);
if (dlg.ShowDialog(this) == DialogResult.OK) {
programNameTextBox.Text = "\"" + dlg.FileName + "\"";
if (!userEditedDisplayName) {
displayNameTextBox.Text = Path.GetFileName(dlg.FileName);
}
}
}
}
void ProgramNameTextBoxTextChanged(object sender, EventArgs e)
{
SetOkButtonEnabled();
}
void DisplayNameTextBoxTextChanged(object sender, EventArgs e)
{
userEditedDisplayName = true;
SetOkButtonEnabled();
}
void SetOkButtonEnabled()
{
okButton.Enabled = !string.IsNullOrEmpty(programNameTextBox.Text)
&& !string.IsNullOrEmpty(displayNameTextBox.Text);
}
}
}

5
src/Main/Base/Project/Src/Gui/Dialogs/OpenWithDialog.Designer.cs generated

@ -64,17 +64,18 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -64,17 +64,18 @@ namespace ICSharpCode.SharpDevelop.Gui
this.programListBox.Name = "programListBox";
this.programListBox.Size = new System.Drawing.Size(268, 156);
this.programListBox.TabIndex = 1;
this.programListBox.SelectedIndexChanged += new System.EventHandler(this.ProgramListBoxSelectedIndexChanged);
//
// addButton
//
this.addButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.addButton.Enabled = false;
this.addButton.Location = new System.Drawing.Point(286, 35);
this.addButton.Name = "addButton";
this.addButton.Size = new System.Drawing.Size(98, 23);
this.addButton.TabIndex = 2;
this.addButton.Text = "Add...";
this.addButton.UseVisualStyleBackColor = true;
this.addButton.Click += new System.EventHandler(this.AddButtonClick);
//
// removeButton
//
@ -86,6 +87,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -86,6 +87,7 @@ namespace ICSharpCode.SharpDevelop.Gui
this.removeButton.TabIndex = 3;
this.removeButton.Text = "Remove";
this.removeButton.UseVisualStyleBackColor = true;
this.removeButton.Click += new System.EventHandler(this.RemoveButtonClick);
//
// setAsDefaultButton
//
@ -102,6 +104,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -102,6 +104,7 @@ namespace ICSharpCode.SharpDevelop.Gui
//
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
this.okButton.Enabled = false;
this.okButton.Location = new System.Drawing.Point(228, 204);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);

41
src/Main/Base/Project/Src/Gui/Dialogs/OpenWithDialog.cs

@ -33,7 +33,9 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -33,7 +33,9 @@ namespace ICSharpCode.SharpDevelop.Gui
}
}
public OpenWithDialog(ICollection<DisplayBindingDescriptor> displayBindings)
string fileExtension;
public OpenWithDialog(ICollection<DisplayBindingDescriptor> displayBindings, string fileExtension)
{
if (displayBindings == null)
throw new ArgumentNullException("list");
@ -41,6 +43,10 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -41,6 +43,10 @@ namespace ICSharpCode.SharpDevelop.Gui
// The InitializeComponent() call is required for Windows Forms designer support.
InitializeComponent();
this.fileExtension = fileExtension;
if (string.IsNullOrEmpty(fileExtension))
addButton.Enabled = false;
foreach (DisplayBindingDescriptor desc in displayBindings) {
programListBox.Items.Add(new ListEntry(desc));
}
@ -61,5 +67,38 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -61,5 +67,38 @@ namespace ICSharpCode.SharpDevelop.Gui
return null;
}
}
void AddButtonClick(object sender, EventArgs e)
{
using (AddOpenWithEntryDialog dlg = new AddOpenWithEntryDialog()) {
if (dlg.ShowDialog(this) == DialogResult.OK) {
ExternalProcessDisplayBinding binding = new ExternalProcessDisplayBinding {
FileExtension = fileExtension,
CommandLine = dlg.ProgramName,
Title = dlg.DisplayName,
Id = Guid.NewGuid().ToString()
};
programListBox.Items.Add(new ListEntry(DisplayBindingService.AddExternalProcessDisplayBinding(binding)));
}
}
}
void ProgramListBoxSelectedIndexChanged(object sender, EventArgs e)
{
DisplayBindingDescriptor binding = SelectedBinding;
if (binding != null) {
okButton.Enabled = true;
removeButton.Enabled = binding.GetLoadedBinding() is ExternalProcessDisplayBinding;
} else {
okButton.Enabled = false;
removeButton.Enabled = false;
}
}
void RemoveButtonClick(object sender, EventArgs e)
{
DisplayBindingService.RemoveExternalProcessDisplayBinding((ExternalProcessDisplayBinding)SelectedBinding.GetLoadedBinding());
programListBox.Items.RemoveAt(programListBox.SelectedIndex);
}
}
}

120
src/Main/Base/Project/Src/Gui/Dialogs/OpenWithDialog.resx

@ -1,120 +0,0 @@ @@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

4
src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ExternalToolPanel.cs

@ -96,11 +96,13 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels @@ -96,11 +96,13 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
selectEvent(this, EventArgs.Empty);
}
internal const string ExecutableFilesFilter = "${res:SharpDevelop.FileFilter.ExecutableFiles}|*.exe;*.com;*.pif;*.bat;*.cmd|${res:SharpDevelop.FileFilter.AllFiles}|*.*";
void browseEvent(object sender, EventArgs e)
{
using (OpenFileDialog fdiag = new OpenFileDialog()) {
fdiag.CheckFileExists = true;
fdiag.Filter = StringParser.Parse("${res:SharpDevelop.FileFilter.ExecutableFiles}|*.exe;*.com;*.pif;*.bat;*.cmd|${res:SharpDevelop.FileFilter.AllFiles}|*.*");
fdiag.Filter = StringParser.Parse(ExecutableFilesFilter);
if (fdiag.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainForm) == DialogResult.OK) {
ControlDictionary["commandTextBox"].Text = fdiag.FileName;

4
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/DefaultFileNodeCommands.cs

@ -68,8 +68,8 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -68,8 +68,8 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
/// </summary>
public static void OpenWith(string fileName)
{
using (OpenWithDialog dlg = new OpenWithDialog(DisplayBindingService.GetCodonsPerFileName(fileName))) {
if (dlg.ShowDialog() == DialogResult.OK) {
using (OpenWithDialog dlg = new OpenWithDialog(DisplayBindingService.GetCodonsPerFileName(fileName), Path.GetExtension(fileName))) {
if (dlg.ShowDialog(WorkbenchSingleton.MainForm) == DialogResult.OK) {
FileUtility.ObservedLoad(new FileService.LoadFileWrapper(dlg.SelectedBinding.Binding).Invoke, fileName);
}
}

10
src/Main/Base/Project/Src/Gui/Pads/ToolsPad.cs

@ -23,7 +23,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -23,7 +23,6 @@ namespace ICSharpCode.SharpDevelop.Gui
/// <summary>
/// A pad that shows a single child control determined by the document that currently has the focus.
///
/// </summary>
public class ToolsPad : AbstractPadContent
{
@ -44,10 +43,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -44,10 +43,6 @@ namespace ICSharpCode.SharpDevelop.Gui
panel.Controls.Add(noToolsAvailable);
child = noToolsAvailable;
WorkbenchSingleton.Workbench.ActiveContentChanged += WorkbenchActiveContentChanged;
// it is possible that ActiveContent changes fires before ActiveViewContent.
// if we listen the new content is not a IToolsHost and we listen only to ActiveContentChanged,
// we might display the ToolsControl of a no longer active view content
WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveContentChanged;
WorkbenchActiveContentChanged(null, null);
}
@ -64,10 +59,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -64,10 +59,7 @@ namespace ICSharpCode.SharpDevelop.Gui
void WorkbenchActiveContentChanged(object sender, EventArgs e)
{
IToolsHost th = WorkbenchSingleton.Workbench.ActiveContent as IToolsHost;
if (th == null) {
th = WorkbenchSingleton.Workbench.ActiveViewContent as IToolsHost;
}
IToolsHost th = WorkbenchSingleton.Workbench.ActiveViewContent as IToolsHost;
if (th != null) {
SetChild(th.ToolsControl ?? noToolsAvailable);
} else {

1
src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs

@ -75,6 +75,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -75,6 +75,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void InitializeWorkbench()
{
DisplayBindingService.InitializeService();
LayoutConfiguration.LoadLayoutConfiguration();
FileService.InitializeService();
StatusBarService.Initialize();

77
src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingDescriptor.cs

@ -13,12 +13,22 @@ namespace ICSharpCode.SharpDevelop @@ -13,12 +13,22 @@ namespace ICSharpCode.SharpDevelop
{
public class DisplayBindingDescriptor
{
object binding = null;
object binding;
bool isSecondary;
Codon codon;
/// <summary>
/// Gets the IDisplayBinding or ISecondaryDisplayBinding if it is already loaded,
/// otherwise returns null.
/// </summary>
internal object GetLoadedBinding()
{
return binding;
}
public IDisplayBinding Binding {
get {
if (binding == null) {
if (codon != null && binding == null) {
binding = codon.AddIn.CreateObject(codon.Properties["class"]);
}
return binding as IDisplayBinding;
@ -27,51 +37,74 @@ namespace ICSharpCode.SharpDevelop @@ -27,51 +37,74 @@ namespace ICSharpCode.SharpDevelop
public ISecondaryDisplayBinding SecondaryBinding {
get {
if (binding == null) {
if (codon != null && binding == null) {
binding = codon.AddIn.CreateObject(codon.Properties["class"]);
}
return binding as ISecondaryDisplayBinding;
}
}
bool isSecondary;
public bool IsSecondary {
get {
return isSecondary;
}
get { return isSecondary; }
}
public string Title {
get {
string title = codon.Properties["title"];
if (string.IsNullOrEmpty(title))
return codon.Id;
else
return title;
}
}
public string Id { get; set; }
public string Title { get; set; }
public string FileNameRegex { get; set; }
public DisplayBindingDescriptor(Codon codon)
{
if (codon == null)
throw new ArgumentNullException("codon");
isSecondary = codon.Properties["type"] == "Secondary";
if (!isSecondary && codon.Properties["type"] != "" && codon.Properties["type"] != "Primary")
MessageService.ShowWarning("Unknown display binding type: " + codon.Properties["type"]);
this.codon = codon;
this.Id = codon.Id;
string title = codon.Properties["title"];
if (string.IsNullOrEmpty(title))
this.Title = codon.Id;
else
this.Title = title;
this.FileNameRegex = codon.Properties["fileNamePattern"];
}
public DisplayBindingDescriptor(IDisplayBinding binding)
{
if (binding == null)
throw new ArgumentNullException("binding");
this.isSecondary = false;
this.binding = binding;
}
public DisplayBindingDescriptor(ISecondaryDisplayBinding binding)
{
if (binding == null)
throw new ArgumentNullException("binding");
this.isSecondary = true;
this.binding = binding;
}
/// <summary>
/// Gets if the display binding can possibly attach to the file.
/// If this method returns false, it cannot attach to it; if the method returns
/// true, it *might* attach to it.
/// Gets if the display binding can possibly open the file.
/// If this method returns false, it cannot open it; if the method returns
/// true, it *might* open it.
/// Call Binding.CanCreateContentForFile() to know for sure if the binding
/// will open the file.
/// </summary>
/// <remarks>
/// This method is used to skip loading addins like the ResourceEditor which cannot
/// attach to a certain file name for sure.
/// </remarks>
public bool CanAttachToFile(string fileName)
public bool CanOpenFile(string fileName)
{
string fileNameRegex = codon.Properties["fileNamePattern"];
string fileNameRegex = this.FileNameRegex;
if (fileNameRegex == null || fileNameRegex.Length == 0) // no regex specified
return true;
if (fileName == null) // regex specified but file has no name

67
src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs

@ -18,9 +18,61 @@ namespace ICSharpCode.SharpDevelop @@ -18,9 +18,61 @@ namespace ICSharpCode.SharpDevelop
/// </summary>
internal static class DisplayBindingService
{
readonly static string displayBindingPath = "/SharpDevelop/Workbench/DisplayBindings";
const string displayBindingPath = "/SharpDevelop/Workbench/DisplayBindings";
static DisplayBindingDescriptor[] bindings = null;
static List<DisplayBindingDescriptor> bindings;
static List<ExternalProcessDisplayBinding> externalProcessDisplayBindings = new List<ExternalProcessDisplayBinding>();
internal static void InitializeService()
{
bindings = AddInTree.BuildItems<DisplayBindingDescriptor>("/SharpDevelop/Workbench/DisplayBindings", null, true);
foreach (ExternalProcessDisplayBinding binding in PropertyService.Get("OpenWithExternalProcesses", new ExternalProcessDisplayBinding[0])) {
if (binding != null) {
AddExternalProcessDisplayBindingInternal(binding);
}
}
}
public static DisplayBindingDescriptor AddExternalProcessDisplayBinding(ExternalProcessDisplayBinding binding)
{
if (binding == null)
throw new ArgumentNullException("binding");
DisplayBindingDescriptor descriptor = AddExternalProcessDisplayBindingInternal(binding);
SaveExternalProcessDisplayBindings();
return descriptor;
}
static void SaveExternalProcessDisplayBindings()
{
PropertyService.Set("OpenWithExternalProcesses", externalProcessDisplayBindings.ToArray());
}
static DisplayBindingDescriptor AddExternalProcessDisplayBindingInternal(ExternalProcessDisplayBinding binding)
{
externalProcessDisplayBindings.Add(binding);
DisplayBindingDescriptor descriptor = new DisplayBindingDescriptor(binding) {
Id = binding.Id,
Title = binding.Title
};
bindings.Add(descriptor);
return descriptor;
}
public static void RemoveExternalProcessDisplayBinding(ExternalProcessDisplayBinding binding)
{
if (binding == null)
throw new ArgumentNullException("binding");
if (!externalProcessDisplayBindings.Remove(binding))
throw new ArgumentException("binding was not added");
SaveExternalProcessDisplayBindings();
for (int i = 0; i < bindings.Count; i++) {
if (bindings[i].GetLoadedBinding() == binding) {
bindings.RemoveAt(i);
return;
}
}
throw new InvalidOperationException("did not find binding descriptor even though binding was registered");
}
/// <summary>
/// Gets the primary display binding for the specified file name.
@ -34,7 +86,7 @@ namespace ICSharpCode.SharpDevelop @@ -34,7 +86,7 @@ namespace ICSharpCode.SharpDevelop
static DisplayBindingDescriptor GetCodonPerFileName(string filename)
{
foreach (DisplayBindingDescriptor binding in bindings) {
if (!binding.IsSecondary && binding.CanAttachToFile(filename)) {
if (!binding.IsSecondary && binding.CanOpenFile(filename)) {
if (binding.Binding != null && binding.Binding.CanCreateContentForFile(filename)) {
return binding;
}
@ -50,7 +102,7 @@ namespace ICSharpCode.SharpDevelop @@ -50,7 +102,7 @@ namespace ICSharpCode.SharpDevelop
{
List<DisplayBindingDescriptor> list = new List<DisplayBindingDescriptor>();
foreach (DisplayBindingDescriptor binding in bindings) {
if (!binding.IsSecondary && binding.CanAttachToFile(filename)) {
if (!binding.IsSecondary && binding.CanOpenFile(filename)) {
if (binding.Binding != null && binding.Binding.CanCreateContentForFile(filename)) {
list.Add(binding);
}
@ -67,7 +119,7 @@ namespace ICSharpCode.SharpDevelop @@ -67,7 +119,7 @@ namespace ICSharpCode.SharpDevelop
public static void AttachSubWindows(IViewContent viewContent, bool isReattaching)
{
foreach (DisplayBindingDescriptor binding in bindings) {
if (binding.IsSecondary && binding.CanAttachToFile(viewContent.PrimaryFileName)) {
if (binding.IsSecondary && binding.CanOpenFile(viewContent.PrimaryFileName)) {
ISecondaryDisplayBinding displayBinding = binding.SecondaryBinding;
if (displayBinding != null
&& (!isReattaching || displayBinding.ReattachWhenParserServiceIsReady)
@ -83,10 +135,5 @@ namespace ICSharpCode.SharpDevelop @@ -83,10 +135,5 @@ namespace ICSharpCode.SharpDevelop
}
}
}
static DisplayBindingService()
{
bindings = (DisplayBindingDescriptor[])(AddInTree.GetTreeNode(displayBindingPath).BuildChildItems(null)).ToArray(typeof(DisplayBindingDescriptor));
}
}
}

116
src/Main/Base/Project/Src/Services/DisplayBinding/ExternalProcessDisplayBinding.cs

@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Display binding for opening a file in an external process.
/// </summary>
[TypeConverter(typeof(ExternalProcessDisplayBindingConverter))]
sealed class ExternalProcessDisplayBinding : IDisplayBinding
{
public string FileExtension { get; set; }
public string CommandLine { get; set; }
public string Title { get; set; }
public string Id { get; set; }
public bool CanCreateContentForFile(string fileName)
{
return string.Equals(Path.GetExtension(fileName), FileExtension, StringComparison.OrdinalIgnoreCase);
}
public ICSharpCode.SharpDevelop.Gui.IViewContent CreateContentForFile(OpenedFile file)
{
if (file.IsDirty) {
// TODO: warn user that the file must be saved
}
try {
string cmd;
if (CommandLine.Contains("%1"))
cmd = CommandLine.Replace("%1", file.FileName);
else
cmd = CommandLine + " \"" + file.FileName + "\"";
StartCommandLine(cmd);
} catch (Exception ex) {
MessageService.ShowError(ex.Message);
}
return null;
}
static void StartCommandLine(string cmd)
{
LoggingService.Debug("ExternalProcessDisplayBinding> " + cmd);
cmd = cmd.Trim();
if (cmd.Length == 0) return;
string program, arguments;
if (cmd[0] == '"') {
int pos = cmd.IndexOf('"', 1);
program = cmd.Substring(1, pos - 1);
arguments = cmd.Substring(pos + 1).TrimStart();
} else {
int pos = cmd.IndexOf(' ', 0);
program = cmd.Substring(0, pos);
arguments = cmd.Substring(pos + 1);
}
Process.Start(program, arguments);
}
}
sealed class ExternalProcessDisplayBindingConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;
else
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string)) {
ExternalProcessDisplayBinding binding = (ExternalProcessDisplayBinding)value;
return binding.Id + "|" + binding.FileExtension + "|" + binding.Title + "|" + binding.CommandLine;
} else {
return base.ConvertTo(context, culture, value, destinationType);
}
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string) {
string[] values = value.ToString().Split('|');
if (values.Length == 4) {
return new ExternalProcessDisplayBinding {
Id = values[0],
FileExtension = values[1],
Title = values[2],
CommandLine = values[3]
};
} else {
return null;
}
} else {
return base.ConvertFrom(context, culture, value);
}
}
}
}
Loading…
Cancel
Save