Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add _ScintillaManagedDragDrop & improve error messages #114

Merged
merged 2 commits into from
May 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 58 additions & 52 deletions Shared/Scintilla.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
Expand All @@ -22,79 +23,71 @@
{
static Scintilla()
{
var basePath = LocateNativeDllDirectory();
modulePathScintilla = Path.Combine(basePath, "Scintilla.dll");
modulePathLexilla = Path.Combine(basePath, "Lexilla.dll");

try
{
var info = FileVersionInfo.GetVersionInfo(modulePathScintilla);
scintillaVersion = info.ProductVersion ?? info.FileVersion;
info = FileVersionInfo.GetVersionInfo(modulePathLexilla);
lexillaVersion = info.ProductVersion ?? info.FileVersion;
}
catch
List<string> searchedPathList = new List<string>();
foreach (string path in EnumerateSatelliteLibrarySearchPaths())
{
scintillaVersion = "ERROR";
lexillaVersion = "ERROR";
// the path to the following .NET or .NET Framework satellite assemblies exists but the assemblies are not found in the directory.
// (surely a problem in the package itself or in its installation of the project).
throw new InvalidOperationException(@$"Scintilla.NET satellite assemblies not found in {basePath}");
string scintillaDllPath = Path.Combine(path, "Scintilla.dll");
string lexillaDllPath = Path.Combine(path, "Lexilla.dll");
if (File.Exists(scintillaDllPath) && File.Exists(lexillaDllPath))
{
modulePathScintilla = scintillaDllPath;
modulePathLexilla = lexillaDllPath;
try
{
var info = FileVersionInfo.GetVersionInfo(modulePathScintilla);
scintillaVersion = info.ProductVersion ?? info.FileVersion;
info = FileVersionInfo.GetVersionInfo(modulePathLexilla);
lexillaVersion = info.ProductVersion ?? info.FileVersion;
return;
}
catch
{
searchedPathList.Add(path);
}
}
else
searchedPathList.Add(path);
}

string searchedPaths = string.Join("\n", searchedPathList);

scintillaVersion = "ERROR";
lexillaVersion = "ERROR";
// the path to the following .NET or .NET Framework satellite assemblies exists but the assemblies are not found in the directory.
// (surely a problem in the package itself or in its installation of the project).
throw new InvalidOperationException($"Scintilla.NET satellite assemblies not found in any of the following paths:\n{searchedPaths}");
}

private static string LocateNativeDllDirectory()
public static IEnumerable<string> EnumerateSatelliteLibrarySearchPaths()
{
// check run-time paths
string platform = Environment.Is64BitProcess ? "x64" : "x86";
Assembly runtimeAssembly = Assembly.GetExecutingAssembly();
string managedLocation = Path.GetDirectoryName(runtimeAssembly.Location) ?? AppDomain.CurrentDomain.BaseDirectory;
string basePath = Path.Combine(managedLocation, platform);

if (Directory.Exists(basePath))
{
return basePath;
}
var runtimeAssembly = Assembly.GetExecutingAssembly();
string managedLocation = Path.GetDirectoryName(runtimeAssembly.Location) ?? AppDomain.CurrentDomain.BaseDirectory;
yield return Path.Combine(managedLocation, platform);

// check design-mode paths
string frameworkName = runtimeAssembly?.GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;

if (frameworkName.Contains("NETFramework"))
{
// In.NET Framework, look for the assemblies in the nuget global packages folder
Assembly designtimeAssembly = Assembly.GetAssembly(typeof(Scintilla));
string nugetScintillaPackageFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\.nuget\packages\scintilla5.net\";
// In .NET Framework, look for the assemblies in the nuget global packages folder
var designtimeAssembly = Assembly.GetAssembly(typeof(Scintilla));
string nugetScintillaPackageFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @".nuget\packages\scintilla5.net");
string nugetScintillaPackageVersion = designtimeAssembly.GetName().Version.ToString();
basePath = Path.Combine(nugetScintillaPackageFolder + nugetScintillaPackageVersion + @"\build\" + platform);

if (Directory.Exists(basePath))
{
return basePath;
}
yield return Path.Combine(nugetScintillaPackageFolder, nugetScintillaPackageVersion, "build", platform);

// then check the project folder using the Scintilla.NET assembly location
// move up a few levels to the host project folder and append the location nuget used at install
string nugetScintillaNETLocation = designtimeAssembly.Location;
string nugetScintillaPackageName = designtimeAssembly.GetName().Name;
string rootProjectFolder = Path.GetFullPath(Path.Combine(nugetScintillaNETLocation, @"..\..\..\..\"));
basePath = Path.Combine(rootProjectFolder, @"packages\" + nugetScintillaPackageName + "." + nugetScintillaPackageVersion + @"\build\" + platform);

if (Directory.Exists(basePath))
{
return basePath;
}

throw new InvalidOperationException(@$"Unable to locate the Scintilla.NET satellite assemblies : directory '{basePath}' not found");
string rootProjectFolder = Path.GetFullPath(Path.Combine(nugetScintillaNETLocation, @"..\..\..\.."));
yield return Path.Combine(rootProjectFolder, "packages", nugetScintillaPackageName + "." + nugetScintillaPackageVersion, "build", platform);
}
else
{
// if .NET in design mode
basePath = Path.GetFullPath(Path.Combine(managedLocation, "..", "..", "build", platform));
if (Directory.Exists(basePath))
{
return basePath;
}

throw new InvalidOperationException(@$"Unable to locate the Scintilla.NET satellite assemblies : directory '{basePath}' not found");
yield return Path.GetFullPath(Path.Combine(managedLocation, @"..\..\build", platform));
}
}

Expand Down Expand Up @@ -1427,7 +1420,7 @@

/// <summary>
/// Default Attribute values do not always get applied to the control.
/// https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.defaultvalueattribute?view=net-8.0&redirectedfrom=MSDN

Check warning on line 1423 in Shared/Scintilla.cs

View workflow job for this annotation

GitHub Actions / build (Debug)

XML comment has badly formed XML -- 'Reference to undefined entity 'redirectedfrom'.'

Check warning on line 1423 in Shared/Scintilla.cs

View workflow job for this annotation

GitHub Actions / build (Release)

XML comment has badly formed XML -- 'Reference to undefined entity 'redirectedfrom'.'
/// "A DefaultValueAttribute will not cause a member to be automatically initialized with the attribute's value. You must set the initial value in your code."
/// This function is created to be called in the OnHandleCreated event so that we can force the default values to be applied.
/// </summary>
Expand Down Expand Up @@ -1818,7 +1811,8 @@
// ways to solve this, but my favorite is to revoke drag and drop from the
// native Scintilla control before base.OnHandleCreated does the standard
// processing of AllowDrop.
NativeMethods.RevokeDragDrop(Handle);
if (!this._ScintillaManagedDragDrop)
NativeMethods.RevokeDragDrop(this.Handle);

base.OnHandleCreated(e);
}
Expand Down Expand Up @@ -3276,6 +3270,18 @@

#region Properties

/// <summary>
/// Gets or sets whether Scintilla's native drag & drop should be used instead of WinForms based one.

Check warning on line 3274 in Shared/Scintilla.cs

View workflow job for this annotation

GitHub Actions / build (Debug)

XML comment has badly formed XML -- 'Whitespace is not allowed at this location.'

Check warning on line 3274 in Shared/Scintilla.cs

View workflow job for this annotation

GitHub Actions / build (Release)

XML comment has badly formed XML -- 'Whitespace is not allowed at this location.'
/// </summary>
/// <value><c>true</c> if Scintilla's native drag & drop should be used; otherwise, <c>false</c>. The default is false.</value>

Check warning on line 3276 in Shared/Scintilla.cs

View workflow job for this annotation

GitHub Actions / build (Debug)

XML comment has badly formed XML -- 'Whitespace is not allowed at this location.'

Check warning on line 3276 in Shared/Scintilla.cs

View workflow job for this annotation

GitHub Actions / build (Release)

XML comment has badly formed XML -- 'Whitespace is not allowed at this location.'
[DefaultValue(false)]
[Category("Behaviour")]
[Description("Indicates whether Scintilla's native drag & drop should be used instead of WinForms based one.")]
public bool _ScintillaManagedDragDrop { get; set; }
// Underscore is used so that WinForms Designer sets it before any other
// property. Otherwise ApplyResources gets called on the control before
// the property is set, which then triggers OnHandleCreated before we
// have the final value.

/// <summary>
/// Gets or sets the bi-directionality of the Scintilla control.
Expand Down
Loading