/// <summary> /// Performs custom actions on validation Ending events</summary> /// <param name="sender">Validation context</param> /// <param name="e">Event args</param> protected override void OnEnding(object sender, EventArgs e) { var referenceValidator = DomNode.Cast<ReferenceValidator>(); referenceValidator.Suspended = false; if (m_undoingOrRedoing) { foreach (var subgraph in m_subGraphs.Where(x => x.Dirty).OrderByDescending(s => s.Level)) { subgraph.Dirty = false; // just reset Dirty flag foreach (var wire in subgraph.Wires) { // reset pin target wire.InputPinTarget = null; wire.OutputPinTarget = null; } subgraph.UpdateGroupPinInfo(); subgraph.OnChanged(EventArgs.Empty); // but notify the change } foreach (var circuit in m_circuits) { foreach (var wire in circuit.Wires) { // reset pin target wire.InputPinTarget = null; wire.OutputPinTarget = null; } circuit.Dirty = false; } return; } var containersToCheck = new List<ICircuitContainer>(); containersToCheck.AddRange(m_subGraphs.Where(g => g.Dirty).AsIEnumerable<ICircuitContainer>()); containersToCheck.AddRange(m_circuits.Where(g => g.Dirty).AsIEnumerable<ICircuitContainer>()); while (m_subGraphs.Any(n => n.Dirty) || m_circuits.Any(n => n.Dirty)) { // inner subgraphs updated first foreach (var subgraph in m_subGraphs.OrderByDescending(s => s.Level)) { subgraph.IgnoreFanInOut = MovingCrossContainer; subgraph.Update(); if (subgraph.IgnoreFanInOut) { subgraph.IgnoreFanInOut = false; subgraph.Dirty = true; } } UpdateWires(containersToCheck); MovingCrossContainer = false; foreach (var circuit in m_circuits) { circuit.Update(); } } // update group pin connectivity and other info from bottom up, for display purpose only foreach (var group in containersToCheck.AsIEnumerable<Group>().OrderByDescending(s => s.Level)) { group.UpdateGroupPinInfo(); } foreach (var subgraph in m_nodesInserted.Keys) { IEnumerable<Element> nodes = m_nodesInserted[subgraph]; if (nodes.Any()) { var viewingContext = subgraph.Cast<ViewingContext>(); if (viewingContext.Control != null) { var subGraphPinAdapter = viewingContext.Control.As<GroupPinEditor>(); if (subGraphPinAdapter != null) subGraphPinAdapter.AdjustLayout(nodes, EmptyEnumerable<GroupPin>.Instance, new Point(0, 0)); } } } }
/// <summary> /// Creates an array of property descriptors that are associated with the adapted DomNode's /// DomNodeType. No duplicates will be in the array (based on the property descriptor's Name /// property).</summary> /// <returns>Array of property descriptors</returns> protected override System.ComponentModel.PropertyDescriptor[] GetPropertyDescriptors() { // Initialize property desciptors with the ones from the base class // If this is not done, the new property descriptors would be used instead of // rather than in addition to the ones defined in the schema List<System.ComponentModel.PropertyDescriptor> descriptors = new List<System.ComponentModel.PropertyDescriptor>(base.GetPropertyDescriptors()); // Add ITransformable properties: // Translation, Rotation, Scale, RotatePivot, ScalePivot (if supported by this object) ITransformable node = this.Cast<ITransformable>(); TransformationTypes transformType = node.TransformationType; NumericTupleEditor tupleEditor = new NumericTupleEditor(typeof(float), new string[] { "x", "y", "z" }); NumericTupleEditor rotationTupleEditor = new NumericTupleEditor(typeof(float), new string[] { "x", "y", "z" }); rotationTupleEditor.ScaleFactor = 360 / (2 * Math.PI); // Radians to Degrees string category = "Transform".Localize(); // Check for transform types if ((transformType & TransformationTypes.Translation) != 0) descriptors.Add( new AttributePropertyDescriptor( "Translation", Schema.transformObjectType.translateAttribute, category, "Translation of Game Object along X, Y, and Z axes".Localize(), false, tupleEditor)); if ((transformType & TransformationTypes.Rotation) != 0) descriptors.Add(new AttributePropertyDescriptor( "Rotation".Localize(), Schema.transformObjectType.rotateAttribute, category, "Origin of Rotation transform relative to Game Object Translation".Localize(), false, rotationTupleEditor)); if ((transformType & TransformationTypes.Scale) != 0) { if ((transformType & TransformationTypes.UniformScale) == 0) descriptors.Add( new AttributePropertyDescriptor( "Scale".Localize(), Schema.transformObjectType.scaleAttribute, category, "Scale of Game Object along X, Y, and Z axes".Localize(), false, tupleEditor)); else descriptors.Add( new AttributePropertyDescriptor( "Uniform Scale".Localize(), Schema.transformObjectType.scaleAttribute, category, "Scale of Game Object uniformly along X, Y, and Z axes".Localize(), false, new UniformArrayEditor<Single>())); } if ((transformType & TransformationTypes.Pivot) != 0) descriptors.Add( new AttributePropertyDescriptor( "Pivot".Localize(), Schema.transformObjectType.pivotAttribute, category, "Origin of Rotation and scale transform relative to Game Object Translation".Localize(), false, tupleEditor)); // remove hidden properties HashSet<string> hiddenProps = (HashSet<string>)this.DomNode.Type.GetTag(SchemaLoader.HiddenProperties); if (hiddenProps != null) { List<PropertyDescriptor> removeList = new List<PropertyDescriptor>(); foreach (AttributePropertyDescriptor propdescr in descriptors.AsIEnumerable<AttributePropertyDescriptor>()) { if (hiddenProps.Contains(propdescr.AttributeInfo.Name)) { removeList.Add(propdescr); } } foreach (PropertyDescriptor propDescr in removeList) descriptors.Remove(propDescr); } return descriptors.ToArray(); }