├── .gitattributes ├── .gitignore ├── Common ├── Common.csproj ├── ConversionRule.cs ├── ExecutableNode.cs ├── ExecutionOutDescription.cs ├── ExposedInput.cs ├── ExposedOutput.cs ├── LabelDisplay.cs ├── NodeBase.cs ├── NodeCategory.cs ├── NodeName.cs ├── Properties │ └── AssemblyInfo.cs └── QueryState.cs ├── DataTypes ├── Boolean.cs ├── DataTypes.csproj ├── IDataTypeContainer.cs ├── Numeric.cs ├── Properties │ └── AssemblyInfo.cs └── String.cs ├── Graph ├── BaseNodePin.cs ├── Graph.csproj ├── GraphNode.cs ├── InputPin.cs ├── NodeGraphManager.cs ├── OutputPin.cs ├── PinConnection.cs └── Properties │ └── AssemblyInfo.cs ├── Nodes ├── Basic SQL │ ├── SELECT.cs │ └── Where.cs ├── Boolean Logic │ ├── And.cs │ ├── Equals.cs │ ├── GreaterThan.cs │ ├── GreaterThanEqualTo.cs │ ├── LessThan.cs │ ├── LessThanEqualTo.cs │ ├── Nand.cs │ ├── Not.cs │ ├── Or.cs │ └── Xor.cs ├── Conversion │ ├── BoolToString.cs │ └── NumericToString.cs ├── DebugNodes │ └── DebugPrint.cs ├── Flow │ └── Branch.cs ├── HTML │ ├── HTMLBegin.cs │ ├── HTMLBody.cs │ ├── HTMLEnd.cs │ ├── HTMLHead.cs │ └── Pure │ │ ├── Div.cs │ │ └── Paragraph.cs ├── Maths │ ├── Add.cs │ ├── Divide.cs │ ├── Multiply.cs │ └── Subtract.cs ├── Nodes.csproj ├── Properties │ └── AssemblyInfo.cs └── String │ └── Concatenate.cs ├── QueryBuilder.sln ├── README.md └── VisualQueryApplication ├── App.config ├── App.xaml ├── App.xaml.cs ├── Controls └── GraphBuilder │ ├── ConstantNode.xaml │ ├── ConstantNode.xaml.cs │ ├── NodePin.xaml │ ├── NodePin.xaml.cs │ ├── VisualEditor.xaml │ ├── VisualEditor.xaml.cs │ ├── VisualNodeControl.xaml │ ├── VisualNodeControl.xaml.cs │ └── ZoomAndPan │ ├── AnimationHelper.cs │ ├── Generic.xaml │ ├── ZoomAndPanControl.cs │ └── ZoomAndPanControl_IScrollInfo.cs ├── GeneratedQueryView.xaml ├── GeneratedQueryView.xaml.cs ├── Graph.cs ├── Images └── Ribbon │ ├── icon_build.png │ ├── icon_delete.png │ ├── icon_placeholder.png │ └── icon_view_query.png ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── RelayCommand.cs ├── ViewModels ├── ConnectionBuilderViewModel.cs ├── ConnectionViewModel.cs ├── GeneratedQueryViewViewModel.cs ├── GraphEditorViewModel.cs ├── MainWindowViewModel.cs ├── NodePinViewModel.cs ├── ViewModelBase.cs ├── VisualConstantNodeViewModel.cs ├── VisualGraphComponentViewModel.cs └── VisualNodeViewModel.cs ├── VisualQueryApplication.csproj └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Roslyn cache directories 20 | *.ide/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | _NCrunch_* 98 | .*crunch*.local.xml 99 | 100 | # MightyMoose 101 | *.mm.* 102 | AutoTest.Net/ 103 | 104 | # Web workbench (sass) 105 | .sass-cache/ 106 | 107 | # Installshield output folder 108 | [Ee]xpress/ 109 | 110 | # DocProject is a documentation generator add-in 111 | DocProject/buildhelp/ 112 | DocProject/Help/*.HxT 113 | DocProject/Help/*.HxC 114 | DocProject/Help/*.hhc 115 | DocProject/Help/*.hhk 116 | DocProject/Help/*.hhp 117 | DocProject/Help/Html2 118 | DocProject/Help/html 119 | 120 | # Click-Once directory 121 | publish/ 122 | 123 | # Publish Web Output 124 | *.[Pp]ublish.xml 125 | *.azurePubxml 126 | ## TODO: Comment the next line if you want to checkin your 127 | ## web deploy settings but do note that will include unencrypted 128 | ## passwords 129 | #*.pubxml 130 | 131 | # NuGet Packages Directory 132 | packages/* 133 | ## TODO: If the tool you use requires repositories.config 134 | ## uncomment the next line 135 | #!packages/repositories.config 136 | 137 | # Enable "build/" folder in the NuGet Packages folder since 138 | # NuGet packages use it for MSBuild targets. 139 | # This line needs to be after the ignore of the build folder 140 | # (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | bower_components/ 163 | 164 | # RIA/Silverlight projects 165 | Generated_Code/ 166 | 167 | # Backup & report files from converting an old project file 168 | # to a newer Visual Studio version. Backup files are not needed, 169 | # because we have git ;-) 170 | _UpgradeReport_Files/ 171 | Backup*/ 172 | UpgradeLog*.XML 173 | UpgradeLog*.htm 174 | 175 | # SQL Server files 176 | *.mdf 177 | *.ldf 178 | 179 | # Business Intelligence projects 180 | *.rdl.data 181 | *.bim.layout 182 | *.bim_*.settings 183 | 184 | # Microsoft Fakes 185 | FakesAssemblies/ 186 | 187 | # LightSwitch generated files 188 | GeneratedArtifacts/ 189 | _Pvt_Extensions/ 190 | ModelManifest.xml -------------------------------------------------------------------------------- /Common/Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A283D3F9-3BCF-405C-A4C8-37CB73AB6B0E} 8 | Library 9 | Properties 10 | Common 11 | Common 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {cb604d32-d358-4f90-9d4a-df5a6dc5d9df} 59 | DataTypes 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /Common/ConversionRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class ConversionRule : Attribute 11 | { 12 | public Type InputType { get; private set; } 13 | public Type OutputType { get; private set; } 14 | 15 | public ConversionRule(Type inputType, Type outputType) 16 | { 17 | InputType = inputType; 18 | OutputType = outputType; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Common/ExecutableNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using DataTypes; 7 | 8 | namespace Common 9 | { 10 | public abstract class ExecutableNode : NodeBase 11 | { 12 | protected QueryState State { get; private set; } 13 | 14 | public ExecutableNode(QueryState state) 15 | { 16 | this.State = state; 17 | } 18 | 19 | public abstract int GetExecutionPath(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Common/ExecutionOutDescription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 10 | public class ExecutionOutDescription : Attribute 11 | { 12 | public int Order { get; private set; } 13 | public string Label { get; private set; } 14 | 15 | public ExecutionOutDescription(int order, string label) 16 | { 17 | Order = order; 18 | Label = label; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Common/ExposedInput.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | [AttributeUsage(AttributeTargets.Field)] 10 | public class ExposedInput : Attribute 11 | { 12 | public LabelDisplay LabelDisplay { get; private set; } 13 | public string Label { get; private set; } 14 | 15 | public ExposedInput() 16 | { 17 | this.LabelDisplay = LabelDisplay.Hidden; 18 | this.Label = ""; 19 | } 20 | 21 | public ExposedInput(LabelDisplay labelDisplay, string label = "") 22 | { 23 | if (labelDisplay == LabelDisplay.Field) 24 | { 25 | this.LabelDisplay = LabelDisplay.Field; 26 | } 27 | else if (labelDisplay == LabelDisplay.Custom) 28 | { 29 | this.LabelDisplay = LabelDisplay.Custom; 30 | this.Label = label; 31 | } 32 | else 33 | { 34 | this.LabelDisplay = LabelDisplay.Hidden; 35 | this.Label = ""; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Common/ExposedOutput.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | [AttributeUsage(AttributeTargets.Field)] 10 | public class ExposedOutput : Attribute 11 | { 12 | public LabelDisplay LabelDisplay { get; private set; } 13 | public string Label { get; private set; } 14 | 15 | public ExposedOutput() 16 | { 17 | this.LabelDisplay = LabelDisplay.Hidden; 18 | this.Label = ""; 19 | } 20 | 21 | public ExposedOutput(LabelDisplay labelDisplay, string label = "") 22 | { 23 | if (labelDisplay == LabelDisplay.Field) 24 | { 25 | this.LabelDisplay = LabelDisplay.Field; 26 | } 27 | else if (labelDisplay == LabelDisplay.Custom) 28 | { 29 | this.LabelDisplay = LabelDisplay.Custom; 30 | this.Label = label; 31 | } 32 | else 33 | { 34 | this.LabelDisplay = LabelDisplay.Hidden; 35 | this.Label = ""; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Common/LabelDisplay.cs: -------------------------------------------------------------------------------- 1 | namespace Common 2 | { 3 | public enum LabelDisplay { Hidden, Custom, Field } 4 | } 5 | -------------------------------------------------------------------------------- /Common/NodeBase.cs: -------------------------------------------------------------------------------- 1 | using DataTypes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Common 9 | { 10 | public abstract class NodeBase 11 | { 12 | public virtual void NodeFunction() { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Common/NodeCategory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class NodeCategory : Attribute 11 | { 12 | public string Category { get; private set; } 13 | 14 | public NodeCategory(string category) 15 | { 16 | this.Category = category; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Common/NodeName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class NodeName : Attribute 11 | { 12 | public string Name { get; private set; } 13 | public bool IsHidden { get; private set; } 14 | 15 | public NodeName(string name, bool hidden = false) 16 | { 17 | Name = name; 18 | IsHidden = hidden; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Common/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Common")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Common")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a283d3f9-3bcf-405c-a4c8-37cb73ab6b0e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Common/QueryState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common 8 | { 9 | public class QueryState 10 | { 11 | public Dictionary VariableBag = new Dictionary(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DataTypes/Boolean.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DataTypes 8 | { 9 | public class Boolean : IDataTypeContainer 10 | { 11 | public bool value = false; 12 | 13 | public Boolean() 14 | { 15 | } 16 | 17 | public Boolean(bool val) 18 | { 19 | this.value = val; 20 | } 21 | 22 | public string GetDataAsString() 23 | { 24 | return this.value.ToString(); 25 | } 26 | 27 | public void SetValue(object value) 28 | { 29 | this.value = Convert.ToBoolean(value); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DataTypes/DataTypes.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CB604D32-D358-4F90-9D4A-DF5A6DC5D9DF} 8 | Library 9 | Properties 10 | DataTypes 11 | DataTypes 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /DataTypes/IDataTypeContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DataTypes 8 | { 9 | /// 10 | /// Defines a DataType for use in the graph system. 11 | /// 12 | public interface IDataTypeContainer 13 | { 14 | void SetValue(object value); 15 | string GetDataAsString(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DataTypes/Numeric.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DataTypes 8 | { 9 | public class Numeric : IDataTypeContainer 10 | { 11 | public double value; 12 | 13 | public Numeric() 14 | { 15 | } 16 | 17 | public Numeric(double val) 18 | { 19 | this.value = val; 20 | } 21 | 22 | public string GetDataAsString() 23 | { 24 | return this.value.ToString(); 25 | } 26 | 27 | public void SetValue(object value) 28 | { 29 | this.value = Double.Parse(value.ToString()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DataTypes/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DataTypes")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DataTypes")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("cb604d32-d358-4f90-9d4a-df5a6dc5d9df")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DataTypes/String.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DataTypes 8 | { 9 | public class String : IDataTypeContainer 10 | { 11 | public string value; 12 | 13 | public String() 14 | { 15 | } 16 | 17 | public String(string val) 18 | { 19 | this.value = val; 20 | } 21 | 22 | public string GetDataAsString() 23 | { 24 | return this.value; 25 | } 26 | 27 | public void SetValue(object value) 28 | { 29 | this.value = Convert.ToString(value); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Graph/BaseNodePin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Graph 8 | { 9 | public abstract class BaseNodePin 10 | { 11 | public Type DataType { get; } 12 | public GraphNode Parent { get; } 13 | 14 | public BaseNodePin(Type type, GraphNode parent) 15 | { 16 | DataType = type; 17 | Parent = parent; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Graph/Graph.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BBA5F488-7F2A-44BD-B945-48124D03D429} 8 | Library 9 | Properties 10 | Graph 11 | Graph 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {a283d3f9-3bcf-405c-a4c8-37cb73ab6b0e} 55 | Common 56 | 57 | 58 | {cb604d32-d358-4f90-9d4a-df5a6dc5d9df} 59 | DataTypes 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /Graph/GraphNode.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using DataTypes; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | namespace Graph 10 | { 11 | public class GraphNode 12 | { 13 | /// 14 | /// The class of the node being implemented 15 | /// 16 | public Type NodeType { get; } 17 | 18 | /// 19 | /// Node input pins 20 | /// 21 | public List NodeInputs { get; set; } 22 | 23 | /// 24 | /// Node output pins 25 | /// 26 | public List NodeOutputs { get; set; } 27 | 28 | /// 29 | /// Parent graph manager for the node 30 | /// 31 | public NodeGraphManager GraphManager { get; } 32 | 33 | /// 34 | /// Returns the given execution path for executable nodes 35 | /// 36 | public int ExecutionPath { get; private set; } = -1; 37 | 38 | /// 39 | /// Represents a single node on a graph of interconnected nodes 40 | /// 41 | /// The class of the node being implemented 42 | /// The parent manager of the node 43 | public GraphNode(Type nodeType, NodeGraphManager manager) 44 | { 45 | GraphManager = manager; 46 | 47 | NodeInputs = new List(); 48 | NodeOutputs = new List(); 49 | 50 | NodeType = nodeType; 51 | 52 | // Extract information about the node 53 | FieldInfo[] fields = NodeType.GetFields(); 54 | 55 | // Set input pins 56 | foreach (FieldInfo field in fields) 57 | { 58 | Attribute[] attributes = field.GetCustomAttributes().ToArray(); 59 | 60 | foreach (Attribute attribute in attributes) 61 | { 62 | if (attribute.GetType() == typeof(ExposedInput)) 63 | { 64 | InputPin input = new InputPin(field.FieldType, this); 65 | NodeInputs.Add(input); 66 | } 67 | } 68 | } 69 | 70 | // Set output pins 71 | foreach (FieldInfo field in fields) 72 | { 73 | Attribute[] attributes = field.GetCustomAttributes().ToArray(); 74 | 75 | foreach (Attribute attribute in attributes) 76 | { 77 | if (attribute.GetType() == typeof(ExposedOutput)) 78 | { 79 | OutputPin output = new OutputPin(field.FieldType, this); 80 | NodeOutputs.Add(output); 81 | } 82 | } 83 | } 84 | } 85 | 86 | /// 87 | /// Calculate and realise outputs for the node 88 | /// 89 | public void CalculateOutput() 90 | { 91 | // Get input values 92 | IList nodeInputList = new List(); 93 | 94 | for (int i = 0; i < NodeInputs.Count; i++) 95 | { 96 | IDataTypeContainer inputValue = (IDataTypeContainer)Activator.CreateInstance(NodeInputs[i].DataType); 97 | inputValue.SetValue(NodeInputs[i].GetValue.GetDataAsString()); 98 | 99 | nodeInputList.Add(inputValue); 100 | } 101 | 102 | // Process inputs and realise the outputs 103 | List result; 104 | NodeBase node; 105 | 106 | // If node is executable we need to make sure we pass the query state to it 107 | if (NodeType.IsSubclassOf(typeof(ExecutableNode))) 108 | { 109 | node = (ExecutableNode)Activator.CreateInstance(NodeType, new object[] { GraphManager.QueryState }); 110 | } 111 | else 112 | { 113 | node = (NodeBase)Activator.CreateInstance(NodeType); 114 | } 115 | 116 | // Forward input values to the instantiated node 117 | for (int i = 0; i < NodeInputs.Count; i++) 118 | { 119 | int fieldCounter = 0; 120 | 121 | foreach (FieldInfo field in node.GetType().GetFields()) 122 | { 123 | foreach (Attribute attribute in field.GetCustomAttributes()) 124 | { 125 | if (attribute.GetType() == typeof(ExposedInput)) 126 | { 127 | if (fieldCounter++ == i) 128 | field.SetValue(node, NodeInputs[i].GetValue); 129 | } 130 | } 131 | } 132 | } 133 | 134 | // Ready to calculate the output 135 | node.NodeFunction(); 136 | 137 | result = new List(); 138 | 139 | // Extract the newly calculated output from the node 140 | for (int i = 0; i < NodeOutputs.Count; i++) 141 | { 142 | int fieldCounter = 0; 143 | 144 | foreach (FieldInfo field in node.GetType().GetFields()) 145 | { 146 | foreach (Attribute attribute in field.GetCustomAttributes()) 147 | { 148 | if (attribute.GetType() == typeof(ExposedOutput)) 149 | { 150 | if (fieldCounter++ == i) 151 | result.Add(field.GetValue(node) as IDataTypeContainer); 152 | } 153 | } 154 | } 155 | } 156 | 157 | // And set the outputs in the graph model 158 | for (int i = 0; i < result.Count; i++) 159 | { 160 | NodeOutputs[i].OutputValue = result[i]; 161 | NodeOutputs[i].OutputRealised = true; 162 | } 163 | 164 | if (node is ExecutableNode) 165 | { 166 | ExecutionPath = (node as ExecutableNode).GetExecutionPath(); 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /Graph/InputPin.cs: -------------------------------------------------------------------------------- 1 | using DataTypes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Graph 9 | { 10 | public class InputPin : BaseNodePin 11 | { 12 | public OutputPin InputProviderPin 13 | { 14 | get 15 | { 16 | foreach (PinConnection connection in Parent.GraphManager.Connections) 17 | { 18 | if (connection.InputPin == this) 19 | return connection.OutputPin; 20 | } 21 | 22 | return null; 23 | } 24 | } 25 | 26 | public IDataTypeContainer GetValue 27 | { 28 | get { return InputProviderPin.OutputValue; } 29 | } 30 | 31 | public InputPin(Type inputType, GraphNode parent) : base(inputType, parent) { } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Graph/NodeGraphManager.cs: -------------------------------------------------------------------------------- 1 | using Common; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Graph 7 | { 8 | /// 9 | /// Maintains and manages a graph of interconnected nodes 10 | /// More specifically, the nodes' connections 11 | /// 12 | public class NodeGraphManager 13 | { 14 | /// 15 | /// Connections between input and output pins 16 | /// 17 | public List Connections { get; private set; } 18 | 19 | /// 20 | /// Execution paths between executable nodes 21 | /// 22 | public List> ExecutionConnections { get; private set; } 23 | 24 | /// 25 | /// The query state of the graph being built 26 | /// 27 | public QueryState QueryState { get; } 28 | 29 | private List nodeNetwork; 30 | 31 | public NodeGraphManager() 32 | { 33 | Connections = new List(); 34 | ExecutionConnections = new List>(); 35 | QueryState = new QueryState(); 36 | 37 | nodeNetwork = new List(); 38 | } 39 | 40 | /// 41 | /// Add a new connection between two pins 42 | /// 43 | /// The output pin that will provide a value 44 | /// The input pin the will receive the input 45 | public void AddConnection(OutputPin outputPin, InputPin targetPin) 46 | { 47 | // Make sure we only have one connection per input 48 | foreach (PinConnection connection in Connections) 49 | { 50 | if (connection.InputPin == targetPin) throw new Exception("InputPin already has a connection."); 51 | } 52 | 53 | Connections.Add(new PinConnection(outputPin, targetPin)); 54 | 55 | // Add the connected nodes to our model if we need to 56 | if ((nodeNetwork.Contains(outputPin.Parent) == false) && (outputPin.Parent != null)) 57 | nodeNetwork.Add(outputPin.Parent); 58 | 59 | if (nodeNetwork.Contains(targetPin.Parent) == false) 60 | nodeNetwork.Add(targetPin.Parent); 61 | } 62 | 63 | /// 64 | /// Adds a new execution node to the graph 65 | /// 66 | /// The node to add to the graph 67 | public void AddNode(GraphNode node) 68 | { 69 | if (nodeNetwork.Contains(node) == false) 70 | nodeNetwork.Add(node); 71 | } 72 | 73 | /// 74 | /// Adds a new execution connection between two nodes 75 | /// 76 | /// Node to make connection from 77 | /// Execution index being set on root node 78 | /// The target node for the execution path 79 | public void AddConnection(GraphNode rootNode, int connectionNumber, GraphNode targetNode) 80 | { 81 | ExecutionConnections.Add(new Tuple(rootNode, connectionNumber, targetNode)); 82 | 83 | // Add the connected nodes to our model if we need to 84 | if (nodeNetwork.Contains(rootNode) == false) 85 | nodeNetwork.Add(rootNode); 86 | 87 | if (nodeNetwork.Contains(targetNode) == false) 88 | nodeNetwork.Add(targetNode); 89 | } 90 | 91 | /// 92 | /// Realises all node outputs 93 | /// 94 | public void RealiseNodeOutputs() 95 | { 96 | List unrealisedNodes = new List(); 97 | List realisableNodes = new List(); 98 | 99 | GraphNode currentExecutionNode = null; 100 | 101 | List executableNodes = new List(); 102 | 103 | // Reference executable nodes 104 | foreach (Tuple connection in ExecutionConnections) 105 | { 106 | if (!executableNodes.Contains(connection.Item1)) 107 | executableNodes.Add(connection.Item1); 108 | 109 | if (!executableNodes.Contains(connection.Item3)) 110 | executableNodes.Add(connection.Item3); 111 | } 112 | 113 | bool hasStart = false; 114 | 115 | // Get start node and set it to the currentExecutionNode 116 | foreach (var executableNode in executableNodes) 117 | { 118 | int connectionsIn = 0; 119 | 120 | 121 | foreach (var executionConnection in ExecutionConnections) 122 | { 123 | if (executionConnection.Item3 == executableNode) 124 | connectionsIn++; 125 | } 126 | 127 | if (connectionsIn > 0) 128 | { 129 | continue; 130 | } 131 | else if (connectionsIn == 0) 132 | { 133 | if (hasStart == true) 134 | throw new Exception("Multiple entry points."); 135 | 136 | currentExecutionNode = executableNode; 137 | hasStart = true; 138 | } 139 | } 140 | 141 | // Assume all nodes are unrealised 142 | foreach (GraphNode node in nodeNetwork) 143 | { 144 | unrealisedNodes.Add(node); 145 | } 146 | 147 | // Until we have no unrealised nodes 148 | do 149 | { 150 | List tempList = new List(); 151 | 152 | // See if any nodes are realisable 153 | foreach (GraphNode node in unrealisedNodes) 154 | { 155 | bool isRealisable = true; 156 | 157 | // If this is an execution node 158 | if (executableNodes.Contains(node) && node != currentExecutionNode) 159 | { 160 | foreach (var connection in ExecutionConnections) 161 | { 162 | // If this is the next target execution node and it is along the correct execution path 163 | // then set this node as the new 'current' node 164 | if (connection.Item1 == currentExecutionNode && connection.Item3 == node) 165 | { 166 | if (currentExecutionNode.ExecutionPath == connection.Item2) 167 | currentExecutionNode = node; 168 | } 169 | } 170 | 171 | // Then make sure it is executable 172 | if (node != currentExecutionNode) 173 | { 174 | continue; 175 | } 176 | } 177 | 178 | foreach (InputPin inPin in node.NodeInputs) 179 | { 180 | if (inPin.InputProviderPin.OutputRealised == false) 181 | isRealisable = false; 182 | } 183 | 184 | if (isRealisable) 185 | { 186 | realisableNodes.Add(node); 187 | tempList.Add(node); 188 | } 189 | } 190 | 191 | // If we don't have any realisable nodes then assume graph execution is complete 192 | if (realisableNodes.Count == 0) 193 | { 194 | break; 195 | } 196 | 197 | Parallel.ForEach(realisableNodes, realisable => realisable.CalculateOutput()); 198 | 199 | // Cleanup 200 | foreach (GraphNode cleanupNode in tempList) 201 | { 202 | realisableNodes.Remove(cleanupNode); 203 | unrealisedNodes.Remove(cleanupNode); 204 | } 205 | 206 | } while (unrealisedNodes.Count > 0); 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /Graph/OutputPin.cs: -------------------------------------------------------------------------------- 1 | using DataTypes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Graph 9 | { 10 | public class OutputPin : BaseNodePin 11 | { 12 | public bool OutputRealised { get; set; } 13 | 14 | public List Connections 15 | { 16 | get 17 | { 18 | List returnConnections = new List(); 19 | 20 | foreach (PinConnection connection in Parent.GraphManager.Connections) 21 | { 22 | if (connection.OutputPin == this) 23 | { 24 | returnConnections.Add(connection.InputPin); 25 | } 26 | } 27 | 28 | return returnConnections; 29 | } 30 | } 31 | 32 | public IDataTypeContainer OutputValue { get; set; } 33 | 34 | public OutputPin(Type outputType, GraphNode parent) : base(outputType, parent) 35 | { 36 | OutputRealised = false; 37 | OutputValue = (IDataTypeContainer)Activator.CreateInstance(outputType); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Graph/PinConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Graph 8 | { 9 | public class PinConnection 10 | { 11 | public OutputPin OutputPin { get; set; } 12 | public InputPin InputPin { get; set; } 13 | 14 | public PinConnection(OutputPin outputPin, InputPin inputPin) 15 | { 16 | OutputPin = outputPin; 17 | InputPin = inputPin; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Graph/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Graph")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Graph")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bba5f488-7f2a-44bd-b945-48124d03d429")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Nodes/Basic SQL/SELECT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Basic_SQL 9 | { 10 | [NodeName("SELECT")] 11 | [NodeCategory("Basic SQL")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class SELECT : ExecutableNode 14 | { 15 | [ExposedInput(LabelDisplay.Custom, "Fields")] 16 | public DataTypes.String fields; 17 | 18 | [ExposedInput(LabelDisplay.Custom, "From")] 19 | public DataTypes.String from; 20 | 21 | public SELECT(QueryState state) : base(state) { } 22 | 23 | public override int GetExecutionPath() 24 | { 25 | return 0; 26 | } 27 | 28 | public override void NodeFunction() 29 | { 30 | List selectFields = new List(); 31 | string fieldsString = fields.value; 32 | 33 | string[] values = fieldsString.Split(','); 34 | selectFields.AddRange(values); 35 | 36 | if (State.VariableBag.ContainsKey("SelectFields") == false) 37 | { 38 | State.VariableBag.Add("SelectFields", selectFields); 39 | } 40 | else 41 | { 42 | object existingList; 43 | State.VariableBag.TryGetValue("SelectFields", out existingList); 44 | 45 | List castList = (List)existingList; 46 | castList.AddRange(selectFields); 47 | 48 | State.VariableBag["SelectFields"] = castList; 49 | } 50 | 51 | if (State.VariableBag.ContainsKey("FromTable") == false) 52 | State.VariableBag.Add("FromTable", from.value); 53 | else 54 | State.VariableBag["FromTable"] = from.value; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Nodes/Basic SQL/Where.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Basic_SQL 9 | { 10 | [NodeName("WHERE")] 11 | [NodeCategory("Basic SQL")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class WHERE : ExecutableNode 14 | { 15 | [ExposedInput(LabelDisplay.Custom, "Field")] 16 | public DataTypes.String fields; 17 | 18 | [ExposedInput(LabelDisplay.Custom, "Operation")] 19 | public DataTypes.String operation; 20 | 21 | [ExposedInput(LabelDisplay.Custom, "Value")] 22 | public DataTypes.String value; 23 | 24 | public WHERE(QueryState state) : base(state) { } 25 | 26 | public override int GetExecutionPath() 27 | { 28 | return 0; 29 | } 30 | 31 | public override void NodeFunction() 32 | { 33 | List> whereFields = new List>(); 34 | 35 | if (State.VariableBag.ContainsKey("WhereFields") == false) 36 | { 37 | whereFields.Add(new Tuple(fields.value, operation.value, value.value)); 38 | State.VariableBag.Add("WhereFields", whereFields); 39 | } 40 | else 41 | { 42 | object existingList; 43 | State.VariableBag.TryGetValue("WhereFields", out existingList); 44 | 45 | List> castList = (List>)existingList; 46 | castList.Add(new Tuple(fields.value, operation.value, value.value)); 47 | 48 | State.VariableBag["WhereFields"] = castList; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/And.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("AND")] 11 | [NodeCategory("Boolean Logic")] 12 | public class AND : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Boolean inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Boolean inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value && inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/Equals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("Equals")] 11 | [NodeCategory("Boolean Logic")] 12 | public class Equals : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Numeric inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Numeric inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value == inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/GreaterThan.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("Greater Than")] 11 | [NodeCategory("Boolean Logic")] 12 | public class GreaterThan : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Numeric inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Numeric inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value > inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/GreaterThanEqualTo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("Greater Than Equal To")] 11 | [NodeCategory("Boolean Logic")] 12 | public class GreaterThanEqualTo : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Numeric inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Numeric inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value >= inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/LessThan.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("Less Than")] 11 | [NodeCategory("Boolean Logic")] 12 | public class LessThan : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Numeric inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Numeric inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value < inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/LessThanEqualTo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("Less Than Equal To")] 11 | [NodeCategory("Boolean Logic")] 12 | public class LessThanEqualTo : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Numeric inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Numeric inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value <= inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/Nand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("NAND")] 11 | [NodeCategory("Boolean Logic")] 12 | public class NAND : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Boolean inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Boolean inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(!inputOne.value && !inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/Not.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("NOT")] 11 | [NodeCategory("Boolean Logic")] 12 | public class NOT : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Boolean input; 16 | 17 | [ExposedOutput(LabelDisplay.Hidden)] 18 | public DataTypes.Boolean output; 19 | 20 | public override void NodeFunction() 21 | { 22 | output = new DataTypes.Boolean(!input.value); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/Or.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("OR")] 11 | [NodeCategory("Boolean Logic")] 12 | public class OR : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Boolean inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Boolean inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value || inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Boolean Logic/Xor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Boolean_Logic 9 | { 10 | [NodeName("XOR")] 11 | [NodeCategory("Boolean Logic")] 12 | public class XOR : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Hidden)] 15 | public DataTypes.Boolean inputOne; 16 | 17 | [ExposedInput(LabelDisplay.Hidden)] 18 | public DataTypes.Boolean inputTwo; 19 | 20 | [ExposedOutput(LabelDisplay.Hidden)] 21 | public DataTypes.Boolean output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Boolean(inputOne.value ^ inputTwo.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Conversion/BoolToString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Conversion 9 | { 10 | [NodeName("Bool to String", true)] 11 | [NodeCategory("Converters")] 12 | [ConversionRule(typeof(DataTypes.Boolean), typeof(DataTypes.String))] 13 | public class BoolToString : NodeBase 14 | { 15 | [ExposedInput] 16 | public DataTypes.Boolean input; 17 | 18 | [ExposedOutput] 19 | public DataTypes.String output; 20 | 21 | public override void NodeFunction() 22 | { 23 | output = new DataTypes.String(input.GetDataAsString()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Nodes/Conversion/NumericToString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | using DataTypes; 8 | 9 | namespace Nodes.Conversion 10 | { 11 | [NodeName("Numeric to String", true)] 12 | [NodeCategory("Converters")] 13 | [ConversionRule(typeof(DataTypes.Numeric), typeof(DataTypes.String))] 14 | public class NumericToString : NodeBase 15 | { 16 | [ExposedInput] 17 | public DataTypes.Numeric input; 18 | 19 | [ExposedOutput] 20 | public DataTypes.String output; 21 | 22 | public override void NodeFunction() 23 | { 24 | output = new DataTypes.String(input.GetDataAsString()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Nodes/DebugNodes/DebugPrint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Debug 9 | { 10 | [NodeName("Print")] 11 | [NodeCategory("Debug")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class PrintNode : ExecutableNode 14 | { 15 | [ExposedInput(LabelDisplay.Custom, "Print")] 16 | public DataTypes.String print; 17 | 18 | public PrintNode(QueryState state) : base(state) { } 19 | 20 | public override int GetExecutionPath() 21 | { 22 | return 0; 23 | } 24 | 25 | public override void NodeFunction() 26 | { 27 | string debugOutput = ""; 28 | 29 | // 'DebugPrint' is the output's string key 30 | if (State.VariableBag.ContainsKey("DebugPrint") == false) 31 | { 32 | State.VariableBag.Add("DebugPrint", ""); 33 | } 34 | 35 | debugOutput = State.VariableBag["DebugPrint"].ToString(); 36 | debugOutput += print.GetDataAsString(); 37 | 38 | State.VariableBag["DebugPrint"] = debugOutput; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Nodes/Flow/Branch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Flow 9 | { 10 | [NodeName("Branch")] 11 | [NodeCategory("Flow")] 12 | [ExecutionOutDescription(0, "True")] 13 | [ExecutionOutDescription(1, "False")] 14 | public class Branch : ExecutableNode 15 | { 16 | [ExposedInput(LabelDisplay.Hidden)] 17 | public DataTypes.Boolean condition; 18 | 19 | public Branch(QueryState state) : base(state) { } 20 | 21 | public override int GetExecutionPath() 22 | { 23 | if (condition.value) 24 | return 0; 25 | else 26 | return 1; 27 | } 28 | 29 | public override void NodeFunction() 30 | { 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Nodes/HTML/HTMLBegin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.HTML 9 | { 10 | [NodeName("HTML Begin")] 11 | [NodeCategory("HTML")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class HTMLBegin : ExecutableNode 14 | { 15 | public HTMLBegin(QueryState state) : base(state) { } 16 | 17 | public override int GetExecutionPath() 18 | { 19 | return 0; 20 | } 21 | 22 | public override void NodeFunction() 23 | { 24 | string htmlOutput = ""; 25 | 26 | if (State.VariableBag.ContainsKey("HTML") == false) 27 | { 28 | State.VariableBag.Add("HTML", ""); 29 | } 30 | 31 | htmlOutput = State.VariableBag["HTML"].ToString(); 32 | htmlOutput += "\n"; 33 | 34 | State.VariableBag["HTML"] = htmlOutput; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Nodes/HTML/HTMLBody.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.HTML 9 | { 10 | [NodeName("HTML Body")] 11 | [NodeCategory("HTML")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class HTMLBody : ExecutableNode 14 | { 15 | [ExposedInput(LabelDisplay.Custom, "Body Content")] 16 | public DataTypes.String bodyHTML; 17 | 18 | public HTMLBody(QueryState state) : base(state) { } 19 | 20 | public override int GetExecutionPath() 21 | { 22 | return 0; 23 | } 24 | 25 | public override void NodeFunction() 26 | { 27 | string htmlOutput = ""; 28 | 29 | if (State.VariableBag.ContainsKey("HTML") == false) 30 | { 31 | State.VariableBag.Add("HTML", ""); 32 | } 33 | 34 | htmlOutput = State.VariableBag["HTML"].ToString(); 35 | 36 | htmlOutput += "\n"; 37 | htmlOutput += bodyHTML.GetDataAsString(); 38 | htmlOutput += "\n"; 39 | 40 | State.VariableBag["HTML"] = htmlOutput; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Nodes/HTML/HTMLEnd.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.HTML 9 | { 10 | [NodeName("HTML End")] 11 | [NodeCategory("HTML")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class HTMLEnd : ExecutableNode 14 | { 15 | public HTMLEnd(QueryState state) : base(state) { } 16 | 17 | public override int GetExecutionPath() 18 | { 19 | return 0; 20 | } 21 | 22 | public override void NodeFunction() 23 | { 24 | string htmlOutput = ""; 25 | 26 | if (State.VariableBag.ContainsKey("HTML") == false) 27 | { 28 | State.VariableBag.Add("HTML", ""); 29 | } 30 | 31 | htmlOutput = State.VariableBag["HTML"].ToString(); 32 | htmlOutput += "\n"; 33 | 34 | State.VariableBag["HTML"] = htmlOutput; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Nodes/HTML/HTMLHead.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.HTML 9 | { 10 | [NodeName("HTML Head")] 11 | [NodeCategory("HTML")] 12 | [ExecutionOutDescription(0, "Out")] 13 | public class HTMLHead : ExecutableNode 14 | { 15 | [ExposedInput(LabelDisplay.Custom, "Title")] 16 | public DataTypes.String title; 17 | 18 | public HTMLHead(QueryState state) : base(state) { } 19 | 20 | public override int GetExecutionPath() 21 | { 22 | return 0; 23 | } 24 | 25 | public override void NodeFunction() 26 | { 27 | string htmlOutput = ""; 28 | 29 | if (State.VariableBag.ContainsKey("HTML") == false) 30 | { 31 | State.VariableBag.Add("HTML", ""); 32 | } 33 | 34 | htmlOutput = State.VariableBag["HTML"].ToString(); 35 | htmlOutput += "\n"; 36 | 37 | htmlOutput += "" + title.GetDataAsString() + "\n"; 38 | 39 | htmlOutput += "\n"; 40 | 41 | State.VariableBag["HTML"] = htmlOutput; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Nodes/HTML/Pure/Div.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.HTML.Pure 9 | { 10 | [NodeName("Div")] 11 | [NodeCategory("HTML")] 12 | public class Div : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Custom, "Div Content")] 15 | public DataTypes.String content; 16 | 17 | [ExposedOutput(LabelDisplay.Hidden)] 18 | public DataTypes.String output; 19 | 20 | public override void NodeFunction() 21 | { 22 | string outString = "
\n" + content.GetDataAsString() + "\n
"; 23 | output = new DataTypes.String(outString); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Nodes/HTML/Pure/Paragraph.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.HTML.Pure 9 | { 10 | [NodeName("Paragraph")] 11 | [NodeCategory("HTML")] 12 | public class Paragraph : NodeBase 13 | { 14 | [ExposedInput(LabelDisplay.Custom, "Paragraph Content")] 15 | public DataTypes.String content; 16 | 17 | [ExposedOutput(LabelDisplay.Hidden)] 18 | public DataTypes.String output; 19 | 20 | public override void NodeFunction() 21 | { 22 | string outString = "

