mirror of
https://github.com/VitalickS/BrightSharp.Toolkit.git
synced 2026-03-21 02:21:15 +00:00
Ok, Just Do It!
This commit is contained in:
282
BrightSharp.Toolkit.Extra/CKEditor.xaml.cs
Normal file
282
BrightSharp.Toolkit.Extra/CKEditor.xaml.cs
Normal file
@@ -0,0 +1,282 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms.Integration;
|
||||
using System.Windows.Threading;
|
||||
using CefSharp;
|
||||
using CefSharp.WinForms;
|
||||
|
||||
namespace BrightSharp.Toolkit.Extra
|
||||
{
|
||||
public partial class CKEditor
|
||||
{
|
||||
internal ChromiumWebBrowser Browser;
|
||||
private CKEditorObjectForScripting _objectForScripting;
|
||||
|
||||
public static void InitializeCef(bool useCache = true, bool reinit = false)
|
||||
{
|
||||
Dispatcher.CurrentDispatcher.ShutdownStarted += (s, e) => Cef.Shutdown();
|
||||
if (!reinit && Cef.IsInitialized) return;
|
||||
CefSettings settings;
|
||||
|
||||
if (useCache)
|
||||
{
|
||||
var cacheDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"cefCache");
|
||||
Directory.CreateDirectory(cacheDir);
|
||||
settings = new CefSettings
|
||||
{
|
||||
CachePath = cacheDir
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
settings = new CefSettings();
|
||||
}
|
||||
|
||||
settings.RegisterScheme(new CefCustomScheme
|
||||
{
|
||||
SchemeName = "local",
|
||||
SchemeHandlerFactory = new FolderSchemeHandlerFactory(Environment.CurrentDirectory)
|
||||
});
|
||||
|
||||
Cef.Initialize(settings);
|
||||
}
|
||||
|
||||
private static void InitializeDesignTimeDirectory()
|
||||
{
|
||||
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
|
||||
{
|
||||
Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
var nugetPackages = DesignTimeConfig.GetNugetPackagesDirectory();
|
||||
if (!Directory.Exists(nugetPackages)) return;
|
||||
var prefix = IntPtr.Size == 4 ? "x86" : "x64";
|
||||
var allDirectoriesToCopy = Directory.GetDirectories(nugetPackages, "cef.redist.*")
|
||||
.Union(Directory.GetDirectories(nugetPackages, "CefSharp.*"))
|
||||
.SelectMany(d => Directory.GetDirectories(d, prefix, SearchOption.AllDirectories));
|
||||
foreach (var dirForCopy in allDirectoriesToCopy)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(dirForCopy))
|
||||
{
|
||||
try { File.Copy(file, Path.Combine(Environment.CurrentDirectory, Path.GetFileName(file)), false); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
foreach (var file in Directory.GetFiles(Directory.GetParent(dirForCopy).FullName))
|
||||
{
|
||||
try { File.Copy(file, Path.Combine(Environment.CurrentDirectory, Path.GetFileName(file)), false); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static CKEditor()
|
||||
{
|
||||
InitializeDesignTimeDirectory();
|
||||
if (!File.Exists("CefSharp.Core.dll"))
|
||||
return;
|
||||
InitializeCef();
|
||||
}
|
||||
|
||||
public CKEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
if (!File.Exists("CefSharp.dll"))
|
||||
return;
|
||||
|
||||
var host = (WindowsFormsHost)Template.FindName("PART_Host", this);
|
||||
|
||||
|
||||
host.Child = Browser = new ChromiumWebBrowser("about:blank");
|
||||
|
||||
_objectForScripting = new CKEditorObjectForScripting(this);
|
||||
Browser.KeyboardHandler = new FixKeyboardHandler();
|
||||
|
||||
Browser.IsBrowserInitializedChanged += (s, e) =>
|
||||
{
|
||||
if (e.IsBrowserInitialized)
|
||||
RefreshState();
|
||||
};
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
public void RefreshState()
|
||||
{
|
||||
if (Browser != null && Browser.IsBrowserInitialized)
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
var docContent = BuildDocContent();
|
||||
Browser.LoadString(docContent, "about:blank");
|
||||
}));
|
||||
UpdateDevToolsState();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnContentChanged(object oldContent, object newContent)
|
||||
{
|
||||
if (Browser != null && _objectForScripting != null && (string)newContent != _objectForScripting.NewData)
|
||||
{
|
||||
//This is not from js
|
||||
Browser.EvaluateScriptAsync($"setData(`{newContent}`)").Wait(TimeSpan.FromSeconds(2));
|
||||
}
|
||||
|
||||
base.OnContentChanged(oldContent, newContent);
|
||||
}
|
||||
|
||||
public string PackageType
|
||||
{
|
||||
get { return (string)GetValue(PackageTypeProperty); }
|
||||
set { SetValue(PackageTypeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PackageTypeProperty =
|
||||
DependencyProperty.Register("PackageType", typeof(string), typeof(CKEditor), new PropertyMetadata("standard", UpdatePackageType));
|
||||
|
||||
private static void UpdatePackageType(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var editor = (CKEditor)d;
|
||||
editor.RefreshState();
|
||||
}
|
||||
|
||||
|
||||
public bool ShowDevTools
|
||||
{
|
||||
get { return (bool)GetValue(ShowDevToolsProperty); }
|
||||
set { SetValue(ShowDevToolsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowDevToolsProperty =
|
||||
DependencyProperty.Register("ShowDevTools", typeof(bool), typeof(CKEditor), new PropertyMetadata(false, ShowDevToolsChanged));
|
||||
|
||||
private static void ShowDevToolsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var editor = (CKEditor)d;
|
||||
editor.UpdateDevToolsState();
|
||||
}
|
||||
|
||||
private void UpdateDevToolsState()
|
||||
{
|
||||
if (Browser != null && Browser.IsBrowserInitialized)
|
||||
{
|
||||
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
if (ShowDevTools)
|
||||
Browser.ShowDevTools();
|
||||
else
|
||||
Browser.CloseDevTools();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildDocContent()
|
||||
{
|
||||
var docContent = Properties.Resources.HtmlEditor;
|
||||
if (EditorConfiguration != null)
|
||||
{
|
||||
EditorConfiguration.Optimize(PackageType);
|
||||
docContent = docContent.Replace("$$CONFIG",
|
||||
new JavaScriptSerializer().Serialize(EditorConfiguration));
|
||||
docContent = docContent.Replace("$$PACKAGE", PackageType);
|
||||
}
|
||||
|
||||
docContent = docContent.Replace("$$CONTENT", (Content ?? "").ToString());
|
||||
|
||||
return docContent;
|
||||
}
|
||||
|
||||
|
||||
public CKEditorConfig EditorConfiguration
|
||||
{
|
||||
get { return (CKEditorConfig)GetValue(EditorConfigurationProperty); }
|
||||
set { SetValue(EditorConfigurationProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EditorConfigurationProperty =
|
||||
DependencyProperty.Register("EditorConfiguration", typeof(CKEditorConfig), typeof(CKEditor), new PropertyMetadata(new CKEditorConfig()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class CKEditorConfig
|
||||
{
|
||||
public string[] contentsCss { get; set; }
|
||||
public string language { get; set; } = Thread.CurrentThread.CurrentUICulture.Name;
|
||||
public string removeButtons { get; set; } =
|
||||
"Save,Print,Preview,Maximize,ShowBlocks,Paste,PasteText,PasteFromWord";
|
||||
public string extraAllowedContent { get; set; } = "span;ul;li;table;td;style;*[id];*(*);*{*}";
|
||||
public string removePlugins { get; set; } = "resize";
|
||||
|
||||
public void Optimize(string packageType)
|
||||
{
|
||||
if (string.Equals("basic", packageType, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
//TODO Basic configuration has many problems.
|
||||
//TODO Need think do we need it, or can we use Standard package as Basic to emulate Basic (from CKE) ?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class CKEditorObjectForScripting
|
||||
{
|
||||
private CKEditor _editor;
|
||||
|
||||
internal string NewData;
|
||||
|
||||
public CKEditorObjectForScripting(CKEditor editor)
|
||||
{
|
||||
_editor = editor;
|
||||
_editor.Browser.RegisterJsObject("$$OBJ", this);
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public void SetupContent(string newData)
|
||||
{
|
||||
NewData = newData;
|
||||
_editor.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => _editor.Content = NewData));
|
||||
}
|
||||
}
|
||||
|
||||
public class CKEditorDesignTimeSettings
|
||||
{
|
||||
public static string DesignTimeCefBinariesDirectory { get; set; }
|
||||
}
|
||||
class FixKeyboardHandler : IKeyboardHandler
|
||||
{
|
||||
public bool OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode,
|
||||
CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut)
|
||||
{
|
||||
//F10, Alt
|
||||
if (windowsKeyCode == 0x79 || windowsKeyCode == 0x12)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode,
|
||||
CefEventFlags modifiers, bool isSystemKey)
|
||||
{
|
||||
if (windowsKeyCode == 0x79 || windowsKeyCode == 0x12)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user