(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 |
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 |
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 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
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 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/VisualQueryApplication/GeneratedQueryView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Forms;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Shapes;
15 | using VisualQueryApplication.ViewModels;
16 |
17 | namespace VisualQueryApplication
18 | {
19 | ///
20 | /// Interaction logic for GeneratedQueryView.xaml
21 | ///
22 | public partial class GeneratedQueryView : Window
23 | {
24 | private readonly Action CallbackOnClose;
25 |
26 | public GeneratedQueryView(Action parentCallbackOnClose)
27 | {
28 | InitializeComponent();
29 |
30 | CallbackOnClose = parentCallbackOnClose;
31 | this.Closed += GeneratedQueryView_Closed;
32 | }
33 |
34 | private void GeneratedQueryView_Closed(object sender, EventArgs e)
35 | {
36 | CallbackOnClose.Invoke();
37 | }
38 |
39 | private void SaveButton_OnClick(object sender, RoutedEventArgs e)
40 | {
41 | SaveFileDialog saveFileDialog = new SaveFileDialog();
42 |
43 | if (saveFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
44 | {
45 | string saveFile = saveFileDialog.FileName;
46 |
47 | string text = ((GeneratedQueryViewViewModel)DataContext).Query;
48 |
49 | System.IO.StreamWriter file = new System.IO.StreamWriter(saveFile);
50 | file.WriteLine(text);
51 |
52 | file.Close();
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/VisualQueryApplication/Graph.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Common;
5 | using DataTypes;
6 | using Graph;
7 | using VisualQueryApplication.ViewModels;
8 | using Boolean = System.Boolean;
9 |
10 | namespace VisualQueryApplication
11 | {
12 | public static class Graph
13 | {
14 | public async static Task BuildGraphAsync(GraphEditorViewModel graph)
15 | {
16 | return await Task.Run(() => BuildGraph(graph));
17 | }
18 |
19 | public static NodeGraphManager BuildGraph(GraphEditorViewModel graph)
20 | {
21 | List visualExecutionNodes = new List();
22 |
23 | foreach (var graphComponent in graph.VisualNodes)
24 | {
25 | VisualNodeViewModel visualNode = graphComponent as VisualNodeViewModel;
26 | if (visualNode != null && visualNode.ExecutionInputs.Count > 0)
27 | {
28 | visualExecutionNodes.Add(visualNode);
29 | }
30 | }
31 |
32 | // Begin to build our graph
33 | NodeGraphManager graphManager = new NodeGraphManager();
34 |
35 | Dictionary functionNodes = new Dictionary();
36 | List constantNodes = new List();
37 |
38 | foreach (dynamic visualNode in graph.VisualNodes)
39 | {
40 | if (visualNode is VisualNodeViewModel)
41 | {
42 | functionNodes.Add(visualNode, new GraphNode(visualNode.NodeType, graphManager));
43 | }
44 | else if (visualNode is VisualConstantNodeViewModel)
45 | {
46 | constantNodes.Add(visualNode as VisualConstantNodeViewModel);
47 | }
48 | }
49 |
50 | // Wire up constant nodes
51 | foreach (var constantNode in constantNodes)
52 | {
53 | List connections = GetPinConnections(constantNode.OutputPin, graph);
54 |
55 | // Lookup each input pin that the constant node is connecting to and add it in our graph manager
56 | foreach (var connection in connections)
57 | {
58 | foreach (var functionNode in functionNodes)
59 | {
60 | if (functionNode.Key.Inputs.Contains(connection.InputPin))
61 | {
62 | // Get pin index
63 | int pindex = ((NodePinViewModel)connection.InputPin).Index;
64 |
65 | IDataTypeContainer valueToSet;
66 |
67 | // Get value to set
68 | if (constantNode.OutputPin.DataType == typeof(DataTypes.Numeric))
69 | {
70 | valueToSet = new DataTypes.Numeric(Double.Parse(constantNode.Value));
71 | }
72 | else if (constantNode.OutputPin.DataType == typeof(DataTypes.Boolean))
73 | {
74 | valueToSet = new DataTypes.Boolean(Boolean.Parse(constantNode.Value));
75 | }
76 | else if (constantNode.OutputPin.DataType == typeof (DataTypes.String))
77 | {
78 | valueToSet = new DataTypes.String(constantNode.Value);
79 | }
80 | else
81 | {
82 | throw new Exception("Data type could not be determined.");
83 | }
84 |
85 | OutputPin pinConnection = new OutputPin(
86 | ((NodePinViewModel)connection.InputPin).DataType, null)
87 | { OutputValue = valueToSet, OutputRealised = true };
88 |
89 |
90 | graphManager.AddConnection(pinConnection, functionNode.Value.NodeInputs[pindex]);
91 | }
92 | }
93 | }
94 | }
95 |
96 | // Wire up functional nodes
97 | foreach (var functionNode in functionNodes)
98 | {
99 | int outputPindex = 0;
100 |
101 | // Check each output pin on the node
102 | foreach (var output in functionNode.Key.Outputs)
103 | {
104 | List connections = GetPinConnections(output, graph);
105 |
106 | foreach (var connection in connections)
107 | {
108 | // Wire up non-execution pins
109 | foreach (var targetFunctionNode in functionNodes)
110 | {
111 | if (targetFunctionNode.Key.Inputs.Contains(connection.InputPin))
112 | {
113 | int pindex = ((NodePinViewModel)connection.InputPin).Index;
114 |
115 | graphManager.AddConnection(
116 | functionNodes[functionNode.Key].NodeOutputs[outputPindex],
117 | targetFunctionNode.Value.NodeInputs[pindex]);
118 | }
119 | }
120 | }
121 | }
122 |
123 | // Wire up execution pins
124 | foreach (var executionOutput in functionNode.Key.ExecutionOutputs)
125 | {
126 | List connections = GetPinConnections(executionOutput, graph);
127 |
128 | if (connections.Count == 0)
129 | {
130 | graphManager.AddNode(functionNode.Value);
131 | }
132 |
133 | foreach (var connection in connections)
134 | {
135 | foreach (var targetFunctionNode in functionNodes)
136 | {
137 | if (targetFunctionNode.Key.ExecutionInputs.Contains(connection.InputPin))
138 | {
139 | int pindex = ((NodePinViewModel)connection.OutputPin).Index;
140 | graphManager.AddConnection(functionNode.Value, pindex, targetFunctionNode.Value);
141 | }
142 | }
143 | }
144 | }
145 | }
146 |
147 | graphManager.RealiseNodeOutputs();
148 |
149 | return graphManager;
150 | }
151 |
152 | public static List GetPinConnections(NodePinViewModel pin, GraphEditorViewModel graph)
153 | {
154 | List pinConnections = new List();
155 |
156 | foreach (var connection in graph.Connections)
157 | {
158 | NodePinViewModel inputPin = connection.InputPin;
159 | NodePinViewModel outputPin = connection.OutputPin;
160 |
161 | if (pin == inputPin || pin == outputPin)
162 | {
163 | pinConnections.Add(connection);
164 | }
165 | }
166 |
167 | return pinConnections;
168 | }
169 |
170 | ///
171 | /// Builds an HTML or SQL query from the query data taken from predefined testing nodes.
172 | /// Testing purposes only.
173 | ///
174 | /// State object to build from.
175 | ///
176 | public static string BuildQuery(QueryState state)
177 | {
178 | string outString = "";
179 |
180 | // Process as a print statement
181 | if (state.VariableBag.ContainsKey("DebugPrint"))
182 | {
183 | object debugString;
184 | state.VariableBag.TryGetValue("DebugPrint", out debugString);
185 |
186 | outString += debugString.ToString();
187 | }
188 | // Process as an SQL statement
189 | else if (state.VariableBag.ContainsKey("SelectFields"))
190 | {
191 | // Select
192 | if (state.VariableBag.ContainsKey("SelectFields"))
193 | {
194 | object fields;
195 | state.VariableBag.TryGetValue("SelectFields", out fields);
196 |
197 | List selectFields = (List) fields;
198 |
199 | outString = "SELECT ";
200 |
201 | for (int i = 0; i < selectFields.Count; i++)
202 | {
203 | // Don't add comma
204 | if (i == selectFields.Count - 1)
205 | outString += selectFields[i];
206 | else
207 | outString += selectFields[i] + ",";
208 | }
209 | }
210 |
211 | // From
212 | if (state.VariableBag.ContainsKey("FromTable"))
213 | {
214 | outString += " ";
215 | outString += "FROM " + state.VariableBag["FromTable"];
216 | }
217 |
218 | // Where
219 | if (state.VariableBag.ContainsKey("WhereFields"))
220 | {
221 | outString += " ";
222 | outString += "WHERE ";
223 |
224 | object whereList;
225 | state.VariableBag.TryGetValue("WhereFields", out whereList);
226 |
227 | List> castList = (List>) whereList;
228 |
229 | foreach (var whereCondition in castList)
230 | {
231 | outString += whereCondition.Item1 + " " + whereCondition.Item2 + "\"" + whereCondition.Item3 + "\"";
232 | }
233 | }
234 |
235 | outString += ";";
236 | }
237 | // Process as an HTML statement
238 | else if (state.VariableBag.ContainsKey("HTML"))
239 | {
240 | outString += state.VariableBag["HTML"].ToString();
241 | }
242 |
243 | return outString;
244 | }
245 | }
246 | }
--------------------------------------------------------------------------------
/VisualQueryApplication/Images/Ribbon/icon_build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callumevans/QueryBuilder/0406c91bd1bbc08298d4af2f9c10a2c276ef9d46/VisualQueryApplication/Images/Ribbon/icon_build.png
--------------------------------------------------------------------------------
/VisualQueryApplication/Images/Ribbon/icon_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callumevans/QueryBuilder/0406c91bd1bbc08298d4af2f9c10a2c276ef9d46/VisualQueryApplication/Images/Ribbon/icon_delete.png
--------------------------------------------------------------------------------
/VisualQueryApplication/Images/Ribbon/icon_placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callumevans/QueryBuilder/0406c91bd1bbc08298d4af2f9c10a2c276ef9d46/VisualQueryApplication/Images/Ribbon/icon_placeholder.png
--------------------------------------------------------------------------------
/VisualQueryApplication/Images/Ribbon/icon_view_query.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callumevans/QueryBuilder/0406c91bd1bbc08298d4af2f9c10a2c276ef9d46/VisualQueryApplication/Images/Ribbon/icon_view_query.png
--------------------------------------------------------------------------------
/VisualQueryApplication/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
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 |
46 |
47 |
52 |
53 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/VisualQueryApplication/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Fluent;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Input;
9 | using Common;
10 | using Graph;
11 | using VisualQueryApplication.Controls.GraphBuilder;
12 | using VisualQueryApplication.ViewModels;
13 |
14 | namespace VisualQueryApplication
15 | {
16 | ///
17 | /// Interaction logic for MainWindow.xaml
18 | ///
19 | public partial class MainWindow : RibbonWindow
20 | {
21 | private GeneratedQueryView queryViewWindow;
22 |
23 | public MainWindow()
24 | {
25 | InitializeComponent();
26 |
27 | this.DataContext = new MainWindowViewModel(VisualEditor.DataContext as GraphEditorViewModel);
28 | }
29 |
30 | private void applicationWindow_Loaded(object sender, RoutedEventArgs e)
31 | {
32 | MainWindowViewModel viewModel = this.DataContext as MainWindowViewModel;
33 |
34 | Dictionary nodeTreeItems = new Dictionary();
35 | Dictionary rootCategories = new Dictionary();
36 |
37 | // Load in all nodes
38 | foreach (var node in viewModel.LoadedNodes)
39 | {
40 | NodeCategory categoryAttribute = (NodeCategory)node.GetCustomAttribute(typeof(NodeCategory));
41 | NodeName nameAttribute = (NodeName)node.GetCustomAttribute(typeof(NodeName));
42 |
43 | if (categoryAttribute != null)
44 | nodeTreeItems.Add(new TreeViewItem() { Header = nameAttribute.Name, Tag = node, FontWeight = FontWeights.Normal }, categoryAttribute.Category);
45 | else
46 | nodeTreeItems.Add(new TreeViewItem() { Header = nameAttribute.Name, Tag = node, FontWeight = FontWeights.Normal }, "Uncategorised");
47 | }
48 |
49 | // Extract categories
50 | foreach (var node in nodeTreeItems)
51 | {
52 | if (!rootCategories.ContainsKey(node.Value))
53 | rootCategories.Add(node.Value, new TreeViewItem() { Header = node.Value, FontWeight = FontWeights.Bold, IsExpanded = true });
54 | }
55 |
56 | // Display categories
57 | foreach (var category in rootCategories)
58 | {
59 | SelectableNodesTree.Items.Add(category.Value);
60 | }
61 |
62 | // Display nodes by category
63 | foreach (var node in nodeTreeItems)
64 | {
65 | if (node.Value == "Uncategorised")
66 | {
67 | foreach (var categoryItem in rootCategories.Where(
68 | categoryItem => categoryItem.Key.Equals("Uncategorised")))
69 | {
70 | categoryItem.Value.Items.Add(node.Key);
71 | }
72 | }
73 | else
74 | {
75 | foreach (var categoryItem in rootCategories.Where(
76 | categoryItem => categoryItem.Key.Equals(node.Value)))
77 | {
78 | categoryItem.Value.Items.Add(node.Key);
79 | }
80 | }
81 | }
82 | }
83 |
84 | private void LoadedNodesList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
85 | {
86 | var selectedItem = SelectableNodesTree.SelectedItem as TreeViewItem;
87 |
88 | if (selectedItem != null && selectedItem.Tag != null)
89 | ((MainWindowViewModel)DataContext).InsertNodeCommand.Execute(selectedItem.Tag);
90 | }
91 |
92 | private async void BuildQuery_Click(object sender, RoutedEventArgs e)
93 | {
94 | BuildButton.IsEnabled = false;
95 |
96 | try
97 | {
98 | NodeGraphManager builtGraph = new NodeGraphManager();
99 | builtGraph = await Graph.BuildGraphAsync(VisualEditor.DataContext as GraphEditorViewModel);
100 |
101 | ((MainWindowViewModel) this.DataContext).ActiveQueryState = builtGraph.QueryState;
102 | }
103 | catch
104 | {
105 | MessageBox.Show("Error building graph.\n" + e.ToString());
106 | }
107 | finally
108 | {
109 | BuildButton.IsEnabled = true;
110 | }
111 | }
112 |
113 | private void ViewQuery_Click(object sender, RoutedEventArgs e)
114 | {
115 | if (queryViewWindow != null)
116 | {
117 | queryViewWindow.Focus();
118 | return;
119 | }
120 |
121 | queryViewWindow = new GeneratedQueryView(
122 | new Action(() => queryViewWindow = null));
123 |
124 | var viewModel = ((MainWindowViewModel)this.DataContext);
125 |
126 | if (viewModel.ActiveQueryState != null)
127 | {
128 | ((GeneratedQueryViewViewModel) queryViewWindow.DataContext).Query =
129 | Graph.BuildQuery(viewModel.ActiveQueryState);
130 | }
131 |
132 | queryViewWindow.Show();
133 | }
134 |
135 | private void DeleteButton_Click(object sender, RoutedEventArgs e)
136 | {
137 | GraphEditorViewModel graph = (GraphEditorViewModel) VisualEditor.DataContext;
138 | graph.VisualNodes.Clear();
139 | graph.Connections.Clear();
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/VisualQueryApplication/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("VisualQueryApplication")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("VisualQueryApplication")]
15 | [assembly: AssemblyCopyright("Copyright © 2015")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/VisualQueryApplication/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace VisualQueryApplication.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VisualQueryApplication.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/VisualQueryApplication/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/VisualQueryApplication/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace VisualQueryApplication.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/VisualQueryApplication/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/VisualQueryApplication/RelayCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Input;
3 |
4 | namespace VisualQueryApplication
5 | {
6 | public sealed class RelayCommand : ICommand
7 | {
8 | public event EventHandler CanExecuteChanged;
9 |
10 | public event CancelCommandEventHandler Executing;
11 |
12 | public event CommandEventHandler Executed;
13 |
14 | private Action action;
15 | private Action