October 31, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Building a WPF Animation DSL Using M and the Oslo SDK

  • April 7, 2009
  • By Jeffrey Juday
  • Send Email »
  • More Articles »

Bringing MGrammar into the Application

Rather than building code to open the MGrammar file to read the code, I chose to add the MGrammar file to my Visual Studio project and make my MGrammar code an embedded resource. The embedded resource property is highlighted in Figure 3 below.


Figure 3 WPFTestingWithMG properties

A DynamicParser object must be constructed from the Resource. DynamicParser is a new class shipping with the Oslo SDK. DynamicParser is in charge of generating the MGraph. MParserBuilder constructs the DynamicParser from the WPFTestingWithMG resource. MParserBuilder's Build function appears below.

public void Build(string resourceName)
{
    
   var assembly = Assembly.GetExecutingAssembly();
   using (var stream = assembly.GetManifestResourceStream(resourceName))
   using (var reader = new StreamReader(stream))
   {
      var errorReporter = ErrorReporter.Standard;
      var compiler = new MGrammarCompiler
      {
         SourceItems = new SourceItem[] { 
            new SourceItem { 
                 Name = "MGrammarInterpreter Grammar", 
                 ContentType = ContentType.Mg, 
                 TextReader = reader,
            },
         },
      };
      if (compiler.Compile(errorReporter) != 0 || errorReporter.HasErrors)
      {
         throw new Exception("Failure compiling WPFTestingWithMG.mg");
      }
      compiler.LoadDynamicParser(this.Parser);
   }
}

Build reads the code from the embedded resource, compiles the MGrammar code, and associates the complied code with the DynamicParser.

The next task was to programmatically generate MGraph from the DynamicParser.

Generating MGraph

MGraphGenerator feeds the DSL code to the DynamicParser object to generate the MGraph. MGraphGenerator Run function appears below.

public void Run(string inputText,DynamicParser parser)
{
   ExceptionErrorReporter errorReporter;
   parser.GraphBuilder = _builder;
   errorReporter = new ExceptionErrorReporter();
   GraphRoot = parser.Parse<object>(string.Empty, 
           new StringReader(inputText), errorReporter);
   if (GraphRoot == null || errorReporter.HasErrors)
   {
   }
   else
   {
   }
}

GraphBuilder contains the data resulting from the parsed DSL code. GraphBuilder is a collection of object classes. GraphBuilder includes a set of functions for adding and traversing the object collection. GraphBuilder is hierarchal with a root and multiple child elements. GraphBuilder is a little clunky to use. I'm hoping future versions of the Oslo SDK will include a richer MGraph consumption experience or more guidance on constructing your own GraphBuider.

You may have noticed that I bypassed building MSchema. In its current incarnation, MSchema is associated more with SQL Server and the Oslo Repository. Since I'm not utilizing the Oslo Repository, I did nothing with MSchema.

Reading and consuming GraphBuilder is the job of the MGraphReader class.

Consuming MGraph

MGraphReader pulls the data from a GraphBuilder. A snippet from the MGraphReader WalkTheNodes function appears below.

private void WalkTheNodes(System.Dataflow.GraphBuilder graph, 
       object nodeOn, List<Move> list)
{
    List<object> vals;
    string MoveX = "";
    string MoveY = "";
    string seqLabel = "";
    object seqLabelObj = null;
    List<object> tempPos;
    Move moveObj = null;
    bool isNode = false;
    double moveOffset = 3.0;
    double moveMultiplier;
    
    foreach (object enumNext in graph.GetSuccessors(nodeOn))
    {
       isNode = graph.IsNode(enumNext);
       if ((isNode)) //Skip the non-nodes
       {
          seqLabelObj = graph.GetSequenceLabel(enumNext);
          if (seqLabelObj != null) //Sometimes label returns null value
          {
             seqLabel = seqLabelObj.ToString();
             if (seqLabel == @"Move") //You reach a Move label
             {
                 //Successors of Move are MoveX, MoveY, and Mult
                 vals = graph.GetSuccessors(enumNext).ToList<object>();
                 //ToList converts IEnumerable to List generic
                 //MoveX Successor is the MoveX value
                 tempPos = graph.GetSuccessors(vals[0]).ToList<object>();
                 MoveX = tempPos[0].ToString();
                 list.Add(moveObj);
             }
          }
          WalkTheNodes(graph, enumNext, list);
       }
    }
}

WalkTheNodes recursively visits the nodes on GraphBuilder, building a list of Move objects required by the EllipseAnimator class discussed earlier in the article. The Nodes labeled "Move" and successors below the "Move" nodes contain the runtime's data.

GraphBuilder functions getting node objects return objects based on the IEnumerble interface. To move GraphBuilder data into List collections, MGraphReader employs .NET classes working with IEnumerable interfaces.

Conclusion

This sample application shows how M and the Olso SDK can be incorporated into a Visual Studio application. Using MGrammar I built a DSL to configure an animation. I also built a WPF animation runtime for consuming data emitted by the MGrammar DSL.

Source Code

The source code for this article: MGrammarInterpreter.zip.

About the Author

Jeffrey Juday is a software developer specializing in enterprise integration solutions utilizing BizTalk, SharePoint, WCF, WF, and SQL Server. Jeff has been developing software with Microsoft tools for more than 15 years in a variety of industries including: military, manufacturing, financial services, management consulting, and computer security. Jeff is a Microsoft BizTalk MVP. Jeff spends his spare time with his wife Sherrill and daughter Alexandra. You can reach Jeff at me@jeffjuday.com.

Sources

Martin Fowler's DSL work

Oslo SDK documentation

WPF Animation Documentation on MSDN

Oslo development center Samples and Documentation





Page 3 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel