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 new LibraryViewExtension project based on System.Windows.Controls.WebBrowser #10241

Merged
merged 23 commits into from
Jan 9, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3a28281
add new project
mjkkirschner Dec 18, 2019
6585e6c
build of libjswebview seems to work
mjkkirschner Dec 18, 2019
795737a
add resource files as links so dont duplicate them in repo
mjkkirschner Dec 18, 2019
8f79259
move to .net 4.7.2 to avoid package ref issues
mjkkirschner Dec 18, 2019
560fa6d
move back to 4.7 to see if we can get a build on self serve
mjkkirschner Dec 18, 2019
7299d67
log msbuild version in appyveyor
mjkkirschner Dec 18, 2019
4be5e27
try using buildxml which restores a bit differently
mjkkirschner Dec 18, 2019
1d58ed0
image should not be under env - bah
mjkkirschner Dec 18, 2019
84eb36b
revet back to nuget restore and build dynamo all
mjkkirschner Dec 18, 2019
250638e
working branch in acad
mjkkirschner Dec 21, 2019
38087f2
icons from host registered streams supported now
mjkkirschner Dec 23, 2019
6ccd1d1
this functions but startup time is slow.
mjkkirschner Dec 24, 2019
c30524c
add some stopwatch logging to resource loading
mjkkirschner Dec 24, 2019
ea48e6d
missed changes
mjkkirschner Dec 24, 2019
77e35ef
semi working lazy load - small change made to librariejs to raise eve…
mjkkirschner Jan 2, 2020
993fd59
some cleanup
mjkkirschner Jan 2, 2020
e9a2f73
update namespace to reflect what components are actually used
mjkkirschner Jan 2, 2020
4fe8162
drop back to packges config
mjkkirschner Jan 2, 2020
8de53e4
assembly and type names changed
mjkkirschner Jan 2, 2020
eea6cfd
remove value tuple use
mjkkirschner Jan 6, 2020
4af994a
get rid of value tuple
mjkkirschner Jan 7, 2020
e63239a
recase some methods
mjkkirschner Jan 7, 2020
86b98b0
address review comments
mjkkirschner Jan 8, 2020
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
5 changes: 4 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ platform: Any CPU

configuration: Release

image: Visual Studio 2017

before_build:
- nuget restore .\src\Dynamo.All.sln

environment:
dynamo_solution: src/Dynamo.All.sln
image: Visual Studio 2017


build_script:
- where msbuild
- msbuild %dynamo_solution%


Expand Down
11 changes: 11 additions & 0 deletions src/Dynamo.All.sln
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspaceDependencyViewExtension", "WorkspaceDependencyViewExtension\WorkspaceDependencyViewExtension.csproj", "{5E76AAB3-6302-473E-9655-081B53FB1419}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibraryViewExtensionMSWebBrowser", "LibraryViewExtensionMSWebBrowser\LibraryViewExtensionMSWebBrowser.csproj", "{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}"
mjkkirschner marked this conversation as resolved.
Show resolved Hide resolved
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -811,6 +813,14 @@ Global
{5E76AAB3-6302-473E-9655-081B53FB1419}.Release|Any CPU.Build.0 = Release|Any CPU
{5E76AAB3-6302-473E-9655-081B53FB1419}.Release|x64.ActiveCfg = Release|Any CPU
{5E76AAB3-6302-473E-9655-081B53FB1419}.Release|x64.Build.0 = Release|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|x64.ActiveCfg = Debug|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|x64.Build.0 = Debug|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Release|Any CPU.Build.0 = Release|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Release|x64.ActiveCfg = Release|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -883,6 +893,7 @@ Global
{C0D6DEE5-5532-4345-9C66-4C00D7FDB8BE} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
{47D2166C-5261-4093-9660-E72B7035E666} = {88D45B00-E564-41DB-B57C-9509646CAA49}
{5E76AAB3-6302-473E-9655-081B53FB1419} = {88D45B00-E564-41DB-B57C-9509646CAA49}
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE} = {88D45B00-E564-41DB-B57C-9509646CAA49}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {89CB19C6-BF0A-4E6A-BFDA-79D143EAB59D}
Expand Down
2 changes: 2 additions & 0 deletions src/DynamoCore/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@
// Internals are visible to the Package Manager extension
// For workspace package dependency collection
[assembly: InternalsVisibleTo("WorkspaceDependencyViewExtension")]

[assembly: InternalsVisibleTo("LibraryViewExtensionMSWebBrowser")]
167 changes: 167 additions & 0 deletions src/LibraryViewExtensionMSWebBrowser/EventObserver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
using System;
using System.Threading;