"+ content.GetDataAsString() + "

\n"; 23 | output = new DataTypes.String(outString); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Nodes/Maths/Add.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Maths 9 | { 10 | [NodeName("Add")] 11 | [NodeCategory("Maths")] 12 | public class Add : NodeBase 13 | { 14 | [ExposedInput] 15 | public DataTypes.Numeric A; 16 | 17 | [ExposedInput] 18 | public DataTypes.Numeric B; 19 | 20 | [ExposedOutput] 21 | public DataTypes.Numeric output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Numeric(A.value + B.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Maths/Divide.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Maths 9 | { 10 | [NodeName("Divide")] 11 | [NodeCategory("Maths")] 12 | public class Divide : NodeBase 13 | { 14 | [ExposedInput] 15 | public DataTypes.Numeric A; 16 | 17 | [ExposedInput] 18 | public DataTypes.Numeric B; 19 | 20 | [ExposedOutput] 21 | public DataTypes.Numeric output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Numeric(A.value / B.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Maths/Multiply.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Maths 9 | { 10 | [NodeName("Multiply")] 11 | [NodeCategory("Maths")] 12 | public class Multiply : NodeBase 13 | { 14 | [ExposedInput] 15 | public DataTypes.Numeric A; 16 | 17 | [ExposedInput] 18 | public DataTypes.Numeric B; 19 | 20 | [ExposedOutput] 21 | public DataTypes.Numeric output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Numeric(A.value * B.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Maths/Subtract.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.Maths 9 | { 10 | [NodeName("Subtract")] 11 | [NodeCategory("Maths")] 12 | public class Subtract : NodeBase 13 | { 14 | [ExposedInput] 15 | public DataTypes.Numeric A; 16 | 17 | [ExposedInput] 18 | public DataTypes.Numeric B; 19 | 20 | [ExposedOutput] 21 | public DataTypes.Numeric output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.Numeric(A.value - B.value); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nodes/Nodes.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A9F4E2B5-C928-44F3-B5FE-C54EDFDE617B} 8 | Library 9 | Properties 10 | Nodes 11 | Nodes 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {a283d3f9-3bcf-405c-a4c8-37cb73ab6b0e} 76 | Common 77 | 78 | 79 | {cb604d32-d358-4f90-9d4a-df5a6dc5d9df} 80 | DataTypes 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 96 | -------------------------------------------------------------------------------- /Nodes/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Nodes")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Nodes")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a9f4e2b5-c928-44f3-b5fe-c54edfde617b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Nodes/String/Concatenate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Common; 7 | 8 | namespace Nodes.String 9 | { 10 | [NodeName("Concatenate")] 11 | [NodeCategory("String")] 12 | public class Concatenate : NodeBase 13 | { 14 | [ExposedInput] 15 | public DataTypes.String A; 16 | 17 | [ExposedInput] 18 | public DataTypes.String B; 19 | 20 | [ExposedOutput] 21 | public DataTypes.String output; 22 | 23 | public override void NodeFunction() 24 | { 25 | output = new DataTypes.String(A.GetDataAsString() + B.GetDataAsString()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /QueryBuilder.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{A283D3F9-3BCF-405C-A4C8-37CB73AB6B0E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataTypes", "DataTypes\DataTypes.csproj", "{CB604D32-D358-4F90-9D4A-DF5A6DC5D9DF}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nodes", "Nodes\Nodes.csproj", "{A9F4E2B5-C928-44F3-B5FE-C54EDFDE617B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Graph", "Graph\Graph.csproj", "{BBA5F488-7F2A-44BD-B945-48124D03D429}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualQueryApplication", "VisualQueryApplication\VisualQueryApplication.csproj", "{C96143EA-51AC-45DC-8619-C4D8564B5CF2}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {A283D3F9-3BCF-405C-A4C8-37CB73AB6B0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {A283D3F9-3BCF-405C-A4C8-37CB73AB6B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {A283D3F9-3BCF-405C-A4C8-37CB73AB6B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {A283D3F9-3BCF-405C-A4C8-37CB73AB6B0E}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {CB604D32-D358-4F90-9D4A-DF5A6DC5D9DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {CB604D32-D358-4F90-9D4A-DF5A6DC5D9DF}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {CB604D32-D358-4F90-9D4A-DF5A6DC5D9DF}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {CB604D32-D358-4F90-9D4A-DF5A6DC5D9DF}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {A9F4E2B5-C928-44F3-B5FE-C54EDFDE617B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {A9F4E2B5-C928-44F3-B5FE-C54EDFDE617B}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {A9F4E2B5-C928-44F3-B5FE-C54EDFDE617B}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {A9F4E2B5-C928-44F3-B5FE-C54EDFDE617B}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {BBA5F488-7F2A-44BD-B945-48124D03D429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {BBA5F488-7F2A-44BD-B945-48124D03D429}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {BBA5F488-7F2A-44BD-B945-48124D03D429}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {BBA5F488-7F2A-44BD-B945-48124D03D429}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {C96143EA-51AC-45DC-8619-C4D8564B5CF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {C96143EA-51AC-45DC-8619-C4D8564B5CF2}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {C96143EA-51AC-45DC-8619-C4D8564B5CF2}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {C96143EA-51AC-45DC-8619-C4D8564B5CF2}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QueryBuilder 2 | QueryBuilder is an extensible, visual programming system written for WPF. 3 | QueryBuilder was built as a part of a university project, and attempts to provide the foundation for developers 4 | that would like to integrate a visual graph editor into their own projects. 5 | 6 | 7 | 8 | ##Installation 9 | 10 | Setting up QueryBuilder should (hopefully) be quite straightforward. Simply clone the repository into Visual Studio and then build it. 11 | 'VisualQueryApplication' is the front-end editor, and demonstrates how developers might go about implementing the system in 12 | one of their applications. 13 | 14 | 15 | 16 | The 'NodePlugins' folder can be found in the same directory as VisualQueryApplication.exe (try running the executable if it isn't there). 17 | 18 | To add nodes to the system, libraries need to be placed into the NodePlugins folder. The 'Nodes' project distributed with this repository is a library of sample nodes to help get you started. To makes these nodes available in the visual editor, find the compiled 'Nodes.dll' library in the Nodes project binaries folder and add it to the NodePlugins folder in the VisualEditor project. 19 | 20 | 21 | 22 | ## Building a Graph 23 | 24 | ### Adding Nodes and Creating Connections 25 | 26 | To add a node to the graph, double click on an entry from the list on the left (this will only populate when you've added some libraries 27 | to NodePlugins). Pins are the coloured circles that come with the nodes, and they represent either a data connection or a control-flow connection. Currently, all input data pins must be connected for the graph to compile. 28 | 29 | You can create a connection from an output pin (those on the right) to an input pin (those on the left). Do this by clicking on the 30 | output pin you want to take data from, and then clicking on the input pin you want to provide that data to. 31 | 32 | 33 | 34 | You can input values directly by clicking from an input pin and onto the grey canvas area. A small box with only an output pin should 35 | automatically be inserted. These boxes have text fields and will convert their values into a data connection. 36 | 37 | 38 | 39 | If we build the graph now, nothing will happen. We need a print node to extract data from our graph. Print nodes are executable 40 | (impure) nodes. These are nodes that can affect the control-flow and internal state of our graph. The Branch node is a good example of this, but the Print node just takes an input value and prints it to the output log. 41 | 42 | 43 | 44 | When you have a complete graph, press Build, and then 'View Query' to see the output! 45 | 46 | ### Data Types 47 | 48 | There are three data types defined in the system: 49 | - Numeric (green) 50 | - String (pink) 51 | - Boolean (red) 52 | 53 | These are defined in the DataTypes project. These can be changed without too much hassle. 54 | 55 | ## Custom Nodes 56 | 57 | Custom nodes can be added by extending the NodeBase and ExecutableNode classes. NodeBase defines a pure node (one with no execution pins) and ExecutableNode defines an impure node. Input and Output pins are denoted by the ExposedInput and ExposedOutput attributes respectively. NodeFunction is the function executed when the graph activates the node. 58 | 59 | ```C# 60 | [NodeName("Add")] 61 | [NodeCategory("Maths")] 62 | public class Add : NodeBase 63 | { 64 | [ExposedInput] 65 | public DataTypes.Numeric A; 66 | 67 | [ExposedInput] 68 | public DataTypes.Numeric B; 69 | 70 | [ExposedOutput] 71 | public DataTypes.Numeric output; 72 | 73 | public override void NodeFunction() 74 | { 75 | output = new DataTypes.Numeric(A.value + B.value); 76 | } 77 | } 78 | ``` 79 | 80 | Executable nodes are defined in a similar way. Their execution paths are declared with ExecutionOutDescription. GetExecutionPath tells the graph which output path to follow. A QueryState object is passed into the constructor--this represents the 'state' of the entire graph and you can add any variables you like to it. This can be used for communicating between nodes and building more complex functionality. 81 | 82 | ```C# 83 | [NodeName("Branch")] 84 | [NodeCategory("Flow")] 85 | [ExecutionOutDescription(0, "True")] 86 | [ExecutionOutDescription(1, "False")] 87 | public class Branch : ExecutableNode 88 | { 89 | [ExposedInput(LabelDisplay.Hidden)] 90 | public DataTypes.Boolean condition; 91 | 92 | public Branch(QueryState state) : base(state) { } 93 | 94 | public override int GetExecutionPath() 95 | { 96 | if (condition.value) 97 | return 0; 98 | else 99 | return 1; 100 | } 101 | 102 | public override void NodeFunction() 103 | { 104 | } 105 | } 106 | ``` 107 | 108 | ## Contact 109 | 110 | Feel free to email callumevans@outlook.com for any help. 111 | -------------------------------------------------------------------------------- /VisualQueryApplication/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /VisualQueryApplication/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /VisualQueryApplication/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows; 4 | 5 | namespace VisualQueryApplication 6 | { 7 | /// 8 | /// Interaction logic for App.xaml 9 | /// 10 | public partial class App : Application 11 | { 12 | public static readonly string ApplicationRoot = AppDomain.CurrentDomain.BaseDirectory; 13 | public static readonly string PluginFolderPath = ApplicationRoot + "/NodePlugins"; 14 | 15 | public App() 16 | { 17 | if (!Directory.Exists(PluginFolderPath)) 18 | Directory.CreateDirectory(PluginFolderPath); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/ConstantNode.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/ConstantNode.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Input; 3 | using VisualQueryApplication.ViewModels; 4 | 5 | namespace VisualQueryApplication.Controls.GraphBuilder 6 | { 7 | /// 8 | /// Interaction logic for ConstantNode.xaml 9 | /// 10 | public partial class ConstantNode : UserControl 11 | { 12 | public ConstantNode() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | private void ConstantNode_MouseDown(object sender, MouseButtonEventArgs e) 18 | { 19 | VisualGraphComponentViewModel viewModel = ((VisualGraphComponentViewModel)this.DataContext); 20 | viewModel.ClickedCommand.Execute(null); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/NodePin.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/NodePin.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Input; 6 | using System.Windows.Media; 7 | using System.Windows.Threading; 8 | using VisualQueryApplication.ViewModels; 9 | 10 | namespace VisualQueryApplication.Controls.GraphBuilder 11 | { 12 | /// 13 | /// Interaction logic for NodePin.xaml 14 | /// 15 | public partial class NodePin : UserControl, INotifyPropertyChanged 16 | { 17 | private SolidColorBrush pinColourCache; 18 | 19 | public event PropertyChangedEventHandler PropertyChanged; 20 | 21 | public Point Centre 22 | { 23 | get 24 | { 25 | 26 | Point centre = this.TransformToAncestor( 27 | ((MainWindow)App.Current.MainWindow).VisualEditor.ContentArea) 28 | .Transform(new Point(this.Width / 2, this.Height / 2)); 29 | 30 | return centre; 31 | } 32 | } 33 | 34 | public NodePin() 35 | { 36 | InitializeComponent(); 37 | } 38 | 39 | public void ParentMoved() 40 | { 41 | OnPropertyChanged(nameof(Centre)); 42 | } 43 | 44 | protected virtual void OnPropertyChanged(string propertyName) 45 | { 46 | var handler = PropertyChanged; 47 | if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 48 | } 49 | 50 | private void NodePin_Loaded(object sender, RoutedEventArgs e) 51 | { 52 | NodePinViewModel viewModel = ((NodePinViewModel)DataContext); 53 | 54 | this.pinColourCache = viewModel.PinColour; 55 | viewModel.Pin = this; 56 | } 57 | 58 | 59 | private void NodePin_MouseEnter(object sender, MouseEventArgs e) 60 | { 61 | var colour = ((NodePinViewModel)DataContext).PinColour.Color; 62 | 63 | SolidColorBrush adjustedColour = new SolidColorBrush(Color.FromArgb( 64 | colour.A, 65 | (byte)Math.Min(255, colour.R + 255 * 0.3), 66 | (byte)Math.Min(255, colour.G + 255 * 0.3), 67 | (byte)Math.Min(255, colour.B + 255 * 0.3) 68 | )); 69 | 70 | ((NodePinViewModel)DataContext).PinColour = adjustedColour; 71 | } 72 | 73 | private void NodePin_MouseLeave(object sender, MouseEventArgs e) 74 | { 75 | ((NodePinViewModel)DataContext).PinColour = pinColourCache; 76 | } 77 | 78 | private void NodePin_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 79 | { 80 | DependencyObject parentObject = VisualTreeHelper.GetParent(this); 81 | 82 | // Find the visual editor 83 | while (!(parentObject is VisualEditor)) 84 | { 85 | parentObject = VisualTreeHelper.GetParent(parentObject); 86 | 87 | if (parentObject == null) 88 | return; 89 | } 90 | 91 | VisualEditor visualEditor = parentObject as VisualEditor; 92 | 93 | // Determine how to handle the click 94 | if (visualEditor.IsCreatingConnection) 95 | { 96 | // If we are creating a new connection then we have to validate and add a new one 97 | GraphEditorViewModel graph = ((GraphEditorViewModel)visualEditor.DataContext); 98 | ConnectionBuilderViewModel connectionBuilder = ((ConnectionBuilderViewModel)visualEditor.NewConnectionLine.DataContext); 99 | 100 | NodePinViewModel rootPin = (NodePinViewModel)connectionBuilder.OutputPin.DataContext; 101 | NodePinViewModel targetPin = (NodePinViewModel)this.DataContext; 102 | 103 | // Validate the output and input pins 104 | // Reverse them if needed 105 | // TODO: More extensive validation. ie. Check for output -> output or input -> input connections. 106 | 107 | // Ensure datatypes are the same between pins 108 | if (rootPin.DataType != targetPin.DataType) 109 | { 110 | // If the data types do not match try and add in an auto-conversion 111 | foreach (var rule in graph.ConversionRules) 112 | { 113 | if (rule.Item1 == rootPin.DataType && rule.Item2 == targetPin.DataType) 114 | { 115 | // Conversion rule found! 116 | // Add the conversion node at the midpoint between pins 117 | Point rootPoint = rootPin.Pin.Centre; 118 | Point targetPoint = targetPin.Pin.Centre; 119 | 120 | Point midPoint = new Point( 121 | ((rootPoint.X + targetPoint.X) / 2), 122 | (rootPoint.Y + targetPoint.Y) / 2); 123 | 124 | VisualNodeViewModel conversionNode = new VisualNodeViewModel(rule.Item3) 125 | { 126 | X = midPoint.X, 127 | Y = midPoint.Y 128 | }; 129 | 130 | graph.VisualNodes.Add(conversionNode); 131 | 132 | // Generate the conversion node's view so we can access its pins 133 | Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null); 134 | 135 | // Add the new connections, but ensure it is an OutputPin -> InputPin connection 136 | // Otherwise, we need to correct for that here 137 | if (((NodePinViewModel)connectionBuilder.OutputPin.DataContext).IsOutputPin == false) 138 | { 139 | // Connections need flipping 140 | graph.Connections.Add(new ConnectionViewModel(targetPin.Pin, conversionNode.Inputs[0].Pin)); 141 | graph.Connections.Add(new ConnectionViewModel(conversionNode.Outputs[0].Pin, rootPin.Pin)); 142 | } 143 | else 144 | { 145 | // Connection is correct 146 | graph.Connections.Add(new ConnectionViewModel(rootPin.Pin, conversionNode.Inputs[0].Pin)); 147 | graph.Connections.Add(new ConnectionViewModel(conversionNode.Outputs[0].Pin, targetPin.Pin)); 148 | } 149 | 150 | } 151 | } 152 | } 153 | // If datatypes are the same, we can just create a connection between the pins 154 | // Make sure the connection is added in an OutputPin -> InputPin order 155 | else 156 | { 157 | if (((NodePinViewModel)connectionBuilder.OutputPin.DataContext).IsOutputPin == false) 158 | graph.Connections.Add(new ConnectionViewModel(this, connectionBuilder.OutputPin)); 159 | else 160 | graph.Connections.Add(new ConnectionViewModel(connectionBuilder.OutputPin, this)); 161 | } 162 | 163 | visualEditor.IsCreatingConnection = false; 164 | } 165 | else 166 | { 167 | // We need to initialise the 'create a connection' mode 168 | visualEditor.IsCreatingConnection = true; 169 | 170 | // And set the root pin 171 | ConnectionBuilderViewModel newConnection = ((ConnectionBuilderViewModel)visualEditor.NewConnectionLine.DataContext); 172 | newConnection.OutputPin = this; 173 | } 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/VisualEditor.xaml: -------------------------------------------------------------------------------- 1 |  17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/VisualEditor.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | using System.Windows.Controls.Primitives; 5 | using System.Windows.Input; 6 | using System.Windows.Threading; 7 | using VisualQueryApplication.ViewModels; 8 | 9 | namespace VisualQueryApplication.Controls.GraphBuilder 10 | { 11 | /// 12 | /// Interaction logic for VisualEditor.xaml 13 | /// 14 | public partial class VisualEditor : UserControl 15 | { 16 | public bool IsCreatingConnection 17 | { 18 | get { return isCreatingConnection; } 19 | set 20 | { 21 | isCreatingConnection = value; 22 | 23 | if (IsCreatingConnection) 24 | NewConnectionLine.Visibility = Visibility.Visible; 25 | else 26 | NewConnectionLine.Visibility = Visibility.Hidden; 27 | } 28 | } 29 | 30 | private bool isCreatingConnection = false; 31 | 32 | public ItemsControl ContentArea 33 | { 34 | get { return ContentDisplay; } 35 | } 36 | 37 | public VisualEditor() 38 | { 39 | InitializeComponent(); 40 | 41 | this.DataContext = new GraphEditorViewModel(this); 42 | NewConnectionLine.DataContext = new ConnectionBuilderViewModel(); 43 | } 44 | 45 | private void Thumb_DragDelta(object sender, DragDeltaEventArgs e) 46 | { 47 | if (IsCreatingConnection) 48 | return; 49 | 50 | Thumb thumb = (Thumb)sender; 51 | 52 | var node = (VisualGraphComponentViewModel)thumb.DataContext; 53 | 54 | node.X += e.HorizontalChange; 55 | node.Y += e.VerticalChange; 56 | 57 | VisualNodeViewModel visualNode = node as VisualNodeViewModel; 58 | 59 | if (visualNode != null) 60 | { 61 | foreach (var input in visualNode.Inputs) 62 | { 63 | input.Pin.ParentMoved(); 64 | } 65 | 66 | foreach (var output in visualNode.Outputs) 67 | { 68 | output.Pin.ParentMoved(); 69 | } 70 | 71 | foreach (var executionInput in visualNode.ExecutionInputs) 72 | { 73 | executionInput.Pin.ParentMoved(); 74 | } 75 | 76 | foreach (var executionOutput in visualNode.ExecutionOutputs) 77 | { 78 | executionOutput.Pin.ParentMoved(); 79 | } 80 | 81 | return; 82 | } 83 | 84 | VisualConstantNodeViewModel constantNode = node as VisualConstantNodeViewModel; 85 | 86 | if (constantNode != null) 87 | { 88 | constantNode.OutputPin.Pin.ParentMoved(); 89 | return; 90 | } 91 | } 92 | 93 | private void VisualNode_MouseDown(object sender, MouseButtonEventArgs e) 94 | { 95 | UserControl controlSender = (UserControl)sender; 96 | VisualGraphComponentViewModel node = (VisualGraphComponentViewModel)controlSender.DataContext; 97 | 98 | GraphEditorViewModel graphViewModel = (GraphEditorViewModel)DataContext; 99 | 100 | node.ZIndex = graphViewModel.FindMaxZIndex() + 10; 101 | } 102 | 103 | private void Editor_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 104 | { 105 | // If we are creating a connection... 106 | if (IsCreatingConnection) 107 | { 108 | ConnectionBuilderViewModel connectionBuilder = (ConnectionBuilderViewModel)NewConnectionLine.DataContext; 109 | NodePinViewModel connectionRootPin = (NodePinViewModel)connectionBuilder.OutputPin.DataContext; 110 | 111 | // Check if we are clicking from an input pin 112 | // If we are, try to automatically place a constant node connecting to the input pin 113 | if (connectionRootPin.IsOutputPin == false && connectionRootPin.IsExecutionPin == false) 114 | { 115 | GraphEditorViewModel viewModel = (GraphEditorViewModel)this.DataContext; 116 | VisualConstantNodeViewModel autoConstantNode = new VisualConstantNodeViewModel(connectionRootPin.DataType) 117 | { 118 | X = viewModel.MousePoint.X, 119 | Y = viewModel.MousePoint.Y 120 | }; 121 | 122 | viewModel.VisualNodes.Add(autoConstantNode); 123 | 124 | // Generates the view for the NodePin in the constant node before we add it 125 | Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null); 126 | 127 | viewModel.Connections.Add(new ConnectionViewModel(autoConstantNode.OutputPin.Pin, connectionRootPin.Pin)); 128 | } 129 | 130 | IsCreatingConnection = false; 131 | return; 132 | } 133 | 134 | // If we aren't creating a connection just deselect any nodes 135 | foreach (VisualGraphComponentViewModel node in ((GraphEditorViewModel)DataContext).VisualNodes) 136 | { 137 | node.IsSelected = false; 138 | } 139 | } 140 | 141 | private void VisualEditor_OnMouseMove(object sender, MouseEventArgs e) 142 | { 143 | if (!isCreatingConnection) 144 | return; 145 | 146 | var connectionLine = ((ConnectionBuilderViewModel)NewConnectionLine.DataContext); 147 | connectionLine.MousePosition = ((GraphEditorViewModel)this.DataContext).MousePoint; 148 | } 149 | 150 | private void VisualEditor_OnKeyDown(object sender, KeyEventArgs e) 151 | { 152 | switch (e.Key) 153 | { 154 | case Key.Delete: 155 | 156 | if (IsCreatingConnection) 157 | { 158 | IsCreatingConnection = false; 159 | return; 160 | } 161 | 162 | ((GraphEditorViewModel)DataContext).DeleteSelectedNodesCommand.Execute(null); 163 | break; 164 | } 165 | } 166 | 167 | private void VisualEditor_OnLostFocus(object sender, RoutedEventArgs e) 168 | { 169 | foreach (var node in ((GraphEditorViewModel)DataContext).VisualNodes) 170 | { 171 | node.IsSelected = false; 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/VisualNodeControl.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 15 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/VisualNodeControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Input; 3 | using VisualQueryApplication.ViewModels; 4 | 5 | namespace VisualQueryApplication.Controls.GraphBuilder 6 | { 7 | /// 8 | /// Interaction logic for VisualChartBox.xaml 9 | /// 10 | public partial class VisualNodeControl : UserControl 11 | { 12 | public VisualNodeControl() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | private void VisualNodeBoxControl_MouseDown(object sender, MouseButtonEventArgs e) 18 | { 19 | VisualGraphComponentViewModel viewModel = ((VisualGraphComponentViewModel)this.DataContext); 20 | viewModel.ClickedCommand.Execute(null); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/ZoomAndPan/AnimationHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Media.Animation; 4 | 5 | namespace VisualQueryApplication.Controls.GraphBuilder.ZoomAndPan 6 | { 7 | /// 8 | /// A helper class to simplify animation. 9 | /// 10 | public static class AnimationHelper 11 | { 12 | /// 13 | /// Starts an animation to a particular value on the specified dependency property. 14 | /// 15 | public static void StartAnimation(UIElement animatableElement, DependencyProperty dependencyProperty, double toValue, double animationDurationSeconds) 16 | { 17 | StartAnimation(animatableElement, dependencyProperty, toValue, animationDurationSeconds, null); 18 | } 19 | 20 | /// 21 | /// Starts an animation to a particular value on the specified dependency property. 22 | /// You can pass in an event handler to call when the animation has completed. 23 | /// 24 | public static void StartAnimation(UIElement animatableElement, DependencyProperty dependencyProperty, double toValue, double animationDurationSeconds, EventHandler completedEvent) 25 | { 26 | double fromValue = (double)animatableElement.GetValue(dependencyProperty); 27 | 28 | DoubleAnimation animation = new DoubleAnimation(); 29 | animation.From = fromValue; 30 | animation.To = toValue; 31 | animation.Duration = TimeSpan.FromSeconds(animationDurationSeconds); 32 | 33 | animation.Completed += delegate (object sender, EventArgs e) 34 | { 35 | // 36 | // When the animation has completed bake final value of the animation 37 | // into the property. 38 | // 39 | animatableElement.SetValue(dependencyProperty, animatableElement.GetValue(dependencyProperty)); 40 | CancelAnimation(animatableElement, dependencyProperty); 41 | 42 | if (completedEvent != null) 43 | { 44 | completedEvent(sender, e); 45 | } 46 | }; 47 | 48 | animation.Freeze(); 49 | 50 | animatableElement.BeginAnimation(dependencyProperty, animation); 51 | } 52 | 53 | /// 54 | /// Cancel any animations that are running on the specified dependency property. 55 | /// 56 | public static void CancelAnimation(UIElement animatableElement, DependencyProperty dependencyProperty) 57 | { 58 | animatableElement.BeginAnimation(dependencyProperty, null); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/ZoomAndPan/Generic.xaml: -------------------------------------------------------------------------------- 1 |  4 | 46 | -------------------------------------------------------------------------------- /VisualQueryApplication/Controls/GraphBuilder/ZoomAndPan/ZoomAndPanControl_IScrollInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using System.Windows.Controls; 4 | 5 | namespace VisualQueryApplication.Controls.GraphBuilder.ZoomAndPan 6 | { 7 | /// 8 | /// This is an extension to the ZoomAndPanControol class that implements 9 | /// the IScrollInfo interface properties and functions. 10 | /// 11 | /// IScrollInfo is implemented to allow ZoomAndPanControl to be wrapped (in XAML) 12 | /// in a ScrollViewer. IScrollInfo allows the ScrollViewer and ZoomAndPanControl to 13 | /// communicate important information such as the horizontal and vertical scrollbar offsets. 14 | /// 15 | /// There is a good series of articles showing how to implement IScrollInfo starting here: 16 | /// http://blogs.msdn.com/bencon/archive/2006/01/05/509991.aspx 17 | /// 18 | /// 19 | public partial class ZoomAndPanControl 20 | { 21 | /// 22 | /// Set to 'true' when the vertical scrollbar is enabled. 23 | /// 24 | public bool CanVerticallyScroll 25 | { 26 | get 27 | { 28 | return canVerticallyScroll; 29 | } 30 | set 31 | { 32 | canVerticallyScroll = value; 33 | } 34 | } 35 | 36 | /// 37 | /// Set to 'true' when the vertical scrollbar is enabled. 38 | /// 39 | public bool CanHorizontallyScroll 40 | { 41 | get 42 | { 43 | return canHorizontallyScroll; 44 | } 45 | set 46 | { 47 | canHorizontallyScroll = value; 48 | } 49 | } 50 | 51 | /// 52 | /// The width of the content (with 'ContentScale' applied). 53 | /// 54 | public double ExtentWidth 55 | { 56 | get 57 | { 58 | return unScaledExtent.Width * ContentScale; 59 | } 60 | } 61 | 62 | /// 63 | /// The height of the content (with 'ContentScale' applied). 64 | /// 65 | public double ExtentHeight 66 | { 67 | get 68 | { 69 | return unScaledExtent.Height * ContentScale; 70 | } 71 | } 72 | 73 | /// 74 | /// Get the width of the viewport onto the content. 75 | /// 76 | public double ViewportWidth 77 | { 78 | get 79 | { 80 | return viewport.Width; 81 | } 82 | } 83 | 84 | /// 85 | /// Get the height of the viewport onto the content. 86 | /// 87 | public double ViewportHeight 88 | { 89 | get 90 | { 91 | return viewport.Height; 92 | } 93 | } 94 | 95 | /// 96 | /// Reference to the ScrollViewer that is wrapped (in XAML) around the ZoomAndPanControl. 97 | /// Or set to null if there is no ScrollViewer. 98 | /// 99 | public ScrollViewer ScrollOwner 100 | { 101 | get 102 | { 103 | return scrollOwner; 104 | } 105 | set 106 | { 107 | scrollOwner = value; 108 | } 109 | } 110 | 111 | /// 112 | /// The offset of the horizontal scrollbar. 113 | /// 114 | public double HorizontalOffset 115 | { 116 | get 117 | { 118 | return ContentOffsetX * ContentScale; 119 | } 120 | } 121 | 122 | /// 123 | /// The offset of the vertical scrollbar. 124 | /// 125 | public double VerticalOffset 126 | { 127 | get 128 | { 129 | return ContentOffsetY * ContentScale; 130 | } 131 | } 132 | 133 | /// 134 | /// Called when the offset of the horizontal scrollbar has been set. 135 | /// 136 | public void SetHorizontalOffset(double offset) 137 | { 138 | if (disableScrollOffsetSync) 139 | { 140 | return; 141 | } 142 | 143 | try 144 | { 145 | disableScrollOffsetSync = true; 146 | 147 | ContentOffsetX = offset / ContentScale; 148 | } 149 | finally 150 | { 151 | disableScrollOffsetSync = false; 152 | } 153 | } 154 | 155 | /// 156 | /// Called when the offset of the vertical scrollbar has been set. 157 | /// 158 | public void SetVerticalOffset(double offset) 159 | { 160 | if (disableScrollOffsetSync) 161 | { 162 | return; 163 | } 164 | 165 | try 166 | { 167 | disableScrollOffsetSync = true; 168 | 169 | ContentOffsetY = offset / ContentScale; 170 | } 171 | finally 172 | { 173 | disableScrollOffsetSync = false; 174 | } 175 | } 176 | 177 | /// 178 | /// Shift the content offset one line up. 179 | /// 180 | public void LineUp() 181 | { 182 | ContentOffsetY -= (ContentViewportHeight / 10); 183 | } 184 | 185 | /// 186 | /// Shift the content offset one line down. 187 | /// 188 | public void LineDown() 189 | { 190 | ContentOffsetY += (ContentViewportHeight / 10); 191 | } 192 | 193 | /// 194 | /// Shift the content offset one line left. 195 | /// 196 | public void LineLeft() 197 | { 198 | ContentOffsetX -= (ContentViewportWidth / 10); 199 | } 200 | 201 | /// 202 | /// Shift the content offset one line right. 203 | /// 204 | public void LineRight() 205 | { 206 | ContentOffsetX += (ContentViewportWidth / 10); 207 | } 208 | 209 | /// 210 | /// Shift the content offset one page up. 211 | /// 212 | public void PageUp() 213 | { 214 | ContentOffsetY -= ContentViewportHeight; 215 | } 216 | 217 | /// 218 | /// Shift the content offset one page down. 219 | /// 220 | public void PageDown() 221 | { 222 | ContentOffsetY += ContentViewportHeight; 223 | } 224 | 225 | /// 226 | /// Shift the content offset one page left. 227 | /// 228 | public void PageLeft() 229 | { 230 | ContentOffsetX -= ContentViewportWidth; 231 | } 232 | 233 | /// 234 | /// Shift the content offset one page right. 235 | /// 236 | public void PageRight() 237 | { 238 | ContentOffsetX += ContentViewportWidth; 239 | } 240 | 241 | /// 242 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is 243 | /// used for zooming in and out, not for manipulating the scrollbars. 244 | /// 245 | public void MouseWheelDown() 246 | { 247 | if (IsMouseWheelScrollingEnabled) 248 | { 249 | LineDown(); 250 | } 251 | } 252 | 253 | /// 254 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is 255 | /// used for zooming in and out, not for manipulating the scrollbars. 256 | /// 257 | public void MouseWheelLeft() 258 | { 259 | if (IsMouseWheelScrollingEnabled) 260 | { 261 | LineLeft(); 262 | } 263 | } 264 | 265 | /// 266 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is 267 | /// used for zooming in and out, not for manipulating the scrollbars. 268 | /// 269 | public void MouseWheelRight() 270 | { 271 | if (IsMouseWheelScrollingEnabled) 272 | { 273 | LineRight(); 274 | } 275 | } 276 | 277 | /// 278 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is 279 | /// used for zooming in and out, not for manipulating the scrollbars. 280 | /// 281 | public void MouseWheelUp() 282 | { 283 | if (IsMouseWheelScrollingEnabled) 284 | { 285 | LineUp(); 286 | } 287 | } 288 | 289 | /// 290 | /// Bring the specified rectangle to view. 291 | /// 292 | public Rect MakeVisible(Visual visual, Rect rectangle) 293 | { 294 | if (content.IsAncestorOf(visual)) 295 | { 296 | Rect transformedRect = visual.TransformToAncestor(content).TransformBounds(rectangle); 297 | Rect viewportRect = new Rect(ContentOffsetX, ContentOffsetY, ContentViewportWidth, ContentViewportHeight); 298 | if (!transformedRect.Contains(viewportRect)) 299 | { 300 | double horizOffset = 0; 301 | double vertOffset = 0; 302 | 303 | if (transformedRect.Left < viewportRect.Left) 304 | { 305 | // 306 | // Want to move viewport left. 307 | // 308 | horizOffset = transformedRect.Left - viewportRect.Left; 309 | } 310 | else if (transformedRect.Right > viewportRect.Right) 311 | { 312 | // 313 | // Want to move viewport right. 314 | // 315 | horizOffset = transformedRect.Right - viewportRect.Right; 316 | } 317 | 318 | if (transformedRect.Top < viewportRect.Top) 319 | { 320 | // 321 | // Want to move viewport up. 322 | // 323 | vertOffset = transformedRect.Top - viewportRect.Top; 324 | } 325 | else if (transformedRect.Bottom > viewportRect.Bottom) 326 | { 327 | // 328 | // Want to move viewport down. 329 | // 330 | vertOffset = transformedRect.Bottom - viewportRect.Bottom; 331 | } 332 | 333 | SnapContentOffsetTo(new Point(ContentOffsetX + horizOffset, ContentOffsetY + vertOffset)); 334 | } 335 | } 336 | return rectangle; 337 | } 338 | 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /VisualQueryApplication/GeneratedQueryView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |