21 changed files with 769 additions and 746 deletions
@ -1,627 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.ComponentModel; |
|
||||||
using System.ComponentModel.Design; |
|
||||||
using System.Drawing; |
|
||||||
using System.Drawing.Design; |
|
||||||
using System.Drawing.Imaging; |
|
||||||
using System.IO; |
|
||||||
using System.Linq; |
|
||||||
using System.Resources; |
|
||||||
using System.Resources.Tools; |
|
||||||
using System.Windows.Forms; |
|
||||||
using System.Windows.Forms.Design; |
|
||||||
using ICSharpCode.Core; |
|
||||||
using ICSharpCode.Core.WinForms; |
|
||||||
using ICSharpCode.FormsDesigner.Services; |
|
||||||
using ICSharpCode.SharpDevelop; |
|
||||||
using ICSharpCode.SharpDevelop.Dom; |
|
||||||
using ICSharpCode.SharpDevelop.Editor; |
|
||||||
using ICSharpCode.SharpDevelop.Gui; |
|
||||||
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; |
|
||||||
Stream originalImage; |
|
||||||
bool selectedImageIsProjectResource; |
|
||||||
Stream selectedImage; |
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
ImageResourceEditorDialog(IProject project, Type requiredResourceType, bool designerSupportsProjectResources) |
|
||||||
: 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"); |
|
||||||
|
|
||||||
this.projectResourceRadioButton.Visible = designerSupportsProjectResources; |
|
||||||
this.projectResourcesTreeView.Visible = designerSupportsProjectResources; |
|
||||||
} |
|
||||||
|
|
||||||
public ImageResourceEditorDialog(IProject project, Type requiredResourceType, IProjectResourceInfoWrapper projectResource) |
|
||||||
: this(project, requiredResourceType, true) |
|
||||||
{ |
|
||||||
if (projectResource == null) |
|
||||||
throw new ArgumentNullException("projectResource"); |
|
||||||
|
|
||||||
this.projectResourceRadioButton.Checked = true; |
|
||||||
this.originalImage = this.selectedImage = projectResource.CreateStream(); |
|
||||||
|
|
||||||
this.selectedImageIsProjectResource = true; |
|
||||||
this.SetPreviewImage(new Bitmap(selectedImage)); |
|
||||||
this.projectTreeScanningBackgroundWorker.RunWorkerAsync(projectResource); |
|
||||||
} |
|
||||||
|
|
||||||
public ImageResourceEditorDialog(IProject project, Stream localResource, bool isIcon, bool designerSupportsProjectResources) |
|
||||||
: this(project, isIcon ? typeof(Icon) : typeof(Image), designerSupportsProjectResources) |
|
||||||
{ |
|
||||||
if (localResource != null) { |
|
||||||
this.localResourceRadioButton.Checked = true; |
|
||||||
this.originalImage = this.selectedImage = localResource; |
|
||||||
this.SetPreviewImage(new Bitmap(localResource)); |
|
||||||
} else { |
|
||||||
this.noResourceRadioButton.Checked = true; |
|
||||||
} |
|
||||||
this.projectTreeScanningBackgroundWorker.RunWorkerAsync(); |
|
||||||
} |
|
||||||
|
|
||||||
Stream CreateStream(object value) |
|
||||||
{ |
|
||||||
MemoryStream stream = new MemoryStream(); |
|
||||||
|
|
||||||
if (value is Image) |
|
||||||
((Image)value).Save(stream, ImageFormat.Png); |
|
||||||
else if (value is Icon) |
|
||||||
((Icon)value).Save(stream); |
|
||||||
else |
|
||||||
return null; |
|
||||||
|
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
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 Stream 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(Stream image, bool isIcon, 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); |
|
||||||
} |
|
||||||
|
|
||||||
if (image == null) { |
|
||||||
this.selectedImageIsProjectResource = false; |
|
||||||
this.selectedImage = null; |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (isIcon) { |
|
||||||
this.selectedImage = image; |
|
||||||
this.selectedImageIsProjectResource = isProjectResource; |
|
||||||
this.SetPreviewImage(new Bitmap(image)); |
|
||||||
} else { |
|
||||||
this.selectedImage = image; |
|
||||||
this.selectedImageIsProjectResource = isProjectResource; |
|
||||||
this.SetPreviewImage(new Bitmap(image)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#region Project tree filling
|
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] |
|
||||||
void ProjectTreeScanningBackgroundWorkerDoWork(object sender, DoWorkEventArgs e) |
|
||||||
{ |
|
||||||
if (this.project == null) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
IProjectResourceInfo selectedProjectResource = e.Argument as IProjectResourceInfo; |
|
||||||
|
|
||||||
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 = null; |
|
||||||
WorkbenchSingleton.SafeThreadCall( |
|
||||||
delegate { |
|
||||||
OpenedFile file = FileService.GetOpenedFile(fileName); |
|
||||||
if (file != null) { |
|
||||||
s = file.OpenRead(); |
|
||||||
} |
|
||||||
}); |
|
||||||
if (s == null) { |
|
||||||
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.ShowException(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, 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) |
|
||||||
{ |
|
||||||
if (this.projectResourceRadioButton.Checked) { |
|
||||||
this.UpdateOnProjectResourceSelection(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void UpdateOnProjectResourceSelection() |
|
||||||
{ |
|
||||||
TreeNode node = this.projectResourcesTreeView.SelectedNode; |
|
||||||
if (node != null && node.Tag != null && this.requiredResourceType.IsAssignableFrom(node.Tag.GetType())) { |
|
||||||
this.SetSelectedImage(CreateStream(node.Tag), false, true); |
|
||||||
this.okButton.Enabled = true; |
|
||||||
} else { |
|
||||||
this.SetSelectedImage(null, false, 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 { |
|
||||||
this.SetSelectedImage(new FileStream(dialog.FileName, FileMode.Open, FileAccess.Read, FileShare.Read), isIcon, 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
|
|
||||||
} |
|
||||||
|
|
||||||
public class ImageResourceEditorDialogWrapper : MarshalByRefObject, IImageResourceEditorDialogWrapper |
|
||||||
{ |
|
||||||
IProject project; |
|
||||||
Func<object, Stream> createStream; |
|
||||||
|
|
||||||
public ImageResourceEditorDialogWrapper(IProject project, Func<object, Stream> createStream) |
|
||||||
{ |
|
||||||
if (project == null) |
|
||||||
throw new ArgumentNullException("project"); |
|
||||||
this.project = project; |
|
||||||
this.createStream = createStream; |
|
||||||
} |
|
||||||
|
|
||||||
public object GetValue(IProjectResourceInfo projectResource, object value, IProjectResourceService prs, Type propertyType, string propertyName, IWindowsFormsEditorService edsvc, IDictionaryService dictService) |
|
||||||
{ |
|
||||||
ImageResourceEditorDialog dialog; |
|
||||||
|
|
||||||
if (projectResource != null && object.ReferenceEquals(projectResource.OriginalValue, value) && prs.DesignerSupportsProjectResources) { |
|
||||||
dialog = new ImageResourceEditorDialog(project, propertyType, (IProjectResourceInfoWrapper)projectResource); |
|
||||||
} else { |
|
||||||
if (propertyType == typeof(Image)) { |
|
||||||
dialog = new ImageResourceEditorDialog(project, createStream(value), false, prs.DesignerSupportsProjectResources); |
|
||||||
} else if (propertyType == typeof(Icon)) { |
|
||||||
dialog = new ImageResourceEditorDialog(project, createStream(value), true, prs.DesignerSupportsProjectResources); |
|
||||||
} else { |
|
||||||
throw new InvalidOperationException("ImageResourceEditor called on unsupported property type: " + propertyType.ToString()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
using(dialog) { |
|
||||||
if (edsvc.ShowDialog(dialog) == DialogResult.OK) { |
|
||||||
projectResource = dialog.SelectedProjectResource; |
|
||||||
if (projectResource != null) { |
|
||||||
dictService.SetValue(prs.ProjectResourceKey + propertyName, 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"; |
|
||||||
const string publicResourceGeneratorToolName = "PublicResXFileCodeGenerator"; |
|
||||||
if (!String.Equals(resourceGeneratorToolName, fpi.CustomTool, StringComparison.Ordinal) && |
|
||||||
!String.Equals(publicResourceGeneratorToolName, fpi.CustomTool, StringComparison.Ordinal)) { |
|
||||||
fpi.CustomTool = resourceGeneratorToolName; |
|
||||||
} |
|
||||||
CustomToolsService.RunCustomTool(fpi, true); |
|
||||||
} |
|
||||||
|
|
||||||
return projectResource.OriginalValue; |
|
||||||
} else { |
|
||||||
dictService.SetValue(prs.ProjectResourceKey + propertyName, null); |
|
||||||
return dialog.SelectedResourceValue; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,179 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.ComponentModel.Design; |
||||||
|
using System.Drawing; |
||||||
|
using System.Drawing.Design; |
||||||
|
using System.Drawing.Imaging; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Resources; |
||||||
|
using System.Resources.Tools; |
||||||
|
using System.Threading; |
||||||
|
using System.Windows.Forms; |
||||||
|
using System.Windows.Forms.Design; |
||||||
|
|
||||||
|
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.Core.WinForms; |
||||||
|
using ICSharpCode.FormsDesigner.Services; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
using ICSharpCode.SharpDevelop.Gui; |
||||||
|
using ICSharpCode.SharpDevelop.Project; |
||||||
|
|
||||||
|
namespace ICSharpCode.FormsDesigner.Gui |
||||||
|
{ |
||||||
|
public class ImageResourceEditorDialogWrapper : MarshalByRefObject, IImageResourceEditorDialogWrapper |
||||||
|
{ |
||||||
|
IProject project; |
||||||
|
Type requiredResourceType; |
||||||
|
|
||||||
|
public ImageResourceEditorDialogWrapper(IProject project) |
||||||
|
{ |
||||||
|
if (project == null) |
||||||
|
throw new ArgumentNullException("project"); |
||||||
|
this.project = project; |
||||||
|
} |
||||||
|
|
||||||
|
TreeScanResult ProduceTreeNodes(IProjectResourceInfo selectedProjectResource, CancellationToken ct) |
||||||
|
{ |
||||||
|
IProjectContent projectContent = ParserService.GetProjectContent(this.project); |
||||||
|
|
||||||
|
TreeScanResult root = new TreeScanResult(project.Name, 0, 0); |
||||||
|
TreeScanResult preSelection = null; |
||||||
|
TreeScanResult lastFileNode = null; |
||||||
|
int fileNodesCount = 0; |
||||||
|
foreach (FileProjectItem item in this.project.GetItemsOfType(ItemType.EmbeddedResource) |
||||||
|
.OfType<FileProjectItem>().OrderBy(fpi => Path.GetFileName(fpi.VirtualName))) { |
||||||
|
ct.ThrowIfCancellationRequested(); |
||||||
|
|
||||||
|
// 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); |
||||||
|
TreeScanResult file = CreateAndAddFileNode(root, item); |
||||||
|
|
||||||
|
if (file != null) { |
||||||
|
lastFileNode = file; |
||||||
|
++fileNodesCount; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Preselect the file node if there is only one
|
||||||
|
if (preSelection == null && fileNodesCount == 1) { |
||||||
|
preSelection = lastFileNode; |
||||||
|
lastFileNode.IsSelected = true; |
||||||
|
} |
||||||
|
return root; |
||||||
|
} |
||||||
|
|
||||||
|
static TreeScanResult CreateAndAddFileNode(TreeScanResult root, FileProjectItem item) |
||||||
|
{ |
||||||
|
string directory = Path.GetDirectoryName(item.VirtualName); |
||||||
|
TreeScanResult dir; |
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(directory)) { |
||||||
|
dir = root; |
||||||
|
} else { |
||||||
|
dir = GetOrCreateDirectoryNode(root, directory); |
||||||
|
} |
||||||
|
|
||||||
|
TreeScanResult file = new TreeScanResult(Path.GetFileName(item.VirtualName), 2, 2); |
||||||
|
dir.Children.Add(file); |
||||||
|
file.FileName = item.FileName; |
||||||
|
return file; |
||||||
|
} |
||||||
|
|
||||||
|
static TreeScanResult GetOrCreateDirectoryNode(TreeScanResult 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); |
||||||
|
} |
||||||
|
|
||||||
|
TreeScanResult node = null; |
||||||
|
foreach (TreeScanResult n in root.Children) { |
||||||
|
if (n.Text == searchDir) { |
||||||
|
node = n; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (node == null) { |
||||||
|
node = new TreeScanResult(searchDir, 1, 1); |
||||||
|
int insertIndex; |
||||||
|
for (insertIndex = 0; insertIndex < root.Children.Count; insertIndex++) { |
||||||
|
TreeScanResult n = root.Children[insertIndex]; |
||||||
|
if (n.ImageIndex != 1 || StringComparer.CurrentCulture.Compare(searchDir, n.Text) < 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
root.Children.Insert(insertIndex, node); |
||||||
|
} |
||||||
|
|
||||||
|
if (index == -1) { |
||||||
|
return node; |
||||||
|
} else { |
||||||
|
return GetOrCreateDirectoryNode(node, directory.Substring(index + 1)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public ImageList CreateImageList() |
||||||
|
{ |
||||||
|
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")); |
||||||
|
return imageList; |
||||||
|
} |
||||||
|
|
||||||
|
public void ProduceTreeNodesAsync(IProjectResourceInfo projectResource, Type requiredResourceType, Action<bool, Exception, TreeScanResult> finishedAction) |
||||||
|
{ |
||||||
|
var ct = new CancellationTokenSource().Token; |
||||||
|
this.requiredResourceType = requiredResourceType; |
||||||
|
var task = new System.Threading.Tasks.Task<TreeScanResult>(() => ProduceTreeNodes(projectResource, ct)); |
||||||
|
task.ContinueWith(t => finishedAction(t.IsCanceled, t.Exception, t.Result)) |
||||||
|
.ContinueWith(t => WorkbenchSingleton.SafeThreadAsyncCall((Action)delegate { if (t.Exception != null) MessageService.ShowException(t.Exception); })); |
||||||
|
task.Start(); |
||||||
|
} |
||||||
|
|
||||||
|
public void UpdateProjectResource(IProjectResourceInfo 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"; |
||||||
|
const string publicResourceGeneratorToolName = "PublicResXFileCodeGenerator"; |
||||||
|
if (!String.Equals(resourceGeneratorToolName, fpi.CustomTool, StringComparison.Ordinal) && |
||||||
|
!String.Equals(publicResourceGeneratorToolName, fpi.CustomTool, StringComparison.Ordinal)) { |
||||||
|
fpi.CustomTool = resourceGeneratorToolName; |
||||||
|
} |
||||||
|
CustomToolsService.RunCustomTool(fpi, true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,398 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.ComponentModel.Design; |
||||||
|
using System.Drawing; |
||||||
|
using System.Drawing.Design; |
||||||
|
using System.Drawing.Imaging; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Resources; |
||||||
|
using System.Resources.Tools; |
||||||
|
using System.Threading; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using System.Windows.Forms; |
||||||
|
using System.Windows.Forms.Design; |
||||||
|
using ICSharpCode.FormsDesigner.Services; |
||||||
|
|
||||||
|
//using ICSharpCode.Core;
|
||||||
|
//using ICSharpCode.Core.WinForms;
|
||||||
|
//using ICSharpCode.SharpDevelop;
|
||||||
|
//using ICSharpCode.SharpDevelop.Dom;
|
||||||
|
//using ICSharpCode.SharpDevelop.Editor;
|
||||||
|
//using ICSharpCode.SharpDevelop.Gui;
|
||||||
|
//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 Type requiredResourceType; |
||||||
|
object originalImage; |
||||||
|
bool selectedImageIsProjectResource; |
||||||
|
object selectedImage; |
||||||
|
IImageResourceEditorDialogWrapper dialogProxy; |
||||||
|
CancellationTokenSource cts; |
||||||
|
IServiceProvider provider; |
||||||
|
ISharpDevelopIDEService messageService; |
||||||
|
IResourceStore resourceStore; |
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
ImageResourceEditorDialog(IServiceProvider provider, IImageResourceEditorDialogWrapper dialogProxy, Type requiredResourceType, bool designerSupportsProjectResources) |
||||||
|
: base() |
||||||
|
{ |
||||||
|
if (requiredResourceType == null) |
||||||
|
throw new ArgumentNullException("requiredResourceType"); |
||||||
|
this.requiredResourceType = requiredResourceType; |
||||||
|
this.dialogProxy = dialogProxy; |
||||||
|
InitializeComponent(); |
||||||
|
|
||||||
|
cts = new CancellationTokenSource(); |
||||||
|
this.provider = provider; |
||||||
|
this.messageService = (ISharpDevelopIDEService)provider.GetService(typeof(ISharpDevelopIDEService)); |
||||||
|
this.resourceStore = (IResourceStore)provider.GetService(typeof(IResourceStore)); |
||||||
|
|
||||||
|
Translate(this); |
||||||
|
this.projectResourcesTreeView.Nodes.Add(messageService.GetResourceString("Global.PleaseWait")); |
||||||
|
|
||||||
|
this.importLocalResourceButton.DataBindings.Add("Enabled", this.localResourceRadioButton, "Checked"); |
||||||
|
this.projectResourcesTreeView.DataBindings.Add("Enabled", this.projectResourceRadioButton, "Checked"); |
||||||
|
|
||||||
|
this.projectResourceRadioButton.Visible = designerSupportsProjectResources; |
||||||
|
this.projectResourcesTreeView.Visible = designerSupportsProjectResources; |
||||||
|
} |
||||||
|
|
||||||
|
public ImageResourceEditorDialog(IServiceProvider provider, IImageResourceEditorDialogWrapper dialogProxy, Type requiredResourceType, IProjectResourceInfo projectResource) |
||||||
|
: this(provider, dialogProxy, requiredResourceType, true) |
||||||
|
{ |
||||||
|
if (projectResource == null) |
||||||
|
throw new ArgumentNullException("projectResource"); |
||||||
|
|
||||||
|
this.projectResourceRadioButton.Checked = true; |
||||||
|
this.originalImage = this.selectedImage = projectResource.OriginalValue; |
||||||
|
|
||||||
|
this.selectedImageIsProjectResource = true; |
||||||
|
if (selectedImage is Stream) |
||||||
|
this.SetPreviewImage(new Bitmap(selectedImage as Stream)); |
||||||
|
else if (selectedImage is Icon) |
||||||
|
this.SetPreviewImage((selectedImage as Icon).ToBitmap()); |
||||||
|
dialogProxy.ProduceTreeNodesAsync(projectResource, requiredResourceType, ProduceNodesFinished); |
||||||
|
} |
||||||
|
|
||||||
|
public ImageResourceEditorDialog(IServiceProvider provider, IImageResourceEditorDialogWrapper dialogProxy, object localResource, bool isIcon, bool designerSupportsProjectResources) |
||||||
|
: this(provider, dialogProxy, isIcon ? typeof(Icon) : typeof(Image), designerSupportsProjectResources) |
||||||
|
{ |
||||||
|
if (selectedImage is Stream) { |
||||||
|
this.localResourceRadioButton.Checked = true; |
||||||
|
this.originalImage = this.selectedImage = localResource; |
||||||
|
this.SetPreviewImage(new Bitmap(localResource as Stream)); |
||||||
|
} else if (selectedImage is Icon) { |
||||||
|
this.localResourceRadioButton.Checked = true; |
||||||
|
this.originalImage = this.selectedImage = localResource; |
||||||
|
this.SetPreviewImage((localResource as Icon).ToBitmap()); |
||||||
|
} else { |
||||||
|
this.noResourceRadioButton.Checked = true; |
||||||
|
} |
||||||
|
dialogProxy.ProduceTreeNodesAsync(null, requiredResourceType, ProduceNodesFinished); |
||||||
|
} |
||||||
|
|
||||||
|
void Translate(Control control) |
||||||
|
{ |
||||||
|
control.Text = messageService.Parse(control.Text); |
||||||
|
foreach (Control child in control.Controls) { |
||||||
|
Translate(child); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
object CreateStream(object value) |
||||||
|
{ |
||||||
|
MemoryStream stream = new MemoryStream(); |
||||||
|
|
||||||
|
if (value is Image) |
||||||
|
((Image)value).Save(stream, ImageFormat.Png); |
||||||
|
else |
||||||
|
return value; |
||||||
|
|
||||||
|
return stream; |
||||||
|
} |
||||||
|
#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 IProjectResourceInfo SelectedProjectResource { |
||||||
|
get { |
||||||
|
if (this.selectedImageIsProjectResource && this.projectResourceRadioButton.Checked) { |
||||||
|
|
||||||
|
TreeNode node = this.projectResourcesTreeView.SelectedNode; |
||||||
|
if (node == null) return null; |
||||||
|
|
||||||
|
return ProjectResourceInfo.Create(resourceStore, (string)node.Parent.Tag, 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 ProduceNodesFinished(bool isCancelled, Exception exception, TreeScanResult result) |
||||||
|
{ |
||||||
|
projectResourcesTreeView.Invoke( |
||||||
|
(Action)delegate { |
||||||
|
if (this.IsDisposed || this.projectResourcesTreeView.IsDisposed) { |
||||||
|
// This can happen when the dialog is closed before
|
||||||
|
// the scan has finished
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
this.projectResourcesTreeView.Nodes.Clear(); |
||||||
|
|
||||||
|
if (isCancelled) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (exception != null) { |
||||||
|
messageService.ShowException(exception, "Error in project tree scanning thread"); |
||||||
|
} |
||||||
|
|
||||||
|
if (result == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
this.projectResourcesTreeView.BeginUpdate(); |
||||||
|
|
||||||
|
this.projectResourcesTreeView.ImageList = dialogProxy.CreateImageList(); |
||||||
|
TreeNode selection = null; |
||||||
|
GenerateTreeNodes(result, this.projectResourcesTreeView.Nodes, ref selection); |
||||||
|
|
||||||
|
if (selection != null) { |
||||||
|
selection.EnsureVisible(); |
||||||
|
this.projectResourcesTreeView.SelectedNode = selection; |
||||||
|
selection.Expand(); |
||||||
|
} else { |
||||||
|
this.projectResourcesTreeView.Nodes[0].Expand(); |
||||||
|
} |
||||||
|
|
||||||
|
this.projectResourcesTreeView.EndUpdate(); |
||||||
|
|
||||||
|
if (selection != null) { |
||||||
|
this.projectResourcesTreeView.Focus(); |
||||||
|
} |
||||||
|
} |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
void GenerateTreeNodes(TreeScanResult parent, TreeNodeCollection nodes, ref TreeNode selection) |
||||||
|
{ |
||||||
|
var treeNode = new TreeNode(parent.Text, parent.ImageIndex, parent.SelectedImageIndex); |
||||||
|
treeNode.Tag = parent.FileName; |
||||||
|
|
||||||
|
foreach (var res in GetResources(parent.FileName)) { |
||||||
|
var resNode = new TreeNode(res.Key, 3, 3); |
||||||
|
resNode.Tag = res.Value; |
||||||
|
treeNode.Nodes.Add(resNode); |
||||||
|
} |
||||||
|
|
||||||
|
if (parent.IsSelected) |
||||||
|
selection = treeNode; |
||||||
|
nodes.Add(treeNode); |
||||||
|
foreach (var node in parent.Children) { |
||||||
|
GenerateTreeNodes(node, treeNode.Nodes, ref selection); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
IEnumerable<KeyValuePair<string, object>> GetResources(string fileName) |
||||||
|
{ |
||||||
|
if (fileName == null) |
||||||
|
yield break; |
||||||
|
|
||||||
|
Stream s = resourceStore.OpenFile(fileName); |
||||||
|
using(s) { |
||||||
|
using(IResourceReader reader = ResourceHelpers.CreateResourceReader(s, ResourceHelpers.GetResourceType(fileName))) { |
||||||
|
ResXResourceReader resXReader = reader as ResXResourceReader; |
||||||
|
if (resXReader != null) { |
||||||
|
resXReader.BasePath = Path.GetDirectoryName(fileName); |
||||||
|
} |
||||||
|
|
||||||
|
foreach (System.Collections.DictionaryEntry entry in reader) { |
||||||
|
if (entry.Value == null) continue; |
||||||
|
if (this.requiredResourceType.IsAssignableFrom(entry.Value.GetType())) { |
||||||
|
yield return new KeyValuePair<string, object>((string)entry.Key, entry.Value); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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 isIcon, 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); |
||||||
|
} |
||||||
|
|
||||||
|
if (image == null) { |
||||||
|
this.selectedImageIsProjectResource = false; |
||||||
|
this.selectedImage = null; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (isIcon) { |
||||||
|
this.selectedImage = image; |
||||||
|
this.selectedImageIsProjectResource = isProjectResource; |
||||||
|
this.SetPreviewImage((image as Icon).ToBitmap()); |
||||||
|
} else { |
||||||
|
this.selectedImage = image; |
||||||
|
this.selectedImageIsProjectResource = isProjectResource; |
||||||
|
this.SetPreviewImage(image as Image); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void NoResourceRadioButtonCheckedChanged(object sender, EventArgs e) |
||||||
|
{ |
||||||
|
if (this.noResourceRadioButton.Checked) { |
||||||
|
this.SetSelectedImage(null, false, 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) |
||||||
|
{ |
||||||
|
if (this.projectResourceRadioButton.Checked) { |
||||||
|
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, false, true); |
||||||
|
this.okButton.Enabled = true; |
||||||
|
} else { |
||||||
|
this.SetSelectedImage(null, false, false); |
||||||
|
this.okButton.Enabled = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ImageResourceEditorDialogFormClosed(object sender, FormClosedEventArgs e) |
||||||
|
{ |
||||||
|
cts.Cancel(); |
||||||
|
} |
||||||
|
|
||||||
|
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 = messageService.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.Gui.ImageResourceEditor.Title}"); |
||||||
|
if (dialog.ShowDialog(this) == DialogResult.OK && !String.IsNullOrEmpty(dialog.FileName)) { |
||||||
|
try { |
||||||
|
object data = null; |
||||||
|
if (isIcon) |
||||||
|
data = new Icon(dialog.FileName); |
||||||
|
else |
||||||
|
data = new Bitmap(dialog.FileName); |
||||||
|
this.SetSelectedImage(data, isIcon, false); |
||||||
|
} catch (Exception ex) { |
||||||
|
messageService.ShowException(ex, null); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#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
|
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue