Fix generation of dummy model with no bound meshes

--- LSLib/Granny/Model/Exporter.cs
+++ LSLib/Granny/Model/Exporter.cs
@@ -321,6 +321,41 @@
             }
         }

+        private Mesh GenerateDummyMesh(MeshBinding meshBinding)
+        {
+            var vertexData = new VertexData();
+            vertexData.VertexComponentNames = meshBinding.Mesh.PrimaryVertexData.VertexComponentNames
+                .Select(name => new GrannyString(name.String)).ToList();
+            vertexData.Vertices = new List<Vertex>();
+            var dummyVertex = Helpers.CreateInstance(meshBinding.Mesh.VertexFormat) as Vertex;
+            vertexData.Vertices.Add(dummyVertex);
+            Root.VertexDatas.Add(vertexData);
+
+            var topology = new TriTopology();
+            topology.Groups = new List<TriTopologyGroup>();
+            var group = new TriTopologyGroup();
+            group.MaterialIndex = 0;
+            group.TriCount = 0;
+            group.TriFirst = 0;
+            topology.Groups.Add(group);
+
+            topology.Indices = new List<int>();
+            Root.TriTopologies.Add(topology);
+
+            var mesh = new Mesh();
+            mesh.Name = meshBinding.Mesh.Name;
+            mesh.VertexFormat = meshBinding.Mesh.VertexFormat;
+            mesh.PrimaryTopology = topology;
+            mesh.PrimaryVertexData = vertexData;
+            if (meshBinding.Mesh.BoneBindings != null)
+            {
+                mesh.BoneBindings = new List<BoneBinding>();
+                ConformMeshBoneBindings(mesh, meshBinding.Mesh);
+            }
+
+            return mesh;
+        }
+
         private Model MakeDummyModel(Model original)
         {
             var newModel = new Model();
@@ -339,49 +374,24 @@
                 newModel.Skeleton = skeleton;
             }

-            newModel.MeshBindings = new List<MeshBinding>();
-            foreach (var meshBinding in original.MeshBindings)
-            {
-                // Try to bind the original mesh, if it exists in the source file.
-                // If it doesn't, generate a dummy mesh with 0 vertices
-                var mesh = Root.Meshes.Where(m => m.Name == meshBinding.Mesh.Name).FirstOrDefault();
-                if (mesh == null)
-                {
-                    var vertexData = new VertexData();
-                    vertexData.VertexComponentNames = meshBinding.Mesh.PrimaryVertexData.VertexComponentNames
-                        .Select(name => new GrannyString(name.String)).ToList();
-                    vertexData.Vertices = new List<Vertex>();
-                    var dummyVertex = Helpers.CreateInstance(meshBinding.Mesh.VertexFormat) as Vertex;
-                    vertexData.Vertices.Add(dummyVertex);
-                    Root.VertexDatas.Add(vertexData);
-
-                    var topology = new TriTopology();
-                    topology.Groups = new List<TriTopologyGroup>();
-                    var group = new TriTopologyGroup();
-                    group.MaterialIndex = 0;
-                    group.TriCount = 0;
-                    group.TriFirst = 0;
-                    topology.Groups.Add(group);
-
-                    topology.Indices = new List<int>();
-                    Root.TriTopologies.Add(topology);
-
-                    mesh = new Mesh();
-                    mesh.Name = meshBinding.Mesh.Name;
-                    mesh.VertexFormat = meshBinding.Mesh.VertexFormat;
-                    mesh.PrimaryTopology = topology;
-                    mesh.PrimaryVertexData = vertexData;
-                    if (meshBinding.Mesh.BoneBindings != null)
-                    {
-                        mesh.BoneBindings = new List<BoneBinding>();
-                        ConformMeshBoneBindings(mesh, meshBinding.Mesh);
-                    }
-                    Root.Meshes.Add(mesh);
-                }
-
-                var binding = new MeshBinding();
-                binding.Mesh = mesh;
-                newModel.MeshBindings.Add(binding);
+            if (original.MeshBindings != null)
+            {
+                newModel.MeshBindings = new List<MeshBinding>();
+                foreach (var meshBinding in original.MeshBindings)
+                {
+                    // Try to bind the original mesh, if it exists in the source file.
+                    // If it doesn't, generate a dummy mesh with 0 vertices
+                    var mesh = Root.Meshes.Where(m => m.Name == meshBinding.Mesh.Name).FirstOrDefault();
+                    if (mesh == null)
+                    {
+                        mesh = GenerateDummyMesh(meshBinding);
+                        Root.Meshes.Add(mesh);
+                    }
+
+                    var binding = new MeshBinding();
+                    binding.Mesh = mesh;
+                    newModel.MeshBindings.Add(binding);
+                }
             }

             Root.Models.Add(newModel);


forgot to implement this

forgot to implement this

--- PogoLocationFeeder.GUI/Models/SniperInfoModel.cs
+++ PogoLocationFeeder.GUI/Models/SniperInfoModel.cs
@@ -7,6 +7,7 @@
 using PogoLocationFeeder.GUI.ViewModels;
 using PogoLocationFeeder.Helper;
 using PogoLocationFeeder.Config;
+using PogoLocationFeeder.GUI.Properties;

 namespace PogoLocationFeeder.Common.Models
 {
@@ -57,7 +58,9 @@
             try
             {
                 Process.Start(
-                    $"pokesniper2://{Info.Id}/{Info.Latitude.ToString(CultureInfo.InvariantCulture)},{Info.Longitude.ToString(CultureInfo.InvariantCulture)}");
+                    Settings.Default.Sniper2Path.Contains(".exe")
+                        ? $"{Settings.Default.Sniper2Path} pokesniper2://{Info.Id}/{Info.Latitude.ToString(CultureInfo.InvariantCulture)},{Info.Longitude.ToString(CultureInfo.InvariantCulture)}"
+                        : $"pokesniper2://{Info.Id}/{Info.Latitude.ToString(CultureInfo.InvariantCulture)},{Info.Longitude.ToString(CultureInfo.InvariantCulture)}");
             }
             catch (Exception e)
             {


Update Battle.cs

Update Battle.cs


Respond to the NPC ready request. As usual, this isn't the 100% right way to do this.

--- PolarisServer/Packets/Handlers/ObjectInteract.cs
+++ PolarisServer/Packets/Handlers/ObjectInteract.cs
@@ -75,6 +75,14 @@
                     }
                 }
             }
+
+            if (command == "READY" && context.CurrentZone == "lobby")
+            {
+                context.SendPacket(new ObjectActionPacket(new EntityHeader((ulong)context.User.PlayerId, EntityType.Player), srcObj.Header, srcObj.Header,
+                    new EntityHeader(), "FavsNeutral"));
+                context.SendPacket(new ObjectActionPacket(new EntityHeader((ulong)context.User.PlayerId, EntityType.Player), srcObj.Header, srcObj.Header,
+                    new EntityHeader(), "AP")); // Short for Appear, Thanks Zapero!
+            }
         }
     }


Add missing ScrollBars.cs file.

Add missing ScrollBars.cs file.


Error handling for datetime parse failure

--- Project/uwpmm/uwpmm.Shared/Utility/Preference.cs
+++ Project/uwpmm/uwpmm.Shared/Utility/Preference.cs
@@ -43,9 +43,20 @@
         {
             get
             {
-                var now = DateTimeOffset.Now.ToString();
-                var date = GetProperty(init_launched_datetime, now);
-                return DateTimeOffset.Parse(date);
+                var now = DateTimeOffset.Now;
+                var date = GetProperty(init_launched_datetime, now.ToString());
+
+                DateTimeOffset loaded;
+                if (DateTimeOffset.TryParse(date, out loaded))
+                {
+                    return loaded;
+                }
+                else
+                {
+                    // Fallback to current datetime
+                    SetProperty(init_launched_datetime, now.ToString());
+                    return now;
+                }
             }
         }


Small fix

Small fix


FIX parsing of MinLength/MaxLength datatype

--- RDFSharp/Model/Validation/RDFValidationHelper.cs
+++ RDFSharp/Model/Validation/RDFValidationHelper.cs
@@ -344,14 +344,14 @@
             //sh:maxLength
             if (!shapesRow.IsNull("?MAXLENGTH")) {
                 RDFPatternMember maxLength = RDFQueryUtilities.ParseRDFPatternMember(shapesRow.Field<string>("?MAXLENGTH"));
-                if (maxLength is RDFTypedLiteral && ((RDFTypedLiteral)maxLength).Datatype.Equals(RDFVocabulary.XSD.INTEGER))
+                if (maxLength is RDFTypedLiteral && ((RDFTypedLiteral)maxLength).Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_INTEGER))
                     shape.AddConstraint(new RDFMaxLengthConstraint(int.Parse(((RDFTypedLiteral)maxLength).Value)));
             }

             //sh:minLength
             if (!shapesRow.IsNull("?MINLENGTH")) {
                 RDFPatternMember minLength = RDFQueryUtilities.ParseRDFPatternMember(shapesRow.Field<string>("?MINLENGTH"));
-                if (minLength is RDFTypedLiteral && ((RDFTypedLiteral)minLength).Datatype.Equals(RDFVocabulary.XSD.INTEGER))
+                if (minLength is RDFTypedLiteral && ((RDFTypedLiteral)minLength).Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_INTEGER))
                     shape.AddConstraint(new RDFMinLengthConstraint(int.Parse(((RDFTypedLiteral)minLength).Value)));
             }


Add jumplist file check to navigated handler

--- Samples/JumpList/ViewModels/MainPageViewModel.cs
+++ Samples/JumpList/ViewModels/MainPageViewModel.cs
@@ -26,7 +26,10 @@

         public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> state)
         {
-            File = await _DataService.GetFileInfoAsync(_SettingService.Recent);
+            if (string.IsNullOrWhiteSpace(parameter as string))
+                File = await _DataService.GetFileInfoAsync(_SettingService.Recent);
+            else
+                File = await _DataService.GetFileInfoAsync(parameter.ToString());
             App.FileReceived += FileReceivedHandler;
         }


DiffLogLogic Types fix

DiffLogLogic Types fix

--- Signum.Engine.Extensions/DiffLog/DiffLogLogic.cs
+++ Signum.Engine.Extensions/DiffLog/DiffLogLogic.cs
@@ -16,10 +16,9 @@
 {
     public static class DiffLogLogic
     {
-        public static Polymorphic<Func<IOperation, bool>> Types = new Polymorphic<Func<IOperation, bool>>(minimumType: typeof(Entity));
-        public static Polymorphic<Func<IEntity, bool>> TypesByEntityTarject = new Polymorphic<Func<IEntity, bool>>(minimumType: typeof(Entity));
+        public static Polymorphic<Func<IEntity, IOperation, bool>> Types = new Polymorphic<Func<IEntity, IOperation, bool>>(minimumType: typeof(Entity));

-        public static void Start(SchemaBuilder sb, DynamicQueryManager dqm)
+        public static void Start(SchemaBuilder sb, DynamicQueryManager dqm, bool registerAll)
         {
             if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
             {
@@ -27,29 +26,20 @@

                 OperationLogic.SurroundOperation += OperationLogic_SurroundOperation;

-                RegisterGraph<Entity>(oper => true);
+                if (registerAll)
+                    RegisterGraph<Entity>((entity, oper) => true);
             }
         }

-        public static void RegisterGraph<T>(Func<IOperation, bool> func) where T : Entity
+        public static void RegisterGraph<T>(Func<IEntity, IOperation, bool> func) where T : Entity
         {
             Types.SetDefinition(typeof(T), func);
         }

         static IDisposable OperationLogic_SurroundOperation(IOperation operation, OperationLogEntity log, Entity entity, object[] args)
         {
-            bool? strategy = null;
-
-            var byEntity = TypesByEntityTarject.TryGetValue(entity.GetType());
-            if (byEntity != null)
-            {
-                strategy = byEntity(entity);
-                if (strategy == false)
-                    return null;
-            }
-
-            var type = operation.OperationType == OperationType.Execute && operation.OperationType == OperationType.Delete ? entity.GetType() : null;
-            strategy = type == null ? (bool?)null : Types.GetValue(type)(operation);
+            var type = entity.GetType();
+            bool strategy = Types.ContainsKey(type) ? Types.TryGetValue(type)(entity, operation) : false;

             if (strategy == false)
                 return null;
@@ -72,7 +62,7 @@
                     {
                         using (CultureInfoUtils.ChangeBothCultures(Schema.Current.ForceCultureInfo))
                         {
-                            if (strategy ?? Types.GetValue(target.GetType())(operation))
+                            if (Types.GetValue(type)(entity, operation))
                                 log.Mixin<DiffLogMixin>().FinalState = entity.Dump();
                         }
                     }


fix ChartRequest

fix ChartRequest

--- Signum.Entities.Extensions/Chart/ChartRequest.cs
+++ Signum.Entities.Extensions/Chart/ChartRequest.cs
@@ -172,7 +172,7 @@
         {
             if (GroupResults)
             {
-                var keys = this.Columns.Where(a => a.IsGroupKey.Value).Select(a => a.Token.Token);
+                var keys = this.Columns.Where(a => a.IsGroupKey.Value).Select(a => a.Token).NotNull().Select(a => a.Token).ToList();

                 Orders.RemoveAll(o => !(o.Token is AggregateToken) && !keys.Contains(o.Token));
             }


FIXME: This completely breaks Xamarin Studio, making it impossible to compile anything.

See the detailed comment inside.

--- mscorlib/system/globalization/gregoriancalendar.cs
+++ mscorlib/system/globalization/gregoriancalendar.cs
@@ -64,6 +64,18 @@
         [OnDeserialized]
         private void OnDeserialized(StreamingContext ctx)
         {
+#if MONO_NOT_SUPPORTED
+            // FIXME: This breaks Xamarin Studio, making it completely impossible to
+            //        compile any projects with the new runtime.
+            //
+            //        To reproduce, compile and install Mono to a custom prefix, for
+            //        instance /Workspace/TEST, add it in "Preferences / .NET Runtimes",
+            //        open a random C# project, select "Project / Active Runtime" and the
+            //        build will abort with this exception.
+            //
+            //        When this happens, 'm_type' is 0.
+            //
+            //        2015-01-24  Martin Baulig
             if (m_type < GregorianCalendarTypes.Localized ||
                 m_type > GregorianCalendarTypes.TransliteratedFrench)
             {
@@ -75,6 +87,7 @@
                                                 "type",
                                                 "GregorianCalendar"));
             }
+#endif
         }
 #endregion Serialization


update BingTranslator example

update BingTranslator example

--- Signum.Web.Extensions/Translation/ITranslator.cs
+++ Signum.Web.Extensions/Translation/ITranslator.cs
@@ -170,7 +170,7 @@
     //                Headers = { { "Authorization", "Bearer " + token } }
     //            };

-    //            return list.GroupsOf(50).SelectMany(gr =>
+    //            return list.GroupsOf(a => a.Length, 10000).SelectMany(gr =>
     //            {
     //                TranslateArrayResponse[] result = client.TranslateArray("", gr.ToArray(), from, to, new TranslateOptions());


Corrected FindItem.  Uses MenuSeed.DebugOnly.

--- Library/Software/WpfApplication/Menu/MainMenu.xaml.cs
+++ Library/Software/WpfApplication/Menu/MainMenu.xaml.cs
@@ -36,6 +36,12 @@

         public void AddCommand<Tkey>(MenuSeed<Tkey> seed)
         {
+#if DEBUG
+#else
+            if (seed.DebugOnly)
+                return;
+#endif
+
             MenuItem item;
             if (seed.ParentKey == null)
                 item = AddMenuItem(seed.Key, seed.Label, seed.DefaultCheck);
@@ -93,7 +99,7 @@

         MenuItem FindItem(object tag, ItemCollection items)
         {
-            MenuItem foundItem = items.Cast<MenuItem>().First(item => tag.Equals(item.Tag));
+            MenuItem foundItem = items.Cast<MenuItem>().FirstOrDefault(item => tag.Equals(item.Tag));
             if (foundItem == null )
             { // recurse
                 foreach ( MenuItem item in items )
@@ -108,6 +114,9 @@

         MenuItem AddMenuItem(ItemsControl container, object key, string label, bool? defaultCheck)
         {
+            if (container == null)
+                throw new ArgumentException("Null container of menu items for " + key);
+
             MenuItem item = new MenuItem();
             item.Header = label;
             //AssignTag(item, key);


Do not get update lock until the vessel is loaded

--- LmpClient/Systems/VesselProtoSys/VesselProtoEvents.cs
+++ LmpClient/Systems/VesselProtoSys/VesselProtoEvents.cs
@@ -50,7 +50,6 @@
             {
                 //We delay it a bit because we must wait until the vessel is named correctly and so on.
                 CoroutineUtil.StartDelayedRoutine("VesselInitialized", ()=> System.MessageSender.SendVesselMessage(vessel), 0.5f);
-                LockSystem.Singleton.AcquireUpdateLock(vessel.id, true);
                 LockSystem.Singleton.AcquireUnloadedUpdateLock(vessel.id, true);
             }
         }
@@ -99,7 +98,6 @@

             if (!LockSystem.LockQuery.UpdateLockExists(vessel.id))
             {
-                LockSystem.Singleton.AcquireUpdateLock(vessel.id, true);
                 LockSystem.Singleton.AcquireUnloadedUpdateLock(vessel.id, true);
                 VesselProtoSystem.Singleton.MessageSender.SendVesselMessage(vessel);
             }


Take slop out of quaternion tests

Take slop out of quaternion tests

--- RocketLeagueReplayParser.Tests/SerializeTests.cs
+++ RocketLeagueReplayParser.Tests/SerializeTests.cs
@@ -241,23 +241,30 @@
                 z /= l;
                 w /= l;

-                var q = new Quaternion(x, y, z, w);
-
-                // 3 round trips for good measure
-                for (var j = 0; j < 2; ++j)
-                {
-                    var bw = new BitWriter(2 + 18 * 3);
-                    q.Serialize(bw);
-                    var br = new BitReader(bw.GetBytes());
-                    var q2 = Quaternion.Deserialize(br);
-
-                    Assert.AreEqual(q.X, q2.X, .0001);
-                    Assert.AreEqual(q.Y, q2.Y, .0001);
-                    Assert.AreEqual(q.Z, q2.Z, .0001);
-                    Assert.AreEqual(q.W, q2.W, .0001);
-
-                    q = q2;
-                }
+                TestQuatRoundTripSerialization(x, y, z, w);
+            }
+        }
+
+        [TestCase(-0.004410246f, 0.00182074378f, 0.923867f, 0.382684022f)]
+        [Test]
+        public void TestQuatRoundTripSerialization(float x, float y, float z, float w)
+        {
+            var q = new Quaternion(x, y, z, w);
+
+            // 3 round trips for good measure
+            for (var j = 0; j < 2; ++j)
+            {
+                var bw = new BitWriter(2 + 18 * 3);
+                q.Serialize(bw);
+                var br = new BitReader(bw.GetBytes());
+                var q2 = Quaternion.Deserialize(br);
+
+                Assert.AreEqual(q.X, q2.X);
+                Assert.AreEqual(q.Y, q2.Y);
+                Assert.AreEqual(q.Z, q2.Z);
+                Assert.AreEqual(q.W, q2.W);
+
+                q = q2;
             }
         }
     }


Fix hidden warnings

Fix hidden warnings

--- osu.Framework.Tests/Visual/Input/TestSceneClickLenience.cs
+++ osu.Framework.Tests/Visual/Input/TestSceneClickLenience.cs
@@ -21,14 +21,14 @@
             switch (type)
             {
                 case TestType.NonBlockingScroll:
-                    return new NonBlockingScroll()
+                    return new NonBlockingScroll
                     {
                         RelativeSizeAxes = Axes.Both,
                         Child = box = new ClickBox()
                     };

                 case TestType.Scroll:
-                    return new BasicScrollContainer()
+                    return new BasicScrollContainer
                     {
                         RelativeSizeAxes = Axes.Both,
                         Child = box = new ClickBox()


Remove static so it is per instance

Remove static so it is per instance

Remove static so it is per instance

--- Mindscape.Raygun4Net/Storage/RaygunIsolatedStorage.cs
+++ Mindscape.Raygun4Net/Storage/RaygunIsolatedStorage.cs
@@ -9,7 +9,7 @@
 {
   public class RaygunIsolatedStorage : IRaygunOfflineStorage
   {
-    private static string _folderNameHash = null;
+    private string _folderNameHash = null;
     private const string RaygunBaseDirectory = "Raygun";
     private const string RaygunFileFormat = ".json";


Fix hitcircle selections not responding to stacking changes

--- osu.Game.Rulesets.Osu/Edit/Masks/HitCircleSelectionMask.cs
+++ osu.Game.Rulesets.Osu/Edit/Masks/HitCircleSelectionMask.cs
@@ -19,7 +19,8 @@

             InternalChild = new HitCircleMask((HitCircle)hitCircle.HitObject);

-            hitCircle.HitObject.PositionChanged += _ => Position = hitCircle.Position;
+            hitCircle.HitObject.PositionChanged += _ => Position = hitCircle.HitObject.StackedPosition;
+            hitCircle.HitObject.StackHeightChanged += _ => Position = hitCircle.HitObject.StackedPosition;
         }
     }
 }


Fix broken spinner rotation logic

Fix broken spinner rotation logic

--- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -197,7 +197,7 @@
             float targetScale = relativeCircleScale + (1 - relativeCircleScale) * Progress;
             Disc.Scale = new Vector2((float)Interpolation.Lerp(Disc.Scale.X, targetScale, Math.Clamp(Math.Abs(Time.Elapsed) / 100, 0, 1)));

-            symbol.Rotation = (float)Interpolation.Lerp(symbol.Rotation, Disc.RotationAbsolute / 2, Math.Clamp(Math.Abs(Time.Elapsed) / 40, 0, 1));
+            symbol.Rotation = (float)Interpolation.Lerp(symbol.Rotation, Disc.Rotation / 2, Math.Clamp(Math.Abs(Time.Elapsed) / 40, 0, 1));
         }

         protected override void UpdateInitialTransforms()
@@ -206,9 +206,6 @@

             circleContainer.ScaleTo(Spinner.Scale * 0.3f);
             circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint);
-
-            Disc.RotateTo(-720);
-            symbol.RotateTo(-720);

             mainContainer
                 .ScaleTo(0)


Update ISession.cs

Update ISession.cs

--- Modules/HtcSharp.HttpModule/Http.Features/ISession.cs
+++ Modules/HtcSharp.HttpModule/Http.Features/ISession.cs
@@ -46,7 +46,7 @@
         /// <param name="key"></param>
         /// <param name="value"></param>
         /// <returns></returns>
-        bool TryGetValue<T>(string key, out T value);
+        bool TryGetValue(string key, out object value);

         /// <summary>
         /// Set the given key and value in the current session. This will throw if the session
@@ -54,7 +54,7 @@
         /// </summary>
         /// <param name="key"></param>
         /// <param name="value"></param>
-        void Set<T>(string key, T value);
+        void Set(string key, object value);

         /// <summary>
         /// Remove the given key from the session if present.


Remove unused class

Remove unused class

--- osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs
+++ osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs
@@ -8,10 +8,6 @@

 namespace osu.Game.Graphics.UserInterface
 {
-    public class ScreenBreadcrumbControl : ScreenBreadcrumbControl<Screen>
-    {
-    }
-
     public class ScreenBreadcrumbControl<T> : BreadcrumbControl<T> where T : Screen
     {
         private T currentScreen;


Fix osu!classic skin elements not showing up in storyboards

--- osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs
+++ osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs
@@ -2,6 +2,7 @@
 // See the LICENCE file in the repository root for full licence text.

 using System;
+using System.IO;
 using osuTK;
 using osu.Framework.Allocation;
 using osu.Framework.Bindables;
@@ -138,7 +139,8 @@
         protected override void SkinChanged(ISkinSource skin, bool allowFallback)
         {
             base.SkinChanged(skin, allowFallback);
-            var newTexture = skin?.GetTexture(Sprite.Path) ?? storyboardTextureStore?.Get(texturePath);
+
+            var newTexture = skin?.GetTexture(Path.GetFileNameWithoutExtension(Sprite.Path)) ?? storyboardTextureStore?.Get(texturePath);

             if (drawableSprite.Texture == newTexture) return;


View all entity pages

View all entity pages

--- SocialToolBox.Core/Entity/Web/EntityPageFacet.cs
+++ SocialToolBox.Core/Entity/Web/EntityPageFacet.cs
@@ -1,4 +1,6 @@
-using SocialToolBox.Core.Present;
+using System.Linq;
+using SocialToolBox.Core.Database.Projection;
+using SocialToolBox.Core.Present;
 using SocialToolBox.Core.Web;
 using SocialToolBox.Core.Web.Args;
 using SocialToolBox.Core.Web.Facets;
@@ -20,14 +22,28 @@
         /// <summary>
         /// View a single entity page.
         /// </summary>
-        public readonly IWebEndpoint<IdArgs> View;
+        public readonly IWebEndpoint<IdArgs> View;
+
+        /// <summary>
+        /// View all entity pages.
+        /// </summary>
+        public readonly IWebEndpoint<PageArgs> All;
+
+        /// <summary>
+        /// The number of pages on each page of <see cref="All"/>
+        /// </summary>
+        public const int PageSize = 20;

         public EntityPageFacet(IWebDriver driver, EntityModule module) : base(driver, "entity")
         {
             Module = module;
             View = OnGet<IdArgs>("").Use(() => new ViewPageHandler(this));
+            All = OnGet<PageArgs>("all").Use(() => new AllPagesHandler(this));
         }

+        /// <summary>
+        /// Handler for viewing an individual page.
+        /// </summary>
         private class ViewPageHandler : FacetHandler<EntityPageFacet,IdArgs>
         {
             public ViewPageHandler(EntityPageFacet facet) : base(facet) {}
@@ -45,5 +61,22 @@
                     .Build());
             }
         }
+
+        private class AllPagesHandler : FacetHandler<EntityPageFacet, PageArgs>
+        {
+            public AllPagesHandler(EntityPageFacet facet) : base(facet) {}
+
+            protected override WebResponse Process()
+            {
+                var pagesT = Facet.Module.PageByTitle.Query(Cursor, PageSize, PageSize * Arguments.Page);
+
+                var pages = pagesT.Result;
+
+                return Page(ColumnPage
+                    .WithTitle("All Entity Pages")
+                    .AddPrimary(HtmlString.Concat(pages.Select(p => HtmlString.Escape(p.Key.Key))))
+                    .Build());
+            }
+        }
     }
 }


Added current level as text in screen

Added current level as text in screen

--- LibraCore/Scenes/LevelScene.cs
+++ LibraCore/Scenes/LevelScene.cs
@@ -220,7 +220,8 @@
         private void CreateRemainingLifesText()
         {
             var textEntity = CreateEntity(RemainingLifesTextEntityName);
-            textEntity.addComponent(new TextSprite(Graphics.instance.bitmapFont, $"LIFES: {lifes}", new Vector2(580, 460), Color.Black)).SetRenderLayer(ScreenSpaceRenderLayer);
+            var text = $"LEVEL: {currentLevel}        LIFES: {lifes}";
+            textEntity.addComponent(new TextSprite(Graphics.instance.bitmapFont, text, new Vector2(510, 460), Color.Black)).SetRenderLayer(ScreenSpaceRenderLayer);
         }

         private void HandleGameWon()


add giltering for Toolbar / ToolbarMenu

add giltering for Toolbar / ToolbarMenu

--- Signum.Engine.Extensions/Toolbar/ToolbarLogic.cs
+++ Signum.Engine.Extensions/Toolbar/ToolbarLogic.cs
@@ -67,11 +67,11 @@
             RegisterDelete<WorkflowEntity>(sb);

             RegisterContentConfig<ToolbarMenuEntity>(
-                lite => true,
+                lite => ToolbarMenus.Value.GetOrCreate(lite).IsAllowedFor(TypeAllowedBasic.Read, inUserInterface: true),
                 lite => TranslatedInstanceLogic.TranslatedField(ToolbarMenus.Value.GetOrCreate(lite), a => a.Name));

             RegisterContentConfig<ToolbarEntity>(
-                lite => true,
+                lite => Toolbars.Value.GetOrCreate(lite).IsAllowedFor(TypeAllowedBasic.Read, inUserInterface: true),
                 lite => TranslatedInstanceLogic.TranslatedField(Toolbars.Value.GetOrCreate(lite), a => a.Name));

             RegisterContentConfig<UserQueryEntity>(


android/host: changes to the error logic Now also warns when trying to decrease the guest limit to something below the current number of guests participating.

--- Solitude.Android/Activities/HostEventActivity.cs
+++ Solitude.Android/Activities/HostEventActivity.cs
@@ -1,188 +1,220 @@
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Android.App;
-using Android.Content;
-using Android.OS;
-using Android.Runtime;
-using Android.Views;
-using Android.Widget;
-
-namespace DineWithaDane.Android
-{
-	[Activity(Label = "Host Event")]
-	public class HostEventActivity : DrawerActivity
-	{
-		protected override void OnCreate(Bundle bundle)
-		{
-			Position = 3;
-			base.OnCreate (bundle);
-
-			var contentFrame = FindViewById<FrameLayout>(Resource.Id.content_frame);
-
-			var content = new LinearLayout(this);
-			content.Orientation = Orientation.Vertical;
-
-			var scroll = new ScrollView(this);
-			scroll.AddView(content);
-			contentFrame.AddView(scroll);
-
-			// Create all visible elements required to create event
-			var titleTitle = new TextView(this);
-			titleTitle.Text = "Event name";
-
-			var title = new EditText(this);
-			title.Hint = "Title";
-			title.Id = 0x0001;
-
-			var descriptionTitle = new TextView(this);
-			descriptionTitle.Text = "Event Description";
-
-			var description = new EditText(this);
-			description.Hint = "Description!";
-			description.Id = 0x0002;
-
-			var locationTitle = new TextView(this);
-			locationTitle.Text = "Location/Address";
-
-			var location = new EditText(this);
-			location.Hint = "Location/Address";
-			location.Id = 0x0003;
-
-			var guestsTitle = new TextView(this);
-			guestsTitle.Text = "Guests";
-
-			var guests = new EditText(this);
-			guests.Hint = "Number of guests";
-			guests.InputType = global::Android.Text.InputTypes.ClassNumber;
-			guests.Id = 0x0004;
-
-			var dateTitle = new TextView(this);
-			dateTitle.Text = "Date";
-
-
-
-			var date = new DatePicker(this);
-			date.DateTime = DateTime.Now;
-			date.Id = 0x0005;
-
-			var timeTitle = new TextView(this);
-			timeTitle.Text = "Time";
-
-			var timePicker = new TimePicker(this);
-			timePicker.Id = 0x0006;
-
-			// Build Activity Content
-			content.AddView(titleTitle);
-			content.AddView(title);
-			content.AddView(descriptionTitle);
-			content.AddView(description);
-			content.AddView(locationTitle);
-			content.AddView(location);
-			content.AddView(guestsTitle);
-			content.AddView(guests);
-			content.AddView(dateTitle);
-			content.AddView(date);
-			content.AddView(timeTitle);
-			content.AddView(timePicker);
-
-			var typeString = Intent.GetStringExtra("type");
-
-			if (typeString.Equals("new"))
-			{
-				// Buttons for creating a new event or cancel.
-				var createEventButton = new Button(this);
-				createEventButton.Text = "Host Event";
-				createEventButton.Id = 0x0007;
-				createEventButton.Click += (object sender, EventArgs e) =>
-				{
-					int res;
-					bool valid = int.TryParse(guests.Text, out res);
-					// Check if all forms have been filled.
-					if (String.IsNullOrEmpty(title.Text) ||
-					    String.IsNullOrEmpty(description.Text) ||
-					    String.IsNullOrEmpty(location.Text) ||
-					    String.IsNullOrEmpty(guests.Text) ||
-						!valid)
-					{
-						AlertDialog.Builder builder = new AlertDialog.Builder(this);
-						AlertDialog alertDialog = builder.Create();
-						alertDialog.SetTitle("Empty fields");
-							alertDialog.SetMessage(String.Format("There are errors in your event:\n{0}{1}{2}{3}{4}",
-								String.IsNullOrEmpty(title.Text) ? "- No title\n" : "",
-								String.IsNullOrEmpty(description.Text) ? "- No description\n" : "",
-								String.IsNullOrEmpty(location.Text) ? "- No address\n" : "",
-								String.IsNullOrEmpty(guests.Text) ? "- No guest limit\n" : "",
-								(!valid && !String.IsNullOrEmpty(guests.Text)) ? "- Too many event guests." : ""));
-						alertDialog.SetButton("OK", (s, ev) => alertDialog.Dismiss());
-						alertDialog.Show();
-					}
-					else
-					{
-						DateTime @dateTime = new DateTime(date.DateTime.Year, date.DateTime.Month, date.DateTime.Day, (int)timePicker.CurrentHour, (int)timePicker.CurrentMinute, 0);
-						Event @event = new Event(title.Text, @dateTime, location.Text, description.Text, int.Parse(guests.Text), 0);
-						bool completed = MainActivity.CIF.CreateEvent(@event);
-						if (completed)
-							Finish();
-						else
-						{
-							var dialog = new AlertDialog.Builder(this);
-							dialog.SetMessage("Sorry, could not create event:\n" + MainActivity.CIF.LatestError);
-							dialog.Show();
-						}
-					}
-				};
-				var cancelButton = new Button(this);
-				cancelButton.Text = "Cancel";
-				cancelButton.Id = 0x0008;
-				cancelButton.Click += (object sender, EventArgs e) => Finish();
-
-				var buttonKeeper = new LinearLayout(this);
-				buttonKeeper.Orientation = Orientation.Horizontal;
-				buttonKeeper.AddView(cancelButton);
-				buttonKeeper.AddView(createEventButton);
-
-				content.AddView(buttonKeeper);
-			}
-			else if (typeString.Equals("edit"))
-			{
-				title.Text = Intent.GetStringExtra("title");
-				description.Text = Intent.GetStringExtra("description");
-				DateTime dateTime = new DateTime(Intent.GetIntExtra("date year", 0), Intent.GetIntExtra("date month", 0), Intent.GetIntExtra("date day", 0), Intent.GetIntExtra("date hour", 0), Intent.GetIntExtra("date minutte", 0), 0);
-				location.Text = Intent.GetStringExtra("place");
-				guests.Text = Intent.GetIntExtra("maxslots", 0).ToString();
-				date.DateTime = dateTime;
-				timePicker.CurrentHour = (Java.Lang.Integer)dateTime.Hour;
-				timePicker.CurrentMinute = (Java.Lang.Integer)dateTime.Minute;
-
-				var buttonConfirm = new Button(this);
-				buttonConfirm.Text = "Save changes";
-				buttonConfirm.Click += (object sender, EventArgs e) =>
-				{
-					Event @event = new Event(title.Text, new DateTime(date.DateTime.Year, date.DateTime.Month, date.DateTime.Day, (int)timePicker.CurrentHour, (int)timePicker.CurrentMinute, 0), location.Text, description.Text, int.Parse(guests.Text), Intent.GetIntExtra("leftslots", 0), Intent.GetIntExtra("id", 0));
-					MainActivity.CIF.UpdateEvent(@event);
-				};
-
-				var buttonCancel = new Button(this);
-				buttonCancel.Text = "Back";
-				buttonCancel.Click += (object sender, EventArgs e) => Finish();
-
-				var buttonKeeper = new LinearLayout(this);
-				buttonKeeper.Orientation = Orientation.Horizontal;
-
-				buttonKeeper.AddView(buttonCancel);
-				buttonKeeper.AddView(buttonConfirm);
-
-				content.AddView(buttonKeeper);
-			}
-			else
-			{
-				throw new ArgumentOutOfRangeException();
-			}
-		}
-	}
-}
-
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Android.App;
+using Android.Content;
+using Android.OS;
+using Android.Runtime;
+using Android.Views;
+using Android.Widget;
+
+namespace DineWithaDane.Android
+{
+	[Activity(Label = "Host Event")]
+	public class HostEventActivity : DrawerActivity
+	{
+		protected override void OnCreate(Bundle bundle)
+		{
+			Position = 3;
+			base.OnCreate(bundle);
+
+			var contentFrame = FindViewById<FrameLayout>(Resource.Id.content_frame);
+
+			var content = new LinearLayout(this);
+			content.Orientation = Orientation.Vertical;
+
+			var scroll = new ScrollView(this);
+			scroll.AddView(content);
+			contentFrame.AddView(scroll);
+
+			// Create all visible elements required to create event
+			var titleTitle = new TextView(this);
+			titleTitle.Text = "Event name";
+
+			var title = new EditText(this);
+			title.Hint = "Title";
+			title.Id = 0x0001;
+
+			var descriptionTitle = new TextView(this);
+			descriptionTitle.Text = "Event Description";
+
+			var description = new EditText(this);
+			description.Hint = "Description!";
+			description.Id = 0x0002;
+
+			var locationTitle = new TextView(this);
+			locationTitle.Text = "Location/Address";
+
+			var location = new EditText(this);
+			location.Hint = "Location/Address";
+			location.Id = 0x0003;
+
+			var guestsTitle = new TextView(this);
+			guestsTitle.Text = "Guests";
+
+			var guests = new EditText(this);
+			guests.Hint = "Number of guests";
+			guests.InputType = global::Android.Text.InputTypes.ClassNumber;
+			guests.Id = 0x0004;
+
+			var dateTitle = new TextView(this);
+			dateTitle.Text = "Date";
+
+
+
+			var date = new DatePicker(this);
+			date.DateTime = DateTime.Now;
+			date.Id = 0x0005;
+
+			var timeTitle = new TextView(this);
+			timeTitle.Text = "Time";
+
+			var timePicker = new TimePicker(this);
+			timePicker.Id = 0x0006;
+
+			// Build Activity Content
+			content.AddView(titleTitle);
+			content.AddView(title);
+			content.AddView(descriptionTitle);
+			content.AddView(description);
+			content.AddView(locationTitle);
+			content.AddView(location);
+			content.AddView(guestsTitle);
+			content.AddView(guests);
+			content.AddView(dateTitle);
+			content.AddView(date);
+			content.AddView(timeTitle);
+			content.AddView(timePicker);
+
+			var typeString = Intent.GetStringExtra("type");
+
+			if (typeString.Equals("new"))
+			{
+				// Buttons for creating a new event or cancel.
+				var createEventButton = new Button(this);
+				createEventButton.Text = "Host Event";
+				createEventButton.Id = 0x0007;
+				createEventButton.Click += (object sender, EventArgs e) =>
+				{
+					int numberOfGuestsMax;
+					bool boolGuestCount = int.TryParse(guests.Text, out numberOfGuestsMax);
+					bool boolTitle = String.IsNullOrEmpty(title.Text);
+					bool boolDescription = String.IsNullOrEmpty(description.Text);
+					bool boolLocation = String.IsNullOrEmpty(location.Text);
+					bool boolGuest = String.IsNullOrEmpty(guests.Text);
+					// Check if all forms have been filled.
+					if (boolTitle
+					    || boolDescription
+					    || boolLocation
+					    || boolGuest
+					    || !boolGuestCount)
+					{
+						AlertDialog.Builder builder = new AlertDialog.Builder(this);
+						AlertDialog alertDialog = builder.Create();
+						alertDialog.SetTitle("Empty fields");
+						alertDialog.SetMessage(String.Format("There are errors in your event:\n{0}{1}{2}{3}{4}",
+								boolTitle ? "- No title\n" : "",
+								boolDescription ? "- No description\n" : "",
+								boolLocation ? "- No address\n" : "",
+								boolGuest ? "- No guest limit\n" : "",
+								(!boolGuestCount && boolGuest) ? "- Too many event guests." : ""));
+						alertDialog.SetButton("OK", (s, ev) => alertDialog.Dismiss());
+						alertDialog.Show();
+					}
+					else
+					{
+						DateTime @dateTime = new DateTime(date.DateTime.Year, date.DateTime.Month, date.DateTime.Day, (int)timePicker.CurrentHour, (int)timePicker.CurrentMinute, 0);
+						Event @event = new Event(title.Text, @dateTime, location.Text, description.Text, numberOfGuestsMax, 0);
+						bool completed = MainActivity.CIF.CreateEvent(@event);
+						if (completed)
+							Finish();
+						else
+						{
+							var dialog = new AlertDialog.Builder(this);
+							dialog.SetMessage("Sorry, could not create event:\n" + MainActivity.CIF.LatestError);
+							dialog.Show();
+						}
+					}
+				};
+				var cancelButton = new Button(this);
+				cancelButton.Text = "Cancel";
+				cancelButton.Id = 0x0008;
+				cancelButton.Click += (object sender, EventArgs e) => Finish();
+
+				var buttonKeeper = new LinearLayout(this);
+				buttonKeeper.Orientation = Orientation.Horizontal;
+				buttonKeeper.AddView(cancelButton);
+				buttonKeeper.AddView(createEventButton);
+
+				content.AddView(buttonKeeper);
+			}
+			else if (typeString.Equals("edit"))
+			{
+				title.Text = Intent.GetStringExtra("title");
+				description.Text = Intent.GetStringExtra("description");
+				DateTime dateTime = new DateTime(Intent.GetIntExtra("date year", 0), Intent.GetIntExtra("date month", 0), Intent.GetIntExtra("date day", 0), Intent.GetIntExtra("date hour", 0), Intent.GetIntExtra("date minutte", 0), 0);
+				location.Text = Intent.GetStringExtra("place");
+				guests.Text = Intent.GetIntExtra("maxslots", 0).ToString();
+				date.DateTime = dateTime;
+				timePicker.CurrentHour = (Java.Lang.Integer)dateTime.Hour;
+				timePicker.CurrentMinute = (Java.Lang.Integer)dateTime.Minute;
+
+				var buttonConfirm = new Button(this);
+				buttonConfirm.Text = "Save changes";
+				buttonConfirm.Click += (object sender, EventArgs e) =>
+				{
+					int numberOfGuestsMax;
+					bool boolGuestCount = int.TryParse(guests.Text, out numberOfGuestsMax);
+					bool boolTitle = String.IsNullOrEmpty(title.Text);
+					bool boolDescription = String.IsNullOrEmpty(description.Text);
+					bool boolLocation = String.IsNullOrEmpty(location.Text);
+					bool boolGuest = String.IsNullOrEmpty(guests.Text);
+					bool bool32BitGuest = numberOfGuestsMax < Intent.GetIntExtra("leftslots", Int32.MaxValue);
+
+					if (boolTitle
+					    || boolDescription
+					    || boolLocation
+					    || boolGuest
+					    || !boolGuestCount
+					    || bool32BitGuest)
+					{
+						AlertDialog.Builder builder = new AlertDialog.Builder(this);
+						AlertDialog alertDialog = builder.Create();
+						alertDialog.SetTitle("Empty fields");
+						alertDialog.SetMessage(String.Format("There are errors in your event:\n{0}{1}{2}{3}{4}{5}",
+								boolTitle ? "- No title\n" : "",
+								boolDescription ? "- No description\n" : "",
+								boolLocation ? "- No address\n" : "",
+								boolGuest ? "- No guest limit\n" : "",
+								(!boolGuestCount && !boolGuest) ? "- Too many event guests." : "",
+								bool32BitGuest ? "- Your new guest limit is below current number of participants" : ""));
+						alertDialog.SetButton("OK", (s, ev) => alertDialog.Dismiss());
+						alertDialog.Show();
+					}
+					Event @event = new Event(title.Text, new DateTime(date.DateTime.Year, date.DateTime.Month, date.DateTime.Day, (int)timePicker.CurrentHour, (int)timePicker.CurrentMinute, 0), location.Text, description.Text, numberOfGuestsMax, Intent.GetIntExtra("leftslots", 0), Intent.GetIntExtra("id", 0));
+					MainActivity.CIF.UpdateEvent(@event);
+				};
+
+				var buttonCancel = new Button(this);
+				buttonCancel.Text = "Back";
+				buttonCancel.Click += (object sender, EventArgs e) => Finish();
+
+				var buttonKeeper = new LinearLayout(this);
+				buttonKeeper.Orientation = Orientation.Horizontal;
+
+				buttonKeeper.AddView(buttonCancel);
+				buttonKeeper.AddView(buttonConfirm);
+
+				content.AddView(buttonKeeper);
+			}
+			else
+			{
+				throw new ArgumentOutOfRangeException();
+			}
+		}
+	}
+}
+


Add test for relationship reading

Add test for relationship reading

--- dotnet/Mammoth.Tests/DocumentConverterTests.cs
+++ dotnet/Mammoth.Tests/DocumentConverterTests.cs
@@ -99,6 +99,15 @@
                     "

 Fin. ↑

");
         }

