private static NotifyCollectionChangedEventHandler ValueCollectionChanged(params object[] path) { return((sender, e) => { IList senderList = (IList)sender; OnPropertyPathChanged?.Invoke(path, PropertyPathChangeType.ValueCollection, senderList); }); }
/// <summary> /// Function to generate a property change handler for model dictionaries /// </summary> /// <param name="path">Property path</param> /// <returns>Property change handler</returns> private static PropertyChangedEventHandler DictionaryChanged(object[] path) { return((sender, e) => { object value = sender.GetType().GetProperty("Item").GetValue(sender, new object[] { e.PropertyName }); OnPropertyPathChanged?.Invoke(AddToPath(path, e.PropertyName), PropertyChangeType.Property, value); }); }
/// <summary> /// Function to generate a value collection change handler /// </summary> /// <param name="collectionName">Name of the collection</param> /// <param name="path">Collection path</param> /// <returns>Property change handler</returns> private static NotifyCollectionChangedEventHandler ValueCollectionChanged(string collectionName, params object[] path) { object[] collectionPath = AddToPath(path, collectionName); return((sender, e) => { IList senderList = (IList)sender; OnPropertyPathChanged?.Invoke(collectionPath, PropertyChangeType.Property, senderList); }); }
private static PropertyChangedEventHandler PropertyChanged(params object[] path) { return((sender, e) => { string propertyName = JsonNamingPolicy.CamelCase.ConvertName(e.PropertyName); object value = sender.GetType().GetProperty(e.PropertyName).GetValue(sender); OnPropertyPathChanged?.Invoke(AddToPath(path, propertyName), PropertyPathChangeType.Property, value); }); }
private static NotifyCollectionChangedEventHandler GrowingCollectionChanged(params object[] path) { return((sender, e) => { if (e.Action == NotifyCollectionChangedAction.Add) { OnPropertyPathChanged?.Invoke(path, PropertyPathChangeType.GrowingCollection, e.NewItems); } else if (e.Action == NotifyCollectionChangedAction.Reset) { OnPropertyPathChanged?.Invoke(path, PropertyPathChangeType.GrowingCollection, null); } }); }
/// <summary> /// Function to generate a property change handler /// </summary> /// <param name="hasVariableModelObjects">Whether this instance has any variable model objects</param> /// <param name="path">Property path</param> /// <returns>Property change handler</returns> private static PropertyChangedEventHandler PropertyChanged(bool hasVariableModelObjects, object[] path) { return((sender, e) => { string propertyName = JsonNamingPolicy.CamelCase.ConvertName(e.PropertyName); object value = sender.GetType().GetProperty(e.PropertyName).GetValue(sender); OnPropertyPathChanged?.Invoke(AddToPath(path, propertyName), PropertyChangeType.Property, value); if (hasVariableModelObjects && value is ModelObject modelMember) { // Subscribe to variable ModelObject events again SubscribeToModelObject(modelMember, AddToPath(path, propertyName)); } }); }
/// <summary> /// Creates a new event change handler for dictionaries /// </summary> /// <typeparam name="Ta">Key type</typeparam> /// <typeparam name="Tb">Value type</typeparam> /// <param name="path">Path to the dictionary</param> /// <returns>Change handler</returns> private static NotifyCollectionChangedEventHandler DictionaryChanged <Ta, Tb>(params object[] path) { return((sender, e) => { if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace) { foreach (var item in e.NewItems) { KeyValuePair <Ta, Tb> kv = (KeyValuePair <Ta, Tb>)item; OnPropertyPathChanged?.Invoke(AddToPath(path, kv.Key), PropertyChangeType.Property, kv.Value); } } else if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset) { foreach (var item in e.OldItems) { KeyValuePair <Ta, Tb> kv = (KeyValuePair <Ta, Tb>)item; OnPropertyPathChanged?.Invoke(AddToPath(path, kv.Key), PropertyChangeType.Property, null); } } }); }
/// <summary> /// Function to generate an object collection change handler /// </summary> /// <param name="collectionName">Name of the collection</param> /// <param name="path">Collection path</param> /// <returns>Property change handler</returns> private static NotifyCollectionChangedEventHandler ObjectCollectionChanged(string collectionName, params object[] path) { return((sender, e) => { // Notify clients that something has been changed in this collection IList senderList = (IList)sender; // Unsubscribe from old items, subscribe to new items, and figure out which items need to be patched bool[] itemNeedsPatch = new bool[senderList.Count]; object[] nodePath; switch (e.Action) { case NotifyCollectionChangedAction.Add: if (e.NewStartingIndex == senderList.Count - 1) { // Item added itemNeedsPatch[e.NewStartingIndex] = true; } else { // Item inserted for (int i = e.NewStartingIndex; i < senderList.Count; i++) { itemNeedsPatch[i] = true; } } nodePath = AddToPath(path, new ItemPathNode(collectionName, e.NewStartingIndex, senderList)); SubscribeToModelObject((ModelObject)e.NewItems[0], nodePath); break; case NotifyCollectionChangedAction.Move: for (int i = Math.Min(e.OldStartingIndex, e.NewStartingIndex); i <= Math.Max(e.OldStartingIndex, e.NewStartingIndex); i++) { itemNeedsPatch[i] = true; } break; case NotifyCollectionChangedAction.Replace: itemNeedsPatch[e.NewStartingIndex] = true; UnsubscribeFromModelObject((ModelObject)e.OldItems[0]); nodePath = AddToPath(path, new ItemPathNode(collectionName, e.NewStartingIndex, senderList)); SubscribeToModelObject((ModelObject)e.NewItems[0], nodePath); break; case NotifyCollectionChangedAction.Remove: for (int i = Math.Max(0, e.OldStartingIndex); i < senderList.Count; i++) { itemNeedsPatch[i] = true; } foreach (object item in e.OldItems) { UnsubscribeFromModelObject((ModelObject)item); } nodePath = AddToPath(path, new ItemPathNode(collectionName, senderList.Count, senderList)); OnPropertyPathChanged?.Invoke(nodePath, PropertyChangeType.ObjectCollection, null); break; case NotifyCollectionChangedAction.Reset: // This is NOT used because e.OldItems is not populated... break; } // Tell clients what items need to be patched for (int i = 0; i < senderList.Count; i++) { if (itemNeedsPatch[i]) { nodePath = AddToPath(path, new ItemPathNode(collectionName, i, senderList)); OnPropertyPathChanged?.Invoke(nodePath, PropertyChangeType.ObjectCollection, senderList[i]); } } }); }
private static NotifyCollectionChangedEventHandler ObjectCollectionChanged(params object[] path) { return((sender, e) => { IList senderList = (IList)sender; OnPropertyPathChanged?.Invoke(path, PropertyPathChangeType.ObjectCollection, senderList.Count); if (e.OldItems != null) { foreach (object oldItem in e.OldItems) { UnregisterItemPropertyChanged(oldItem); if (oldItem is ExpansionBoard board) { UnregisterItemPropertyChanged(board.Firmware); UnregisterItemPropertyChanged(board.VIn); UnregisterItemPropertyChanged(board.McuTemp); } else if (oldItem is Fan fan) { UnregisterItemPropertyChanged(fan.Thermostatic); } else if (oldItem is BedOrChamber bedOrChamber) { UnregisterItemPropertyChanged(bedOrChamber.Heaters); UnregisterItemPropertyChanged(bedOrChamber.Active); UnregisterItemPropertyChanged(bedOrChamber.Standby); } else if (oldItem is Heater heater) { UnregisterItemPropertyChanged(heater.Model); } else if (oldItem is Axis axis) { UnregisterItemPropertyChanged(axis.Drives); } else if (oldItem is Extruder extruder) { UnregisterItemPropertyChanged(extruder.Drives); } else if (oldItem is Drive drive) { UnregisterItemPropertyChanged(drive.Microstepping); } else if (oldItem is Probe probe) { UnregisterItemPropertyChanged(probe.SecondaryValues); UnregisterItemPropertyChanged(probe.Offsets); } else if (oldItem is Tool tool) { UnregisterItemPropertyChanged(tool.Active); UnregisterItemPropertyChanged(tool.Standby); UnregisterItemPropertyChanged(tool.Fans); UnregisterItemPropertyChanged(tool.Heaters); UnregisterItemPropertyChanged(tool.Extruders); UnregisterItemPropertyChanged(tool.Mix); UnregisterItemPropertyChanged(tool.Axes); UnregisterItemPropertyChanged(tool.Offsets); } } } if (e.NewItems != null) { foreach (object newItem in e.NewItems) { int index = senderList.IndexOf(newItem); RegisterItemPropertyChanged(path, newItem, index, senderList); if (newItem is ExpansionBoard board) { RegisterItemPropertyChanged(path, board.Firmware, index, senderList, "firmware"); RegisterItemPropertyChanged(path, board.Firmware, index, senderList, "vIn"); RegisterItemPropertyChanged(path, board.Firmware, index, senderList, "mcuTemp"); } else if (newItem is Fan fan) { RegisterItemPropertyChanged(path, fan.Thermostatic, index, senderList, "thermostatic"); } else if (newItem is BedOrChamber bedOrChamber) { RegisterItemPropertyChanged(path, bedOrChamber.Active, index, senderList, "active"); RegisterItemPropertyChanged(path, bedOrChamber.Standby, index, senderList, "standby"); RegisterItemPropertyChanged(path, bedOrChamber.Heaters, index, senderList, "heaters"); } else if (newItem is Heater heater) { RegisterItemPropertyChanged(path, heater.Model, index, senderList, "model"); } else if (newItem is Axis axis) { RegisterItemPropertyChanged(path, axis.Drives, index, senderList, "drives"); } else if (newItem is Extruder extruder) { RegisterItemPropertyChanged(path, extruder.Drives, index, senderList, "drives"); } else if (newItem is Drive drive) { RegisterItemPropertyChanged(path, drive.Microstepping, index, senderList, "microstepping"); } else if (newItem is Probe probe) { RegisterItemPropertyChanged(path, probe.SecondaryValues, index, senderList, "secondaryValues"); RegisterItemPropertyChanged(path, probe.Offsets, index, senderList, "offsets"); } else if (newItem is Tool tool) { RegisterItemPropertyChanged(path, tool.Active, index, senderList, "active"); RegisterItemPropertyChanged(path, tool.Standby, index, senderList, "standby"); RegisterItemPropertyChanged(path, tool.Fans, index, senderList, "fans"); RegisterItemPropertyChanged(path, tool.Heaters, index, senderList, "heaters"); RegisterItemPropertyChanged(path, tool.Extruders, index, senderList, "extruders"); RegisterItemPropertyChanged(path, tool.Mix, index, senderList, "mix"); RegisterItemPropertyChanged(path, tool.Axes, index, senderList, "axes"); RegisterItemPropertyChanged(path, tool.Offsets, index, senderList, "offsets"); } } } }); }
/// <summary> /// Notify subscribers that the list of global variables has been reset /// </summary> public static void GlobalVariablesCleared() { string jsonName = JsonNamingPolicy.CamelCase.ConvertName(nameof(ObjectModel.Global)); OnPropertyPathChanged?.Invoke(new object[] { jsonName }, PropertyChangeType.Property, null); }