/// <summary> /// Get all of the dependencies from a workspace /// </summary> /// <param name="workspace">The workspace to read the dependencies from</param> /// <param name="customNodeManager">A custom node manager to look up dependencies</param> /// <returns>A WorkspaceDependencies object containing the workspace and its CustomNodeWorkspaceModel dependencies</returns> public static WorkspaceDependencies Collect(HomeWorkspaceModel workspace, ICustomNodeManager customNodeManager) { if (workspace == null) throw new ArgumentNullException("workspace"); if (customNodeManager == null) throw new ArgumentNullException("customNodeManager"); // collect all dependencies var dependencies = new HashSet<CustomNodeDefinition>(); foreach (var node in workspace.Nodes.OfType<Function>()) { dependencies.Add(node.Definition); foreach (var dep in node.Definition.Dependencies) { dependencies.Add(dep); } } var customNodeWorkspaces = new List<ICustomNodeWorkspaceModel>(); foreach (var dependency in dependencies) { ICustomNodeWorkspaceModel customNodeWs; var workspaceExists = customNodeManager.TryGetFunctionWorkspace(dependency.FunctionId, false, out customNodeWs); if (!workspaceExists) { throw new InvalidOperationException(String.Format(Resources.CustomNodeDefinitionNotFoundErrorMessage, dependency.FunctionName)); } if (!customNodeWorkspaces.Contains(customNodeWs)) { customNodeWorkspaces.Add(customNodeWs); } } return new WorkspaceDependencies(workspace, customNodeWorkspaces); }
/// <summary> /// create a new presetsState, this will serialize all the referenced nodes by calling their serialize method, /// the resulting XML elements will be used to save this state when the presetModel is saved on workspace save /// </summary> /// <param name="name">name for the state, must not be null </param> /// <param name="description">description of the state, can be null</param> /// <param name="inputsToSave">set of nodeModels, must not be null</param> /// <param name="id">an id GUID, can be empty GUID</param> public PresetModel(string name, string description, IEnumerable<NodeModel> inputsToSave):base() { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (inputsToSave == null || inputsToSave.Count() < 1) { throw new ArgumentNullException("inputsToSave"); } Name = name; Description = description; nodes = inputsToSave.ToList(); var tempdoc = new XmlDocument(); serializedNodes = new List<XmlElement>(); foreach (var node in Nodes) { serializedNodes.Add(node.Serialize(tempdoc, SaveContext.Preset)); } }
public override Value Evaluate(FSharpList<Value> args) { CurveLoop firstLoop = (CurveLoop)((Value.Container)args[0]).Item; CurveLoop secondLoop = (CurveLoop)((Value.Container)args[1]).Item; List<VertexPair> vertPairs = null; if (dynRevitSettings.Revit.Application.VersionName.Contains("2013")) { vertPairs = new List<VertexPair>(); int i = 0; int nCurves1 = firstLoop.Count(); int nCurves2 = secondLoop.Count(); for (; i < nCurves1 && i < nCurves2; i++) { vertPairs.Add(new VertexPair(i, i)); } } var result = GeometryCreationUtilities.CreateBlendGeometry(firstLoop, secondLoop, vertPairs); solids.Add(result); return Value.NewContainer(result); }
public static Dictionary<string, object> GetCarbonNeutralPotential(RunResultSummary Results) { // Populate Carbon Neutral Potential data List<object> CO2Emission = new List<Object>(); CO2Emission.Add(Results.CarbonNeutralPotential.Units); CO2Emission.Add((double)Results.CarbonNeutralPotential.RunEmissions.Value); List<object> RenewablePotential = new List<object>(); RenewablePotential.Add(Results.CarbonNeutralPotential.Units); RenewablePotential.Add((double)Results.CarbonNeutralPotential.OnsiteRenewablePotentialEmissions.Value); List<object> NVentilationPotential = new List<object>(); NVentilationPotential.Add(Results.CarbonNeutralPotential.Units); NVentilationPotential.Add(Results.CarbonNeutralPotential.NaturalVentilationPotentialEmissions.Value); List<object> BiofuelUse = new List<object>(); BiofuelUse.Add(Results.CarbonNeutralPotential.Units); BiofuelUse.Add((double)Results.CarbonNeutralPotential.OnsiteBiofuelUseEmissions.Value); List<object> NetCO2Emission = new List<object>(); NetCO2Emission.Add(Results.CarbonNeutralPotential.Units); NetCO2Emission.Add((double)Results.CarbonNeutralPotential.NetCO2Emissions.Value); List<object> LargeSUV = new List<object>(); LargeSUV.Add(Results.CarbonNeutralPotential.NetLargeSUVEquivalent.Units); LargeSUV.Add((double)Results.CarbonNeutralPotential.NetLargeSUVEquivalent.Value); // Populate Outputs return new Dictionary<string, object> { {"Run CO2 Emission",CO2Emission}, {"Onsite Renewable Potential", RenewablePotential}, {"Natural Ventilation Potential",NVentilationPotential}, {"Onsite Biofuel Use",BiofuelUse}, {"Net CO2 Emission",NetCO2Emission}, {"Net Large SUV Equivalent", LargeSUV} }; }
private void PreUpdateModel(object dataItem) { // Attempt get to the data-bound model (if there's any). NodeModel nodeModel = dataItem as NodeModel; NoteModel noteModel = dataItem as NoteModel; if (null == nodeModel && (null == noteModel)) { NodeViewModel nodeViewModel = dataItem as NodeViewModel; if (null != nodeViewModel) nodeModel = nodeViewModel.NodeModel; else { // TODO(Ben): We temporary do not handle NoteModel here // because NoteView actively update the data-bound "Text" // property as user types, so when this method is called, // it will be too late to record the states before the // text change happened. // // NoteViewModel noteViewModel = dataItem as NoteViewModel; // if (null != noteViewModel) // noteModel = noteViewModel.Model; } } // If we do get a node/note, record it for undo. if (null != nodeModel || (null != noteModel)) { List<ModelBase> models = new List<ModelBase>(); if (null != nodeModel) models.Add(nodeModel); if (null != noteModel) models.Add(noteModel); DynamoModel dynamo = dynSettings.Controller.DynamoModel; dynamo.CurrentWorkspace.RecordModelsForModification(models); dynSettings.Controller.DynamoViewModel.UndoCommand.RaiseCanExecuteChanged(); dynSettings.Controller.DynamoViewModel.RedoCommand.RaiseCanExecuteChanged(); } }
/// <summary> /// Call this method to get a list of lists of variables defined in /// the given set of Statement objects. This method is typically used /// in conjunction with DoesStatementRequireOutputPort method. /// </summary> /// <param name="statements">A list of Statement objects whose defined /// variables are to be retrieved. This list can be empty but it cannot /// be null.</param> /// <param name="onlyTopLevel">Set this parameter to false to retrieve /// all variables defined in nested Statement objects.</param> /// <returns>Returns a list of lists of variables defined by the given /// set of Statement objects.</returns> /// public static IEnumerable<IEnumerable<string>> GetStatementVariables( IEnumerable<Statement> statements, bool onlyTopLevel) { if (statements == null) throw new ArgumentNullException("statements"); var definedVariables = new List<List<string>>(); foreach (var statement in statements) { definedVariables.Add(Statement.GetDefinedVariableNames( statement, onlyTopLevel)); } return definedVariables; }
internal RectangularSectionSinglyReinforced(double b, double h, double A_s, double c_cntr, ConcreteMaterial ConcreteMaterial, RebarMaterial LongitudinalRebarMaterial, bool hasTies=false) { CrossSectionRectangularShape shape = new CrossSectionRectangularShape(ConcreteMaterial.Concrete, null, b, h); base.ConcreteMaterial = ConcreteMaterial; //duplicate save of concrete material into base Dynamo class List<wosadAci.RebarPoint> LongitudinalBars = new List<wosadAci.RebarPoint>(); wosadAci.Rebar thisBar = new wosadAci.Rebar(A_s, LongitudinalRebarMaterial.Material); wosadAci.RebarPoint point = new wosadAci.RebarPoint(thisBar, new wosadAci.RebarCoordinate() { X = 0, Y = -h / 2.0 + c_cntr }); LongitudinalBars.Add(point); wosadAci.IConcreteFlexuralMember fs = new wosadAci14.ConcreteSectionFlexure(shape, LongitudinalBars, new CalcLog()); this.FlexuralSection = fs; }
public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args) { Element thisElement = (Element)((FScheme.Value.Container)args[0]).Item; instanceGeometryObjects = new List<GeometryObject>(); var result = FSharpList<FScheme.Value>.Empty; Autodesk.Revit.DB.Options geoOptionsOne = new Autodesk.Revit.DB.Options(); geoOptionsOne.ComputeReferences = true; GeometryObject geomObj = thisElement.get_Geometry(geoOptionsOne); GeometryElement geomElement = geomObj as GeometryElement; if ((thisElement is GenericForm) && (geomElement.Count() < 1)) { GenericForm gF = (GenericForm)thisElement; if (!gF.Combinations.IsEmpty) { Autodesk.Revit.DB.Options geoOptionsTwo = new Autodesk.Revit.DB.Options(); geoOptionsTwo.IncludeNonVisibleObjects = true; geoOptionsTwo.ComputeReferences = true; geomObj = thisElement.get_Geometry(geoOptionsTwo); geomElement = geomObj as GeometryElement; } } foreach (GeometryObject geob in geomElement) { GeometryInstance ginsta = geob as GeometryInstance; if (ginsta != null) { GeometryElement instanceGeom = ginsta.GetInstanceGeometry(); instanceGeometryObjects.Add(instanceGeom); foreach (GeometryObject geobInst in instanceGeom) { result = FSharpList<FScheme.Value>.Cons(FScheme.Value.NewContainer(geobInst), result); } } else { result = FSharpList<FScheme.Value>.Cons(FScheme.Value.NewContainer(geob), result); } } return FScheme.Value.NewList(result); }
protected override void BuildAstForPartialMultiOutput( NodeModel model, AssociativeNode rhs, List<AssociativeNode> resultAst) { base.BuildAstForPartialMultiOutput(model, rhs, resultAst); var emptyList = AstFactory.BuildExprList(new List<AssociativeNode>()); var previewIdInit = AstFactory.BuildAssignment(model.AstIdentifierForPreview, emptyList); resultAst.Add(previewIdInit); resultAst.AddRange( Definition.ReturnKeys.Select( (rtnKey, idx) => AstFactory.BuildAssignment( AstFactory.BuildIdentifier( model.AstIdentifierForPreview.Name, AstFactory.BuildStringNode(rtnKey)), model.GetAstIdentifierForOutputIndex(idx)))); }
public override Value Evaluate(FSharpList<Value> args) { var input = args[0]; var xi = ((Value.Number)args[1]).Item;// Number var x0 = ((Value.Number)args[2]).Item;// Starting Coord var xs = (SpacingRuleLayout)((Value.Container)args[3]).Item; // Spacing Autodesk.Revit.DB.DividedPath divPath; var refList = new List<Reference>(); refList.Clear(); var c = (CurveElement)((Value.Container)input).Item; FSharpList<Value> result = FSharpList<Value>.Empty; Curve crvRef = c.GeometryCurve; refList.Add(crvRef.Reference); if (this.Elements.Any()) { if (dynUtils.TryGetElement(this.Elements[0], out divPath)) { SetSpacing(divPath, xi, xs); } else { divPath = Autodesk.Revit.DB.DividedPath.Create(this.UIDocument.Document, refList); SetSpacing(divPath, xi, xs); this.Elements[0] = divPath.Id; } } else { divPath = Autodesk.Revit.DB.DividedPath.Create(this.UIDocument.Document, refList); SetSpacing(divPath, xi, xs); this.Elements.Add(divPath.Id); } refList.Clear(); return Value.NewContainer(divPath); }
public override Value Evaluate(FSharpList<Value> args) { CurveLoop firstLoop = (CurveLoop)((Value.Container)args[0]).Item; CurveLoop secondLoop = (CurveLoop)((Value.Container)args[1]).Item; List<VertexPair> vertPairs = new List<VertexPair>(); int i = 0; foreach (Curve c in firstLoop) { vertPairs.Add(new VertexPair(i, i)); i++; } var result = GeometryCreationUtilities.CreateBlendGeometry(firstLoop, secondLoop, vertPairs); solids.Add(result); return Value.NewContainer(result); }
internal void RunMutationTests() { String logTarget = dynamoViewModel.Model.Logger.LogPath + "MutationLog.log"; StreamWriter writer = new StreamWriter(logTarget); writer.WriteLine("MutateTest Internal activate"); System.Diagnostics.Debug.WriteLine("MutateTest Internal activate"); new Thread(() => { try { Assembly assembly = Assembly.GetExecutingAssembly(); var mutators = new List<AbstractMutator>(); foreach (Type type in assembly.GetTypes()) { var attribute = Attribute.GetCustomAttribute(type, typeof(MutationTestAttribute)); if (attribute != null) { object[] args = new object[] { dynamoViewModel }; var classInstance = Activator.CreateInstance(type, args); mutators.Add((AbstractMutator)classInstance); } } foreach (var mutator in mutators) InvokeTest(mutator, writer); } finally { dynamoViewModel.Model.Logger.Log("Fuzz testing finished."); writer.Flush(); writer.Close(); writer.Dispose(); } }).Start(); }
/// <summary> /// Call this method to generate a list of PortData from given set of /// unbound identifiers. This method ensures that the generated ports /// are only having names that do not exceed a preconfigured length. /// </summary> /// <param name="unboundIdents">A list of unbound identifiers for which /// input port data is to be generated. This list can be empty but it /// cannot be null.</param> /// <returns>Returns a list of input port data generated based on the /// input unbound identifier list.</returns> /// public static IEnumerable<PortData> GenerateInputPortData( IEnumerable<string> unboundIdents) { if (unboundIdents == null) throw new ArgumentNullException("unboundIdents"); int maxLength = Configurations.CBNMaxPortNameLength; List<PortData> inputPorts = new List<PortData>(); foreach (string name in unboundIdents) { string portName = name; if (portName.Length > maxLength) portName = portName.Remove(maxLength - 3) + "..."; inputPorts.Add(new PortData(portName, name)); } return inputPorts; }
/// <summary> /// Produces AST for a partial function application of a multi-output function. /// </summary> /// <param name="model">NodeModel to produce AST for.</param> /// <param name="rhs">AST representing the partial application. This will need to be used to assign all output port identifiers.</param> /// <param name="resultAst">Result accumulator: add all new output AST to this list.</param> protected virtual void BuildAstForPartialMultiOutput( NodeModel model, AssociativeNode rhs, List<AssociativeNode> resultAst) { var missingAmt = Enumerable.Range(0, model.InPortData.Count).Count(x => !model.HasInput(x)); var tmp = AstFactory.BuildIdentifier("__partial_" + model.GUID.ToString().Replace('-', '_')); resultAst.Add(AstFactory.BuildAssignment(tmp, rhs)); resultAst.AddRange( (Definition.ReturnKeys ?? Enumerable.Empty<string>()).Select( AstFactory.BuildStringNode) .Select( (rtnKey, index) => AstFactory.BuildAssignment( model.GetAstIdentifierForOutputIndex(index), AstFactory.BuildFunctionObject( "__ComposeBuffered", 3, new[] { 0, 1 }, new List<AssociativeNode> { AstFactory.BuildExprList( new List<AssociativeNode> { AstFactory.BuildFunctionObject( "__GetOutput", 2, new[] { 1 }, new List<AssociativeNode> { AstFactory.BuildNullNode(), rtnKey }), tmp }), AstFactory.BuildIntNode(missingAmt), AstFactory.BuildNullNode() })))); }
void mi_Click(object sender, System.Windows.RoutedEventArgs e) { if (AllElements.Count == 0) return; //select the elements dynRevitSettings.Doc.Selection.Elements.Clear(); var existingElements = new List<Element>(); foreach (var id in AllElements) { Element el; if (dynUtils.TryGetElement(id, typeof (Element), out el)) { existingElements.Add(el); } } existingElements.ForEach(x => dynRevitSettings.Doc.Selection.Elements.Add(x)); //show the elements dynRevitSettings.Doc.ShowElements(existingElements.Select(x => x.Id).ToList()); }
public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args) { var pts = ((FScheme.Value.List)args[0]).Item; hs = null; var containers = Utils.SequenceToFSharpList(pts); var ctrlPts = new List<XYZ>(); foreach (FScheme.Value e in containers) { if (e.IsContainer) { XYZ pt = (XYZ)((FScheme.Value.Container)(e)).Item; ctrlPts.Add(pt); } } if (pts.Count() > 0) { hs = dynRevitSettings.Doc.Application.Application.Create.NewHermiteSpline(ctrlPts, false); } return FScheme.Value.NewContainer(hs); }
/// <summary> /// Collapse a set of nodes in a given workspace. /// </summary> /// <param name="selectedNodes"> The function definition for the user-defined node </param> /// <param name="currentWorkspace"> The workspace where</param> /// <param name="isTestMode"></param> /// <param name="args"></param> public CustomNodeWorkspaceModel Collapse( IEnumerable<NodeModel> selectedNodes, WorkspaceModel currentWorkspace, bool isTestMode, FunctionNamePromptEventArgs args) { var selectedNodeSet = new HashSet<NodeModel>(selectedNodes); // Note that undoable actions are only recorded for the "currentWorkspace", // the nodes which get moved into "newNodeWorkspace" are not recorded for undo, // even in the new workspace. Their creations will simply be treated as part of // the opening of that new workspace (i.e. when a user opens a file, she will // not expect the nodes that show up to be undoable). // // After local nodes are moved into "newNodeWorkspace" as the result of // conversion, if user performs an undo, new set of nodes will be created in // "currentWorkspace" (not moving those nodes in the "newNodeWorkspace" back // into "currentWorkspace"). In another word, undo recording is on a per- // workspace basis, it does not work across different workspaces. // UndoRedoRecorder undoRecorder = currentWorkspace.UndoRecorder; CustomNodeWorkspaceModel newWorkspace; using (undoRecorder.BeginActionGroup()) { #region Determine Inputs and Outputs //Step 1: determine which nodes will be inputs to the new node var inputs = new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>( selectedNodeSet.SelectMany( node => Enumerable.Range(0, node.InPortData.Count) .Where(node.HasConnectedInput) .Select(data => Tuple.Create(node, data, node.InputNodes[data])) .Where(input => !selectedNodeSet.Contains(input.Item3.Item2)))); var outputs = new HashSet<Tuple<NodeModel, int, Tuple<int, NodeModel>>>( selectedNodeSet.SelectMany( node => Enumerable.Range(0, node.OutPortData.Count) .Where(node.HasOutput) .SelectMany( data => node.OutputNodes[data].Where( output => !selectedNodeSet.Contains(output.Item2)) .Select(output => Tuple.Create(node, data, output))))); #endregion #region Detect 1-node holes (higher-order function extraction) Log(Properties.Resources.CouldNotRepairOneNodeHoles, WarningLevel.Mild); // http://adsk-oss.myjetbrains.com/youtrack/issue/MAGN-5603 //var curriedNodeArgs = // new HashSet<NodeModel>( // inputs.Select(x => x.Item3.Item2) // .Intersect(outputs.Select(x => x.Item3.Item2))).Select( // outerNode => // { // //var node = new Apply1(); // var node = newNodeWorkspace.AddNode<Apply1>(); // node.SetNickNameFromAttribute(); // node.DisableReporting(); // node.X = outerNode.X; // node.Y = outerNode.Y; // //Fetch all input ports // // in order // // that have inputs // // and whose input comes from an inner node // List<int> inPortsConnected = // Enumerable.Range(0, outerNode.InPortData.Count) // .Where( // x => // outerNode.HasInput(x) // && selectedNodeSet.Contains( // outerNode.Inputs[x].Item2)) // .ToList(); // var nodeInputs = // outputs.Where(output => output.Item3.Item2 == outerNode) // .Select( // output => // new // { // InnerNodeInputSender = output.Item1, // OuterNodeInPortData = output.Item3.Item1 // }) // .ToList(); // nodeInputs.ForEach(_ => node.AddInput()); // node.RegisterAllPorts(); // return // new // { // OuterNode = outerNode, // InnerNode = node, // Outputs = // inputs.Where( // input => input.Item3.Item2 == outerNode) // .Select(input => input.Item3.Item1), // Inputs = nodeInputs, // OuterNodePortDataList = inPortsConnected // }; // }).ToList(); #endregion #region UI Positioning Calculations double avgX = selectedNodeSet.Average(node => node.X); double avgY = selectedNodeSet.Average(node => node.Y); double leftMost = selectedNodeSet.Min(node => node.X); double topMost = selectedNodeSet.Min(node => node.Y); double rightMost = selectedNodeSet.Max(node => node.X + node.Width); double leftShift = leftMost - 250; #endregion #region Handle full selected connectors // Step 2: Determine all the connectors whose start/end owners are // both in the selection set, and then move them from the current // workspace into the new workspace. var fullySelectedConns = new HashSet<ConnectorModel>( currentWorkspace.Connectors.Where( conn => { bool startSelected = selectedNodeSet.Contains(conn.Start.Owner); bool endSelected = selectedNodeSet.Contains(conn.End.Owner); return startSelected && endSelected; })); foreach (var connector in fullySelectedConns) { undoRecorder.RecordDeletionForUndo(connector); connector.Delete(); } #endregion #region Handle partially selected connectors // Step 3: Partially selected connectors (either one of its start // and end owners is in the selection) are to be destroyed. var partiallySelectedConns = currentWorkspace.Connectors.Where( conn => selectedNodeSet.Contains(conn.Start.Owner) || selectedNodeSet.Contains(conn.End.Owner)).ToList(); foreach (var connector in partiallySelectedConns) { undoRecorder.RecordDeletionForUndo(connector); connector.Delete(); } #endregion #region Transfer nodes and connectors to new workspace var newNodes = new List<NodeModel>(); var newAnnotations = new List<AnnotationModel>(); // Step 4: move all nodes to new workspace remove from old // PB: This could be more efficiently handled by a copy paste, but we // are preservering the node foreach (var node in selectedNodeSet) { undoRecorder.RecordDeletionForUndo(node); currentWorkspace.RemoveNode(node); // Assign a new guid to this node, otherwise when node is // compiled to AST, literally it is still in global scope // instead of in function scope. node.GUID = Guid.NewGuid(); node.RenderPackages.Clear(); // shift nodes node.X = node.X - leftShift; node.Y = node.Y - topMost; newNodes.Add(node); } //Copy the group from newNodes foreach (var group in DynamoSelection.Instance.Selection.OfType<AnnotationModel>()) { undoRecorder.RecordDeletionForUndo(group); currentWorkspace.RemoveGroup(group); group.GUID = Guid.NewGuid(); group.SelectedModels = group.DeletedModelBases; newAnnotations.Add(group); } foreach (var conn in fullySelectedConns) { ConnectorModel.Make(conn.Start.Owner, conn.End.Owner, conn.Start.Index, conn.End.Index); } #endregion #region Process inputs var inConnectors = new List<Tuple<NodeModel, int>>(); var uniqueInputSenders = new Dictionary<Tuple<NodeModel, int>, Symbol>(); //Step 3: insert variables (reference step 1) foreach (var input in Enumerable.Range(0, inputs.Count).Zip(inputs, Tuple.Create)) { int inputIndex = input.Item1; NodeModel inputReceiverNode = input.Item2.Item1; int inputReceiverData = input.Item2.Item2; NodeModel inputNode = input.Item2.Item3.Item2; int inputData = input.Item2.Item3.Item1; Symbol node; var key = Tuple.Create(inputNode, inputData); if (uniqueInputSenders.ContainsKey(key)) { node = uniqueInputSenders[key]; } else { inConnectors.Add(Tuple.Create(inputNode, inputData)); node = new Symbol { InputSymbol = inputReceiverNode.InPortData[inputReceiverData].NickName, X = 0 }; // Try to figure out the type of input of custom node // from the type of input of selected node. There are // two kinds of nodes whose input type are available: // function node and custom node. List<Library.TypedParameter> parameters = null; if (inputReceiverNode is Function) { var func = inputReceiverNode as Function; parameters = func.Controller.Definition.Parameters.ToList(); } else if (inputReceiverNode is DSFunctionBase) { var dsFunc = inputReceiverNode as DSFunctionBase; var funcDesc = dsFunc.Controller.Definition; parameters = funcDesc.Parameters.ToList(); if (funcDesc.Type == DSEngine.FunctionType.InstanceMethod || funcDesc.Type == DSEngine.FunctionType.InstanceProperty) { var dummyType = new ProtoCore.Type() { Name = funcDesc.ClassName }; var instanceParam = new TypedParameter(funcDesc.ClassName, dummyType); parameters.Insert(0, instanceParam); } } // so the input of custom node has format // input_var_name : type if (parameters != null && parameters.Count() > inputReceiverData) { var typeName = parameters[inputReceiverData].DisplayTypeName; if (!string.IsNullOrEmpty(typeName)) { node.InputSymbol += " : " + typeName; } } node.SetNickNameFromAttribute(); node.Y = inputIndex*(50 + node.Height); uniqueInputSenders[key] = node; newNodes.Add(node); } //var curriedNode = curriedNodeArgs.FirstOrDefault(x => x.OuterNode == inputNode); //if (curriedNode == null) //{ ConnectorModel.Make(node, inputReceiverNode, 0, inputReceiverData); //} //else //{ // //Connect it to the applier // newNodeWorkspace.AddConnection(node, curriedNode.InnerNode, 0, 0); // //Connect applier to the inner input receive // newNodeWorkspace.AddConnection( // curriedNode.InnerNode, // inputReceiverNode, // 0, // inputReceiverData); //} } #endregion #region Process outputs //List of all inner nodes to connect an output. Unique. var outportList = new List<Tuple<NodeModel, int>>(); var outConnectors = new List<Tuple<NodeModel, int, int>>(); int i = 0; if (outputs.Any()) { foreach (var output in outputs) { if (outportList.All(x => !(x.Item1 == output.Item1 && x.Item2 == output.Item2))) { NodeModel outputSenderNode = output.Item1; int outputSenderData = output.Item2; //NodeModel outputReceiverNode = output.Item3.Item2; //if (curriedNodeArgs.Any(x => x.OuterNode == outputReceiverNode)) // continue; outportList.Add(Tuple.Create(outputSenderNode, outputSenderData)); //Create Symbol Node var node = new Output { Symbol = outputSenderNode.OutPortData[outputSenderData].NickName, X = rightMost + 75 - leftShift }; node.Y = i*(50 + node.Height); node.SetNickNameFromAttribute(); newNodes.Add(node); ConnectorModel.Make(outputSenderNode, node, outputSenderData, 0); i++; } } //Connect outputs to new node outConnectors.AddRange( from output in outputs let outputSenderNode = output.Item1 let outputSenderData = output.Item2 let outputReceiverData = output.Item3.Item1 let outputReceiverNode = output.Item3.Item2 select Tuple.Create( outputReceiverNode, outportList.FindIndex( x => x.Item1 == outputSenderNode && x.Item2 == outputSenderData), outputReceiverData)); } else { foreach (var hanging in selectedNodeSet.SelectMany( node => Enumerable.Range(0, node.OutPortData.Count) .Where(port => !node.HasOutput(port)) .Select(port => new { node, port })).Distinct()) { //Create Symbol Node var node = new Output { Symbol = hanging.node.OutPortData[hanging.port].NickName, X = rightMost + 75 - leftShift }; node.Y = i*(50 + node.Height); node.SetNickNameFromAttribute(); newNodes.Add(node); ConnectorModel.Make(hanging.node, node, hanging.port, 0); i++; } } #endregion var newId = Guid.NewGuid(); newWorkspace = new CustomNodeWorkspaceModel( nodeFactory, newNodes, Enumerable.Empty<NoteModel>(), newAnnotations, Enumerable.Empty<PresetModel>(), new WorkspaceInfo() { X = 0, Y = 0, Name = args.Name, Category = args.Category, Description = args.Description, ID = newId.ToString(), FileName = string.Empty }, currentWorkspace.ElementResolver); newWorkspace.HasUnsavedChanges = true; RegisterCustomNodeWorkspace(newWorkspace); var collapsedNode = CreateCustomNodeInstance(newId, isTestMode: isTestMode); collapsedNode.X = avgX; collapsedNode.Y = avgY; currentWorkspace.AddNode(collapsedNode, centered: false); undoRecorder.RecordCreationForUndo(collapsedNode); foreach (var connector in inConnectors.Select((x, idx) => new { node = x.Item1, from = x.Item2, to = idx }) .Select( nodeTuple => ConnectorModel.Make( nodeTuple.node, collapsedNode, nodeTuple.@from, nodeTuple.to)) .Where(connector => connector != null)) { undoRecorder.RecordCreationForUndo(connector); } foreach (var connector in outConnectors.Select( nodeTuple => ConnectorModel.Make( collapsedNode, nodeTuple.Item1, nodeTuple.Item2, nodeTuple.Item3)).Where(connector => connector != null)) { undoRecorder.RecordCreationForUndo(connector); } } return newWorkspace; }
private static IDoubleInputToken ParseToken(string id, HashSet<string> identifiers, List<string> list) { double dbl; if (double.TryParse(id, NumberStyles.Any, CultureInfo.InvariantCulture, out dbl)) return new DoubleToken(dbl); var match = Sublists.IdentifierPattern.Match(id); if (match.Success) { var tokenId = match.Groups["id"].Value; if (!identifiers.Contains(tokenId)) { identifiers.Add(tokenId); list.Add(tokenId); } return new IdentifierToken(tokenId); } throw new Exception("Bad identifier syntax: \"" + id + "\""); }
/// <summary> /// Scans the given path for custom node files, retaining their information in the manager for later /// potential initialization. /// </summary> /// <param name="path">Path on disk to scan for custom nodes.</param> /// <param name="isTestMode"> /// Flag specifying whether or not this should operate in "test mode". /// </param> /// <param name="isPackageMember"> /// Indicates whether custom node comes from package or not. /// </param> /// <returns></returns> public IEnumerable<CustomNodeInfo> AddUninitializedCustomNodesInPath(string path, bool isTestMode, bool isPackageMember = false) { var result = new List<CustomNodeInfo>(); foreach (var info in ScanNodeHeadersInDirectory(path, isTestMode)) { info.IsPackageMember = isPackageMember; SetNodeInfo(info); result.Add(info); } return result; }
public static void GetReferencedVariables(Node astNode, List<Variable> refVariableList) { //DFS Search to find all identifier nodes if (astNode == null) return; if (astNode is FunctionCallNode) { var currentNode = astNode as FunctionCallNode; foreach (AssociativeNode node in currentNode.FormalArguments) GetReferencedVariables(node, refVariableList); } else if (astNode is IdentifierNode) { var resultVariable = new Variable(astNode as IdentifierNode); refVariableList.Add(resultVariable); GetReferencedVariables((astNode as IdentifierNode).ArrayDimensions, refVariableList); } else if (astNode is ArrayNode) { var currentNode = astNode as ArrayNode; GetReferencedVariables(currentNode.Expr, refVariableList); GetReferencedVariables(currentNode.Type, refVariableList); } else if (astNode is ExprListNode) { var currentNode = astNode as ExprListNode; foreach (AssociativeNode node in currentNode.list) GetReferencedVariables(node, refVariableList); } else if (astNode is FunctionDotCallNode) { var currentNode = astNode as FunctionDotCallNode; GetReferencedVariables(currentNode.FunctionCall, refVariableList); } else if (astNode is InlineConditionalNode) { var currentNode = astNode as InlineConditionalNode; GetReferencedVariables(currentNode.ConditionExpression, refVariableList); GetReferencedVariables(currentNode.TrueExpression, refVariableList); GetReferencedVariables(currentNode.FalseExpression, refVariableList); } else if (astNode is RangeExprNode) { var currentNode = astNode as RangeExprNode; GetReferencedVariables(currentNode.FromNode, refVariableList); GetReferencedVariables(currentNode.ToNode, refVariableList); GetReferencedVariables(currentNode.StepNode, refVariableList); } else if (astNode is BinaryExpressionNode) { var currentNode = astNode as BinaryExpressionNode; GetReferencedVariables(currentNode.RightNode, refVariableList); } else { //Its could be something like a literal //Or node not completely implemented YET } }
public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args) { var worksheet = (Microsoft.Office.Interop.Excel.Worksheet)((FScheme.Value.Container)args[0]).Item; Microsoft.Office.Interop.Excel.Range range = worksheet.UsedRange; int rows = range.Rows.Count; int cols = range.Columns.Count; var rowData = new List<FScheme.Value>(); for (int r = 1; r <= rows; r++) { var row = new List<FScheme.Value>(); for (int c = 1; c <= cols; c++) { row.Add(FScheme.Value.NewContainer(range.Cells[r, c].Value2)); } rowData.Add(FScheme.Value.NewList(Utils.SequenceToFSharpList(row))); } return FScheme.Value.NewList(Utils.SequenceToFSharpList(rowData)); }
private void ProcessCode(ref string errorMessage, ref string warningMessage, ElementResolver workspaceElementResolver = null) { code = CodeBlockUtils.FormatUserText(code); codeStatements.Clear(); if (string.IsNullOrEmpty(Code)) previewVariable = null; try { // During loading of CBN from file, the elementResolver from the workspace is unavailable // in which case, a local copy of the ER obtained from the CBN is used var resolver = workspaceElementResolver ?? this.ElementResolver; var parseParam = new ParseParam(GUID, code, resolver); if (CompilerUtils.PreCompileCodeBlock(libraryServices.LibraryManagementCore, ref parseParam)) { if (parseParam.ParsedNodes != null) { // Create an instance of statement for each code statement written by the user foreach (var parsedNode in parseParam.ParsedNodes) { // Create a statement variable from the generated nodes codeStatements.Add(Statement.CreateInstance(parsedNode)); } SetPreviewVariable(parseParam.ParsedNodes); } } if (parseParam.Errors != null && parseParam.Errors.Any()) { errorMessage = string.Join("\n", parseParam.Errors.Select(m => m.Message)); ProcessError(); CreateInputOutputPorts(); return; } if (parseParam.Warnings != null) { // Unbound identifiers in CBN will have input slots. // // To check function redefinition, we need to check other // CBN to find out if it has been defined yet. Now just // skip this warning. var warnings = parseParam.Warnings.Where( w => w.ID != WarningID.kIdUnboundIdentifier && w.ID != WarningID.kFunctionAlreadyDefined); if (warnings.Any()) { warningMessage = string.Join("\n", warnings.Select(m => m.Message)); } } if (parseParam.UnboundIdentifiers != null) { inputIdentifiers = new List<string>(); inputPortNames = new List<string>(); foreach (var kvp in parseParam.UnboundIdentifiers) { inputIdentifiers.Add(kvp.Value); inputPortNames.Add(kvp.Key); } } else { inputIdentifiers.Clear(); inputPortNames.Clear(); } } catch (Exception e) { errorMessage = e.Message; previewVariable = null; ProcessError(); return; } // Set the input and output ports based on the statements CreateInputOutputPorts(); }
/// <summary> /// Now that the portData has been set for the new ports, we recreate the connections we /// so mercilessly destroyed, restoring peace and balance to the world once again. /// </summary> /// <param name="inportConnections"></param> /// <param name="outportConnections"> List of the connections that were killed</param> private void LoadAndCreateConnectors(OrderedDictionary inportConnections, OrderedDictionary outportConnections) { //----------------------------Inputs--------------------------------- /* Input Port connections are matched only if the name is the same */ for (int i = 0; i < InPortData.Count; i++) { string varName = InPortData[i].ToolTipString; if (inportConnections.Contains(varName)) { if (inportConnections[varName] != null) { foreach (var startPortModel in (inportConnections[varName] as List<PortModel>)) { NodeModel startNode = startPortModel.Owner; var connector = ConnectorModel.Make( startNode, this, startPortModel.Index, i); } outportConnections[varName] = null; } } } //----------------------------Outputs-------------------------------- /*The matching is done in three parts: *Step 1: * First, it tries to match the connectors wrt to the defined * variable name. Hence it first checks to see if any of the old * variable names are present. If so, if there were any connectors * presnt then it makes the new connectors. As it iterates through * the new ports, it also finds the ports that didnt exist before */ List<int> undefinedIndices = new List<int>(); for (int i = 0; i < OutPortData.Count; i++) { string varName = OutPortData[i].ToolTipString; if (outportConnections.Contains(varName)) { if (outportConnections[varName] != null) { foreach (var endPortModel in (outportConnections[varName] as List<PortModel>)) { NodeModel endNode = endPortModel.Owner; var connector = ConnectorModel.Make(this, endNode, i, endPortModel.Index); } outportConnections[varName] = null; } } else undefinedIndices.Add(i); } /* *Step 2: * The second priority is to match the connections to the previous * indices. For all the ports that were not previously defined, it * now checks if that "numbered" port had any connections * previously, ie, if the old third port had 2 connections, then * these would go to the new 3rd port (if it is not a variable that * was defined before) */ for (int i = 0; i < undefinedIndices.Count; i++) { int index = undefinedIndices[i]; if (index < outportConnections.Count && outportConnections[index] != null) { foreach (PortModel endPortModel in (outportConnections[index] as List<PortModel>)) { NodeModel endNode = endPortModel.Owner; var connector = ConnectorModel.Make(this, endNode, index, endPortModel.Index); } outportConnections[index] = null; undefinedIndices.Remove(index); i--; } } /* *Step 2: * The final step. Now that the priorties are finished, the * function tries to reuse any existing connections by attaching * them to any ports that have not already been given connections */ List<List<PortModel>> unusedConnections = outportConnections.Values.Cast<List<PortModel>>() .Where(portModelList => portModelList != null) .ToList(); while (undefinedIndices.Count > 0 && unusedConnections.Count != 0) { foreach (PortModel endPortModel in unusedConnections[0]) { NodeModel endNode = endPortModel.Owner; ConnectorModel connector = ConnectorModel.Make( this, endNode, undefinedIndices[0], endPortModel.Index); } undefinedIndices.RemoveAt(0); unusedConnections.RemoveAt(0); } }
public AssociativeNode CompileToAstNode(AstBuilder builder) { if (!RequiresRecalc) { return this.AstIdentifier; } builder.ClearAstNodes(GUID); bool isPartiallyApplied = false; // Recursively compile its inputs to ast nodes and add intermediate // nodes to builder var inputAstNodes = new List<AssociativeNode>(); for (int index = 0; index < InPortData.Count; ++index) { Tuple<int, NodeModel> input; if (!TryGetInput(index, out input)) { isPartiallyApplied = true; inputAstNodes.Add(null); } else { inputAstNodes.Add(input.Item2.CompileToAstNode(builder)); } } // Build evaluatiion for this node. If the rhs is a partially // applied function, then a function defintion node will be created. // But in the end there is always an assignment: // // AstIdentifier = ...; var rhs = BuildAstNode(builder, inputAstNodes) ?? builder.BuildEvaluator(this, inputAstNodes); builder.BuildEvaluation(this, rhs, isPartiallyApplied); return AstIdentifier; }
internal override IEnumerable<AssociativeNode> BuildAst(List<AssociativeNode> inputAstNodes, AstBuilder.CompilationContext context) { //Do not build if the node is in error. if (State == ElementState.Error) { return Enumerable.Empty<AssociativeNode>(); } var resultNodes = new List<AssociativeNode>(); // Define unbound variables if necessary if (inputIdentifiers != null && inputAstNodes != null && inputIdentifiers.Count == inputAstNodes.Count) { var initStatments = inputIdentifiers.Zip(inputAstNodes, (ident, rhs) => { var identNode = AstFactory.BuildIdentifier(ident); if (context != AstBuilder.CompilationContext.NodeToCode) MapIdentifiers(identNode); return AstFactory.BuildAssignment(identNode, rhs); }); resultNodes.AddRange(initStatments); } foreach (var astNode in codeStatements.Select(stmnt => NodeUtils.Clone(stmnt.AstNode))) { if (context != AstBuilder.CompilationContext.NodeToCode) MapIdentifiers(astNode); resultNodes.Add(astNode as AssociativeNode); } return resultNodes; }
protected virtual void __eval_internal_recursive(FSharpList<FScheme.Value> args, Dictionary<PortData, FScheme.Value> outPuts, int level = 0) { var argSets = new List<FSharpList<FScheme.Value>>(); //create a zip of the incoming args and the port data //to be used for type comparison var portComparison = args.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)) .ToList(); var listOfListComparison = args.Zip(InPortData, (first, second) => new Tuple<bool, Type>(Utils.IsListOfLists(first), second.PortType)); //there are more than zero arguments //and there is either an argument which does not match its expections //OR an argument which requires a list and gets a list of lists //AND argument lacing is not disabled if (ArgumentLacing != LacingStrategy.Disabled && args.Any() && (portComparison.Any(x => x.Item1 == typeof (Value.List) && x.Item2 != typeof (Value.List)) || listOfListComparison.Any(x => x.Item1 && x.Item2 == typeof (Value.List)))) { //if the argument is of the expected type, then //leave it alone otherwise, wrap it in a list int j = 0; foreach (var arg in args) { //incoming value is list and expecting single if (portComparison.ElementAt(j).Item1 == typeof (Value.List) && portComparison.ElementAt(j).Item2 != typeof (Value.List)) { //leave as list argSets.Add(((Value.List) arg).Item); } //incoming value is list and expecting list else { //check if we have a list of lists, if so, then don't wrap argSets.Add( Utils.IsListOfLists(arg) && !AcceptsListOfLists(arg) ? ((Value.List) arg).Item : Utils.MakeFSharpList(arg)); } j++; } IEnumerable<IEnumerable<Value>> lacedArgs = null; switch (ArgumentLacing) { case LacingStrategy.First: lacedArgs = argSets.SingleSet(); break; case LacingStrategy.Shortest: lacedArgs = argSets.ShortestSet(); break; case LacingStrategy.Longest: lacedArgs = argSets.LongestSet(); break; case LacingStrategy.CrossProduct: lacedArgs = argSets.CartesianProduct(); break; } var evalResult = OutPortData.ToDictionary( x => x, _ => FSharpList<Value>.Empty); var evalDict = new Dictionary<PortData, Value>(); //run the evaluate method for each set of //arguments in the lace result. foreach (var argList in lacedArgs) { evalDict.Clear(); var thisArgsAsFSharpList = Utils.ToFSharpList(argList); var portComparisonLaced = thisArgsAsFSharpList.Zip(InPortData, (first, second) => new Tuple<Type, Type>(first.GetType(), second.PortType)).ToList(); int jj = 0; bool bHasListNotExpecting = false; foreach (var argLaced in argList) { //incoming value is list and expecting single if (ArgumentLacing != LacingStrategy.Disabled && thisArgsAsFSharpList.Any() && portComparisonLaced.ElementAt(jj).Item1 == typeof (Value.List) && portComparison.ElementAt(jj).Item2 != typeof (Value.List) && (!AcceptsListOfLists(argLaced) || !Utils.IsListOfLists(argLaced)) ) { bHasListNotExpecting = true; break; } jj++; } if (bHasListNotExpecting) { if (level > 20) throw new Exception("Too deep recursive list containment by lists, only 21 are allowed"); Dictionary<PortData, FScheme.Value> outPutsLevelPlusOne = new Dictionary<PortData, FScheme.Value>(); __eval_internal_recursive(Utils.ToFSharpList(argList), outPutsLevelPlusOne, level + 1); //pack result back foreach (var dataLaced in outPutsLevelPlusOne) { var dataL = dataLaced.Key; var valueL = outPutsLevelPlusOne[dataL]; evalResult[dataL] = FSharpList<Value>.Cons(valueL, evalResult[dataL]); } continue; } else Evaluate(Utils.ToFSharpList(argList), evalDict); OnEvaluate(); foreach (var data in OutPortData) { evalResult[data] = FSharpList<Value>.Cons(evalDict[data], evalResult[data]); } } //the result of evaluation will be a list. we split that result //and send the results to the outputs foreach (var data in OutPortData) { var portResults = evalResult[data]; //if the lacing is cross product, the results //need to be split back out into a set of lists //equal in dimension to the first list argument if (args[0].IsList && ArgumentLacing == LacingStrategy.CrossProduct) { var length = portResults.Count(); var innerLength = length/((Value.List) args[0]).Item.Count(); int subCount = 0; var listOfLists = FSharpList<Value>.Empty; var innerList = FSharpList<Value>.Empty; for (int i = 0; i < length; i++) { innerList = FSharpList<Value>.Cons(portResults.ElementAt(i), innerList); subCount++; if (subCount == innerLength) { subCount = 0; listOfLists = FSharpList<Value>.Cons(Value.NewList(innerList), listOfLists); innerList = FSharpList<Value>.Empty; } } evalResult[data] = Utils.ToFSharpList(listOfLists); } else { //Reverse the evaluation results so they come out right way around evalResult[data] = Utils.ToFSharpList(evalResult[data].Reverse()); } outPuts[data] = Value.NewList(evalResult[data]); } } else { Evaluate(args, outPuts); OnEvaluate(); } }
//TODO: do all of this as the Ui is modified, simply return this? /// <summary> /// Builds an INode out of this Element. Override this or Compile() if you want complete control over this Element's /// execution. /// </summary> /// <returns>The INode representation of this Element.</returns> protected internal virtual INode Build(Dictionary<NodeModel, Dictionary<int, INode>> preBuilt, int outPort) { //Debug.WriteLine("Building node..."); Dictionary<int, INode> result; if (preBuilt.TryGetValue(this, out result)) return result[outPort]; //Fetch the names of input ports. var portNames = InPortData.Zip(Enumerable.Range(0, InPortData.Count), (x, i) => x.NickName + i).ToList(); //Is this a partial application? var partial = false; var connections = new List<Tuple<string, INode>>(); var partialSymList = new List<string>(); //For each index in InPortData foreach (var data in Enumerable.Range(0, InPortData.Count).Zip(portNames, (data, name) => new { Index = data, Name = name })) { Tuple<int, NodeModel> input; //If this port has connectors... //if (port.Connectors.Any()) if (TryGetInput(data.Index, out input)) { //Compile input and connect it connections.Add(Tuple.Create(data.Name, input.Item2.Build(preBuilt, input.Item1))); } else if (InPorts[data.Index].UsingDefaultValue) { connections.Add(Tuple.Create(data.Name, new ValueNode(InPortData[data.Index].DefaultValue) as INode)); } else //othwise, remember that this is a partial application { partial = true; partialSymList.Add(data.Name); } } Dictionary<int, INode> nodes = OutPortData.Count == 1 ? (partial ? buildPartialSingleOut(portNames, connections, partialSymList) : buildSingleOut(portNames, connections)) : (partial ? buildPartialMultiOut(portNames, connections, partialSymList) : buildMultiOut(portNames, connections)); //If this is a partial application, then remember not to re-eval. if (partial) { OldValue = Value.NewFunction(null); // cache an old value for display to the user RequiresRecalc = false; } preBuilt[this] = nodes; //And we're done return nodes[outPort]; }
//TODO: do all of this as the Ui is modified, simply return this? /// <summary> /// Builds an INode out of this Element. Override this or Compile() if you want complete control over this Element's /// execution. /// </summary> /// <returns>The INode representation of this Element.</returns> protected internal virtual INode Build(Dictionary<dynNode, Dictionary<int, INode>> preBuilt, int outPort) { Dictionary<int, INode> result; if (preBuilt.TryGetValue(this, out result)) return result[outPort]; //Fetch the names of input ports. var portNames = InPortData.Zip(Enumerable.Range(0, InPortData.Count), (x, i) => x.NickName + i); //Compile the procedure for this node. InputNode node = Compile(portNames); //Is this a partial application? var partial = false; var partialSymList = new List<string>(); //For each index in InPortData //for (int i = 0; i < InPortData.Count; i++) foreach (var data in Enumerable.Range(0, InPortData.Count).Zip(portNames, (data, name) => new { Index=data, Name=name })) { //Fetch the corresponding port //var port = InPorts[i]; Tuple<int, dynNode> input; //If this port has connectors... //if (port.Connectors.Any()) if (TryGetInput(data.Index, out input)) { //Compile input and connect it node.ConnectInput(data.Name, input.Item2.Build(preBuilt, input.Item1)); } else //othwise, remember that this is a partial application { partial = true; partialSymList.Add(data.Name); } } var nodes = new Dictionary<int, INode>(); if (OutPortData.Count > 1) { foreach (var data in partialSymList) node.ConnectInput(data, new SymbolNode(data)); InputNode prev = node; int prevIndex = 0; foreach (var data in Enumerable.Range(0, OutPortData.Count).Zip(OutPortData, (i, d) => new { Index = i, Data = d })) { if (HasOutput(data.Index)) { if (data.Index > 0) { var diff = data.Index - prevIndex; InputNode restNode; if (diff > 1) { restNode = new ExternalFunctionNode(FScheme.Drop, new List<string>() { "amt", "list" }); restNode.ConnectInput("amt", new NumberNode(diff)); restNode.ConnectInput("list", prev); } else { restNode = new ExternalFunctionNode(FScheme.Cdr, new List<string>() { "list" }); restNode.ConnectInput("list", prev); } prev = restNode; prevIndex = data.Index; } var firstNode = new ExternalFunctionNode(FScheme.Car, new List<string>() { "list" }); firstNode.ConnectInput("list", prev); if (partial) nodes[data.Index] = new AnonymousFunctionNode(partialSymList, firstNode); else nodes[data.Index] = firstNode; } } } else { nodes[outPort] = node; } //If this is a partial application, then remember not to re-eval. if (partial) { RequiresRecalc = false; } preBuilt[this] = nodes; //And we're done return nodes[outPort]; }
/// <summary> /// Paste ISelectable objects from the clipboard to the workspace. /// </summary> public void Paste() { //clear the selection so we can put the //paste contents in DynamoSelection.Instance.ClearSelection(); //make a lookup table to store the guids of the //old models and the guids of their pasted versions var modelLookup = new Dictionary<Guid, ModelBase>(); //make a list of all newly created models so that their //creations can be recorded in the undo recorder. var createdModels = new List<ModelBase>(); var nodes = ClipBoard.OfType<NodeModel>(); var connectors = ClipBoard.OfType<ConnectorModel>(); var notes = ClipBoard.OfType<NoteModel>(); var annotations = ClipBoard.OfType<AnnotationModel>(); var minX = Double.MaxValue; var minY = Double.MaxValue; // Create the new NoteModel's var newNoteModels = new List<NoteModel>(); foreach (var note in notes) { var noteModel = new NoteModel(note.X, note.Y, note.Text, Guid.NewGuid()); //Store the old note as Key and newnote as value. modelLookup.Add(note.GUID,noteModel); newNoteModels.Add(noteModel); minX = Math.Min(note.X, minX); minY = Math.Min(note.Y, minY); } var xmlDoc = new XmlDocument(); // Create the new NodeModel's var newNodeModels = new List<NodeModel>(); foreach (var node in nodes) { NodeModel newNode; if (CurrentWorkspace is HomeWorkspaceModel && (node is Symbol || node is Output)) { var symbol = (node is Symbol ? (node as Symbol).InputSymbol : (node as Output).Symbol); var code = (string.IsNullOrEmpty(symbol) ? "x" : symbol) + ";"; newNode = new CodeBlockNodeModel(code, node.X, node.Y, LibraryServices, CurrentWorkspace.ElementResolver); } else { var dynEl = node.Serialize(xmlDoc, SaveContext.Copy); newNode = NodeFactory.CreateNodeFromXml(dynEl, SaveContext.Copy, CurrentWorkspace.ElementResolver); } var lacing = node.ArgumentLacing.ToString(); newNode.UpdateValue(new UpdateValueParams("ArgumentLacing", lacing)); if (!string.IsNullOrEmpty(node.NickName)) newNode.NickName = node.NickName; modelLookup.Add(node.GUID, newNode); newNodeModels.Add( newNode ); minX = Math.Min(node.X, minX); minY = Math.Min(node.Y, minY); } // Move all of the notes and nodes such that they are aligned with // the top left of the workspace var workspaceX = -CurrentWorkspace.X / CurrentWorkspace.Zoom; var workspaceY = -CurrentWorkspace.Y / CurrentWorkspace.Zoom; // Provide a small offset when pasting so duplicate pastes aren't directly on top of each other CurrentWorkspace.IncrementPasteOffset(); var shiftX = workspaceX - minX + CurrentWorkspace.CurrentPasteOffset; var shiftY = workspaceY - minY + CurrentWorkspace.CurrentPasteOffset; foreach (var model in newNodeModels.Concat<ModelBase>(newNoteModels)) { model.X = model.X + shiftX; model.Y = model.Y + shiftY; } // Add the new NodeModel's to the Workspace foreach (var newNode in newNodeModels) { CurrentWorkspace.AddAndRegisterNode(newNode, false); createdModels.Add(newNode); AddToSelection(newNode); } // TODO: is this required? OnRequestLayoutUpdate(this, EventArgs.Empty); // Add the new NoteModel's to the Workspace foreach (var newNote in newNoteModels) { CurrentWorkspace.AddNote(newNote, false); createdModels.Add(newNote); AddToSelection(newNote); } ModelBase start; ModelBase end; var newConnectors = from c in connectors // If the guid is in nodeLookup, then we connect to the new pasted node. Otherwise we // re-connect to the original. let startNode = modelLookup.TryGetValue(c.Start.Owner.GUID, out start) ? start as NodeModel : CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == c.Start.Owner.GUID) let endNode = modelLookup.TryGetValue(c.End.Owner.GUID, out end) ? end as NodeModel : CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == c.End.Owner.GUID) // Don't make a connector if either end is null. where startNode != null && endNode != null select ConnectorModel.Make(startNode, endNode, c.Start.Index, c.End.Index); createdModels.AddRange(newConnectors); //Grouping depends on the selected node models. //so adding the group after nodes / notes are added to workspace. //select only those nodes that are part of a group. var newAnnotations = new List<AnnotationModel>(); foreach (var annotation in annotations) { var annotationNodeModel = new List<NodeModel>(); var annotationNoteModel = new List<NoteModel>(); //checked condition here that supports pasting of multiple groups foreach (var models in annotation.SelectedModels) { ModelBase mbase; modelLookup.TryGetValue(models.GUID, out mbase); if (mbase is NodeModel) { annotationNodeModel.Add(mbase as NodeModel); } if (mbase is NoteModel) { annotationNoteModel.Add(mbase as NoteModel); } } var annotationModel = new AnnotationModel(annotationNodeModel, annotationNoteModel) { GUID = Guid.NewGuid(), AnnotationText = annotation.AnnotationText, Background = annotation.Background, FontSize = annotation.FontSize }; newAnnotations.Add(annotationModel); } // Add the new Annotation's to the Workspace foreach (var newAnnotation in newAnnotations) { CurrentWorkspace.AddAnnotation(newAnnotation); createdModels.Add(newAnnotation); AddToSelection(newAnnotation); } // Record models that are created as part of the command. CurrentWorkspace.RecordCreatedModels(createdModels); }
internal void UngroupModel(List<ModelBase> modelsToUngroup) { var emptyGroup = new List<ModelBase>(); var annotations = Workspaces.SelectMany(ws => ws.Annotations); foreach (var model in modelsToUngroup) { foreach (var annotation in annotations) { if (annotation.SelectedModels.Any(x => x.GUID == model.GUID)) { var list = annotation.SelectedModels.ToList(); if(list.Count > 1) { CurrentWorkspace.RecordGroupModelBeforeUngroup(annotation); if (list.Remove(model)) { annotation.SelectedModels = list; annotation.UpdateBoundaryFromSelection(); } } else { emptyGroup.Add(annotation); } } } } if(emptyGroup.Any()) { DeleteModelInternal(emptyGroup); } }