+        [Fact]
+        public void RelationshipsAreReadForEachFileContainingBodyXml() {
+            AssertSuccessfulConversion(
+                ConvertToHtml("footnote-hyperlink.docx", mammoth => mammoth.IdPrefix("doc-42-")),
+
+                    "
[1]
" +
+                    "

 Example ↑

");
+        }
+
 		[Fact]
 		public void CanExtractRawTextFromFile() {
 			AssertSuccessfulConversion(


fix TSGenerator for nullable lites

fix TSGenerator for nullable lites

--- Signum.TSGenerator/EntityDeclarationGenerator.cs
+++ Signum.TSGenerator/EntityDeclarationGenerator.cs
@@ -448,9 +448,9 @@

         public static bool GetTypescriptUndefined(this PropertyDefinition p)
         {
-            var attr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == Cache.InTypeScriptAttribute.FullName);
-
-            var b = attr == null ? null : (bool?)attr.Properties.SingleOrDefault(a => a.Name == "Undefined").Argument.Value;
+            var ainTSAttr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == Cache.InTypeScriptAttribute.FullName);
+
+            var b = (bool?)ainTSAttr?.Properties.SingleOrDefault(a => a.Name == "Undefined").Argument.Value;

             if (b != null)
                 return b.Value;
@@ -460,23 +460,38 @@

         private static bool? GetTypescriptUndefined(TypeDefinition declaringType)
         {
-            var attr = GetAttributeInherit(declaringType, Cache.InTypeScriptAttribute.FullName);
-
-            return attr == null ? null : (bool?)attr.Properties.SingleOrDefault(a => a.Name == "Undefined").Argument.Value;
+            var inTSAttr = GetAttributeInherit(declaringType, Cache.InTypeScriptAttribute.FullName);
+
+            return (bool?)inTSAttr?.Properties.SingleOrDefault(a => a.Name == "Undefined").Argument.Value;
         }

         public static bool GetTypescriptNull(this PropertyDefinition p)
         {
-            var attr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == Cache.InTypeScriptAttribute.FullName);
-
-            var b = attr == null ? null : (bool?)attr.Properties.SingleOrDefault(a => a.Name == "Null").Argument.Value;
+            var inTSAttr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == Cache.InTypeScriptAttribute.FullName);
+
+            var b = (bool?)inTSAttr?.Properties.SingleOrDefault(a => a.Name == "Null").Argument.Value;
             if (b != null)
                 return b.Value;

             if (p.PropertyType.IsValueType)
                 return p.PropertyType.IsNullable();
             else
-                return p.CustomAttributes.Any(a => a.AttributeType.Name == "NullableAttribute" && ((byte)2).Equals(a.ConstructorArguments[0].Value));
+            {
+                var nullableAttr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.Name == "NullableAttribute");
+
+                if (nullableAttr == null)
+                    return false;
+
+                var arg = nullableAttr.ConstructorArguments[0].Value;
+
+                if (arg is byte val)
+                    return val == 2;
+
+                if (arg is CustomAttributeArgument[] args)
+                    return ((byte)args[0].Value) == 2;
+
+                throw new InvalidOperationException("Unexpected value of type " + arg.GetType() + " in NullableAttribute constructor");
+            }
         }

         private static string FirstLower(string name)


better progress description

better progress description

--- Solutionizer/ViewModels/FileScanningViewModel.cs
+++ Solutionizer/ViewModels/FileScanningViewModel.cs
@@ -34,12 +34,19 @@

         public IDictionary<string, Project> Projects { get { return _projects; } }

-        public event EventHandler ProjectCountChanged;
-
-        private void InvokeProjectCountChanged() {
-            var handler = ProjectCountChanged;
-            if (handler != null) {
-                handler(this,EventArgs.Empty);
+        private string _progressText;
+        public event EventHandler ProgressTextChanged;
+
+        public string ProgressText {
+            get { return _progressText; }
+            private set {
+                if (_progressText != value) {
+                    _progressText = value;
+                    var handler = ProgressTextChanged;
+                    if (handler != null) {
+                        handler(this, EventArgs.Empty);
+                    }
+                }
             }
         }

@@ -96,6 +103,8 @@
             if (_cancellationToken.IsCancellationRequested) {
                 return null;
             }
+
+            ProgressText = "Analyzing project dependencies";

             // load project details asynchronously
             Parallel.ForEach(_projects.Values, project => {
@@ -148,7 +157,7 @@

         private Project CreateProject(string projectPath, ProjectFolder projectFolder) {
             return _projects.GetOrAdd(projectPath, path => {
-                InvokeProjectCountChanged();
+                ProgressText = _projects.Count + " projects loaded";
                 return new Project(path, projectFolder);
             });
         }
@@ -168,8 +177,8 @@
             _scanningCommand = new ScanningCommand(path, _settings.SimplifyProjectTree);
         }

-        private void OnProjectCountChanged(object sender, EventArgs eventArgs) {
-            ProgressText = _scanningCommand.Projects.Count + " projects loaded";
+        private void OnProgressTextChanged(object sender, EventArgs eventArgs) {
+            ProgressText = _scanningCommand.ProgressText;
         }

         public string ProgressText {
@@ -200,13 +209,13 @@

         protected override void OnActivate() {
             base.OnActivate();
-            _scanningCommand.ProjectCountChanged += OnProjectCountChanged;
+            _scanningCommand.ProgressTextChanged += OnProgressTextChanged;
             _scanningCommand.Start().ContinueWith(t => {
                 Result = t.Result;  TryClose(true); }, TaskScheduler.Current);
         }

         protected override void OnDeactivate(bool close) {
-            _scanningCommand.ProjectCountChanged -= OnProjectCountChanged;
+            _scanningCommand.ProgressTextChanged -= OnProgressTextChanged;
             base.OnDeactivate(close);
         }
     }


LanguageServiceClient sample changes

LanguageServiceClient sample changes

--- Signum.Web.Extensions/Translation/ITranslator.cs
+++ Signum.Web.Extensions/Translation/ITranslator.cs
@@ -83,13 +83,26 @@

     //public class BingTranslator : ITranslator
     //{
-
     //    public List<string> TranslateBatch(List<string> list, string from, string to)
     //    {
-    //        LanguageServiceClient cliente = new LanguageServiceClient();
-    //        TranslateArrayResponse[] result = cliente.TranslateArray(YourAppId, list.ToArray(), from, to, new TranslateOptions());
+    //        string token = AdmAuthentication.GetAccessToken( "ClientId", "Secret"); //find one in https://datamarket.azure.com/developer/applications/register
+    //        LanguageServiceClient client = new LanguageServiceClient();
+    //        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
+    //        {
+    //            System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = new HttpRequestMessageProperty
+    //            {
+    //                Method = "POST",
+    //                Headers = { { "Authorization", "Bearer " + token } }
+    //            };

-    //        return result.Select(a => a.TranslatedText).ToList();
+    //            return list.GroupsOf(50).SelectMany(gr =>
+    //            {
+    //                TranslateArrayResponse[] result = client.TranslateArray("", gr.ToArray(), from, to, new TranslateOptions());
+
+    //                return result.Select(a => a.TranslatedText).ToList();
+
+    //            }).ToList();
+    //        }
     //    }
     //}


Update flattening tests to use the new naming convention for sub-object field names.

--- Silk.Data.SQL.ORM.Tests/FlattenEmbeddingTests.cs
+++ Silk.Data.SQL.ORM.Tests/FlattenEmbeddingTests.cs
@@ -69,9 +69,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.AreEqual(modelInstance.ModelA.Data, queryResult.GetString(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.AreEqual(modelInstance.ModelA.Data, queryResult.GetString(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -111,9 +111,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -154,9 +154,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -197,9 +197,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -223,9 +223,9 @@
 			{
 				var modelInstance = new ObjectWithPocoSubModelsView
 				{
-					ModelAData = "Hello World",
-					ModelB1Data = 5,
-					ModelB2Data = 10
+					ModelA_Data = "Hello World",
+					ModelB1_Data = 5,
+					ModelB2_Data = 10
 				};
 				await database
 					.Insert<ObjectWithPocoSubModelsView>(modelInstance)
@@ -241,9 +241,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.AreEqual(modelInstance.ModelAData, queryResult.GetString(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.AreEqual(modelInstance.ModelA_Data, queryResult.GetString(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1_Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2_Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -289,9 +289,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.AreEqual(modelInstance.ModelA.Data, queryResult.GetString(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.AreEqual(modelInstance.ModelA.Data, queryResult.GetString(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -337,9 +337,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -385,9 +385,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -433,9 +433,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.IsTrue(queryResult.IsDBNull(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2.Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -459,16 +459,16 @@
 			{
 				var modelInstance = new ObjectWithPocoSubModelsView
 				{
-					ModelAData = "Hello World",
-					ModelB1Data = 5,
-					ModelB2Data = 10
+					ModelA_Data = "Hello World",
+					ModelB1_Data = 5,
+					ModelB2_Data = 10
 				};
 				await database
 					.Insert<ObjectWithPocoSubModelsView>(modelInstance)
 					.ExecuteAsync();
-				modelInstance.ModelAData = "Changed World!";
-				modelInstance.ModelB1Data = 15;
-				modelInstance.ModelB2Data = 20;
+				modelInstance.ModelA_Data = "Changed World!";
+				modelInstance.ModelB1_Data = 15;
+				modelInstance.ModelB2_Data = 20;
 				await database
 					.Update<ObjectWithPocoSubModelsView>(modelInstance)
 					.ExecuteAsync();
@@ -483,9 +483,9 @@
 					Assert.IsTrue(await queryResult.ReadAsync());

 					Assert.AreEqual(modelInstance.Id, queryResult.GetGuid(queryResult.GetOrdinal(nameof(modelInstance.Id))));
-					Assert.AreEqual(modelInstance.ModelAData, queryResult.GetString(queryResult.GetOrdinal("ModelAData")));
-					Assert.AreEqual(modelInstance.ModelB1Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1Data")));
-					Assert.AreEqual(modelInstance.ModelB2Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2Data")));
+					Assert.AreEqual(modelInstance.ModelA_Data, queryResult.GetString(queryResult.GetOrdinal("ModelA_Data")));
+					Assert.AreEqual(modelInstance.ModelB1_Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB1_Data")));
+					Assert.AreEqual(modelInstance.ModelB2_Data, queryResult.GetInt32(queryResult.GetOrdinal("ModelB2_Data")));
 				}
 			}
 			finally
@@ -628,9 +628,9 @@
 			{
 				var modelInstance = new ObjectWithPocoSubModelsView
 				{
-					ModelAData = "Hello World",
-					ModelB1Data = 5,
-					ModelB2Data = 10
+					ModelA_Data = "Hello World",
+					ModelB1_Data = 5,
+					ModelB2_Data = 10
 				};
 				await database
 					.Insert<ObjectWithPocoSubModelsView>(modelInstance)
@@ -792,9 +792,9 @@

 				Assert.AreEqual(1, selectResults.Count);
 				var selectedInstance = selectResults.First();
-				Assert.AreEqual(modelInstance.ModelA.Data, selectedInstance.ModelAData);
-				Assert.AreEqual(modelInstance.ModelB1.Data, selectedInstance.ModelB1Data);
-				Assert.AreEqual(modelInstance.ModelB2.Data, selectedInstance.ModelB2Data);
+				Assert.AreEqual(modelInstance.ModelA.Data, selectedInstance.ModelA_Data);
+				Assert.AreEqual(modelInstance.ModelB1.Data, selectedInstance.ModelB1_Data);
+				Assert.AreEqual(modelInstance.ModelB2.Data, selectedInstance.ModelB2_Data);
 			}
 			finally
 			{
@@ -813,9 +813,9 @@
 		private class ObjectWithPocoSubModelsView
 		{
 			public Guid Id { get; private set; }
-			public string ModelAData { get; set; }
-			public int ModelB1Data { get; set; }
-			public int ModelB2Data { get; set; }
+			public string ModelA_Data { get; set; }
+			public int ModelB1_Data { get; set; }
+			public int ModelB2_Data { get; set; }
 		}

 		private class SubModelA


PHPDoc cleanup

PHPDoc cleanup

--- Source/Devsense.PHP.Parser/Syntax/PHPDocBlock.cs
+++ Source/Devsense.PHP.Parser/Syntax/PHPDocBlock.cs
@@ -30,6 +30,7 @@
     /// </summary>
     /// <remarks>define() statements, functions, classes, class methods, and class vars, include() statements, and global variables can all be documented.
     /// See http://en.wikipedia.org/wiki/PHPDoc for specifications.</remarks>
+    [DebuggerDisplay("{PHPDocPreview,nq} {Span}")]
     public sealed class PHPDocBlock : LangElement
     {
         #region Nested classes: Element
@@ -74,12 +75,12 @@
             /// <summary>
             /// Tag elements initialized using reflection.
             /// </summary>
-            private static Dictionary<string, Func<string, string, Element>>/*!!*/elementFactories;
+            private static Dictionary<string, Func<string, string, Element>>/*!!*/s_elementFactories;

             static Element()
             {
                 // initilize dictionary of known tags and their factories:
-                elementFactories = new Dictionary<string, Func<string, string, Element>>(20, StringComparer.OrdinalIgnoreCase);
+                s_elementFactories = new Dictionary<string, Func<string, string, Element>>(20, StringComparer.OrdinalIgnoreCase);
                 var types = typeof(PHPDocBlock).GetTypeInfo().DeclaredNestedTypes.Where(t => t.IsNestedPublic && !t.IsAbstract);
                 var eltype = typeof(Element).GetTypeInfo();
                 foreach (var t in types)
@@ -91,7 +92,7 @@
                         if (fld != null)
                         {
                             var factory = CreateElementFactory(t);
-                            elementFactories.Add(TagNameHelper(fld), factory);
+                            s_elementFactories.Add(TagNameHelper(fld), factory);
                         }
                         else
                         {
@@ -102,11 +103,11 @@
                             if (f1 != null && f2 != null)
                             {
                                 var factory = CreateElementFactory(t);
-                                elementFactories.Add(TagNameHelper(f1), factory);
-                                elementFactories.Add(TagNameHelper(f2), factory);
+                                s_elementFactories.Add(TagNameHelper(f1), factory);
+                                s_elementFactories.Add(TagNameHelper(f2), factory);

                                 if (f3 != null)
-                                    elementFactories.Add(TagNameHelper(f3), factory);
+                                    s_elementFactories.Add(TagNameHelper(f3), factory);
                             }
                             else
                             {
@@ -121,9 +122,9 @@
                 }

                 // ensure we have some tags:
-                Debug.Assert(elementFactories.ContainsKey("@param"));
-                Debug.Assert(elementFactories.ContainsKey("@ignore"));
-                Debug.Assert(elementFactories.ContainsKey("@var"));
+                Debug.Assert(s_elementFactories.ContainsKey("@param"));
+                Debug.Assert(s_elementFactories.ContainsKey("@ignore"));
+                Debug.Assert(s_elementFactories.ContainsKey("@var"));
                 // ...
             }

@@ -184,7 +185,7 @@
                 string tagName = (endIndex < line.Length) ? line.Remove(endIndex) : line;

                 Func<string, string, Element> tmp;
-                if (elementFactories.TryGetValue(tagName, out tmp))
+                if (s_elementFactories.TryGetValue(tagName, out tmp))
                     return new KeyValuePair<string, Func<string, string, Element>>(tagName, tmp);
                 else
                     return new KeyValuePair<string, Func<string, string, Element>>(tagName, (_name, _line) => new UnknownTextTag(_name, _line));
@@ -1881,8 +1882,8 @@
         {
             var elements = this.Elements;
             for (int i = 0; i < elements.Length; i++)
-                if (elements[i] is T)
-                    return (T)elements[i];
+                if (elements[i] is T e)
+                    return e;

             return null;
         }
@@ -1927,8 +1928,7 @@
         {
             get
             {
-                var tag = GetElement<ShortDescriptionElement>();
-                return (tag != null) ? tag.Text : null;
+                return GetElement<ShortDescriptionElement>()?.Text;
             }
         }

@@ -1939,8 +1939,7 @@
         {
             get
             {
-                var tag = GetElement<LongDescriptionElement>();
-                return (tag != null) ? tag.Text : null;
+                return GetElement<LongDescriptionElement>()?.Text;
             }
         }


- Inclusion fichier manquant TaxonomyHelper

--- Source/GSoft.Dynamite/Taxonomy/TaxonomyHelper.cs
+++ Source/GSoft.Dynamite/Taxonomy/TaxonomyHelper.cs
@@ -313,13 +313,25 @@
             SPWeb web, TaxonomyField field, TaxonomyFullValue defaultValue)
         {
             var termGroupName = defaultValue.Context.Group.Name;
+            var defaultLanguage = new CultureInfo(this.GetTermStoreDefaultLanguage(web.Site));

             // Get the term set name according to the default term store language
-            var termSetName = defaultValue.Context.TermSet.Labels[new CultureInfo(this.GetTermStoreDefaultLanguage(web.Site))];
-
-            if (defaultValue.Term != null)
-            {
-                this.SetDefaultTaxonomyFieldValue(web, field, termGroupName, termSetName, defaultValue.Term.Label);
+            var termSetName = defaultValue.Context.TermSet.Labels[defaultLanguage];
+
+            var term = defaultValue.Term;
+
+            if (term != null)
+            {
+                string label = string.Empty;
+
+               //  May arrive if the term label haven't been updated correctly on the source object for the current language
+                if (string.IsNullOrEmpty(term.Label) && term.Labels.Count > 0)
+                {
+                    // Trying to get the default language label
+                    label = term.Labels[defaultLanguage];
+                }
+
+                this.SetDefaultTaxonomyFieldValue(web, field, termGroupName, termSetName, label);

                 // TODO: add SetDefaultTaxonomyFieldValueMulti


Another case - should ignore large numbers.

--- StringCalculator/StringCalculator.Tests/Tests.cs
+++ StringCalculator/StringCalculator.Tests/Tests.cs
@@ -80,6 +80,17 @@
         }
     }

+    public class When_I_supply_large_numbers
+    {
+        [Fact]
+        public void It_should_ignore_numbers_greater_than_one_thousand()
+        {
+            var sut = new StringCalculator();
+            int actual = sut.Add("999,1000,1001");
+            actual.Should().Be(1999);
+        }
+    }
+
     public class StringCalculator
     {
         public int Add(string input)


Expanded actions in DenyChildAttachTest for debug

--- Tests/System/Threading/Tasks/MinimalTaskTests.cs
+++ Tests/System/Threading/Tasks/MinimalTaskTests.cs
@@ -530,10 +530,24 @@
         {
             var mre = new ManualResetEventSlim();
             Task nested = null;
-            Task parent = Task.Factory.StartNew(() => {
-                nested = Task.Factory.StartNew(() => mre.Wait(2000), TaskCreationOptions.AttachedToParent);
-            }, TaskCreationOptions.DenyChildAttach);
-            Assert.IsTrue(parent.Wait(1000), "#1");
+            Action innerAction = () =>
+            {
+                mre.Wait(2000);
+            };
+            Action outerAction = () =>
+            {
+                nested = Task.Factory.StartNew
+                (
+                    innerAction,
+                    TaskCreationOptions.AttachedToParent
+                );
+            };
+            Task parent = Task.Factory.StartNew
+                (
+                    outerAction,
+                    TaskCreationOptions.DenyChildAttach
+                );
+            Assert.IsTrue(parent.Wait(10000), "#1");
             mre.Set();
             Assert.IsTrue(nested.Wait(2000), "#2");
         }


Update Demo

Update Demo

--- Src/Asp.Net/SqlServerTest/UnitTest/UQueryable.cs
+++ Src/Asp.Net/SqlServerTest/UnitTest/UQueryable.cs
@@ -42,6 +42,13 @@
             sql= Db.Updateable<UnitSelectTest2>(new UnitSelectTest2()).ToSql().Key;
             UValidate.Check(sql, @"UPDATE [UnitSelectTest2]  SET
            [Dc]=@Dc,[IntNull]=@IntNull  WHERE [Int]=@Int", "Queryable");
+
+            sql= Db.Queryable<Order>().IgnoreColumns(it => it.CreateTime).ToSql().Key;
+            UValidate.Check(sql, "SELECT [Id],[Name],[Price],[CustomId] FROM [Order] ", "Queryable");
+            sql = Db.Queryable<Order>().IgnoreColumns(it => new { it.Id,it.Name }).ToSql().Key;
+            UValidate.Check(sql, "SELECT [Price],[CreateTime],[CustomId] FROM [Order] ", "Queryable");
+            sql = Db.Queryable<Order>().IgnoreColumns("id").ToSql().Key;
+            UValidate.Check(sql, "SELECT [Name],[Price],[CreateTime],[CustomId] FROM [Order] ", "Queryable");
         }


Slightly loosened the invariants of adapted builders, as this may prove to be a fruitful direction in order to enable the SpecimenBuilderNodeCollection to adapt a vertical slice as well as the current horisontal slice of nodes.

--- Src/AutoFixture/SpecimenBuilderNodeCollection.cs
+++ Src/AutoFixture/SpecimenBuilderNodeCollection.cs
@@ -10,7 +10,7 @@
     {
         private ISpecimenBuilderNode graph;
         private readonly Func<ISpecimenBuilderNode, bool> isAdaptedBuilder;
-        private ISpecimenBuilderNode adaptedNode;
+        private IEnumerable<ISpecimenBuilder> adaptedBuilders;

         public SpecimenBuilderNodeCollection(
             ISpecimenBuilderNode graph,
@@ -18,41 +18,41 @@
         {
             this.graph = graph;
             this.isAdaptedBuilder = adaptedBuilderPredicate;
-            this.adaptedNode = this.SelectAdaptedNodes(this.graph).Single();
+            this.adaptedBuilders = this.SelectAdaptedNodes(this.graph).Single();
         }

         public event EventHandler<SpecimenBuilderNodeEventArgs> GraphChanged;

         public int IndexOf(ISpecimenBuilder item)
         {
-            return this.adaptedNode.IndexOf(item);
+            return this.adaptedBuilders.IndexOf(item);
         }

         public void Insert(int index, ISpecimenBuilder item)
         {
-            this.Mutate(this.adaptedNode.Insert(index, item));
+            this.Mutate(this.adaptedBuilders.Insert(index, item));
         }

         public void RemoveAt(int index)
         {
-            this.Mutate(this.adaptedNode.RemoveAt(index));
+            this.Mutate(this.adaptedBuilders.RemoveAt(index));
         }

         public ISpecimenBuilder this[int index]
         {
             get
             {
-                return this.adaptedNode.ElementAt(index);
+                return this.adaptedBuilders.ElementAt(index);
             }
             set
             {
-                this.Mutate(this.adaptedNode.SetItem(index, value));
+                this.Mutate(this.adaptedBuilders.SetItem(index, value));
             }
         }

         public void Add(ISpecimenBuilder item)
         {
-            this.Mutate(this.adaptedNode.Concat(new[] { item }));
+            this.Mutate(this.adaptedBuilders.Concat(new[] { item }));
         }

         public void Clear()
@@ -62,17 +62,17 @@

         public bool Contains(ISpecimenBuilder item)
         {
-            return this.adaptedNode.Contains(item);
+            return this.adaptedBuilders.Contains(item);
         }

         public void CopyTo(ISpecimenBuilder[] array, int arrayIndex)
         {
-            this.adaptedNode.ToArray().CopyTo(array, arrayIndex);
+            this.adaptedBuilders.ToArray().CopyTo(array, arrayIndex);
         }

         public int Count
         {
-            get { return this.adaptedNode.Count(); }
+            get { return this.adaptedBuilders.Count(); }
         }

         public bool IsReadOnly
@@ -92,7 +92,7 @@

         public IEnumerator<ISpecimenBuilder> GetEnumerator()
         {
-            return this.adaptedNode.GetEnumerator();
+            return this.adaptedBuilders.GetEnumerator();
         }

         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
@@ -115,7 +115,7 @@
         private void Mutate(IEnumerable<ISpecimenBuilder> builders)
         {
             this.graph = this.graph.ReplaceNode(with: builders, when: this.isAdaptedBuilder);
-            this.adaptedNode = this.SelectAdaptedNodes(this.graph).Single();
+            this.adaptedBuilders = this.SelectAdaptedNodes(this.graph).Single();

             this.OnGraphChanged(new SpecimenBuilderNodeEventArgs(this.graph));
         }
@@ -125,9 +125,9 @@
             if (this.isAdaptedBuilder(graph))
                 yield return graph;

-            foreach (var g in graph)
+            foreach (var b in graph)
             {
-                var n = g as ISpecimenBuilderNode;
+                var n = b as ISpecimenBuilderNode;
                 if (n != null)
                     foreach (var n1 in this.SelectAdaptedNodes(n))
                         yield return n1;


Fixed ImapFolder.Rename() to handle cases where the new ParentFolder's FullName is empty

Fixes issue #64

--- MailKit/Net/Imap/ImapFolder.cs
+++ MailKit/Net/Imap/ImapFolder.cs
@@ -564,7 +564,14 @@

 			CheckState (false, false);

-			var encodedName = ImapEncoding.Encode (parent.FullName + parent.DirectorySeparator + name);
+			string newFullName;
+
+			if (!string.IsNullOrEmpty (parent.FullName))
+				newFullName = parent.FullName + parent.DirectorySeparator + name;
+			else
+				newFullName = name;
+
+			var encodedName = ImapEncoding.Encode (newFullName);
 			var ic = Engine.QueueCommand (cancellationToken, null, "RENAME %F %S\r\n", this, encodedName);
 			var oldFullName = FullName;


Search query new minimum of 2 characters.

--- TeacherPouch.Web/Controllers/SearchController.cs
+++ TeacherPouch.Web/Controllers/SearchController.cs
@@ -1,10 +1,9 @@
 using System;
 using System.Web.Mvc;

+using TeacherPouch.Models;
+using TeacherPouch.Providers;
 using TeacherPouch.Repositories;
-using TeacherPouch.Utilities.Extensions;
-using TeacherPouch.Providers;
-using TeacherPouch.Models;

 namespace TeacherPouch.Web.Controllers
 {
@@ -19,7 +18,7 @@
         // GET: /Search?q=spring&op=and
         public virtual ViewResult Search(string q, string op)
         {
-            if (String.IsNullOrWhiteSpace(q) || q.Length <= 2)
+            if (String.IsNullOrWhiteSpace(q) || q.Length < 2)
                 return base.View(Views.NoneFound);

             ViewBag.SearchTerm = q;


Compiler error.

Compiler error.

--- Tests/Cosmos.Compiler.Tests.Exceptions/Kernel.cs
+++ Tests/Cosmos.Compiler.Tests.Exceptions/Kernel.cs
@@ -104,7 +104,7 @@
             {
                 TestReturnSimpleException();
             }
-            catch (Exception ex) where (xShouldCatch == true)
+            catch (Exception ex) when (xShouldCatch == true)
             {
                 Console.WriteLine("Caught filtered exception.");
                 mDebugger.Send("EXCEPTION: " + ex.Message);
@@ -136,7 +136,7 @@
             {
                 TestReturnSimpleException();
             }
-            catch (Exception ex) where (xShouldCatch == true)
+            catch (Exception ex) when (xShouldCatch == true)
             {
                 Console.WriteLine("Caught filtered exception.");
                 mDebugger.Send("EXCEPTION: " + ex.Message);


Fixed tests that were out of date

Fixed tests that were out of date

--- Tests/Datasource/Datasources/RandomDatasource.cs
+++ Tests/Datasource/Datasources/RandomDatasource.cs
@@ -1,10 +1,6 @@
-using System;
-using System.Collections.Generic;
-using Manufacturing.DataCollector;
+using Manufacturing.DataCollector;
 using Manufacturing.DataCollector.Datasources.Simulation;
-using Manufacturing.Framework.Utility;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;

 namespace Manufacturing.Framework.Datasource.Datasources
 {
@@ -14,14 +10,12 @@
         [TestMethod]
         public void StartRead_CreatesValue()
         {
-            var timer = new Mock<ITimer>();
             var config = new DataCollectorConfiguration
             {
-                RandomDatasourceIntervalSeconds = 30,
                 RandomDatasourceMin = 10,
                 RandomDatasourceMax = 20
             };
-            var r = new RandomDatasource(timer.Object, config);
+            var r = new RandomDatasource(config);

             DataReceivedEventArgs<decimal> args = null;
             r.DataReceived += (s, a) => args = a;
@@ -30,30 +24,5 @@
             Assert.IsTrue(args.Value > 10);
             Assert.IsTrue(args.Value < 20);
         }
-
-        [TestMethod]
-        public void TimerFireCreatesValue()
-        {
-            var timer = new Mock<ITimer>();
-            var config = new DataCollectorConfiguration
-            {
-                RandomDatasourceIntervalSeconds = 30,
-                RandomDatasourceMin = 10,
-                RandomDatasourceMax = 20
-            };
-            var r = new RandomDatasource(timer.Object, config);
-
-            var argsList = new List<DataReceivedEventArgs<decimal>>();
-            r.DataReceived += (s, a) => argsList.Add(a);
-
-            Assert.AreEqual(0, argsList.Count);
-            timer.Raise(x => x.Tick += null, null, null);
-            Assert.AreEqual(1, argsList.Count);
-            timer.Raise(x => x.Tick += null, null, null);
-            Assert.AreEqual(2, argsList.Count);
-
-            Assert.IsTrue(argsList[0].Value > 10);
-            Assert.IsTrue(argsList[1].Value < 20);
-        }
     }
 }


Adding children tasks has not been implemented

--- Tests/System/Threading/Tasks/MinimalTaskTests.cs
+++ Tests/System/Threading/Tasks/MinimalTaskTests.cs
@@ -528,6 +528,7 @@
         [Test]
         public void DenyChildAttachTest()
         {
+            Assert.Fail();
             var mre = new ManualResetEventSlim();
             Task nested = null;
             Task parent = Task.Factory.StartNew(() => {


Removing the file cache from the constructor (this won't deploy, or even run locally unless the user has very special permissions).

It would be possible to use a Session cache (as there is a user), but not a file cache

--- TodoListWebApp/Controllers/TodoListController.cs
+++ TodoListWebApp/Controllers/TodoListController.cs
@@ -65,7 +65,7 @@
         private static string todoListBaseAddress = ConfigurationManager.AppSettings["todo:TodoListBaseAddress"];

         private static HttpClient httpClient = new HttpClient();
-        private static AuthenticationContext authContext = new AuthenticationContext(authority, new FileCache());
+        private static AuthenticationContext authContext = new AuthenticationContext(authority /*, new FileCache()*/);
         private static ClientCredential clientCredential = new ClientCredential(clientId, appKey);

         private const string TenantIdClaimType = "http://schemas.microsoft.com/identity/claims/tenantid";


Fix formatting

Fix formatting

--- MaxMind.GeoIP2/Model/Traits.cs
+++ MaxMind.GeoIP2/Model/Traits.cs
@@ -92,7 +92,7 @@
             bool isPublicProxy,
             bool isResidentialProxy,
             bool isSatelliteProvider,
-             bool isTorExitNode,
+            bool isTorExitNode,
             string? isp,
             string? organization,
             string? userType,


MeidoCommon: Add another arg getting method

This one is kinda niche, but I do have one plugin that has need of it.

--- MeidoCommon/Parsing/GetArgs.cs
+++ MeidoCommon/Parsing/GetArgs.cs
@@ -78,6 +78,28 @@
             }

             return argv.Skip(skipCount);
+        }
+
+
+        public static IEnumerable<string> GetEndArg(this IIrcMsg msg, out string argument)
+        {
+            if (msg == null)
+                throw new ArgumentNullException(nameof(msg));
+
+            return GetEndArg(SkipTrigger(msg), out argument);
+        }
+
+        public static IEnumerable<string> GetEndArg(this IEnumerable<string> argv, out string argument)
+        {
+            if (argv == null)
+                throw new ArgumentNullException(nameof(argv));
+
+            // Quick and dirty, but I suppose this is good enough for the small
+            // sequences we're dealing with.
+            return
+                argv.Reverse()
+                .GetArg(out argument)
+                .Reverse();
         }


Add work-around for BL-422, where the editing model is trying to update, but there is no currently-displayed book.

--- src/BloomExe/Edit/EditingModel.cs
+++ src/BloomExe/Edit/EditingModel.cs
@@ -538,6 +538,14 @@
 		{
 			System.Windows.Forms.Application.Idle -= OnIdleAfterDocumentSupposedlyCompleted;

+			//Work-around for BL-422: https://jira.sil.org/browse/BL-422
+			if (_currentlyDisplayedBook == null)
+			{
+				Debug.Fail(
+					"Debug Only: BL-422 reproduction (currentlyDisplayedBook was null in OnIdleAfterDocumentSupposedlyCompleted).");
+				Logger.WriteEvent("BL-422 happened just now (currentlyDisplayedBook was null in OnIdleAfterDocumentSupposedlyCompleted).");
+				return;
+			}
 			// listen for events raised by javascript
 			_view.AddMessageEventListener("saveAccordionSettingsEvent", SaveAccordionSettings);
 			_view.AddMessageEventListener("openTextsFolderEvent", OpenTextsFolder);


Added todo.

Added todo.

--- Migrations/MigrationService.cs
+++ Migrations/MigrationService.cs
@@ -10,7 +10,7 @@
     public class MigrationService
     {
         private IVersionDataSource versionDataSource;
-        public List<IMigration> Migrations {get;set;}
+        public List<IMigration> Migrations { get; set; }

         private const string TRACE_SWITCH_NAME = "Migrations";
         private static TraceSwitch ts = new TraceSwitch(TRACE_SWITCH_NAME, String.Empty);
@@ -35,7 +35,7 @@
         {
             int schemaVersion = this.versionDataSource.GetVersionNumber();
             Predicate<IMigration> results = delegate(IMigration migration)
-            {
+            {
                 MigrationAttribute atr = GetMigrationsAttributes(migration);
                 if (atr != null)
                 {
@@ -43,7 +43,7 @@
                     return atr.Version <= schemaVersion;
                 }

-                return false;
+                return false;
             };

             return results;
@@ -53,7 +53,7 @@
         {
             int schemaVersion = this.versionDataSource.GetVersionNumber();
             Predicate<IMigration> results = delegate(IMigration migration)
-            {
+            {
                 MigrationAttribute atr = GetMigrationsAttributes(migration);
                 if (atr != null)
                 {
@@ -65,7 +65,7 @@
                     return atr.Version > versionTo && atr.Version <= schemaVersion;
                 }

-                return false;
+                return false;
             };

             return results;
@@ -235,6 +235,7 @@
                 if (predicate.Invoke(migration))
                 {
                     action.Invoke(migration); // Action to invoke on migration
+                    // TODO: It might be nice to keep track of the last migration that ran, and if any migrations are skipped, emit a warning.
                 }
             }

@@ -243,7 +244,7 @@
             Trace.Unindent();
         }

-        public void LoadMigrationsFromAssembly(Assembly asm, params object [] args)
+        public void LoadMigrationsFromAssembly(Assembly asm, params object[] args)
         {
             Trace.WriteLineIf(ts.TraceInfo, "MigrationService - LoadMigrationsFromAssembly() - Start");
             Trace.WriteLineIf(ts.TraceInfo, "MigrationService - LoadMigrationsFromAssembly() - Assembly: " + asm.FullName);
@@ -292,7 +293,7 @@

             Trace.Unindent();
             Trace.WriteLineIf(ts.TraceInfo, "MigrationService - LoadMigrationsFromAssembly() - End");
-        }
+        }

         public static MigrationAttribute GetMigrationsAttributes(IMigration migration)
         {


used existing JSON library to greatly simplify things

--- src/BloomExe/Edit/EditingModel.cs
+++ src/BloomExe/Edit/EditingModel.cs
@@ -860,14 +860,6 @@
 			_view.SetModalState(isModal == "true");
 			if (isModal != "true")
 				_addPageDialogShowing = false;
-		}
-
-		private static string CleanUpDataForJavascript(string data)
-		{
-			// We need to escape backslashes and quotes so the whole content arrives intact.
-			// Backslash first so the ones we insert for quotes don't get further escaped.
-			// Since the input is going to be processed as a string literal in JavaScript, it also can't contain real newlines.
-			return data.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "\\r").Replace("\n", "\\n");
 		}

 		private string MakeAccordionContent()
@@ -1196,25 +1188,27 @@
 			}
 		}

+		private string GetJsonTemplatePageObject
+		{
+			get
+			{
+				var addPageSettings = new Dictionary<string, object>();
+				var folderPath = MassageUrlForJavascript(Path.GetDirectoryName(GetPathToCurrentTemplateHtml));
+				addPageSettings.Add("templateBookFolderUrl", folderPath);
+				var htmlFilePath = MassageUrlForJavascript(GetPathToCurrentTemplateHtml);
+				addPageSettings.Add("templateBookUrl", htmlFilePath);
+				addPageSettings.Add("lastPageAdded", _lastPageAdded);
+				var settingsString = JsonConvert.SerializeObject(new object[] {addPageSettings});
+				return settingsString;
+			}
+		}
+
 		private const string URL_PREFIX = "/bloom/localhost/";
-		private const string JSON_START = "[{ ";
-		private const string JSON_DIVIDER = " , ";
-		private const string JSON_END = " }]";
-
-		private string GetJsonTemplatePageObject
-		{
-			get
-			{
-				var folderPath = Path.GetDirectoryName(GetPathToCurrentTemplateHtml);
-				folderPath = URL_PREFIX + folderPath.Replace(':', '$').Replace('\\', '/');
-				var jsonBookFolder = "\"templateBookFolderUrl\": \"" + folderPath + "\"";
-				var htmlFilePath = URL_PREFIX + GetPathToCurrentTemplateHtml;
-				htmlFilePath = htmlFilePath.Replace(':', '$').Replace('\\', '/');
-				var jsonBook = "\"templateBookUrl\": \"" + htmlFilePath + "\"";
-				var jsonLastPage = "\"lastPageAdded\": \"" + _lastPageAdded + "\"";
-				var jsonString = JSON_START + jsonBookFolder + JSON_DIVIDER + jsonBook + JSON_DIVIDER + jsonLastPage + JSON_END;
-				return jsonString;
-			}
+
+		private static string MassageUrlForJavascript(string url)
+		{
+			var newUrl = URL_PREFIX + url;
+			return newUrl.Replace(':', '$').Replace('\\', '/');
 		}
 	}


Fixed wrong text in error message resource file

--- src/CommandLineParser/Messages.cs
+++ src/CommandLineParser/Messages.cs
@@ -94,7 +94,7 @@

         public static string GROUP_ALL_USED = "All of these arguments: {0} must be used.";

-        public static string GROUP_AT_LEAST_ONE_USED = "Only one of these arguments: {0} can be used.";
+        public static string GROUP_AT_LEAST_ONE_USED = "At least one of these arguments: {0} must be used.";

         public static string GROUP_EXACTLY_ONE_USED = "One (and only one) of these arguments: {0} must be used.";


Fix to cert expiration

Fix to cert expiration

--- Utilities/Security/ClientCertificateWebClient.cs
+++ Utilities/Security/ClientCertificateWebClient.cs
@@ -50,7 +50,7 @@
 				// If we have a time-valid self-signed or untrusted cert use it
 				foreach (var cert in certs)
 				{
-					if (cert.NotAfter < DateTime.UtcNow && cert.NotBefore < DateTime.UtcNow)
+					if (cert.NotAfter > DateTime.UtcNow && cert.NotBefore < DateTime.UtcNow)
 					{
 						Certificate = cert;
 						return;


Form1

--- VerticesToCenter/ButtonOptionVerticesToCenter.cs
+++ VerticesToCenter/ButtonOptionVerticesToCenter.cs
@@ -44,8 +44,8 @@
             //
             //  TODO: Sample code showing how to access button host
             //
-            //FormOptionVerticesToCenter formVCOption = new FormOptionVerticesToCenter();
-            //formVCOption.Show();
+            FormOptionVerticesToCenter formVCOption = new FormOptionVerticesToCenter();
+            formVCOption.Show();
         }
         protected override void OnUpdate()
         {


turn wheels into spheres

turn wheels into spheres

I don't think cylinders is an option currently. The thing seems to roll
:D

--- Voxalia/ServerGame/EntitySystem/VehicleEntity.cs
+++ Voxalia/ServerGame/EntitySystem/VehicleEntity.cs
@@ -50,6 +50,7 @@
                             wheel.Gravity = Gravity;
                             wheel.CGroup = CGroup;
                             wheel.SetMass(5);
+                            wheel.mode = ModelCollisionMode.SPHERE;
                             TheWorld.SpawnEntity(wheel);
                             // TODO: better joints
                             JointBallSocket jbs = new JointBallSocket(this, wheel, pos);


Fix build

Fix build

--- WalletWasabi/WebClients/ExchangeRateProviders.cs
+++ WalletWasabi/WebClients/ExchangeRateProviders.cs
@@ -22,8 +22,8 @@
 			new CoinGeckoExchangeRateProvider(),
 			new CoinbaseExchangeRateProvider(),
 			new GeminiExchangeRateProvider(),
-			new ItBitExchangeRateProvider()
-			new SmartBitExchangeRateProvider(new SmartBitClient(Network.Main)),
+			new ItBitExchangeRateProvider(),
+			new SmartBitExchangeRateProvider(new SmartBitClient(Network.Main))
 		};

 		public async Task<List<ExchangeRate>> GetExchangeRateAsync()


Removed async compile warning

Removed async compile warning

--- Watsonia.Data.SQLite/SQLiteDataAccessProvider.cs
+++ Watsonia.Data.SQLite/SQLiteDataAccessProvider.cs
@@ -55,20 +55,21 @@
 		/// Ensures that the database is deleted.
 		/// </summary>
 		/// <param name="configuration">The configuration options used for mapping to and accessing the database.</param>
-		public async Task EnsureDatabaseDeletedAsync(DatabaseConfiguration configuration)
+		public Task EnsureDatabaseDeletedAsync(DatabaseConfiguration configuration)
 		{
 			var connectionBuilder = new SqliteConnectionStringBuilder(configuration.ConnectionString);
 			if (File.Exists(connectionBuilder.DataSource))
 			{
 				File.Delete(connectionBuilder.DataSource);
 			}
+			return Task.FromResult(0);
 		}

 		/// <summary>
 		/// Ensures that the database is created.
 		/// </summary>
 		/// <param name="configuration">The configuration options used for mapping to and accessing the database.</param>
-		public async Task EnsureDatabaseCreatedAsync(DatabaseConfiguration configuration)
+		public Task EnsureDatabaseCreatedAsync(DatabaseConfiguration configuration)
 		{
 			var connectionBuilder = new SqliteConnectionStringBuilder(configuration.ConnectionString);
 			if (!File.Exists(connectionBuilder.DataSource))
@@ -77,6 +78,7 @@
 				var fs = File.Create(connectionBuilder.DataSource);
 				fs.Close();
 			}
+			return Task.FromResult(0);
 		}

 		/// <summary>


Delete test which doesn't seem to be adding much value (and is failing because mstest template targets .NET Core 2.2)

--- test/dotnet-new.Tests/GivenThatIWantANewApp.cs
+++ test/dotnet-new.Tests/GivenThatIWantANewApp.cs
@@ -35,43 +35,5 @@

             result.Should().Fail();
         }
-
-        [Fact]
-        public void RestoreDoesNotUseAnyCliProducedPackagesOnItsTemplates()
-        {
-            string[] cSharpTemplates = new[] { "console", "classlib", "mstest", "xunit", "web", "mvc", "webapi" };
-
-            var rootPath = TestAssets.CreateTestDirectory().FullName;
-            var packagesDirectory = Path.Combine(rootPath, "packages");
-
-            var configFile = Path.Combine(RepoDirectoriesProvider.RepoRoot, "NuGet.Config");
-
-            foreach (string cSharpTemplate in cSharpTemplates)
-            {
-                var projectFolder = Path.Combine(rootPath, cSharpTemplate + "1");
-                Directory.CreateDirectory(projectFolder);
-                CreateAndRestoreNewProject(cSharpTemplate, projectFolder, packagesDirectory, configFile);
-            }
-
-            Directory.EnumerateFiles(packagesDirectory, $"*.nupkg", SearchOption.AllDirectories)
-                .Should().NotContain(p => p.Contains("Microsoft.DotNet.Cli.Utils"));
-        }
-
-        private void CreateAndRestoreNewProject(
-            string projectType,
-            string projectFolder,
-            string packagesDirectory,
-            string configFile)
-        {
-            new NewCommand()
-                .WithWorkingDirectory(projectFolder)
-                .Execute($"{projectType} --debug:ephemeral-hive --no-restore")
-                .Should().Pass();
-
-            new RestoreCommand()
-                .WithWorkingDirectory(projectFolder)
-                .Execute($"--configfile {configFile} --packages {packagesDirectory}")
-                .Should().Pass();
-        }
     }
 }


Quote package sources that contain spaces (#943)

* Escape uris that contain spaces
cannot apply Uri.EscapeUriString blinbdly, or it will double-escape already escaped strings
For https://github.com/NuKeeperDotNet/NuKeeper/issues/942

* escape with ""

* Use `ArgumentEscaper.EscapeAndConcatenate` which will wrap in quotes if need be
And is generally more detailed and robust than what I  did
see https://github.com/natemcmaster/CommandLineUtils/blob/master/src/CommandLineUtils/Utilities/ArgumentEscaper.cs

Co-authored-by: Anthony Steele <5121b98bafbcdca593a0e3f01dedec84888d9f6d@pockit.com>

--- NuKeeper.Update/Process/DotNetUpdatePackageCommand.cs
+++ NuKeeper.Update/Process/DotNetUpdatePackageCommand.cs
@@ -1,4 +1,6 @@
+using System;
 using System.Threading.Tasks;
+using McMaster.Extensions.CommandLineUtils;
 using NuGet.Configuration;
 using NuGet.Versioning;
 using NuKeeper.Abstractions.NuGet;
@@ -21,7 +23,7 @@
         {
             var projectPath = currentPackage.Path.Info.DirectoryName;
             var projectFileName = currentPackage.Path.Info.Name;
-            var sourceUrl = packageSource.SourceUri.ToString();
+            var sourceUrl = UriEscapedForArgument(packageSource.SourceUri);
             var sources = allSources.CommandLine("-s");

             var restoreCommand = $"restore {projectFileName} {sources}";
@@ -36,5 +38,15 @@
             var addCommand = $"add {projectFileName} package {currentPackage.Id} -v {newVersion} -s {sourceUrl}";
             await _externalProcess.Run(projectPath, "dotnet", addCommand, true);
         }
+
+        private static string UriEscapedForArgument(Uri uri)
+        {
+            if (uri == null)
+            {
+                return string.Empty;
+            }
+
+            return ArgumentEscaper.EscapeAndConcatenate(new string[] { uri.ToString() });
+        }
     }
 }


Use a rectangle to make the crop selection clearer

--- OpenKh.Tools.LayoutEditor/Dialogs/SpriteEditDialog.cs
+++ OpenKh.Tools.LayoutEditor/Dialogs/SpriteEditDialog.cs
@@ -4,6 +4,7 @@
 using OpenKh.Kh2;
 using OpenKh.Tools.LayoutEditor.Interfaces;
 using OpenKh.Tools.LayoutEditor.Models;
+using SharpDX.Direct2D1.Effects;
 using System;
 using System.Numerics;

@@ -55,7 +56,7 @@
                 _spriteModel.Sprite.Right, _spriteModel.Sprite.Bottom
             };

-            ImGui.Columns(4);
+            ImGui.Columns(4, "ltrb", false);
             bool sourceChanged = ImGui.DragInt("UA", ref source[0]); ImGui.NextColumn();
             sourceChanged |= ImGui.DragInt("VA", ref source[1]); ImGui.NextColumn();
             sourceChanged |= ImGui.DragInt("UB", ref source[2]); ImGui.NextColumn();
@@ -110,6 +111,9 @@
             var sBottom = _spriteModel.Sprite.Bottom;
             var cropColor = _settings.EditorBackground;
             cropColor.A = 0.75f;
+            var invertedCropColor = new ColorF(
+                1f - cropColor.R, 1f - cropColor.G,
+                1f - cropColor.G, 1.0f);

             var context = new SpriteDrawingContext()
                 .SpriteTexture(_atlasTexture)
@@ -129,6 +133,8 @@
             _spriteDrawing.FillRectangle(0, sTop, sLeft, sBottom - sTop, cropColor);
             _spriteDrawing.FillRectangle(sRight, sTop, _cropAtlasTexture.Width, sBottom - sTop, cropColor);
             _spriteDrawing.FillRectangle(0, sBottom, _cropAtlasTexture.Width, _cropAtlasTexture.Height, cropColor);
+            _spriteDrawing.DrawRectangle(sLeft - 1, sTop - 1,
+                sRight - sLeft + 2, sBottom - sTop + 2, invertedCropColor);

             _spriteDrawing.Flush();
             _spriteDrawing.DestinationTexture = null;