<commit_before>﻿// Copyright (c) 2013-2021  <NAME> <<EMAIL>>
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;

using Crow.IML;
using Crow.Drawing;
using Glfw;
using Path = System.IO.Path;

namespace Crow
{
	/// <summary>
	/// Interface is the base class for building crow application.
	/// It is thread safe allowing application to run multiple interfaces in different threads.
	/// </summary>
	/// <remarks>
	/// The Interface contains :
	/// 	- rendering and layouting queues and logic.
	/// 	- helpers to load IML interfaces files directely bound to this interface
	/// 	- global static constants and variables of CROW
	/// 	- Keyboard and Mouse logic
	///
	/// </remarks>
	public class Interface : ILayoutable, IDisposable, ICommandHost
	{
		#region IValueChange implementation
		public event EventHandler<ValueChangeEventArgs> ValueChanged;
		public void NotifyValueChanged (string MemberName, object _value)
		{
			//Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
			ValueChanged.Raise (this, new ValueChangeEventArgs (MemberName, _value));
		}
		public void NotifyValueChanged (object _value, [CallerMemberName] string caller = null)
		{
			NotifyValueChanged (caller, _value);
		}
		#endregion

		internal static List<Assembly> crowAssemblies = new List<Assembly> ();
		/// <summary>
		/// Add Assembly that may contains CROW ui ressources like custom widget classes, IML, images, ...
		/// Styling fond in those assemblies are automatically loaded on addition;
		/// This assembly will be searched for embedded ressource resolution, extension methods, and custom widgets.
		/// For those assemblies to be added by simple name, see 'CrowAssemblyNames'.
		/// </summary>
		/// <param name="a">The assembly to add.</param>
		public void AddCrowAssembly (Assembly a) {
			lock (UpdateMutex) {
				if (crowAssemblies.Contains (a))
					return;
				crowAssemblies.Add (a);
				loadStylingFromAssembly (a);
			}
		}
		/// <summary>
		/// Remove Assembly from the CrowAssembly list. See 'AddCrowAssembly' for details.
		/// </summary>
		/// <param name="a">The assembly to unload</param>
		public void RemoveCrowAssembly (Assembly a) {
			lock (UpdateMutex) {
				if (!crowAssemblies.Contains (a))
					return;
				crowAssemblies.Remove (a);
				init_internal ();
			}
		}

