Browse Source

Added full support for project resources to the Windows.Forms designer. Fixed SD2-576 - Visual Studio Project Resources used in Form.

ResourceCodeGeneratorTool: Set BasePath so that relative file references inside ResX files work.
ParserService.GetParseableFileContent can now retrieve the file content from an OpenedFile if that exists.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3534 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Christian Hornung 17 years ago
parent
commit
d9265c5144
  1. BIN
      data/resources/StringResources.de.resources
  2. BIN
      data/resources/StringResources.es-mx.resources
  3. BIN
      data/resources/StringResources.es.resources
  4. BIN
      data/resources/StringResources.nl.resources
  5. 16
      src/AddIns/DisplayBindings/FormsDesigner/Project/FormsDesigner.csproj
  6. 2
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/AbstractCodeDomDesignerLoader.cs
  7. 13
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs
  8. 247
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/ImageResourceEditorDialog.Designer.cs
  9. 571
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/ImageResourceEditorDialog.cs
  10. 135
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/ImageResourceEditorDialog.resx
  11. 157
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ImageResourceEditor.cs
  12. 94
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourceInfo.cs
  13. 177
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourceService.cs
  14. 258
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourcesComponentCodeDomSerializer.cs
  15. 172
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourcesMemberCodeDomSerializer.cs
  16. 8
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ResourceStore.cs
  17. 48
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/SharpDevelopSerializationProvider.cs
  18. 1
      src/AddIns/DisplayBindings/ResourceEditor/Project/Src/ResourceCodeGeneratorTool.cs
  19. 9
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  20. BIN
      src/Main/StartUp/Project/Resources/StringResources.resources

BIN
data/resources/StringResources.de.resources

Binary file not shown.

BIN
data/resources/StringResources.es-mx.resources

Binary file not shown.

BIN
data/resources/StringResources.es.resources

Binary file not shown.

BIN
data/resources/StringResources.nl.resources

Binary file not shown.

16
src/AddIns/DisplayBindings/FormsDesigner/Project/FormsDesigner.csproj

@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
<Reference Include="System.Core" />
<Reference Include="System.Design" />
<Reference Include="System.Drawing" />
<Reference Include="System.Drawing.Design" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
</ItemGroup>
@ -59,6 +60,10 @@ @@ -59,6 +60,10 @@
<Compile Include="Src\DesignerLoader\AbstractCodeDomDesignerLoader.cs" />
<Compile Include="Src\DesignerLoader\NRefactoryDesignerLoader.cs" />
<Compile Include="Src\DesignerLoader\XmlDesignerLoader.cs" />
<Compile Include="Src\Gui\ImageResourceEditorDialog.cs" />
<Compile Include="Src\Gui\ImageResourceEditorDialog.Designer.cs">
<DependentUpon>ImageResourceEditorDialog.cs</DependentUpon>
</Compile>
<Compile Include="Src\Gui\OptionPanels\LocalizationModelOptionsPanel.cs" />
<Compile Include="Src\SecondaryDisplayBinding.cs" />
<Compile Include="Src\DesignerViewContent.cs" />
@ -85,9 +90,15 @@ @@ -85,9 +90,15 @@
<Compile Include="Src\Services\DesignerResourceService.cs" />
<Compile Include="Src\Services\EventBindingService.cs" />
<Compile Include="Src\Services\HelpService.cs" />
<Compile Include="Src\Services\ImageResourceEditor.cs" />
<Compile Include="Src\Services\MenuCommandService.cs" />
<Compile Include="Src\Services\ProjectResourceInfo.cs" />
<Compile Include="Src\Services\ProjectResourcesComponentCodeDomSerializer.cs" />
<Compile Include="Src\Services\ProjectResourceService.cs" />
<Compile Include="Src\Services\ProjectResourcesMemberCodeDomSerializer.cs" />
<Compile Include="Src\Services\PropertyValueUIService.cs" />
<Compile Include="Src\Services\ResourceStore.cs" />
<Compile Include="Src\Services\SharpDevelopSerializationProvider.cs" />
<Compile Include="Src\Services\ToolboxService.cs" />
<Compile Include="Src\Services\TypeResolutionService.cs" />
<Compile Include="Src\Services\UIService.cs" />
@ -106,6 +117,9 @@ @@ -106,6 +117,9 @@
</Compile>
<Compile Include="Src\Gui\OptionPanels\GeneralOptions.cs" />
<EmbeddedResource Include="Resources\WindowsFormsGeneralOptions.xfrm" />
<EmbeddedResource Include="Src\Gui\ImageResourceEditorDialog.resx">
<DependentUpon>ImageResourceEditorDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Src\Gui\OptionPanels\LocalizationModelOptionsPanel.resx">
<DependentUpon>LocalizationModelOptionsPanel.cs</DependentUpon>
</EmbeddedResource>
@ -151,4 +165,4 @@ @@ -151,4 +165,4 @@
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<Import Project="PostBuildEvent.proj" />
</Project>
</Project>

2
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/AbstractCodeDomDesignerLoader.cs

@ -14,6 +14,7 @@ using System.ComponentModel.Design.Serialization; @@ -14,6 +14,7 @@ using System.ComponentModel.Design.Serialization;
using System.Reflection;
using ICSharpCode.Core;
using ICSharpCode.FormsDesigner.Services;
namespace ICSharpCode.FormsDesigner
{
@ -122,6 +123,7 @@ namespace ICSharpCode.FormsDesigner @@ -122,6 +123,7 @@ namespace ICSharpCode.FormsDesigner
CodeDomLocalizationProvider localizationProvider = new CodeDomLocalizationProvider(designerLoaderHost, model);
IDesignerSerializationManager manager = (IDesignerSerializationManager)designerLoaderHost.GetService(typeof(IDesignerSerializationManager));
manager.AddSerializationProvider(new SharpDevelopSerializationProvider());
manager.AddSerializationProvider(localizationProvider);
base.Initialize();

13
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
@ -45,6 +46,8 @@ namespace ICSharpCode.FormsDesigner @@ -45,6 +46,8 @@ namespace ICSharpCode.FormsDesigner
OpenedFile designerCodeFile;
IDocument designerCodeFileDocument;
readonly Dictionary<Type, TypeDescriptionProvider> addedTypeDescriptionProviders = new Dictionary<Type, TypeDescriptionProvider>();
protected DesignSurface DesignSurface {
get {
return designSurface;
@ -261,6 +264,11 @@ namespace ICSharpCode.FormsDesigner @@ -261,6 +264,11 @@ namespace ICSharpCode.FormsDesigner
serviceContainer.AddService(typeof(DesignerOptionService), new SharpDevelopDesignerOptionService());
serviceContainer.AddService(typeof(ITypeDiscoveryService), new TypeDiscoveryService());
serviceContainer.AddService(typeof(MemberRelationshipService), new DefaultMemberRelationshipService());
serviceContainer.AddService(typeof(ProjectResourceService), new ProjectResourceService(ParserService.GetParseInformation(this.DesignerCodeFile.FileName).MostRecentCompilationUnit.ProjectContent));
// Provide the ImageResourceEditor for all Image and Icon properties
this.addedTypeDescriptionProviders.Add(typeof(Image), TypeDescriptor.AddAttributes(typeof(Image), new EditorAttribute(typeof(ImageResourceEditor), typeof(System.Drawing.Design.UITypeEditor))));
this.addedTypeDescriptionProviders.Add(typeof(Icon), TypeDescriptor.AddAttributes(typeof(Icon), new EditorAttribute(typeof(ImageResourceEditor), typeof(System.Drawing.Design.UITypeEditor))));
if (generator.CodeDomProvider != null) {
serviceContainer.AddService(typeof(System.CodeDom.Compiler.CodeDomProvider), generator.CodeDomProvider);
@ -378,6 +386,11 @@ namespace ICSharpCode.FormsDesigner @@ -378,6 +386,11 @@ namespace ICSharpCode.FormsDesigner
}
this.loader = null;
foreach (KeyValuePair<Type, TypeDescriptionProvider> entry in this.addedTypeDescriptionProviders) {
TypeDescriptor.RemoveProvider(entry.Value, entry.Key);
}
this.addedTypeDescriptionProviders.Clear();
}
readonly PropertyContainer propertyContainer = new PropertyContainer();

247
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/ImageResourceEditorDialog.Designer.cs generated

@ -0,0 +1,247 @@ @@ -0,0 +1,247 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
namespace ICSharpCode.FormsDesigner.Gui
{
partial class ImageResourceEditorDialog
{
/// <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()
{
System.Windows.Forms.Button cancelButton;
System.Windows.Forms.SplitContainer splitContainer;
System.Windows.Forms.GroupBox resourceSelectionGroup;
System.Windows.Forms.GroupBox previewGroup;
this.projectResourcesTreeView = new System.Windows.Forms.TreeView();
this.projectResourceRadioButton = new System.Windows.Forms.RadioButton();
this.importLocalResourceButton = new System.Windows.Forms.Button();
this.noResourceRadioButton = new System.Windows.Forms.RadioButton();
this.localResourceRadioButton = new System.Windows.Forms.RadioButton();
this.previewPictureBox = new System.Windows.Forms.PictureBox();
this.okButton = new System.Windows.Forms.Button();
this.projectTreeScanningBackgroundWorker = new System.ComponentModel.BackgroundWorker();
cancelButton = new System.Windows.Forms.Button();
splitContainer = new System.Windows.Forms.SplitContainer();
resourceSelectionGroup = new System.Windows.Forms.GroupBox();
previewGroup = new System.Windows.Forms.GroupBox();
splitContainer.Panel1.SuspendLayout();
splitContainer.Panel2.SuspendLayout();
splitContainer.SuspendLayout();
resourceSelectionGroup.SuspendLayout();
previewGroup.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();
this.SuspendLayout();
//
// cancelButton
//
cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
cancelButton.Location = new System.Drawing.Point(509, 317);
cancelButton.Name = "cancelButton";
cancelButton.Size = new System.Drawing.Size(75, 23);
cancelButton.TabIndex = 1;
cancelButton.Text = "${res:Global.CancelButtonText}";
cancelButton.UseVisualStyleBackColor = true;
//
// splitContainer
//
splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
splitContainer.Location = new System.Drawing.Point(12, 12);
splitContainer.Name = "splitContainer";
//
// splitContainer.Panel1
//
splitContainer.Panel1.Controls.Add(resourceSelectionGroup);
//
// splitContainer.Panel2
//
splitContainer.Panel2.Controls.Add(previewGroup);
splitContainer.Size = new System.Drawing.Size(572, 299);
splitContainer.SplitterDistance = 280;
splitContainer.TabIndex = 2;
//
// resourceSelectionGroup
//
resourceSelectionGroup.Controls.Add(this.projectResourcesTreeView);
resourceSelectionGroup.Controls.Add(this.projectResourceRadioButton);
resourceSelectionGroup.Controls.Add(this.importLocalResourceButton);
resourceSelectionGroup.Controls.Add(this.noResourceRadioButton);
resourceSelectionGroup.Controls.Add(this.localResourceRadioButton);
resourceSelectionGroup.Dock = System.Windows.Forms.DockStyle.Fill;
resourceSelectionGroup.Location = new System.Drawing.Point(0, 0);
resourceSelectionGroup.Name = "resourceSelectionGroup";
resourceSelectionGroup.Size = new System.Drawing.Size(280, 299);
resourceSelectionGroup.TabIndex = 0;
resourceSelectionGroup.TabStop = false;
//
// projectResourcesTreeView
//
this.projectResourcesTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.projectResourcesTreeView.HideSelection = false;
this.projectResourcesTreeView.Location = new System.Drawing.Point(26, 138);
this.projectResourcesTreeView.Name = "projectResourcesTreeView";
this.projectResourcesTreeView.Size = new System.Drawing.Size(248, 155);
this.projectResourcesTreeView.TabIndex = 4;
this.projectResourcesTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.ProjectResourcesTreeViewAfterSelect);
//
// projectResourceRadioButton
//
this.projectResourceRadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.projectResourceRadioButton.Location = new System.Drawing.Point(6, 108);
this.projectResourceRadioButton.Name = "projectResourceRadioButton";
this.projectResourceRadioButton.Size = new System.Drawing.Size(268, 24);
this.projectResourceRadioButton.TabIndex = 3;
this.projectResourceRadioButton.TabStop = true;
this.projectResourceRadioButton.Text = "${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.ProjectResour" +
"ceButton}";
this.projectResourceRadioButton.UseVisualStyleBackColor = true;
this.projectResourceRadioButton.CheckedChanged += new System.EventHandler(this.ProjectResourceRadioButtonCheckedChanged);
//
// importLocalResourceButton
//
this.importLocalResourceButton.Location = new System.Drawing.Point(26, 79);
this.importLocalResourceButton.Name = "importLocalResourceButton";
this.importLocalResourceButton.Size = new System.Drawing.Size(126, 23);
this.importLocalResourceButton.TabIndex = 2;
this.importLocalResourceButton.Text = "${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.ImportLocalRe" +
"sourceButton}";
this.importLocalResourceButton.UseVisualStyleBackColor = true;
this.importLocalResourceButton.Click += new System.EventHandler(this.ImportLocalResourceButtonClick);
//
// noResourceRadioButton
//
this.noResourceRadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.noResourceRadioButton.Location = new System.Drawing.Point(6, 19);
this.noResourceRadioButton.Name = "noResourceRadioButton";
this.noResourceRadioButton.Size = new System.Drawing.Size(268, 24);
this.noResourceRadioButton.TabIndex = 0;
this.noResourceRadioButton.TabStop = true;
this.noResourceRadioButton.Text = "${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.NoResourceBut" +
"ton}";
this.noResourceRadioButton.UseVisualStyleBackColor = true;
this.noResourceRadioButton.CheckedChanged += new System.EventHandler(this.NoResourceRadioButtonCheckedChanged);
//
// localResourceRadioButton
//
this.localResourceRadioButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.localResourceRadioButton.Location = new System.Drawing.Point(6, 49);
this.localResourceRadioButton.Name = "localResourceRadioButton";
this.localResourceRadioButton.Size = new System.Drawing.Size(268, 24);
this.localResourceRadioButton.TabIndex = 1;
this.localResourceRadioButton.TabStop = true;
this.localResourceRadioButton.Text = "${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.LocalResource" +
"Button}";
this.localResourceRadioButton.UseVisualStyleBackColor = true;
this.localResourceRadioButton.CheckedChanged += new System.EventHandler(this.LocalResourceRadioButtonCheckedChanged);
//
// previewGroup
//
previewGroup.Controls.Add(this.previewPictureBox);
previewGroup.Dock = System.Windows.Forms.DockStyle.Fill;
previewGroup.Location = new System.Drawing.Point(0, 0);
previewGroup.Name = "previewGroup";
previewGroup.Size = new System.Drawing.Size(288, 299);
previewGroup.TabIndex = 0;
previewGroup.TabStop = false;
previewGroup.Text = "${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.Preview}";
//
// previewPictureBox
//
this.previewPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.previewPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.previewPictureBox.Location = new System.Drawing.Point(6, 19);
this.previewPictureBox.Name = "previewPictureBox";
this.previewPictureBox.Size = new System.Drawing.Size(276, 274);
this.previewPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.previewPictureBox.TabIndex = 0;
this.previewPictureBox.TabStop = false;
//
// okButton
//
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.Location = new System.Drawing.Point(428, 317);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 23);
this.okButton.TabIndex = 0;
this.okButton.Text = "${res:Global.OKButtonText}";
this.okButton.UseVisualStyleBackColor = true;
//
// projectTreeScanningBackgroundWorker
//
this.projectTreeScanningBackgroundWorker.WorkerSupportsCancellation = true;
this.projectTreeScanningBackgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.ProjectTreeScanningBackgroundWorkerDoWork);
this.projectTreeScanningBackgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.ProjectTreeScanningBackgroundWorkerRunWorkerCompleted);
//
// ImageResourceEditorDialog
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = cancelButton;
this.ClientSize = new System.Drawing.Size(596, 352);
this.Controls.Add(splitContainer);
this.Controls.Add(cancelButton);
this.Controls.Add(this.okButton);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ImageResourceEditorDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.Title}";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ImageResourceEditorDialogFormClosed);
splitContainer.Panel1.ResumeLayout(false);
splitContainer.Panel2.ResumeLayout(false);
splitContainer.ResumeLayout(false);
resourceSelectionGroup.ResumeLayout(false);
previewGroup.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();
this.ResumeLayout(false);
}
private System.ComponentModel.BackgroundWorker projectTreeScanningBackgroundWorker;
private System.Windows.Forms.RadioButton noResourceRadioButton;
private System.Windows.Forms.Button importLocalResourceButton;
private System.Windows.Forms.RadioButton projectResourceRadioButton;
private System.Windows.Forms.TreeView projectResourcesTreeView;
private System.Windows.Forms.RadioButton localResourceRadioButton;
private System.Windows.Forms.PictureBox previewPictureBox;
private System.Windows.Forms.Button okButton;
}
}

571
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/ImageResourceEditorDialog.cs

@ -0,0 +1,571 @@ @@ -0,0 +1,571 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Linq;
using System.Resources;
using System.Resources.Tools;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.FormsDesigner.Services;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.FormsDesigner.Gui
{
/// <summary>
/// Allows the user to select a resource for an image or icon property.
/// </summary>
public sealed partial class ImageResourceEditorDialog : Form
{
readonly IProject project;
readonly Type requiredResourceType;
object originalImage;
bool selectedImageIsProjectResource;
object selectedImage;
#region Constructors
ImageResourceEditorDialog(IProject project, Type requiredResourceType)
: base()
{
if (requiredResourceType == null)
throw new ArgumentNullException("requiredResourceType");
this.requiredResourceType = requiredResourceType;
this.project = project;
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
Translate(this);
this.projectResourcesTreeView.Nodes.Add(ResourceService.GetString("Global.PleaseWait"));
this.importLocalResourceButton.DataBindings.Add("Enabled", this.localResourceRadioButton, "Checked");
this.projectResourcesTreeView.DataBindings.Add("Enabled", this.projectResourceRadioButton, "Checked");
}
public ImageResourceEditorDialog(IProject project, Type requiredResourceType, ProjectResourceInfo projectResource)
: this(project, requiredResourceType)
{
if (projectResource == null)
throw new ArgumentNullException("projectResource");
this.projectResourceRadioButton.Checked = true;
this.originalImage = this.selectedImage = projectResource.OriginalValue;
Image image = this.selectedImage as Image;
if (image != null) {
this.selectedImageIsProjectResource = true;
this.SetPreviewImage(image);
} else {
Icon icon = this.selectedImage as Icon;
if (icon != null) {
this.selectedImageIsProjectResource = true;
this.SetPreviewImage(icon.ToBitmap());
}
}
this.projectTreeScanningBackgroundWorker.RunWorkerAsync(projectResource);
}
public ImageResourceEditorDialog(IProject project, Image localResource)
: this(project, typeof(Image))
{
if (localResource != null) {
this.localResourceRadioButton.Checked = true;
this.originalImage = this.selectedImage = localResource;
this.SetPreviewImage(localResource);
} else {
this.noResourceRadioButton.Checked = true;
}
this.projectTreeScanningBackgroundWorker.RunWorkerAsync();
}
public ImageResourceEditorDialog(IProject project, Icon localResource)
: this(project, typeof(Icon))
{
if (localResource != null) {
this.localResourceRadioButton.Checked = true;
this.originalImage = this.selectedImage = localResource;
this.SetPreviewImage(localResource.ToBitmap());
} else {
this.noResourceRadioButton.Checked = true;
}
this.projectTreeScanningBackgroundWorker.RunWorkerAsync();
}
static void Translate(Control c)
{
c.Text = StringParser.Parse(c.Text);
foreach (Control child in c.Controls) {
Translate(child);
}
}
#endregion
#region Properties
/// <summary>
/// Gets the <see cref="ProjectResourceInfo"/> for the selected project resource,
/// or <c>null</c> if the selected resource is not a project resource.
/// </summary>
public ProjectResourceInfo SelectedProjectResource {
get {
if (this.selectedImageIsProjectResource && this.projectResourceRadioButton.Checked) {
TreeNode node = this.projectResourcesTreeView.SelectedNode;
if (node == null) return null;
return new ProjectResourceInfo(((FileProjectItem)node.Parent.Tag).FileName, node.Text);
} else {
return null;
}
}
}
/// <summary>
/// Gets the selected image.
/// This can be an Image or an Icon (matching the type that was passed to the constructor) or null.
/// </summary>
public object SelectedResourceValue {
get {
return this.selectedImage;
}
}
#endregion
void SetPreviewImage(Image image)
{
this.previewPictureBox.Image = image;
if (image != null) {
if (image.Width > this.previewPictureBox.ClientSize.Width ||
image.Height > this.previewPictureBox.ClientSize.Height) {
this.previewPictureBox.SizeMode = PictureBoxSizeMode.Zoom;
} else {
this.previewPictureBox.SizeMode = PictureBoxSizeMode.CenterImage;
}
}
}
void DisposeImageIfNotOriginal(object image)
{
if (!Object.ReferenceEquals(image, this.originalImage)) {
IDisposable d = image as IDisposable;
if (d != null) {
d.Dispose();
}
}
}
void SetSelectedImage(object image, bool isProjectResource)
{
if (!Object.ReferenceEquals(this.selectedImage, this.previewPictureBox.Image)) {
Image temp = this.previewPictureBox.Image;
this.previewPictureBox.Image = null;
this.DisposeImageIfNotOriginal(temp);
} else {
this.previewPictureBox.Image = null;
}
if (!this.selectedImageIsProjectResource) {
this.DisposeImageIfNotOriginal(this.selectedImage);
}
Image img = image as Image;
if (img != null) {
this.selectedImage = img;
this.selectedImageIsProjectResource = isProjectResource;
this.SetPreviewImage(img);
} else {
Icon icon = image as Icon;
if (icon != null) {
this.selectedImage = icon;
this.selectedImageIsProjectResource = isProjectResource;
this.SetPreviewImage(icon.ToBitmap());
} else {
this.selectedImageIsProjectResource = false;
this.selectedImage = null;
}
}
}
#region Project tree filling
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
void ProjectTreeScanningBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
if (this.project == null) {
return;
}
ProjectResourceInfo selectedProjectResource = e.Argument as ProjectResourceInfo;
IProjectContent projectContent = ParserService.GetProjectContent(this.project);
TreeNode root = new TreeNode(this.project.Name, 0, 0);
TreeNode preSelection = null;
TreeNode lastFileNode = null;
int fileNodesCount = 0;
foreach (FileProjectItem item in this.project.GetItemsOfType(ItemType.EmbeddedResource).OfType<FileProjectItem>().OrderBy(fpi => Path.GetFileName(fpi.VirtualName))) {
if (this.projectTreeScanningBackgroundWorker.CancellationPending) {
e.Cancel = true;
break;
}
// Skip files where the generated class name
// would conflict with an existing class.
string namespaceName = item.GetEvaluatedMetadata("CustomToolNamespace");
if (string.IsNullOrEmpty(namespaceName)) {
namespaceName = CustomToolsService.GetDefaultNamespace(item.Project, item.FileName);
}
IClass existingClass = projectContent.GetClass(namespaceName + "." + StronglyTypedResourceBuilder.VerifyResourceName(Path.GetFileNameWithoutExtension(item.FileName), projectContent.Language.CodeDomProvider), 0);
if (existingClass != null) {
if (!ProjectResourceService.IsGeneratedResourceClass(existingClass)) {
continue;
}
}
bool selectedFile = (selectedProjectResource != null) && FileUtility.IsEqualFileName(selectedProjectResource.ResourceFile, item.FileName);
TreeNode file = null;
try {
foreach (KeyValuePair<string, object> r in this.GetResources(item.FileName).OrderBy(pair => pair.Key)) {
if (this.projectTreeScanningBackgroundWorker.CancellationPending) {
e.Cancel = true;
break;
}
if (file == null) {
file = CreateAndAddFileNode(root, item);
}
TreeNode resNode = new TreeNode(r.Key, 3, 3);
resNode.Tag = r.Value;
file.Nodes.Add(resNode);
if (selectedFile) {
if (String.Equals(r.Key, selectedProjectResource.ResourceKey, StringComparison.Ordinal)) {
preSelection = resNode;
}
}
}
if (file != null) {
lastFileNode = file;
++fileNodesCount;
}
} catch (Exception ex) {
if (file == null) {
file = CreateAndAddFileNode(root, item);
}
TreeNode error = new TreeNode(ex.Message, 4, 4);
file.Nodes.Add(error);
}
}
if (e.Cancel) {
DisposeNodeImages(root);
} else {
// Preselect the file node if there is only one
if (preSelection == null && fileNodesCount == 1) {
preSelection = lastFileNode;
}
e.Result = new TreeScanResult(root, preSelection);
}
}
sealed class TreeScanResult {
readonly TreeNode root;
readonly TreeNode preSelection;
public TreeNode Root {
get { return root; }
}
public TreeNode PreSelection {
get { return preSelection; }
}
public TreeScanResult(TreeNode root, TreeNode preSelection)
{
this.root = root;
this.preSelection = preSelection;
}
}
static TreeNode CreateAndAddFileNode(TreeNode root, FileProjectItem item)
{
string directory = Path.GetDirectoryName(item.VirtualName);
TreeNode dir;
if (String.IsNullOrEmpty(directory)) {
dir = root;
} else {
dir = GetOrCreateDirectoryNode(root, directory);
}
TreeNode file = new TreeNode(Path.GetFileName(item.VirtualName), 2, 2);
file.Tag = item;
dir.Nodes.Add(file);
return file;
}
static TreeNode GetOrCreateDirectoryNode(TreeNode root, string directory)
{
int index = directory.IndexOfAny(new [] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar});
string searchDir;
if (index == -1) {
searchDir = directory;
} else {
searchDir = directory.Substring(0, index);
}
TreeNode node = null;
foreach (TreeNode n in root.Nodes) {
if (n.Text == searchDir) {
node = n;
break;
}
}
if (node == null) {
node = new TreeNode(searchDir, 1, 1);
int insertIndex;
for (insertIndex = 0; insertIndex < root.Nodes.Count; insertIndex++) {
TreeNode n = root.Nodes[insertIndex];
if (n.ImageIndex != 1 || StringComparer.CurrentCulture.Compare(searchDir, n.Text) < 0) {
break;
}
}
root.Nodes.Insert(insertIndex, node);
}
if (index == -1) {
return node;
} else {
return GetOrCreateDirectoryNode(node, directory.Substring(index + 1));
}
}
Dictionary<string, object> GetResources(string fileName)
{
Stream s;
OpenedFile file = FileService.GetOpenedFile(fileName);
if (file != null) {
s = file.OpenRead();
} else {
s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
}
using(s) {
using(IResourceReader reader = ResourceStore.CreateResourceReader(s, ResourceStore.GetResourceType(fileName))) {
ResXResourceReader resXReader = reader as ResXResourceReader;
if (resXReader != null) {
resXReader.BasePath = Path.GetDirectoryName(fileName);
}
var resources = new Dictionary<string, object>();
foreach (System.Collections.DictionaryEntry entry in reader) {
if (entry.Value == null) continue;
if (this.requiredResourceType.IsAssignableFrom(entry.Value.GetType())) {
resources.Add((string)entry.Key, entry.Value);
}
}
return resources;
}
}
}
void ProjectTreeScanningBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (this.IsDisposed || this.projectResourcesTreeView.IsDisposed) {
// This can happen when the dialog is closed before
// the scan has finished
if (!e.Cancelled && e.Error == null) {
TreeScanResult r = e.Result as TreeScanResult;
if (r != null) {
DisposeNodeImages(r.Root);
}
}
return;
}
this.projectResourcesTreeView.Nodes.Clear();
if (e.Cancelled) {
return;
}
if (e.Error != null) {
MessageService.ShowError(e.Error, "Error in project tree scanning thread");
}
TreeScanResult result = e.Result as TreeScanResult;
if (result == null) {
return;
}
this.projectResourcesTreeView.BeginUpdate();
ImageList imageList = new ImageList();
imageList.ColorDepth = ColorDepth.Depth32Bit;
imageList.Images.Add(IconService.GetBitmap(IconService.GetImageForProjectType(this.project.Language)));
imageList.Images.Add(WinFormsResourceService.GetBitmap("ProjectBrowser.Folder.Closed"));
imageList.Images.Add(IconService.GetBitmap(IconService.GetImageForFile("a.resx")));
imageList.Images.Add(WinFormsResourceService.GetBitmap("Icons.16x16.Field"));
imageList.Images.Add(WinFormsResourceService.GetBitmap("Icons.16x16.Error"));
this.projectResourcesTreeView.ImageList = imageList;
this.projectResourcesTreeView.Nodes.Add(result.Root);
if (result.PreSelection != null) {
result.PreSelection.EnsureVisible();
this.projectResourcesTreeView.SelectedNode = result.PreSelection;
result.PreSelection.Expand();
} else {
result.Root.Expand();
}
this.projectResourcesTreeView.EndUpdate();
if (result.PreSelection != null) {
this.projectResourcesTreeView.Focus();
}
}
#endregion
void NoResourceRadioButtonCheckedChanged(object sender, EventArgs e)
{
if (this.noResourceRadioButton.Checked) {
this.SetSelectedImage(null, false);
this.okButton.Enabled = true;
}
}
void LocalResourceRadioButtonCheckedChanged(object sender, EventArgs e)
{
if (this.localResourceRadioButton.Checked) {
this.okButton.Enabled = true;
}
}
void ProjectResourceRadioButtonCheckedChanged(object sender, EventArgs e)
{
if (this.projectResourceRadioButton.Checked) {
this.UpdateOnProjectResourceSelection();
this.projectResourcesTreeView.Focus();
}
}
void ProjectResourcesTreeViewAfterSelect(object sender, TreeViewEventArgs e)
{
this.UpdateOnProjectResourceSelection();
}
void UpdateOnProjectResourceSelection()
{
TreeNode node = this.projectResourcesTreeView.SelectedNode;
if (node != null && node.Tag != null && this.requiredResourceType.IsAssignableFrom(node.Tag.GetType())) {
this.SetSelectedImage(node.Tag, true);
this.okButton.Enabled = true;
} else {
this.SetSelectedImage(null, false);
this.okButton.Enabled = false;
}
}
void ImageResourceEditorDialogFormClosed(object sender, FormClosedEventArgs e)
{
this.projectTreeScanningBackgroundWorker.CancelAsync();
if (this.projectResourcesTreeView.Nodes.Count > 0) {
DisposeNodeImages(this.projectResourcesTreeView.Nodes[0]);
}
}
static void DisposeNodeImages(TreeNode root)
{
if (root.Nodes.Count == 0) {
IDisposable d = root.Tag as IDisposable;
if (d != null) {
d.Dispose();
}
root.Tag = null;
} else {
foreach (TreeNode node in root.Nodes) {
DisposeNodeImages(node);
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
void ImportLocalResourceButtonClick(object sender, EventArgs e)
{
bool isIcon = typeof(Icon).IsAssignableFrom(this.requiredResourceType);
using(OpenFileDialog dialog = new OpenFileDialog()) {
dialog.Filter = (isIcon ? DummyIconEditor.FileFilterEntry : DummyImageEditor.FileFilterEntry);
dialog.RestoreDirectory = true;
dialog.Title = StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.Title}");
if (dialog.ShowDialog(this) == DialogResult.OK && !String.IsNullOrEmpty(dialog.FileName)) {
try {
if (isIcon) {
this.SetSelectedImage(new Icon(dialog.FileName), false);
} else {
this.SetSelectedImage(Image.FromFile(dialog.FileName), false);
}
} catch (Exception ex) {
MessageService.ShowError(ex.Message);
}
}
}
}
#region Dummy editors for getting the file filter from the framework
sealed class DummyImageEditor : ImageEditor
{
DummyImageEditor()
{
}
internal static string FileFilterEntry {
get { return CreateFilterEntry(new ImageEditor()); }
}
}
sealed class DummyIconEditor : IconEditor
{
DummyIconEditor()
{
}
internal static string FileFilterEntry {
get { return CreateFilterEntry(new IconEditor()); }
}
}
#endregion
}
}

135
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/ImageResourceEditorDialog.resx

@ -0,0 +1,135 @@ @@ -0,0 +1,135 @@
<?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>
<metadata name="cancelButton.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="splitContainer.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="resourceSelectionGroup.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="previewGroup.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="projectTreeScanningBackgroundWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

157
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ImageResourceEditor.cs

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Security.Permissions;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using ICSharpCode.Core;
using ICSharpCode.FormsDesigner.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.FormsDesigner.Services
{
/// <summary>
/// Edit image and icon properties with the option to use a project resource
/// in an <see cref="ImageResourceEditorDialog"/>.
/// </summary>
public sealed class ImageResourceEditor : UITypeEditor
{
public ImageResourceEditor()
{
}
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
if (context == null || context.PropertyDescriptor == null)
return UITypeEditorEditStyle.None;
if (typeof(Image).IsAssignableFrom(context.PropertyDescriptor.PropertyType) ||
typeof(Icon).IsAssignableFrom(context.PropertyDescriptor.PropertyType)) {
if (context.GetService(typeof(ProjectResourceService)) is ProjectResourceService) {
return UITypeEditorEditStyle.Modal;
}
}
return UITypeEditorEditStyle.Modal;
}
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
if (context == null || context.PropertyDescriptor == null || context.Instance == null || provider == null) {
return value;
}
IComponent component = context.Instance as IComponent;
if (component == null || component.Site == null) {
LoggingService.Info("Editing of image properties on objects not implementing IComponent and components without Site is not supported by the ImageResourceEditor.");
if (typeof(Icon).IsAssignableFrom(context.PropertyDescriptor.PropertyType)) {
return new IconEditor().EditValue(context, provider, value);
} else {
return new ImageEditor().EditValue(context, provider, value);
}
}
var prs = provider.GetService(typeof(ProjectResourceService)) as ProjectResourceService;
if (prs == null) {
return value;
}
var edsvc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
if (edsvc == null) {
throw new InvalidOperationException("The required IWindowsFormsEditorService is not available.");
}
var dictService = component.Site.GetService(typeof(IDictionaryService)) as IDictionaryService;
if (dictService == null) {
throw new InvalidOperationException("The required IDictionaryService is not available.");
}
var projectResource = dictService.GetValue(ProjectResourceService.ProjectResourceKey + context.PropertyDescriptor.Name) as ProjectResourceInfo;
IProject project = prs.ProjectContent.Project as IProject;
ImageResourceEditorDialog dialog;
if (projectResource != null && Object.ReferenceEquals(projectResource.OriginalValue, value)) {
dialog = new ImageResourceEditorDialog(project, context.PropertyDescriptor.PropertyType, projectResource);
} else {
if (context.PropertyDescriptor.PropertyType == typeof(Image)) {
dialog = new ImageResourceEditorDialog(project, value as Image);
} else if (context.PropertyDescriptor.PropertyType == typeof(Icon)) {
dialog = new ImageResourceEditorDialog(project, value as Icon);
} else {
throw new InvalidOperationException("ImageResourceEditor called on unsupported property type: " + context.PropertyDescriptor.PropertyType.ToString());
}
}
using(dialog) {
if (edsvc.ShowDialog(dialog) == DialogResult.OK) {
projectResource = dialog.SelectedProjectResource;
if (projectResource != null) {
dictService.SetValue(ProjectResourceService.ProjectResourceKey + context.PropertyDescriptor.Name, projectResource);
// Ensure the resource generator is turned on for the selected resource file.
if (project != null) {
FileProjectItem fpi = project.FindFile(projectResource.ResourceFile);
if (fpi == null) {
throw new InvalidOperationException("The selected resource file '" + projectResource.ResourceFile + "' was not found in the project.");
}
const string resourceGeneratorToolName = "ResXFileCodeGenerator";
if (!String.Equals(resourceGeneratorToolName, fpi.CustomTool, StringComparison.Ordinal)) {
fpi.CustomTool = resourceGeneratorToolName;
}
CustomToolsService.RunCustomTool(fpi, true);
}
return projectResource.OriginalValue;
} else {
dictService.SetValue(ProjectResourceService.ProjectResourceKey + context.PropertyDescriptor.Name, null);
return dialog.SelectedResourceValue;
}
}
}
return value;
}
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
public override bool GetPaintValueSupported(ITypeDescriptorContext context)
{
if (context != null && context.PropertyDescriptor != null &&
(context.PropertyDescriptor.PropertyType == typeof(Image) ||
context.PropertyDescriptor.PropertyType == typeof(Icon))) {
return true;
}
return base.GetPaintValueSupported(context);
}
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
public override void PaintValue(PaintValueEventArgs e)
{
Image img = e.Value as Image;
if (img != null) {
e.Graphics.DrawImage(img, e.Bounds);
} else {
Icon icon = e.Value as Icon;
if (icon != null) {
e.Graphics.DrawIcon(icon, e.Bounds);
} else {
base.PaintValue(e);
}
}
}
}
}

94
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourceInfo.cs

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.IO;
using System.Resources;
using ICSharpCode.SharpDevelop;
namespace ICSharpCode.FormsDesigner.Services
{
/// <summary>
/// Describes a project resource reference.
/// </summary>
public sealed class ProjectResourceInfo
{
readonly string resourceFile;
readonly string resourceKey;
readonly object originalValue;
/// <summary>
/// Gets the full file name of the resource file that contains the resource.
/// </summary>
public string ResourceFile {
get { return resourceFile; }
}
/// <summary>
/// Gets the resource key.
/// </summary>
public string ResourceKey {
get { return resourceKey; }
}
/// <summary>
/// Gets the value of the resource at creation time of this instance.
/// Can be <c>null</c> if the resource or the file was not found.
/// </summary>
public object OriginalValue {
get { return originalValue; }
}
/// <summary>
/// Initializes a new instance of the <see cref="ProjectResourceInfo"/> class
/// and stores the resource value in the <see cref="OriginalValue"/> property
/// if the resource file is found and it contains the specified key.
/// </summary>
/// <param name="resourceFile">The full name of the resource file that contains the resource.</param>
/// <param name="resourceKey">The resource key.</param>
public ProjectResourceInfo(string resourceFile, string resourceKey)
{
if (resourceFile == null)
throw new ArgumentNullException("resourceFile");
if (resourceKey == null)
throw new ArgumentNullException("resourceKey");
this.resourceFile = resourceFile;
this.resourceKey = resourceKey;
if (File.Exists(resourceFile)) {
OpenedFile openedFile = FileService.GetOpenedFile(resourceFile);
Stream s;
if (openedFile != null) {
s = openedFile.OpenRead();
} else {
s = new FileStream(resourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
}
using(s) {
using(IResourceReader reader = ResourceStore.CreateResourceReader(s, ResourceStore.GetResourceType(resourceFile))) {
ResXResourceReader resXReader = reader as ResXResourceReader;
if (resXReader != null) {
resXReader.BasePath = Path.GetDirectoryName(resourceFile);
}
foreach (DictionaryEntry entry in reader) {
if (String.Equals(resourceKey, entry.Key as string, StringComparison.Ordinal)) {
this.originalValue = entry.Value;
break;
}
}
}
}
}
}
}
}

177
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourceService.cs

@ -0,0 +1,177 @@ @@ -0,0 +1,177 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.CodeDom;
using System.IO;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.FormsDesigner.Services
{
/// <summary>
/// Supports project-level resources in the Windows.Forms designer.
/// </summary>
public sealed class ProjectResourceService
{
public const string ProjectResourceKey = "SDProjectResource_";
IProjectContent projectContent;
string stringLiteralDelimiter;
public ProjectResourceService(IProjectContent projectContent)
{
if (projectContent == null)
throw new ArgumentNullException("projectContent");
this.projectContent = projectContent;
}
public IProjectContent ProjectContent {
get { return projectContent; }
set {
if (value == null)
throw new ArgumentNullException("value");
if (this.projectContent != value) {
this.projectContent = value;
this.stringLiteralDelimiter = null;
}
}
}
/// <summary>
/// Gets the string literal delimiter for the current language
/// by generating code for a known literal.
/// </summary>
string StringLiteralDelimiter {
get {
if (stringLiteralDelimiter == null) {
const string TestString = "A";
string testCode = this.projectContent.Language.CodeGenerator.GenerateCode(new NRefactory.Ast.PrimitiveExpression(TestString, TestString), String.Empty);
stringLiteralDelimiter = testCode.Substring(0, testCode.IndexOf(TestString, StringComparison.Ordinal));
}
return stringLiteralDelimiter;
}
}
/// <summary>
/// Gets the project resource from the specified expression.
/// </summary>
public ProjectResourceInfo GetProjectResource(CodePropertyReferenceExpression propRef)
{
CodeTypeReferenceExpression typeRef = propRef.TargetObject as CodeTypeReferenceExpression;
if (typeRef == null) {
LoggingService.Info("Target of possible project resources property reference is not a type reference, but " + propRef.TargetObject.ToString() + ".");
return null;
}
// Get the (generated) class where the resource is defined.
IClass resourceClass = this.projectContent.GetClass(typeRef.Type.BaseType, 0);
if (resourceClass == null) {
throw new InvalidOperationException("Could not find class for project resources: '" + typeRef.Type.BaseType + "'.");
}
if (resourceClass.CompilationUnit == null || resourceClass.CompilationUnit.FileName == null) {
return null;
}
// Make sure the class we have found is a generated resource class.
if (!IsGeneratedResourceClass(resourceClass)) {
return null;
}
// Get the name of the resource file based on the file that contains the generated class.
string resourceFileName = Path.GetFileNameWithoutExtension(resourceClass.CompilationUnit.FileName);
if (resourceFileName.EndsWith("Designer", StringComparison.OrdinalIgnoreCase)) {
resourceFileName = Path.GetFileNameWithoutExtension(resourceFileName);
}
resourceFileName = Path.Combine(Path.GetDirectoryName(resourceClass.CompilationUnit.FileName), resourceFileName);
if (File.Exists(resourceFileName + ".resources")) {
resourceFileName = resourceFileName + ".resources";
} else if (File.Exists(resourceFileName + ".resx")) {
resourceFileName = resourceFileName + ".resx";
} else {
throw new FileNotFoundException("Could not find the resource file for type '" + resourceClass.FullyQualifiedName + "'. Tried these file names: '" + resourceFileName + ".(resources|resx)'.");
}
// Get the property for the resource.
IProperty prop = resourceClass.Properties.SingleOrDefault(p => p.Name == propRef.PropertyName);
if (prop == null) {
throw new InvalidOperationException("Property '" + propRef.PropertyName + "' not found in type '" + resourceClass.FullyQualifiedName + "'.");
}
if (!prop.CanGet) {
throw new InvalidOperationException("Property '" + propRef.PropertyName + "' in type '" + resourceClass.FullyQualifiedName + "' does not have a getter.");
}
// Get the code of the resource class and
// extract the resource key from the property.
// This is necessary because the key may differ from the property name
// if special characters are used.
// It would be better if we could use a real code parser for this, but
// that is not possible without getting dependent on the programming language.
IDocument doc = new DocumentFactory().CreateDocument();
doc.TextContent = ParserService.GetParseableFileContent(resourceClass.CompilationUnit.FileName);
int startOffset = doc.PositionToOffset(new TextLocation(prop.GetterRegion.BeginColumn - 1, prop.GetterRegion.BeginLine - 1));
int endOffset = doc.PositionToOffset(new TextLocation(prop.GetterRegion.EndColumn - 1, prop.GetterRegion.EndLine - 1));
string code = doc.GetText(startOffset, endOffset - startOffset + 1);
int index = code.IndexOf("ResourceManager", StringComparison.Ordinal);
if (index == -1) {
throw new InvalidOperationException("No reference to ResourceManager found in property getter of '" + prop.FullyQualifiedName + "'. Code: '" + code + "'");
}
index = code.IndexOf("Get", index, StringComparison.Ordinal);
if (index == -1) {
throw new InvalidOperationException("No call to Get... found in property getter of '" + prop.FullyQualifiedName + "'. Code: '" + code + "'");
}
index = code.IndexOf(this.StringLiteralDelimiter, index + 1, StringComparison.Ordinal);
if (index == -1) {
throw new InvalidOperationException("No string delimiter ('" + this.StringLiteralDelimiter + "') found in property getter of '" + prop.FullyQualifiedName + "'. Code: '" + code + "'");
}
index += this.StringLiteralDelimiter.Length;
int endIndex = code.LastIndexOf(this.StringLiteralDelimiter, StringComparison.Ordinal);
if (endIndex == -1) {
throw new InvalidOperationException("No string terminator ('" + this.StringLiteralDelimiter + "') found in property getter of '" + prop.FullyQualifiedName + "'. Code: '" + code + "'");
}
string resourceKey = code.Substring(index, endIndex - index);
LoggingService.Debug("-> Decoded resource: In: " + resourceFileName + ". Key: " + resourceKey);
return new ProjectResourceInfo(resourceFileName, resourceKey);
}
/// <summary>
/// Determines whether the specified class is a generated resource
/// class, based on the attached attributes.
/// </summary>
public static bool IsGeneratedResourceClass(IClass @class)
{
IClass generatedCodeAttributeClass = @class.ProjectContent.GetClass("System.CodeDom.Compiler.GeneratedCodeAttribute", 0);
if (generatedCodeAttributeClass == null) {
LoggingService.Info("Could not find the class for 'System.CodeDom.Compiler.GeneratedCodeAttribute'.");
return false;
}
IReturnType generatedCodeAttribute = generatedCodeAttributeClass.DefaultReturnType;
return @class.Attributes.Any(
att =>
att.AttributeType.Equals(generatedCodeAttribute) &&
att.PositionalArguments.Count == 2 &&
String.Equals("System.Resources.Tools.StronglyTypedResourceBuilder", att.PositionalArguments[0] as string, StringComparison.Ordinal)
);
}
}
}

258
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourcesComponentCodeDomSerializer.cs

@ -0,0 +1,258 @@ @@ -0,0 +1,258 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.IO;
using System.Reflection;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Visitors;
namespace ICSharpCode.FormsDesigner.Services
{
/// <summary>
/// Can deserialize project resources used in a component definition.
/// </summary>
internal sealed class ProjectResourcesComponentCodeDomSerializer : CodeDomSerializer
{
readonly CodeDomSerializer baseSerializer;
internal ProjectResourcesComponentCodeDomSerializer(CodeDomSerializer baseSerializer)
{
if (baseSerializer == null)
throw new ArgumentNullException("baseSerializer");
this.baseSerializer = baseSerializer;
}
public override object Deserialize(IDesignerSerializationManager manager, object codeObject)
{
if (manager == null)
throw new ArgumentNullException("manager");
if (codeObject == null)
throw new ArgumentNullException("codeObject");
object instance = null;
CodeStatementCollection statements = codeObject as CodeStatementCollection;
if (statements != null) {
foreach (CodeStatement statement in statements) {
if (!this.DeserializeProjectResourceStatement(manager, statement)) {
object result = this.baseSerializer.Deserialize(manager, new CodeStatementCollection(new [] {statement}));
if (instance == null) {
instance = result;
}
}
}
return instance;
}
return this.baseSerializer.Deserialize(manager, codeObject);
}
/// <summary>
/// Attempts to deserialize the specified statement as
/// a statement which accesses a project resource.
/// </summary>
/// <returns><c>true</c> if the statement was deserialized successfully, otherwise <c>false</c>.</returns>
bool DeserializeProjectResourceStatement(IDesignerSerializationManager manager, CodeStatement statement)
{
var assignStatement = statement as CodeAssignStatement;
if (assignStatement != null) {
return this.DeserializeProjectResourceAssignStatement(manager, assignStatement);
}
var exprStatement = statement as CodeExpressionStatement;
if (exprStatement != null) {
var invokeExpr = exprStatement.Expression as CodeMethodInvokeExpression;
if (invokeExpr != null) {
return this.DeserializeProjectResourceMethodInvokeExpression(manager, invokeExpr);
}
}
return false;
}
/// <summary>
/// Deserializes an assignment.
/// This is used for standard properties, e.g.
/// <code>myPictureBox.Image = value</code>
/// </summary>
bool DeserializeProjectResourceAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement assignStatement)
{
var propRefTarget = assignStatement.Left as CodePropertyReferenceExpression;
if (propRefTarget == null) {
return false;
}
var propRefSource = assignStatement.Right as CodePropertyReferenceExpression;
if (propRefSource == null) {
return false;
}
LoggingService.Debug("Forms designer: deserializing a property assignment:");
LoggingService.Debug("-> " + CodeStatementToString(assignStatement));
IComponent component = this.baseSerializer.Deserialize(manager, propRefTarget.TargetObject) as IComponent;
if (component == null) {
LoggingService.Info("Forms designer: ProjectResourcesComponentCodeDomSerializer could not deserialze the target object to IComponent");
return false;
}
if (component.Site == null) {
LoggingService.Info("Forms designer: ProjectResourcesComponentCodeDomSerializer: The deserialized component '" + component.ToString() + "' does not have a Site.");
return false;
}
PropertyDescriptor propDescTarget = TypeDescriptor.GetProperties(component).Find(propRefTarget.PropertyName, false);
if (propDescTarget == null) {
throw new InvalidOperationException("Could not find the property descriptor for property '" + propRefTarget.PropertyName + "' on object '" + component.ToString() + "'.");
}
ProjectResourceInfo resourceInfo = GetProjectResourceFromPropertyReference(manager, propRefSource);
if (resourceInfo == null) {
return false;
}
// Set the property value of the target component to the value from the resource
propDescTarget.SetValue(component, resourceInfo.OriginalValue);
// Store our resource info in the dictionary service.
// This is needed for the serializer so that it can
// serialize this value as a project resource reference again.
StoreResourceInfo(component, propDescTarget.Name, resourceInfo);
return true;
}
/// <summary>
/// Deserializes a method invocation expression.
/// This is used for extender providers, e.g.
/// <code>myProvider.SetSomeProperty(targetComponent, value)</code>
/// </summary>
bool DeserializeProjectResourceMethodInvokeExpression(IDesignerSerializationManager manager, CodeMethodInvokeExpression invokeExpression)
{
if (!invokeExpression.Method.MethodName.StartsWith("Set", StringComparison.OrdinalIgnoreCase) ||
invokeExpression.Parameters.Count != 2) {
return false;
}
var propRefSource = invokeExpression.Parameters[1] as CodePropertyReferenceExpression;
if (propRefSource == null) {
return false;
}
LoggingService.Debug("Forms designer: deserializing a method invocation:");
LoggingService.Debug("-> " + CodeStatementToString(new CodeExpressionStatement(invokeExpression)));
object extenderProvider = this.baseSerializer.Deserialize(manager, invokeExpression.Method.TargetObject);
if (extenderProvider == null) {
return false;
}
IComponent targetComponent = this.baseSerializer.Deserialize(manager, invokeExpression.Parameters[0]) as IComponent;
if (targetComponent == null) {
LoggingService.Info("Forms designer: ProjectResourcesComponentCodeDomSerializer could not deserialze the target object to IComponent");
return false;
}
if (targetComponent.Site == null) {
LoggingService.Info("Forms designer: ProjectResourcesComponentCodeDomSerializer: The deserialized component '" + targetComponent.ToString() + "' does not have a Site.");
return false;
}
ProjectResourceInfo resourceInfo = GetProjectResourceFromPropertyReference(manager, propRefSource);
if (resourceInfo == null) {
return false;
}
// Set the property value of the target component to the value from the resource
extenderProvider.GetType()
.InvokeMember(invokeExpression.Method.MethodName,
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
extenderProvider,
new [] {targetComponent, resourceInfo.OriginalValue},
System.Globalization.CultureInfo.InvariantCulture);
// Store our resource info in the dictionary service.
// This is needed for the serializer so that it can
// serialize this value as a project resource reference again.
StoreResourceInfo(targetComponent, invokeExpression.Method.MethodName.Substring(3), resourceInfo);
return true;
}
static ProjectResourceInfo GetProjectResourceFromPropertyReference(IDesignerSerializationManager manager, CodePropertyReferenceExpression propRefSource)
{
ProjectResourceService prs = manager.GetService(typeof(ProjectResourceService)) as ProjectResourceService;
if (prs == null) {
throw new InvalidOperationException("The required ProjectResourceService is not available.");
}
return prs.GetProjectResource(propRefSource);
}
static void StoreResourceInfo(IComponent component, string propertyName, ProjectResourceInfo resourceInfo)
{
var dictService = component.Site.GetService(typeof(IDictionaryService)) as IDictionaryService;
if (dictService == null) {
throw new InvalidOperationException("The required IDictionaryService is not available on component '" + component.ToString() + "'.");
}
dictService.SetValue(ProjectResourceService.ProjectResourceKey + propertyName, resourceInfo);
}
#region Default overrides redirecting to baseSerializer
protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer)
{
// Because this method is protected, we cannot call into the baseSerializer.
// However, as we do not use any serialization of this serializer,
// this is should never be called.
throw new NotImplementedException();
}
public override string GetTargetComponentName(CodeStatement statement, CodeExpression expression, Type targetType)
{
return this.baseSerializer.GetTargetComponentName(statement, expression, targetType);
}
public override object Serialize(IDesignerSerializationManager manager, object value)
{
return this.baseSerializer.Serialize(manager, value);
}
public override object SerializeAbsolute(IDesignerSerializationManager manager, object value)
{
return this.baseSerializer.SerializeAbsolute(manager, value);
}
public override CodeStatementCollection SerializeMember(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)
{
return this.baseSerializer.SerializeMember(manager, owningObject, member);
}
public override CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)
{
return this.baseSerializer.SerializeMemberAbsolute(manager, owningObject, member);
}
#endregion
static string CodeStatementToString(CodeStatement statement)
{
CodeDomVerboseOutputGenerator outputGenerator = new CodeDomVerboseOutputGenerator();
using(StringWriter sw = new StringWriter(System.Globalization.CultureInfo.InvariantCulture)) {
outputGenerator.PublicGenerateCodeFromStatement(statement, sw, null);
return sw.ToString().TrimEnd();
}
}
}
}

172
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ProjectResourcesMemberCodeDomSerializer.cs

@ -0,0 +1,172 @@ @@ -0,0 +1,172 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.IO;
using System.Linq;
using System.Resources.Tools;
using ICSharpCode.Core;
using ICSharpCode.EasyCodeDom;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.FormsDesigner.Services
{
/// <summary>
/// Can serialize assignments to component properties using project resource references.
/// </summary>
internal sealed class ProjectResourcesMemberCodeDomSerializer : MemberCodeDomSerializer
{
readonly MemberCodeDomSerializer baseSerializer;
public ProjectResourcesMemberCodeDomSerializer(MemberCodeDomSerializer baseSerializer)
{
if (baseSerializer == null)
throw new ArgumentNullException("baseSerializer");
this.baseSerializer = baseSerializer;
}
public override void Serialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements)
{
if (!this.SerializeProjectResource(manager, value, descriptor, statements)) {
this.baseSerializer.Serialize(manager, value, descriptor, statements);
}
}
bool SerializeProjectResource(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor, CodeStatementCollection statements)
{
var propDesc = descriptor as PropertyDescriptor;
if (propDesc == null) return false;
var component = value as IComponent;
if (component == null || component.Site == null) return false;
if (!propDesc.ShouldSerializeValue(component)) {
return false;
}
var dictService = component.Site.GetService(typeof(IDictionaryService)) as IDictionaryService;
if (dictService == null) return false;
var resourceInfo = dictService.GetValue(ProjectResourceService.ProjectResourceKey + propDesc.Name) as ProjectResourceInfo;
if (resourceInfo == null) return false;
if (!Object.ReferenceEquals(resourceInfo.OriginalValue, propDesc.GetValue(value))) {
LoggingService.Info("Value of property '" + propDesc.Name + "' on component '" + value.ToString() + "' is not equal to stored project resource value. Ignoring this resource.");
return false;
}
// Find the generated file with the resource accessing class.
var prs = manager.GetService(typeof(ProjectResourceService)) as ProjectResourceService;
if (prs == null) {
LoggingService.Warn("ProjectResourceService not found");
return false;
}
IProject project = prs.ProjectContent.Project as IProject;
if (project == null) {
LoggingService.Warn("Serializer cannot proceed because project is not an IProject");
return false;
}
string resourceFileDirectory = Path.GetDirectoryName(resourceInfo.ResourceFile);
string resourceFileName = Path.GetFileName(resourceInfo.ResourceFile);
var items = project.Items
.OfType<FileProjectItem>()
.Where(
fpi =>
FileUtility.IsEqualFileName(Path.GetDirectoryName(fpi.FileName), resourceFileDirectory) &&
FileUtility.IsEqualFileName(fpi.DependentUpon, resourceFileName) &&
fpi.ItemType == ItemType.Compile &&
fpi.VirtualName.ToUpperInvariant().Contains("DESIGNER")
);
if (items.Count() != 1) {
LoggingService.Info("Did not find exactly one possible file that contains the generated class for the resource file '" + resourceInfo.ResourceFile + "'. Ignoring this resource.");
return false;
}
string resourceCodeFile = items.Single().FileName;
// We expect a single class to be in this file.
IClass resourceClass = ParserService.GetParseInformation(resourceCodeFile).MostRecentCompilationUnit.Classes.Single();
// Here we assume that VerifyResourceName is the same name transform that
// was used when generating the resource code file.
// This should be true as long as the code is generated using the
// custom tool in SharpDevelop or Visual Studio.
string resourcePropertyName = StronglyTypedResourceBuilder.VerifyResourceName(resourceInfo.ResourceKey, prs.ProjectContent.Language.CodeDomProvider ?? LanguageProperties.CSharp.CodeDomProvider);
if (resourcePropertyName == null) {
throw new InvalidOperationException("The resource name '" + resourceInfo.ResourceKey + "' could not be transformed to a name that is valid in the current programming language.");
}
// Now do the actual serialization.
LoggingService.Debug("Serializing project resource: Component '" + component.ToString() + "', Property: '" + propDesc.Name + "', Resource class: '" + resourceClass.FullyQualifiedName + "', Resource property: '" + resourcePropertyName + "'");
var targetObjectExpr = base.SerializeToExpression(manager, value);
if (targetObjectExpr == null) {
LoggingService.Info("Target object could not be serialized: " + value.ToString());
return false;
}
if (propDesc.SerializationVisibility == DesignerSerializationVisibility.Content) {
LoggingService.Debug("-> is a content property, ignoring this.");
return false;
}
var propRefSource =
Easy.Type(
new CodeTypeReference(resourceClass.FullyQualifiedName, CodeTypeReferenceOptions.GlobalReference)
).Property(resourcePropertyName);
var extAttr = propDesc.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
if (extAttr != null && extAttr.Provider != null) {
// This is an extender property.
var extProvider = base.SerializeToExpression(manager, extAttr.Provider);
if (extProvider == null) {
throw new InvalidOperationException("Could not serialize the extender provider '" + extAttr.Provider.ToString() + "'.");
}
statements.Add(
new EasyExpression(extProvider)
.InvokeMethod(
"Set" + propDesc.Name,
targetObjectExpr,
propRefSource
)
);
} else {
// This is a standard property.
statements.Add(
new CodeAssignStatement(
new CodePropertyReferenceExpression(targetObjectExpr, propDesc.Name),
propRefSource)
);
}
return true;
}
public override bool ShouldSerialize(IDesignerSerializationManager manager, object value, MemberDescriptor descriptor)
{
return this.baseSerializer.ShouldSerialize(manager, value, descriptor);
}
}
}

8
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ResourceStore.cs

@ -225,7 +225,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -225,7 +225,7 @@ namespace ICSharpCode.FormsDesigner.Services
}
#endregion
enum ResourceType {
internal enum ResourceType {
Resx = 0,
Resources = 1
};
@ -312,7 +312,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -312,7 +312,7 @@ namespace ICSharpCode.FormsDesigner.Services
return resourceFileName.ToString();
}
static IResourceReader CreateResourceReader(Stream stream, ResourceType type)
internal static IResourceReader CreateResourceReader(Stream stream, ResourceType type)
{
if (stream.Length == 0)
return null;
@ -322,7 +322,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -322,7 +322,7 @@ namespace ICSharpCode.FormsDesigner.Services
return new ResXResourceReader(stream);
}
static IResourceWriter CreateResourceWriter(Stream stream, ResourceType type)
internal static IResourceWriter CreateResourceWriter(Stream stream, ResourceType type)
{
if (type == ResourceType.Resources) {
return new ResourceWriter(stream);
@ -330,7 +330,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -330,7 +330,7 @@ namespace ICSharpCode.FormsDesigner.Services
return new ResXResourceWriter(stream);
}
static ResourceType GetResourceType(string fileName)
internal static ResourceType GetResourceType(string fileName)
{
if (Path.GetExtension(fileName).ToLowerInvariant() == ".resx") {
return ResourceType.Resx;

48
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/SharpDevelopSerializationProvider.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Christian Hornung" email="chhornung@googlemail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
namespace ICSharpCode.FormsDesigner.Services
{
/// <summary>
/// Provides a custom serialization service for the designer.
/// </summary>
internal sealed class SharpDevelopSerializationProvider : IDesignerSerializationProvider
{
internal SharpDevelopSerializationProvider()
{
}
object IDesignerSerializationProvider.GetSerializer(IDesignerSerializationManager manager, object currentSerializer, Type objectType, Type serializerType)
{
if (currentSerializer == null) {
// We need a base serializer to proceed.
return null;
}
if (serializerType == typeof(MemberCodeDomSerializer)) {
if (typeof(PropertyDescriptor).IsAssignableFrom(objectType) && !(currentSerializer is ProjectResourcesMemberCodeDomSerializer)) {
return new ProjectResourcesMemberCodeDomSerializer((MemberCodeDomSerializer)currentSerializer);
}
} else if (serializerType == typeof(CodeDomSerializer)) {
if (typeof(IComponent).IsAssignableFrom(objectType) && !(currentSerializer is ProjectResourcesComponentCodeDomSerializer)) {
return new ProjectResourcesComponentCodeDomSerializer((CodeDomSerializer)currentSerializer);
}
}
return null;
}
}
}

1
src/AddIns/DisplayBindings/ResourceEditor/Project/Src/ResourceCodeGeneratorTool.cs

@ -27,6 +27,7 @@ namespace ResourceEditor @@ -27,6 +27,7 @@ namespace ResourceEditor
IResourceReader reader;
if (string.Equals(Path.GetExtension(inputFilePath), ".resx", StringComparison.OrdinalIgnoreCase)) {
reader = new ResXResourceReader(inputFilePath);
((ResXResourceReader)reader).BasePath = Path.GetDirectoryName(inputFilePath);
} else {
reader = new ResourceReader(inputFilePath);
}

9
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -636,6 +636,15 @@ namespace ICSharpCode.SharpDevelop @@ -636,6 +636,15 @@ namespace ICSharpCode.SharpDevelop
//if (res != null)
// return res;
OpenedFile file = FileService.GetOpenedFile(fileName);
if (file != null) {
using(Stream s = file.OpenRead()) {
// load file
Encoding encoding = DefaultFileEncoding;
return ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(s, ref encoding);
}
}
// load file
return ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(fileName, DefaultFileEncoding);
}

BIN
src/Main/StartUp/Project/Resources/StringResources.resources

Binary file not shown.
Loading…
Cancel
Save