fix update changed IDs (#209)

* fix update changed IDs

* better naming

* remove initial count

* move layer order method also to mapMemberUtils

* loop

* better names

* comment

* fix

* split layers and tables

* refactor layer loop
This commit is contained in:
KatKatKateryna
2024-09-03 14:15:22 +01:00
committed by GitHub
parent d78345367b
commit ff540caad7
4 changed files with 107 additions and 38 deletions
@@ -8,6 +8,7 @@ using ArcGIS.Desktop.Mapping.Events;
using Microsoft.Extensions.Logging;
using Speckle.Autofac.DependencyInjection;
using Speckle.Connectors.ArcGIS.Filters;
using Speckle.Connectors.ArcGIS.Utils;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Exceptions;
@@ -38,6 +39,7 @@ public sealed class ArcGISSendBinding : ISendBinding
private readonly IOperationProgressManager _operationProgressManager;
private readonly ILogger<ArcGISSendBinding> _logger;
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly MapMembersUtils _mapMemberUtils;
/// <summary>
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
@@ -58,7 +60,8 @@ public sealed class ArcGISSendBinding : ISendBinding
CancellationManager cancellationManager,
ISendConversionCache sendConversionCache,
IOperationProgressManager operationProgressManager,
ILogger<ArcGISSendBinding> logger
ILogger<ArcGISSendBinding> logger,
MapMembersUtils mapMemberUtils
)
{
_store = store;
@@ -69,6 +72,7 @@ public sealed class ArcGISSendBinding : ISendBinding
_operationProgressManager = operationProgressManager;
_logger = logger;
_topLevelExceptionHandler = parent.TopLevelExceptionHandler;
_mapMemberUtils = mapMemberUtils;
Parent = parent;
Commands = new SendBindingUICommands(parent);
@@ -199,23 +203,37 @@ public sealed class ArcGISSendBinding : ISendBinding
}
// get the path of the edited dataset
var datasetURI = args.Row.GetTable().GetPath();
Uri datasetPath = args.Row.GetTable().GetPath();
// find all layers & tables reading from the dataset
foreach (Layer layer in MapView.Active.Map.Layers)
{
if (layer.GetPath() == datasetURI)
try
{
ChangedObjectIds[layer.URI] = 1;
if (layer.GetPath() == datasetPath)
{
ChangedObjectIds[layer.URI] = 1;
}
}
catch (UriFormatException) // layer.GetPath() or table.GetPath() can throw this error, if data source was removed from the hard drive
{
// ignore layers with invalid source URI
}
}
foreach (StandaloneTable table in MapView.Active.Map.StandaloneTables)
{
if (table.GetPath() == datasetURI)
try
{
ChangedObjectIds[table.URI] = 1;
if (table.GetPath() == datasetPath)
{
ChangedObjectIds[table.URI] = 1;
}
}
catch (UriFormatException) // layer.GetPath() or table.GetPath() can throw this error, if data source was removed from the hard drive
{
// ignore layers with invalid source URI
}
}
RunExpirationChecks(false);
}
@@ -68,7 +68,9 @@ public class ArcGISConnectorModule : ISpeckleModule
builder.AddScoped<SendOperation<MapMember>>();
builder.AddScoped<ArcGISRootObjectBuilder>();
builder.AddScoped<IRootObjectBuilder<MapMember>, ArcGISRootObjectBuilder>();
builder.AddScoped<ArcGISColorManager>();
builder.AddScoped<MapMembersUtils>();
builder.AddScoped<ILocalToGlobalUnpacker, LocalToGlobalUnpacker>();
@@ -5,6 +5,7 @@ using ArcGIS.Desktop.Internal.Mapping;
using ArcGIS.Desktop.Mapping;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.ArcGIS.HostApp;
using Speckle.Connectors.ArcGIS.Utils;
using Speckle.Connectors.Utils.Builders;
using Speckle.Connectors.Utils.Caching;
using Speckle.Connectors.Utils.Conversion;
@@ -30,6 +31,7 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
private readonly ISendConversionCache _sendConversionCache;
private readonly ArcGISColorManager _colorManager;
private readonly IConversionContextStack<ArcGISDocument, Unit> _contextStack;
private readonly MapMembersUtils _mapMemberUtils;
private readonly ILogger<ArcGISRootObjectBuilder> _logger;
public ArcGISRootObjectBuilder(
@@ -37,6 +39,7 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
ArcGISColorManager colorManager,
IConversionContextStack<ArcGISDocument, Unit> contextStack,
IRootToSpeckleConverter rootToSpeckleConverter,
MapMembersUtils mapMemberUtils,
ILogger<ArcGISRootObjectBuilder> logger
)
{
@@ -44,6 +47,7 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
_colorManager = colorManager;
_contextStack = contextStack;
_rootToSpeckleConverter = rootToSpeckleConverter;
_mapMemberUtils = mapMemberUtils;
_logger = logger;
}
@@ -66,7 +70,10 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
List<(GroupLayer, Collection)> nestedGroups = new();
// reorder selected layers by Table of Content (TOC) order
List<(MapMember, int)> layersWithDisplayPriority = GetLayerDisplayPriority(MapView.Active.Map, objects);
List<(MapMember, int)> layersWithDisplayPriority = _mapMemberUtils.GetLayerDisplayPriority(
MapView.Active.Map,
objects
);
onOperationProgressed?.Invoke("Converting", null);
@@ -181,36 +188,6 @@ public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
return new RootObjectBuilderResult(rootObjectCollection, results);
}
// Gets the layer display priority for selected layers
public List<(MapMember, int)> GetLayerDisplayPriority(Map map, IReadOnlyList<MapMember> mapMembers)
{
// first get all map layers
Dictionary<MapMember, int> layersIndices = new();
int count = 0;
var layers = map.Layers;
count = UnpackLayersOrder(layersIndices, layers, count);
// iterate through tables
foreach (var layer in map.StandaloneTables)
{
layersIndices[layer] = count + 100; // random number, will be recalculated below
}
// recalculate selected layer priority from all map layers
List<(MapMember, int)> selectedLayers = new();
int newCount = 0;
foreach (KeyValuePair<MapMember, int> valuePair in layersIndices)
{
if (mapMembers.Contains(valuePair.Key))
{
selectedLayers.Add((valuePair.Key, newCount));
newCount++;
}
}
return selectedLayers;
}
private int UnpackLayersOrder(
Dictionary<MapMember, int> layersIndices,
IEnumerable<ArcLayer> layersToUnpack,
@@ -0,0 +1,72 @@
using ArcGIS.Desktop.Internal.Mapping;
using ArcGIS.Desktop.Mapping;
namespace Speckle.Connectors.ArcGIS.Utils;
public class MapMembersUtils
{
/// <summary>
/// Returns all Layers and Standalone Tables present on the Map
/// </summary>
/// <param name="map"></param>
/// <returns></returns>
public List<MapMember> GetAllMapMembers(Map map)
{
// first get all map layers
List<MapMember> mapMembers = new();
var layerMapMembers = UnpackMapLayers(map.Layers);
mapMembers.AddRange(layerMapMembers);
// add tables
var standaloneTableMapMembers = UnpackMapLayers(map.StandaloneTables);
mapMembers.AddRange(standaloneTableMapMembers);
return mapMembers;
}
public List<MapMember> UnpackMapLayers(IEnumerable<MapMember> mapMembersToUnpack)
{
List<MapMember> mapMembers = new();
foreach (var layer in mapMembersToUnpack)
{
switch (layer)
{
case GroupLayer subGroup:
mapMembers.Add(layer);
var subGroupMapMembers = UnpackMapLayers(subGroup.Layers);
mapMembers.AddRange(subGroupMapMembers);
break;
case ILayerContainerInternal subLayerContainerInternal:
mapMembers.Add(layer);
var subLayerMapMembers = UnpackMapLayers(subLayerContainerInternal.InternalLayers);
mapMembers.AddRange(subLayerMapMembers);
break;
default:
mapMembers.Add(layer);
break;
}
}
return mapMembers;
}
// Gets the layer display priority for selected layers
public List<(MapMember, int)> GetLayerDisplayPriority(Map map, IReadOnlyList<MapMember> selectedMapMembers)
{
// first get all map layers
List<MapMember> allMapMembers = GetAllMapMembers(map);
// recalculate selected layer priority from all map layers
List<(MapMember, int)> selectedLayers = new();
int newCount = 0;
foreach (MapMember mapMember in allMapMembers)
{
if (selectedMapMembers.Contains(mapMember))
{
selectedLayers.Add((mapMember, newCount));
newCount++;
}
}
return selectedLayers;
}
}