Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
valentasm committed Dec 25, 2020
2 parents 62793d4 + e46f437 commit bf74386
Show file tree
Hide file tree
Showing 12 changed files with 515 additions and 76 deletions.
27 changes: 22 additions & 5 deletions GoogleMapsComponents/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ private static string SerializeObject(object obj)
return value;
}

internal static async Task<TRes> MyInvokeAsync<TRes>(
this IJSRuntime jsRuntime,
string identifier,
params object[] args)
{
private static IEnumerable<object> MakeArgJsFriendly( IJSRuntime jsRuntime,IEnumerable<object> args) {
var jsFriendlyArgs = args
.Select(arg =>
{
Expand Down Expand Up @@ -100,6 +96,16 @@ internal static async Task<TRes> MyInvokeAsync<TRes>(
}
}
});
return jsFriendlyArgs;
}

internal static async Task<TRes> MyInvokeAsync<TRes>(
this IJSRuntime jsRuntime,
string identifier,
params object[] args)
{

var jsFriendlyArgs = MakeArgJsFriendly(jsRuntime,args);

if (typeof(IJsObjectRef).IsAssignableFrom(typeof(TRes)))
{
Expand Down Expand Up @@ -145,6 +151,17 @@ internal static async Task<TRes> MyInvokeAsync<TRes>(
}
}

internal static async Task<object> MyAddListenerAsync(
this IJSRuntime jsRuntime,
string identifier,
params object[] args)
{

var jsFriendlyArgs = MakeArgJsFriendly(jsRuntime,args);

return await jsRuntime.InvokeAsync<object>(identifier, jsFriendlyArgs);
}

private static async Task<object> InvokeAsync(
this IJSRuntime jsRuntime,
string identifier,
Expand Down
9 changes: 9 additions & 0 deletions GoogleMapsComponents/JsObjectRef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ public Task InvokeMultipleAsync(string functionName, Dictionary<Guid, object> di
);
}

public Task AddMultipleListenersAsync(string eventName, Dictionary<Guid, object> dictArgs)
{
return _jsRuntime.MyAddListenerAsync(
"googleMapsObjectManager.addMultipleListeners",
new object[] { dictArgs.Select(e => e.Key.ToString()).ToList(), eventName }
.Concat(dictArgs.Values).ToArray()
);
}

public Task<T> InvokeAsync<T>(string functionName, params object[] args)
{
return _jsRuntime.MyInvokeAsync<T>(
Expand Down
49 changes: 42 additions & 7 deletions GoogleMapsComponents/Maps/Extension/CircleList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,63 @@ public static async Task<CircleList> CreateAsync(IJSRuntime jsRuntime, Dictionar
JsObjectRef jsObjectRef = new JsObjectRef(jsRuntime, Guid.NewGuid());

CircleList obj;
if (opts.Count > 0)
{
Dictionary<string, JsObjectRef> jsObjectRefs = await JsObjectRef.CreateMultipleAsync(
jsRuntime,
"google.maps.Circle",
opts.ToDictionary(e => e.Key, e => (object)e.Value));
Dictionary<string, Circle> objs = jsObjectRefs.ToDictionary(e => e.Key, e => new Circle(e.Value));
obj = new CircleList(jsObjectRef, objs);
}
else
{
obj = new CircleList(jsObjectRef, null);
}

return obj;
}

/// <summary>
/// Manage list over lifetime: Create and remove list depending on entity count;
/// entities will be removed, added or changed to mirror the given set.
/// </summary>
/// <param name="list">
/// The list to manage. May be null.
/// </param>
/// <param name="jsRuntime"></param>
/// <param name="opts"></param>
/// <returns>
/// The managed list. Assign to the variable you used as parameter.
/// </returns>
public static async Task<CircleList> ManageAsync(CircleList list,IJSRuntime jsRuntime, Dictionary<string, CircleOptions> opts,Action<MouseEvent,string,Circle> clickCallback=null)
{
if (opts.Count==0) {
if (list!=null) {
await list.SetMultipleAsync(opts);
list=null;
}
} else {
if (list==null) {
list = await CircleList.CreateAsync(jsRuntime,new Dictionary<string, CircleOptions>());
if (clickCallback!=null) {
list.EntityClicked+=(sender,e)=>{
clickCallback(e.MouseEvent,e.Key,e.Entity);
};
}
}
await list.SetMultipleAsync(opts);
}
return list;
}

private CircleList(JsObjectRef jsObjectRef, Dictionary<string, Circle> circles)
: base(jsObjectRef, circles)
{
}

/// <summary>
/// Set the set of entities; entities will be removed, added or changed to mirror the given set.
/// </summary>
/// <param name="opts"></param>
/// <returns></returns>
public async Task SetMultipleAsync(Dictionary<string, CircleOptions> opts)
{
await base.SetMultipleAsync(opts, "google.maps.Circle");
}

/// <summary>
/// Only keys not matching with existent Circle keys will be created
Expand Down
73 changes: 71 additions & 2 deletions GoogleMapsComponents/Maps/Extension/ListableEntityListBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,60 @@ public void Dispose()
}
}

/// <summary>
/// Set the set of entities; entities will be removed, added or changed to mirror the given set.
/// </summary>
/// <param name="opts"></param>
/// <returns></returns>
public async Task SetMultipleAsync(Dictionary<string, TEntityOptionsBase> opts, string googleMapListableEntityTypeName)
{
var nonVisibles = new Dictionary<string,bool>();
var lToRemove = new List<string>();
var dictToAdd = new Dictionary<string,TEntityOptionsBase>();
var dictToChange = new Dictionary<string,TEntityOptionsBase>();
foreach (var sKey in this.BaseListableEntities.Keys) {
if (!opts.ContainsKey(sKey)) {
lToRemove.Add(sKey);
}
}
foreach (var sKey in lToRemove) {
nonVisibles[sKey]=false;
}
foreach (var sKey in opts.Keys) {
if (this.BaseListableEntities.ContainsKey(sKey)) {
dictToChange[sKey]=opts[sKey];
} else {
dictToAdd[sKey]=opts[sKey];
}
}
await this.SetVisibles(nonVisibles);
await this.RemoveMultipleAsync(lToRemove);
await this.AddMultipleAsync(dictToAdd,googleMapListableEntityTypeName);
await this.SetOptions(dictToChange);
}

public class EntityMouseEvent
{
public MouseEvent MouseEvent { get; set; }
public string Key { get; set; }
public TEntityBase Entity { get; set; }
}

/// <summary>
/// Entity clicked event containing coordinates, entity key and value.
/// This event will be fired for entities which are being added after at least one
/// event handler is added to this event.
/// Adding handlers to the event will slow down adding entities by a small amount.
/// If no handler is added, performance is not impaired.
/// </summary>
public event EventHandler<EntityMouseEvent> EntityClicked;

private void FireEvent<TEvent>(EventHandler<TEvent> eventHandler, TEvent ea) {
if (eventHandler!=null) {
eventHandler(this,ea);
}
}

/// <summary>
/// only keys not matching with existent listable entity keys will be created
/// </summary>
Expand Down Expand Up @@ -61,10 +115,17 @@ public virtual async Task AddMultipleAsync(Dictionary<string, TEntityOptionsBase
//Now we can add all required object as NEW object
foreach (string key in objs.Keys)
{
BaseListableEntities.Add(key, objs[key]);
var entity = objs[key];
BaseListableEntities.Add(key, entity);
}
//add event listener to the click event in one call to all added entities.
if (this.EntityClicked!=null) {
await this.AddListeners<MouseEvent>(objs.Keys,"click",(mev,key) => {
this.FireEvent(this.EntityClicked,new EntityMouseEvent { MouseEvent=mev,Key=key,Entity=BaseListableEntities[key] });
});
}
}
}
}

/// <summary>
/// only Marker having keys matching with existent keys will be removed
Expand Down Expand Up @@ -246,5 +307,13 @@ public virtual Task SetVisibles(Dictionary<string, bool> visibles)
"setVisible",
dictArgs);
}

public virtual async Task AddListeners<V>(IEnumerable<string> enitityKeys, string eventName, Action<V,string> handler)
{
Dictionary<Guid, object> dictArgs = enitityKeys.ToDictionary(key => BaseListableEntities[key].Guid, key => (object)new Action<V>((e)=>{
handler(e,key);
}));
await _jsObjectRef.AddMultipleListenersAsync(eventName,dictArgs);
}
}
}
50 changes: 43 additions & 7 deletions GoogleMapsComponents/Maps/Extension/MarkerList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,64 @@ public static async Task<MarkerList> CreateAsync(IJSRuntime jsRuntime, Dictionar
JsObjectRef jsObjectRef = new JsObjectRef(jsRuntime, Guid.NewGuid());

MarkerList obj;
if (opts.Count > 0)
{
Dictionary<string, JsObjectRef> jsObjectRefs = await JsObjectRef.CreateMultipleAsync(
jsRuntime,
"google.maps.Marker",
opts.ToDictionary(e => e.Key, e => (object)e.Value));
Dictionary<string, Marker> objs = jsObjectRefs.ToDictionary(e => e.Key, e => new Marker(e.Value));
obj = new MarkerList(jsObjectRef, objs);
}
else
{
obj = new MarkerList(jsObjectRef, null);
}

return obj;
}

/// <summary>
/// Manage list over lifetime: Create and remove list depending on entity count;
/// entities will be removed, added or changed to mirror the given set.
/// </summary>
/// <param name="list">
/// The list to manage. May be null.
/// </param>
/// <param name="jsRuntime"></param>
/// <param name="opts"></param>
/// <returns>
/// The managed list. Assign to the variable you used as parameter.
/// </returns>
public static async Task<MarkerList> ManageAsync(MarkerList list,IJSRuntime jsRuntime, Dictionary<string, MarkerOptions> opts,Action<MouseEvent,string,Marker> clickCallback=null)
{
if (opts.Count==0) {
if (list!=null) {
await list.SetMultipleAsync(opts);
list=null;
}
} else {
if (list==null) {
list = await MarkerList.CreateAsync(jsRuntime,new Dictionary<string, MarkerOptions>());
if (clickCallback!=null) {
list.EntityClicked+=(sender,e)=>{
clickCallback(e.MouseEvent,e.Key,e.Entity);
};
}
}
await list.SetMultipleAsync(opts);
}
return list;
}

private MarkerList(JsObjectRef jsObjectRef, Dictionary<string, Marker> markers)
: base(jsObjectRef, markers)
{
}

/// <summary>
/// Set the set of entities; entities will be removed, added or changed to mirror the given set.
/// </summary>
/// <param name="opts"></param>
/// <returns></returns>
public async Task SetMultipleAsync(Dictionary<string, MarkerOptions> opts)
{
await base.SetMultipleAsync(opts, "google.maps.Marker");
}

/// <summary>
/// only keys not matching with existent Marker keys will be created
/// </summary>
Expand Down
Loading

0 comments on commit bf74386

Please sign in to comment.