		static IntPtr resolveUnmanaged(Assembly assembly, String libraryName)
		{

			switch (libraryName)
			{
				case "cairo":
					IntPtr cairoNative = NativeLibrary.Load("cairo-2", assembly, null);
					if (cairoNative == IntPtr.Zero && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
						Console.WriteLine ("[Error] Native dlls required by crow are not found.");
						Console.WriteLine ("You can download them here:\n\thttps://onedrive.live.com/download?cid=B3181664476E9B48&resid=B3181664476E9B48%21493&authkey=<KEY>");
						Console.WriteLine ("Then extract them in one of the following directory or in your build target one: ");
						foreach (string dir in System.AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES").ToString().Split (';'))
							Console.WriteLine ($"\t- {dir}");
					}
					return cairoNative;
				/*case "glfw3":
					return NativeLibrary.Load("glfw", assembly, null);*/
				case "rsvg-2.40":
					return NativeLibrary.Load("rsvg-2", assembly, null);
			}
			return IntPtr.Zero;
		}


		#region CTOR
		static Interface ()
		{
			System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()).ResolvingUnmanagedDll += resolveUnmanaged;

			CROW_CONFIG_ROOT =
				System.IO.Path.Combine (
					Environment.GetFolderPath (Environment.SpecialFolder.UserProfile),
					".config");
			CROW_CONFIG_ROOT = System.IO.Path.Combine (CROW_CONFIG_ROOT, "crow");
			if (!Directory.Exists (CROW_CONFIG_ROOT))
				Directory.CreateDirectory (CROW_CONFIG_ROOT);<commit_msg>add error message and needed links for native dll resolution on windows<commit_after>﻿// Copyright (c) 2013-2021  <NAME> <<EMAIL>>
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;

using Crow.IML;
using Crow.Drawing;
using Glfw;
using Path = System.IO.Path;

namespace Crow
{
	/// <summary>
	/// Interface is the base class for building crow application.
	/// It is thread safe allowing application to run multiple interfaces in different threads.
	/// </summary>
	/// <remarks>
	/// The Interface contains :
	/// 	- rendering and layouting queues and logic.
	/// 	- helpers to load IML interfaces files directely bound to this interface
	/// 	- global static constants and variables of CROW
	/// 	- Keyboard and Mouse logic
	///
	/// </remarks>
	public class Interface : ILayoutable, IDisposable, ICommandHost
	{
		#region IValueChange implementation
		public event EventHandler<ValueChangeEventArgs> ValueChanged;
		public void NotifyValueChanged (string MemberName, object _value)
		{
			//Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value);
			ValueChanged.Raise (this, new ValueChangeEventArgs (MemberName, _value));
		}
		public void NotifyValueChanged (object _value, [CallerMemberName] string caller = null)
		{
			NotifyValueChanged (caller, _value);
		}
		#endregion

		internal static List<Assembly> crowAssemblies = new List<Assembly> ();
		/// <summary>
		/// Add Assembly that may contains CROW ui ressources like custom widget classes, IML, images, ...
		/// Styling fond in those assemblies are automatically loaded on addition;
		/// This assembly will be searched for embedded ressource resolution, extension methods, and custom widgets.
		/// For those assemblies to be added by simple name, see 'CrowAssemblyNames'.
		/// </summary>
		/// <param name="a">The assembly to add.</param>
		public void AddCrowAssembly (Assembly a) {
			lock (UpdateMutex) {
				if (crowAssemblies.Contains (a))
					return;
				crowAssemblies.Add (a);
				loadStylingFromAssembly (a);
			}
		}
		/// <summary>
		/// Remove Assembly from the CrowAssembly list. See 'AddCrowAssembly' for details.
		/// </summary>
		/// <param name="a">The assembly to unload</param>
		public void RemoveCrowAssembly (Assembly a) {
			lock (UpdateMutex) {
				if (!crowAssemblies.Contains (a))
					return;
				crowAssemblies.Remove (a);
				init_internal ();
			}
		}
		static void nativeHelpMessage () {
		}
		static IntPtr resolveUnmanaged(Assembly assembly, String libraryName)
		{
			try {
				switch (libraryName)
				{
					case "cairo":
						return NativeLibrary.Load("cairo-2", assembly, null);
					/*case "glfw3":
						return NativeLibrary.Load("glfw", assembly, null);*/
					case "rsvg-2.40":
						return NativeLibrary.Load("rsvg-2", assembly, null);
				}
			} catch {
				if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
					Console.ForegroundColor = ConsoleColor.DarkRed;
					Console.WriteLine ("Native dlls required by crow cant be found.");
					Console.ResetColor();
					Console.WriteLine ("You can download them here:");
					Console.ForegroundColor = ConsoleColor.Blue;
					Console.WriteLine ("  https://onedrive.live.com/download?cid=B3181664476E9B48&resid=B3181664476E9B48%21493&authkey=AJCso6KAKMCBfAM");
					Console.ResetColor();
					Console.WriteLine ("Then extract them in one of the following directories or in your project output directory.");
					foreach (string dir in System.AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES").ToString().Split (';', StringSplitOptions.RemoveEmptyEntries))
						Console.WriteLine ($" - {dir}");
				}
				Environment.Exit(0);
			}
			return IntPtr.Zero;
		}


		#region CTOR
		static Interface ()
		{
			System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()).ResolvingUnmanagedDll += resolveUnmanaged;

			CROW_CONFIG_ROOT =
				System.IO.Path.Combine (
					Environment.GetFolderPath (Environment.SpecialFolder.UserProfile),
					".config");
			CROW_CONFIG_ROOT = System.IO.Path.Combine (CROW_CONFIG_ROOT, "crow");
			if (!Directory.Exists (CROW_CONFIG_ROOT))
				Directory.CreateDirectory (CROW_CONFIG_ROOT);
{'fraction_non_alphanumeric': 0.116066257384455, 'fraction_numerical': 0.011351789644387815, 'mean_word_length': 3.807349665924276, 'pattern_counts': {'":': 6, '<': 40, '<?xml version=': 0, '>': 42, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5791657', 'n_tokens_mistral': 2958, 'n_tokens_neox': 2520, 'n_words': 730}