-
Notifications
You must be signed in to change notification settings - Fork 1
/
DXHtmlEditorWebView.cs
110 lines (109 loc) · 4.08 KB
/
DXHtmlEditorWebView.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Threading.Tasks;
using DevExpress.Utils;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
namespace DXHtmlEditor {
public class DXHtmlEditorWebView : WebView2, IDXHtmlEditorAPI {
DXHtmlEditorClient client;
public DXHtmlEditorWebView() {
if(!DesignMode)
Initialize();
}
#region API
public async Task<string> GetHtmlText() {
await EnsureIsLoaded();
return await client.GetHtmlText();
}
public async Task<string> SetHtmlText(string htmlString) {
await EnsureIsLoaded();
return await client.SetHtmlText(htmlString);
}
public bool CanSetTheme(string themeName) {
return client.ThemeName != themeName;
}
public async Task SetTheme(string themeName) {
string htmlText = await GetHtmlText();
StartLoading();
client.ThemeName = themeName;
await SetHtmlText(htmlText);
Refresh();
}
#endregion API
#region Custom API Sample
public async Task Undo() {
await EnsureIsLoaded();
await client.Undo();
}
public async Task Redo() {
await EnsureIsLoaded();
await client.Redo();
}
#endregion
#region Events
static readonly object htmlChanged = new object();
static readonly object htmlLoaded = new object();
//
public event EventHandler HtmlChanged {
add { Events.AddHandler(htmlChanged, value); }
remove { Events.RemoveHandler(htmlChanged, value); }
}
public event EventHandler HtmlLoaded {
add { Events.AddHandler(htmlLoaded, value); }
remove { Events.RemoveHandler(htmlLoaded, value); }
}
void IDXHtmlEditorAPI.RaiseOnHtmlChanged() {
(Events[htmlChanged] as EventHandler)?.Invoke(this, EventArgs.Empty);
}
void IDXHtmlEditorAPI.RaiseOnLoaded() {
loadedSource?.TrySetResult(true);
(Events[htmlLoaded] as EventHandler)?.Invoke(this, EventArgs.Empty);
}
#endregion Events
#region Internal
void Initialize() {
StartLoading();
client = new DXHtmlEditorClient(this);
CoreWebView2InitializationCompleted += OnCoreWebView2InitializationCompleted;
}
protected override void Dispose(bool disposing) {
CoreWebView2InitializationCompleted -= OnCoreWebView2InitializationCompleted;
loadedSource?.TrySetCanceled();
loadedSource = null;
DisposeHelper.Dispose(ref client);
base.Dispose(disposing);
}
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
if(!DesignMode)
EnsureCoreWebView2Async();
}
protected override void OnHandleDestroyed(EventArgs e) {
base.OnHandleDestroyed(e);
loadedSource?.TrySetCanceled();
}
void OnCoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) {
client.Initialize(CoreWebView2);
}
TaskCompletionSource<bool> loadedSource;
void StartLoading() {
var prevSource = loadedSource;
loadedSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
if(prevSource != null && !prevSource.Task.IsCompleted)
prevSource.TrySetCanceled();
}
async Task EnsureIsLoaded() {
try {
Task<bool> loadingTask = loadedSource?.Task;
bool loaded = await loadingTask;
if(!loaded || loadingTask.IsFaulted)
throw new Exception("DXHtmlEditor loading failed", loadingTask?.Exception);
}
catch(TaskCanceledException e) {
if(e.Task != loadedSource?.Task)
await EnsureIsLoaded();
}
}
#endregion
}
}