namespace Dynamo.LibraryViewExtensionMSWebBrowser
{
/// <summary>
/// A class that observes an event and notifies the clients with a transformed
/// data as configured using reduce function.
/// </summary>
/// <typeparam name="TValue">Type of value passed when event is raised</typeparam>
/// <typeparam name="TResult">Type of transformed data to notify to the client</typeparam>
class EventObserver<TValue, TResult> : IDisposable
{
private Timer throttler = null;
private TimeSpan duetime;
private bool accumulate = false;
private bool disposed = false;

private TResult result;
private Func<TResult, TValue, TResult> reducer;
private Action<TResult> observer;

private object root = new object();

/// <summary>
/// This event is fired when this object is disposed, clients can
/// register a callback for Dispose.
/// </summary>
public event Action Disposed;

/// <summary>
/// Creates the event observer with a registered observe action and
/// a reduce function for notification.
/// </summary>
/// <param name="observe">This action will be invoked to notify the client</param>
/// <param name="reduce">This function will be invoked to reduce the
/// actual event parameter together with last reduced value returned by this reducer.</param>
public EventObserver(Action<TResult> observe, Func<TResult, TValue, TResult> reduce)
{
observer = observe;
reducer = reduce;
accumulate = true;
result = default(TResult);
}

/// <summary>
/// Creates the event observer with a registered observe action and
/// a reduce function for notification.
/// </summary>
/// <param name="observe">This action will be invoked to notify the client</param>
/// <param name="transform">This function will be invoked to transform the
/// actual event parameter.</param>
public EventObserver(Action<TResult> observe, Func<TValue, TResult> transform)
{
observer = observe;
reducer = (x, y) => transform(y);
result = default(TResult);
}

public static TValue Identity(TValue last, TValue current)
mjkkirschner marked this conversation as resolved.
Show resolved Hide resolved
{
return current;
}

/// <summary>
/// The client need to register this method as an event callback for
/// the event that needs to be observed.
/// </summary>
/// <param name="value">Event parameter passed</param>
public void OnEvent(TValue value)
{
if (disposed) return;

lock (root) { result = reducer(result, value); }

OnEventCore(value);
}

/// <summary>
/// The core implementation for OnEvent, if throttle is active it will
/// update the throttle timer with the due time, so that if no subsequent
/// event is raised within the given throttle due time, the client will
/// be notified.
/// </summary>
/// <param name="value"></param>
protected virtual void OnEventCore(TValue value)
{
if (throttler != null)
{
throttler.Change(duetime, TimeSpan.FromMilliseconds(0));
}
else
{
Notify(this);
}
}

/// <summary>
/// Creates an observer that throttle the stream of notification
/// for a given duetime i.e. notification will be fired only if duetime
/// is ellapsed from the last event trigger, if the event trigger is
/// sooner then the observer will again wait for the given duetime
/// to notify the client.
/// </summary>
/// <param name="duetime">Due time for throttle</param>
/// <returns>The modified event Observer which throttle the events</returns>
public EventObserver<TValue, TResult> Throttle(TimeSpan duetime)
{
if (disposed) throw new ObjectDisposedException("EventObserver");

this.duetime = duetime;
this.throttler = new Timer(Notify, this, Timeout.Infinite, Timeout.Infinite);
//when throttled, reset the result after notification is fired.
accumulate = false;
return this;
}

/// <summary>
/// Notify the client, could be triggered from throttle timer or
/// called directly by passing this object as state.
/// </summary>
/// <param name="state"></param>
protected void Notify(object state)
{
if (disposed) throw new ObjectDisposedException("EventObserver");

TResult r;
lock (root)
{
r = result;
if (!accumulate) result = default(TResult);
}
observer(r);
}

public void Dispose()
{
if (!disposed)
{
disposed = true;
if (Disposed != null) { Disposed(); }
Disposed = null;
observer = null;
reducer = null;
}
}
}

/// <summary>
/// Implements IDisposable to invoke a given dispose action on Dispose().
/// </summary>
class AnonymousDisposable : IDisposable
{
private Action dispose;

public AnonymousDisposable(Action dispose)
{
this.dispose = dispose;
}

public void Dispose()
{
if(dispose != null) { dispose(); }
dispose = null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Dynamo.LibraryViewExtensionMSWebBrowser.Handlers
{
/// <summary>
/// A simple DllResourceProvider, which provides embedded resources from the dll.
/// </summary>
public class DllResourceProvider : ResourceProviderBase
{
/// <summary>
/// Creates a resource provider to get embedded resources from a given assembly.
/// </summary>
/// <param name="baseUrl">The base url from where the request is served.</param>
/// <param name="rootNamespace">Root namespace for this resource provider.</param>
/// <param name="assembly">Assembly from where the resources are to be obtained.</param>
public DllResourceProvider(string baseUrl, string rootNamespace, Assembly assembly = null)
{
RootNamespace = rootNamespace;
BaseUrl = baseUrl;
Assembly = assembly;
if (Assembly == null)
Assembly = Assembly.GetExecutingAssembly();
}

/// <summary>
/// Root namespace for this resource provider. For an example, if this provider
/// serves resources at "Dynamo.LibraryUI.Web.Xxxx" (where "Xxxx" is the actual
/// name of the resource), then root namespace would be "Dynamo.LibraryUI.Web".
/// </summary>
public string RootNamespace { get; private set; }

/// <summary>
/// The base url from where the request is served. For example, if this provider
/// serves requests at http://localhost/dist/v0.0.1/Xxxx (where "Xxxx" is the name
/// of the request), then the base url is "http://localhost/dist/v0.0.1".
/// </summary>
public string BaseUrl { get; private set; }

/// <summary>
/// Assembly from where the resources are to be obtained.
/// </summary>
public Assembly Assembly { get; private set; }

/// <summary>
/// Call this method to get the stream for a given requested resource.
/// </summary>
/// <param name="url">The requested url.</param>
/// <param name="extension">Output parameter whose value is the extension
/// of the requested resource. This extension does not contain "." character.</param>
/// <returns>Returns the stream if the requested resource can be found, or null
/// otherwise.</returns>
public override Stream GetResource(string url, out string extension)
{
extension = "txt";
var uri = new Uri(url);
string resourceName;
var assembly = GetResourceAssembly(uri, out resourceName);
if (null == assembly)
{
return null;
}

var stream = assembly.GetManifestResourceStream(resourceName);
var idx = resourceName.LastIndexOf('.');
if (idx > 0)
{
extension = resourceName.Substring(idx + 1);
}

return stream;
}

protected virtual Assembly GetResourceAssembly(Uri url, out string resourceName)
{
var path = url.AbsoluteUri.Replace(BaseUrl, "").Replace('/', '.');
resourceName = RootNamespace + path;
return this.Assembly;
}
}
}
Loading