You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.9 KiB
165 lines
5.9 KiB
4 years ago
|
using Monaco.Helpers;
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Diagnostics;
|
||
|
using System.Linq;
|
||
|
using System.Text;
|
||
|
using System.Threading.Tasks;
|
||
|
using System.Reflection;
|
||
|
using Windows.Foundation;
|
||
|
using Windows.UI.Xaml;
|
||
|
using Windows.UI.Xaml.Controls;
|
||
|
using Windows.UI.Xaml.Input;
|
||
|
|
||
|
namespace Monaco
|
||
|
{
|
||
|
public partial class CodeEditor
|
||
|
{
|
||
|
// Override default Loaded/Loading event so we can make sure we've initialized our WebView contents with the CodeEditor.
|
||
|
|
||
|
/// <summary>
|
||
|
/// When Editor is Loading, it is ready to receive commands to the Monaco Engine.
|
||
|
/// </summary>
|
||
|
public new event RoutedEventHandler Loading;
|
||
|
|
||
|
/// <summary>
|
||
|
/// When Editor is Loaded, it has been rendered and is ready to be displayed.
|
||
|
/// </summary>
|
||
|
public new event RoutedEventHandler Loaded;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called when a link is Ctrl+Clicked on in the editor, set Handled to true to prevent opening.
|
||
|
/// </summary>
|
||
|
public event TypedEventHandler<WebView, WebViewNewWindowRequestedEventArgs> OpenLinkRequested;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Called when an internal exception is encountered while executing a command. (for testing/reporting issues)
|
||
|
/// </summary>
|
||
|
public event TypedEventHandler<CodeEditor, Exception> InternalException;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Custom Keyboard Handler.
|
||
|
/// </summary>
|
||
|
public new event WebKeyEventHandler KeyDown;
|
||
|
|
||
|
private ThemeListener _themeListener;
|
||
|
|
||
|
private void WebView_DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
|
||
|
{
|
||
|
#if DEBUG
|
||
|
Debug.WriteLine("DOM Content Loaded");
|
||
|
#endif
|
||
|
this._initialized = true;
|
||
|
}
|
||
|
|
||
|
private async void WebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
|
||
|
{
|
||
|
this.IsLoaded = true;
|
||
|
|
||
|
// Make sure inner editor is focused
|
||
|
await SendScriptAsync("editor.focus();");
|
||
|
|
||
|
// If we're supposed to have focus, make sure we try and refocus on our now loaded webview.
|
||
|
if (FocusManager.GetFocusedElement() == this)
|
||
|
{
|
||
|
this._view.Focus(FocusState.Programmatic);
|
||
|
}
|
||
|
|
||
|
Loaded?.Invoke(this, new RoutedEventArgs());
|
||
|
}
|
||
|
|
||
|
internal ParentAccessor _parentAccessor;
|
||
|
private KeyboardListener _keyboardListener;
|
||
|
private long _themeToken;
|
||
|
|
||
|
private void WebView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
|
||
|
{
|
||
|
#if DEBUG
|
||
|
Debug.WriteLine("Navigation Starting");
|
||
|
#endif
|
||
|
_parentAccessor = new ParentAccessor(this);
|
||
|
_parentAccessor.AddAssemblyForTypeLookup(typeof(Range).GetTypeInfo().Assembly);
|
||
|
_parentAccessor.RegisterAction("Loaded", CodeEditorLoaded);
|
||
|
|
||
|
_themeListener = new ThemeListener();
|
||
|
_themeListener.ThemeChanged += _themeListener_ThemeChanged;
|
||
|
_themeToken = RegisterPropertyChangedCallback(RequestedThemeProperty, RequestedTheme_PropertyChanged);
|
||
|
|
||
|
_keyboardListener = new KeyboardListener(this);
|
||
|
|
||
|
this._view.AddWebAllowedObject("Debug", new DebugLogger());
|
||
|
this._view.AddWebAllowedObject("Parent", _parentAccessor);
|
||
|
this._view.AddWebAllowedObject("Theme", _themeListener);
|
||
|
this._view.AddWebAllowedObject("Keyboard", _keyboardListener);
|
||
|
}
|
||
|
|
||
|
private async void CodeEditorLoaded()
|
||
|
{
|
||
|
if (Decorations != null && Decorations.Count > 0)
|
||
|
{
|
||
|
// Need to retrigger highlights after load if they were set before load.
|
||
|
await DeltaDecorationsHelperAsync(Decorations.ToArray());
|
||
|
}
|
||
|
|
||
|
// Now we're done loading
|
||
|
Loading?.Invoke(this, new RoutedEventArgs());
|
||
|
}
|
||
|
|
||
|
private void WebView_NewWindowRequested(WebView sender, WebViewNewWindowRequestedEventArgs args)
|
||
|
{
|
||
|
// TODO: Should probably create own event args here as we don't want to expose the referrer to our internal page?
|
||
|
OpenLinkRequested?.Invoke(sender, args);
|
||
|
}
|
||
|
|
||
|
private async void RequestedTheme_PropertyChanged(DependencyObject obj, DependencyProperty property)
|
||
|
{
|
||
|
var editor = obj as CodeEditor;
|
||
|
var theme = editor.RequestedTheme;
|
||
|
var tstr = string.Empty;
|
||
|
|
||
|
if (theme == ElementTheme.Default)
|
||
|
{
|
||
|
tstr = _themeListener.CurrentThemeName;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tstr = theme.ToString();
|
||
|
}
|
||
|
|
||
|
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
|
||
|
{
|
||
|
await this.InvokeScriptAsync("changeTheme", new string[] { tstr, _themeListener.IsHighContrast.ToString() });
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private async void _themeListener_ThemeChanged(ThemeListener sender)
|
||
|
{
|
||
|
if (RequestedTheme == ElementTheme.Default)
|
||
|
{
|
||
|
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
|
||
|
{
|
||
|
await this.InvokeScriptAsync("changeTheme", args: new string[] { sender.CurrentTheme.ToString(), sender.IsHighContrast.ToString() });
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool TriggerKeyDown(WebKeyEventArgs args)
|
||
|
{
|
||
|
this.KeyDown?.Invoke(this, args);
|
||
|
|
||
|
return args.Handled;
|
||
|
}
|
||
|
|
||
|
protected override void OnGotFocus(RoutedEventArgs e)
|
||
|
{
|
||
|
base.OnGotFocus(e);
|
||
|
|
||
|
if (this._view != null && FocusManager.GetFocusedElement() == this)
|
||
|
{
|
||
|
// Forward Focus onto our inner WebView
|
||
|
this._view.Focus(FocusState.Programmatic);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|