From 13fd6824e12cf9c841a4e9d861b880287e9b9e27 Mon Sep 17 00:00:00 2001 From: Chris Moore Date: Fri, 26 Jul 2019 11:08:12 -0400 Subject: [PATCH 1/3] Address crash if open from clicking on mxd --- .../Config.Designer.cs | Bin 17978 -> 16730 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/Config.Designer.cs b/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/Config.Designer.cs index 6c83dc20aa842245410c4bc5d0e34705b740891c..8d68e69f5c0d49c513d3c5141b0993b4ecae412f 100644 GIT binary patch delta 551 zcmZWm!D`FU`dngDTGQo*T?0=wXMgV=m8~h?sbV zxmy_GJZ_^6gBAYrkMl|S3_n*4_ZIDSAJhE>tccac05`P)VNc6oniXL!RU4p>4YaVW z{sO<8TBbdlOWvC>JrtxyO(s^R?3QSMYtnwjD~Vo*@uJ6DH=*87H`ts{HwE1dveBLU5rGz zA>AF}9#-W&P%lAUbw^QAXc9!W9w62;^hMqh3iz>7=E$vCRldlrvbdJfmmV5_TfS!h E0Tl^_+@383UuE>1Lu~aCE@c$v7JqH^bm}E~PCIg)o_y`|i2t-gC}(e!o0&yjyfEHS(0( z#UC15OPj;B-OK!&iF0R%pK& z;HSp7${C3Gllg>~eD!=kuvkVH<#1blQPCt_qG7Dlz*wLZjO9V4fiFw9%d`b539h9* z$zZ>Um*Q0l9tk+P%j25|E%Fx4;2*=X!MTGygVQYb1oX!7E(5+D)=H`-W4KOY_2FR^ zOde(=Txm-1TyvWMZ%{N%$rtb2i=wvxjVXx8GqF__T~{qO1&83W@t5dlk%fdli+ob^ zZ0$=99#~pp{iO|G#N!a+B;E-v+H&B;>yV8BV}KtAU-GJd|G_QN%%1~3UTNuM)q9B7 zx;ldkP;SAvqHXd_20KD-ety)$uTM5{*yk}7-NUEI0FbB->8u7;6I8gPXo!FIp8%p( z{-L_tMmJT`HCRVd_^sJ76sxJQGQYOcM3c7mHx2C#Ca@U%%4Nj;Y!DdQx9${YnXf-Fyfj?hKqZk#TF oGpu{t*4>;Y6ZYL3k+`~>NK|WLw^0aE@V|({S?}S}TKI Date: Wed, 14 Aug 2019 11:09:30 -0400 Subject: [PATCH 2/3] Refactor HasMapGraphics property Refactor HasMapGraphics property to not use .Result --- .../ViewModels/ProCircleViewModel.cs | 4 +- .../ViewModels/ProEllipseViewModel.cs | 4 +- .../ViewModels/ProLinesViewModel.cs | 4 +- .../ViewModels/ProRangeViewModel.cs | 4 +- .../ViewModels/ProTabBaseViewModel.cs | 49 ++++++++++++------- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProCircleViewModel.cs b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProCircleViewModel.cs index d32357b3..0e0af09b 100644 --- a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProCircleViewModel.cs +++ b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProCircleViewModel.cs @@ -835,11 +835,11 @@ private async void CreateCircleFeature(Geometry geom, CircleAttributes circleAtt await QueuedTask.Run(async () => message = await AddFeatureToLayer(geom, circleAttributes)); - RaisePropertyChanged(() => HasMapGraphics); - if (!string.IsNullOrEmpty(message)) ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, DistanceAndDirectionLibrary.Properties.Resources.ErrorFeatureCreateTitle); + else + HasMapGraphics = true; } private async Task AddFeatureToLayer(Geometry geom, CircleAttributes attributes) diff --git a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProEllipseViewModel.cs b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProEllipseViewModel.cs index 31b1e2e0..c873bf86 100644 --- a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProEllipseViewModel.cs +++ b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProEllipseViewModel.cs @@ -636,11 +636,11 @@ private async void CreateEllipseFeature(Geometry geom, EllipseAttributes ellipse await QueuedTask.Run(async () => message = await AddFeatureToLayer(geom, ellipseAttributes)); - RaisePropertyChanged(() => HasMapGraphics); - if (!string.IsNullOrEmpty(message)) ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, DistanceAndDirectionLibrary.Properties.Resources.ErrorFeatureCreateTitle); + else + HasMapGraphics = true; } private async Task AddFeatureToLayer(Geometry geom, EllipseAttributes attributes) diff --git a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProLinesViewModel.cs b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProLinesViewModel.cs index 870ebaab..7360a39c 100644 --- a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProLinesViewModel.cs +++ b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProLinesViewModel.cs @@ -610,11 +610,11 @@ private async void CreateLineFeature(Geometry geom, LineAttributes lineAttribute await QueuedTask.Run(async () => message = await AddFeatureToLayer(geom, lineAttributes)); - RaisePropertyChanged(() => HasMapGraphics); - if (!string.IsNullOrEmpty(message)) ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, DistanceAndDirectionLibrary.Properties.Resources.ErrorFeatureCreateTitle); + else + HasMapGraphics = true; } private async Task AddFeatureToLayer(Geometry geom, LineAttributes attributes) diff --git a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProRangeViewModel.cs b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProRangeViewModel.cs index 2da90f96..716c9374 100644 --- a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProRangeViewModel.cs +++ b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProRangeViewModel.cs @@ -614,11 +614,11 @@ private async void CreateRangeRingOrRadialFeature(Geometry geom, RangeAttributes await QueuedTask.Run(async () => message = await AddFeatureToLayer(geom, rangeAttributes)); - RaisePropertyChanged(() => HasMapGraphics); - if (!string.IsNullOrEmpty(message)) ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, DistanceAndDirectionLibrary.Properties.Resources.ErrorFeatureCreateTitle); + else + HasMapGraphics = true; } private async Task AddFeatureToLayer(Geometry geom, RangeAttributes attributes) diff --git a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProTabBaseViewModel.cs b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProTabBaseViewModel.cs index 9acf1a1f..711cc8a7 100644 --- a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProTabBaseViewModel.cs +++ b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/ViewModels/ProTabBaseViewModel.cs @@ -77,11 +77,7 @@ public ProTabBaseViewModel() System.Diagnostics.Debug.WriteLine("Probably Running from Unit Tests"); } - ArcGIS.Desktop.Mapping.Events.ActiveMapViewChangedEvent.Subscribe((args) => - { - // Subscribe to this event in case the ActiveMap already has layers with features (so buttons are enabled on load) - RaisePropertyChanged(() => HasMapGraphics); - }); + ArcGIS.Desktop.Mapping.Events.ActiveMapViewChangedEvent.Subscribe(OnActiveMapViewChanged); configObserver = new PropertyObserver(DistanceAndDirectionConfig.AddInConfig) .RegisterHandler(n => n.DisplayCoordinateType, n => @@ -182,17 +178,17 @@ public virtual bool IsToolActive public bool HasMapGraphics { + set + { + hasMapGraphics = value; + RaisePropertyChanged(() => HasMapGraphics); + } get { - // Call helper method (must be run on MCT) - bool hasFeatures = QueuedTask.Run(async () => - { - return await this.HasLayerFeatures(); - }).Result; - - return hasFeatures; + return hasMapGraphics; } } + private bool hasMapGraphics = false; private MapPoint point1 = null; /// @@ -614,7 +610,7 @@ private void OnClearGraphics() return this.DeleteAllFeatures(); }); - RaisePropertyChanged(() => HasMapGraphics); + HasMapGraphics = false; } /// @@ -1275,6 +1271,13 @@ private async void OnSaveAs() } } + private async void OnActiveMapViewChanged(ArcGIS.Desktop.Mapping.Events.ActiveMapViewChangedEventArgs obj) + { + // Subscribe to this event in case the ActiveMap already has layers with features (so buttons are enabled on load) + await HasLayerFeatures(); + RaisePropertyChanged(() => HasMapGraphics); + } + #endregion Private Functions #region Feature Class Support @@ -1408,16 +1411,24 @@ await System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.T return featureClass; } - protected async Task HasLayerFeatures() + protected async Task HasLayerFeatures() { - FeatureClass fc = null; + string featureLayerName = this.GetLayerName(); - await QueuedTask.Run(async () => + FeatureLayer featureLayer = GetFeatureLayerByNameInActiveView(featureLayerName); + + if (featureLayer == null) { - fc = await GetFeatureClass(addToMapIfNotPresent: false); - }); + hasMapGraphics = false; + return; + } - return fc == null ? false : fc.GetCount() > 0; + FeatureClass featureClass = null; + await QueuedTask.Run(() => + { + featureClass = featureLayer.GetFeatureClass(); + hasMapGraphics = (featureClass == null) ? false : featureClass.GetCount() > 0; + }); } protected async Task DeleteAllFeatures() From e6c9a100481e2bdd44ee9ccec8fd6ba60ec6ea8d Mon Sep 17 00:00:00 2001 From: SaiP Date: Tue, 3 Sep 2019 18:50:49 +0530 Subject: [PATCH 3/3] #660 - User should be presented with warning when using invalid feature class names to save #649 - Rename Clear and Save As buttons --- .../Models/FeatureClassUtils.cs | 31 +++++++++++++ .../ViewModels/TabBaseViewModel.cs | 44 ++++++++++--------- .../Properties/Resources.Designer.cs | 4 +- .../Properties/Resources.resx | 4 +- .../Models/FeatureClassUtils.cs | 34 +++++++++++--- 5 files changed, 86 insertions(+), 31 deletions(-) diff --git a/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/Models/FeatureClassUtils.cs b/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/Models/FeatureClassUtils.cs index cb5670f5..fa5270db 100644 --- a/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/Models/FeatureClassUtils.cs +++ b/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/Models/FeatureClassUtils.cs @@ -30,6 +30,8 @@ using ESRI.ArcGIS.ADF; using DistanceAndDirectionLibrary; using ESRI.ArcGIS.Display; +using System.Text.RegularExpressions; +using System.Linq; namespace ArcMapAddinDistanceAndDirection.Models { @@ -290,6 +292,35 @@ public IFeatureClass CreateFCOutput(string outputPath, SaveAsType saveAsType, Li } } + /// + /// Checks if file name has illegal characters + /// + /// + /// + internal bool ContainsInvalidChars(string path) + { + var fileName = System.IO.Path.GetFileNameWithoutExtension(path); + var regexItem = new Regex("^[A-Za-z_][A-Za-z0-9_]*$"); + var isValidFileName = regexItem.IsMatch(fileName); + if (!isValidFileName) + return true; + else if (fileName.Length > 32) + return true; + else if (ValidateReservedWords(fileName)) + return true; + return false; + } + + private static bool ValidateReservedWords(string fileName) + { + //https://support.esri.com/en/technical-article/000010906 - Used the keyword list mentioned here for 10.1 and above + var reservedWords = new List() { + "ADD","ALTER","AND","BETWEEN","BY","COLUMN","CREATE","DELETE","DROP","EXISTS","FOR","FROM","GROUP","IN","INSERT","INTO","IS","LIKE","NOT","NULL","OR","ORDER","SELECT","SET","TABLE","UPDATE","VALUES","WHERE" + }; + return reservedWords.Where(x => fileName.ToUpper() == x).Any(); + } + + public void DeleteShapeFile(string shapeFilePath) { string shapeFile = shapeFilePath; diff --git a/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/ViewModels/TabBaseViewModel.cs b/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/ViewModels/TabBaseViewModel.cs index de43f815..8ef2f8e8 100644 --- a/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/ViewModels/TabBaseViewModel.cs +++ b/source/addins/ArcMapAddinDistanceAndDirection/ArcMapAddinDistanceAndDirection/ViewModels/TabBaseViewModel.cs @@ -13,28 +13,26 @@ // limitations under the License. // System +using ArcMapAddinDistanceAndDirection.Models; +using DistanceAndDirectionLibrary; +using DistanceAndDirectionLibrary.Helpers; +using DistanceAndDirectionLibrary.Models; +using DistanceAndDirectionLibrary.ViewModels; +using DistanceAndDirectionLibrary.Views; +using ESRI.ArcGIS.ArcMapUI; +using ESRI.ArcGIS.Carto; +using ESRI.ArcGIS.Display; +// Esri +using ESRI.ArcGIS.esriSystem; +using ESRI.ArcGIS.Geodatabase; +using ESRI.ArcGIS.Geometry; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; -using System.Windows.Controls; using System.Text.RegularExpressions; +using System.Windows.Controls; using System.Windows.Forms; -using System.Collections.ObjectModel; - -// Esri -using ESRI.ArcGIS.esriSystem; -using ESRI.ArcGIS.ArcMapUI; -using ESRI.ArcGIS.Carto; -using ESRI.ArcGIS.Geometry; -using ESRI.ArcGIS.Display; -using ESRI.ArcGIS.Geodatabase; - -using DistanceAndDirectionLibrary; -using DistanceAndDirectionLibrary.Helpers; -using DistanceAndDirectionLibrary.ViewModels; -using ArcMapAddinDistanceAndDirection.Models; -using DistanceAndDirectionLibrary.Models; -using DistanceAndDirectionLibrary.Views; namespace ArcMapAddinDistanceAndDirection.ViewModels { @@ -465,7 +463,7 @@ public virtual bool IsToolActive OnActivateTool(null); else if (ArcMap.Application.CurrentTool != null) - ArcMap.Application.CurrentTool = null; + ArcMap.Application.CurrentTool = null; RaisePropertyChanged(() => IsToolActive); } @@ -572,7 +570,13 @@ private void OnSaveAs(object obj) } else { - fc = fcUtils.CreateFCOutput(path, SaveAsType.FileGDB, typeGraphicsList, ArcMap.Document.FocusMap.SpatialReference); + if (!fcUtils.ContainsInvalidChars(path)) + fc = fcUtils.CreateFCOutput(path, SaveAsType.FileGDB, typeGraphicsList, ArcMap.Document.FocusMap.SpatialReference); + else + MessageBox.Show(DistanceAndDirectionLibrary.Properties.Resources.FeatureClassNameError, + DistanceAndDirectionLibrary.Properties.Resources.DistanceDirectionLabel, + MessageBoxButtons.OK, + MessageBoxIcon.Information); } } } @@ -645,7 +649,7 @@ private void AddFeatureLayerToMap(IFeatureClass fc) ESRI.ArcGIS.Carto.IMap map = ArcMap.Document.FocusMap; - map.AddLayer((ILayer)outputFeatureLayer); + map.AddLayer(outputFeatureLayer); } private string PromptSaveFileDialog() diff --git a/source/addins/DistanceAndDirectionLibrary/Properties/Resources.Designer.cs b/source/addins/DistanceAndDirectionLibrary/Properties/Resources.Designer.cs index 168fdcee..77970d70 100644 --- a/source/addins/DistanceAndDirectionLibrary/Properties/Resources.Designer.cs +++ b/source/addins/DistanceAndDirectionLibrary/Properties/Resources.Designer.cs @@ -565,7 +565,7 @@ public static string LabelCenterPoint { } /// - /// Looks up a localized string similar to Clear. + /// Looks up a localized string similar to Clear All. /// public static string LabelClearGraphics { get { @@ -835,7 +835,7 @@ public static string LabelRingType { } /// - /// Looks up a localized string similar to Save As. + /// Looks up a localized string similar to Export. /// public static string LabelSaveAs { get { diff --git a/source/addins/DistanceAndDirectionLibrary/Properties/Resources.resx b/source/addins/DistanceAndDirectionLibrary/Properties/Resources.resx index 063b2359..0b113895 100644 --- a/source/addins/DistanceAndDirectionLibrary/Properties/Resources.resx +++ b/source/addins/DistanceAndDirectionLibrary/Properties/Resources.resx @@ -286,7 +286,7 @@ Center Point - Clear + Clear All From @@ -376,7 +376,7 @@ Ring Type - Save As + Export Starting Point diff --git a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/Models/FeatureClassUtils.cs b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/Models/FeatureClassUtils.cs index 32cb8258..26795696 100644 --- a/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/Models/FeatureClassUtils.cs +++ b/source/addins/ProAppDistanceAndDirectionModule/ProAppDistanceAndDirectionModule/Models/FeatureClassUtils.cs @@ -34,6 +34,7 @@ using DistanceAndDirectionLibrary; using System.Windows; +using System.Text.RegularExpressions; namespace ProAppDistanceAndDirectionModule.Models { @@ -82,10 +83,11 @@ public string PromptUserWithSaveDialog(bool featureShapeChecked) if (ok == true) { if (ContainsInvalidChars(Path.GetFileName(saveItemDlg.FilePath))) - { - MessageBox.Show(DistanceAndDirectionLibrary.Properties.Resources.FeatureClassNameError, - DistanceAndDirectionLibrary.Properties.Resources.DistanceDirectionLabel, MessageBoxButton.OK, - MessageBoxImage.Exclamation); + { + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show( + DistanceAndDirectionLibrary.Properties.Resources.FeatureClassNameError, + DistanceAndDirectionLibrary.Properties.Resources.DistanceDirectionLabel, + System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Exclamation); return null; } previousLocation = Path.GetDirectoryName(saveItemDlg.FilePath); @@ -206,10 +208,28 @@ private static IReadOnlyList makeValueArray (string featureClass, string /// Checks if file name has illegal characters /// /// - /// - private static bool ContainsInvalidChars(string filename) + /// + private static bool ContainsInvalidChars(string path) + { + var fileName = System.IO.Path.GetFileNameWithoutExtension(path); + var regexItem = new Regex("^[A-Za-z_][A-Za-z0-9_]*$"); + var isValidFileName = regexItem.IsMatch(fileName); + if (!isValidFileName) + return true; + else if (fileName.Length > 32) + return true; + else if (ValidateReservedWords(fileName)) + return true; + return false; + } + + private static bool ValidateReservedWords(string fileName) { - return Path.GetInvalidFileNameChars().Concat(new[] { ' ', '-' }).Any(item => filename.Contains(item)); + //https://support.esri.com/en/technical-article/000010906 - Used the keyword list mentioned here for 10.1 and above + var reservedWords = new List() { + "ADD","ALTER","AND","BETWEEN","BY","COLUMN","CREATE","DELETE","DROP","EXISTS","FOR","FROM","GROUP","IN","INSERT","INTO","IS","LIKE","NOT","NULL","OR","ORDER","SELECT","SET","TABLE","UPDATE","VALUES","WHERE" + }; + return reservedWords.Where(x => fileName.ToUpper() == x).Any(); } private static List ClearTempGraphics(List graphicsList)