/// <summary>
        /// Split this up in to sections so I can more easliy re-use it in the future.
        /// </summary>
        /// <param name="className"></param>
        public static void Generate(string className, string outputAssemblyName, CompilerFlags flags, List <String> assemblies)
        {
            string prefix = (flags.IsAbstract ? ABSTRACT_PREFIX : String.Empty);

            //this *can* generate more than one entry
            ControlTree[] trees = GenerateTree(className, outputAssemblyName, assemblies);
            if (trees != null && trees.Length == 1)
            {
                ControlTree tree     = trees[0];
                string      s        = ClassGenerator(tree, flags);
                string      infill   = (flags.AppendDesignedToFilename ? ".Designer" : String.Empty); //add in the Designed
                string      fileName = System.IO.Path.Combine(flags.OutputPath, String.Format("{1}{0}Controller{2}.cs", tree.ClassName, prefix, infill));

                //added a check to see if file exists, otherwise we might get weird streaming issues
                //if it does, I delete it for now.
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }

                WriteFile(s, fileName);

                if (flags.CreateEmptyNonDesignedFile)
                {
                    string stubFileName = System.IO.Path.Combine(flags.OutputPath, String.Format("{1}{0}Controller.cs", tree.ClassName, prefix));
                    if (!System.IO.File.Exists(stubFileName))
                    {
                        WriteFile(CreateStubFile(tree, flags), stubFileName);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This fixes the subcontrol issues
        /// </summary>
        private static void IterateTree(System.Windows.Forms.Control targetControl, ControlTree tree, string path)
        {
            Console.WriteLine(path);

            foreach (System.Windows.Forms.Control control in targetControl.Controls)
            {
                //this works around the fact that the toolStrip does weird stuff with named controls
                if (control.Name != null && control.Name != String.Empty)
                {
                    tree.AddControl(control.Name, control.GetType());
                }

                if (control.Controls.Count > 0)
                {
                    IterateTree(control, tree, String.Format("{0}_{1}", path, control.Name)); //recurse....
                }

                //special case - controlstrip holds its own components
                if (control is System.Windows.Forms.StatusStrip)
                {
                    foreach (System.Windows.Forms.ToolStripItem item in (control as System.Windows.Forms.StatusStrip).Items)
                    {
                        if (item is System.Windows.Forms.ToolStripItem)
                        {
                            var name = (item as System.Windows.Forms.ToolStripItem).Name;
                            tree.AddControl((name == null || name == String.Empty ? "Blah" : name), item.GetType());
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Builds a tree of control info
        /// </summary>
        /// <param name="className"></param>
        public static ControlTree[] GenerateTree(string className, string outputAssemblyName)
        {
            List <ControlTree> trees = new List <ControlTree>();

            Assembly a = Assembly.LoadFrom(outputAssemblyName /*"temp.dll"*/); //we dictate this name

            Type[] ts = a.GetTypes();
            foreach (Type t in ts)
            {
                if (t.Name.Equals(className))
                {
                    ControlTree tree = new ControlTree();
                    trees.Add(tree); //just to get it sorted..

                    //essentially, we only support "Winforms" so we assume it is a form or descends from one
                    //I might be able to alter this to "component" I gues...
                    System.Windows.Forms.Form form = (Activator.CreateInstance(t) as System.Windows.Forms.Form);

                    tree.ClassName     = t.Name;
                    tree.NamespaceName = t.Namespace;

                    ////we now have access to the controls
                    //foreach (System.Windows.Forms.Control control in form.Controls)
                    //{
                    //  tree.AddControl(control.Name, control.GetType());
                    //}

                    IterateTree(form, tree, className);

                    //add in the components that are non visual and in the container on the form
                    IterateComponents(form, tree, className);
                }
            }
            return(trees.ToArray());
        }
        private static void IterateDropDownItems(ControlTree tree, System.Windows.Forms.ToolStripDropDownItem item)
        {
            foreach (var menuitem in item.DropDownItems)
            {
                var name = (menuitem as System.Windows.Forms.ToolStripItem).Name;
                tree.AddControl((name == null || name == String.Empty ? "Blah" : name), item.GetType());

                if (menuitem is System.Windows.Forms.ToolStripDropDownItem)
                {
                    IterateDropDownItems(tree, (System.Windows.Forms.ToolStripDropDownItem)menuitem);
                }
            }
        }
        /// <summary>
        /// Creates a stub file with the same makeup of the main file
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        private static string CreateStubFile(ControlTree tree, CompilerFlags flags)
        {
            string prefix = (flags.IsAbstract ? ABSTRACT_PREFIX : String.Empty);

            StringBuilder code = new StringBuilder();

            code.AppendLine("/*This stub code was generated by the MvcFramework compiler, created by RatCow Soft - \r\n See http://code.google.com/p/ratcowsoftopensource/ */ \r\n\r\nusing System; \r\nusing System.Windows.Forms;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Reflection;\r\n\r\n//3rd Party\r\nusing RatCow.MvcFramework;\r\n");
            code.AppendFormat("namespace {0}\r\n", tree.NamespaceName);
            code.AppendLine("{");
            code.AppendFormat("\tinternal partial class {1}{0}Controller: BaseController<{0}>\r\n", tree.ClassName, prefix);
            code.AppendLine("\t{");
            code.AppendLine("\t}");
            code.AppendLine("}");

            return(code.ToString());
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Hack around the fact we don't have any access to the stuff in container on the form.
        ///
        /// Here's the issue: Winforms have a private components collection. This contains a reference
        /// to all the components on the form. It's trivial to get access to this - to be honest, I went
        /// for the simple hack, but it would probably have worked with the right BindingFlags params
        /// no matter what. But here's the thing - Components don't have a name....
        ///
        /// So how can we pull through the name? Well, I could completely refactor all of the code to
        /// look at the fields of the form and pull out all of the controls and components, but to be honest,
        /// that seems like a faff. So what I instead did was this - we know the field is a reference, and the
        /// same reference is in the components collection. Only the stuff we want is ref'd in the components
        /// collection. So, if we iterate through the components collection, get the ref and then cross
        /// ref that reference with the fields on the folrm (using a bit of Linq to reduce the list by type)
        /// we can then do the look-up cross ref and get the fields name.
        ///
        /// I'm not sure if there's an easier way, but this works for now.
        /// </summary>
        private static void IterateComponents(System.Windows.Forms.Form form, ControlTree tree, string className)
        {
            //the componments are in a private list (so we need hackery to access it)
            //when we compiled the class, we added in a public accessor called "ContainerAccess"

            //This of course doesn't work very well.... but it does give us a handle on the component
            //types we should be looking for...
            Type formType = form.GetType();
            var  accessor = formType.GetProperty("ComponentsAccess");

            if (accessor != null)
            {
                var payload = accessor.GetValue(form, null);
                System.ComponentModel.IContainer container = (System.ComponentModel.IContainer)payload;

                if (container == null)
                {
                    return;
                }

                foreach (System.ComponentModel.Component component in container.Components)
                {
                    //we must now look for component in the fields with in the form, to look up the name
                    Type        fieldType = component.GetType(); //we use this to match types
                    FieldInfo[] fia       = formType.GetFields(BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);

                    //limit to just the same calss type
                    var fiar = from field in fia
                               where field.FieldType == fieldType
                               select field;

                    if (fiar == null)
                    {
                        continue;     //this is no ideal
                    }
                    //iterate the resultset, hoping we find at least one value and can match it.
                    foreach (var fi in fiar)
                    {
                        var instance = fi.GetValue(form);
                        if (instance == component)
                        {
                            tree.AddControl(fi.Name, fieldType);
                        }
                    }
                }
            }
        }
        private static void ContextMenuStrip_IterateToolStripItems(ControlTree tree, System.Windows.Forms.Control control)
        {
            foreach (System.Windows.Forms.ToolStripItem item in (control as System.Windows.Forms.ContextMenuStrip).Items)
            {
                if (item is System.Windows.Forms.ToolStripItem)
                {
                    var name = (item as System.Windows.Forms.ToolStripItem).Name;
                    tree.AddControl((name == null || name == String.Empty ? "Blah" : name), item.GetType());

                    if (item is System.Windows.Forms.ToolStripDropDownItem)
                    {
                        var item2 = (System.Windows.Forms.ToolStripDropDownItem)item;
                        IterateDropDownItems(tree, item2);
                    }
                }
            }
        }
        /// <summary>
        /// Builds a tree of control info
        /// </summary>
        /// <param name="className"></param>
        public static ControlTree[] GenerateTree(string className, string outputAssemblyName, List <String> assemblies)
        {
            List <ControlTree> trees = new List <ControlTree>();

            var resolver = new AssemblyResolver(assemblies);                   //this *should* reslve the missing assemblies for us

            Assembly a = Assembly.LoadFrom(outputAssemblyName /*"temp.dll"*/); //we dictate this name

            Type[] ts = a.GetTypes();
            foreach (Type t in ts)
            {
                if (t.Name.Equals(className))
                {
                    ControlTree tree = new ControlTree();
                    trees.Add(tree); //just to get it sorted..

                    //essentially, we only support "Winforms" so we assume it is a form or descends from one
                    //I might be able to alter this to "component" I guess...
                    try
                    {
                        System.Windows.Forms.Form form = (Activator.CreateInstance(t) as System.Windows.Forms.Form);
                        tree.ClassName     = t.Name;
                        tree.NamespaceName = t.Namespace;

                        ////we now have access to the controls
                        //foreach (System.Windows.Forms.Control control in form.Controls)
                        //{
                        //  tree.AddControl(control.Name, control.GetType());
                        //}

                        IterateTree(form, tree, className);

                        //add in the components that are non visual and in the container on the form
                        IterateComponents(form, tree, className);
                    }
                    catch (Exception ex) //todo: handle this better.
                    {
                        //okay... we have failed big time, so we just bail
                        System.Diagnostics.Debug.WriteLine(ex.Message);
                        System.Diagnostics.Debug.WriteLine(ex.StackTrace);
                        return(null);
                    }
                }
            }
            return(trees.ToArray());
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="isAbstract"></param>
        /// <returns></returns>
        public static string ClassGenerator(ControlTree tree, CompilerFlags flags)
        {
            string prefix = (flags.IsAbstract ? ABSTRACT_PREFIX : String.Empty);

            StringBuilder code = new StringBuilder();

            code.AppendLine("/*Auto generated - this code was generated by the MvcFramework compiler, created by RatCow Soft - \r\n See http://code.google.com/p/ratcowsoftopensource/ */ \r\n\r\nusing System; \r\nusing System.Windows.Forms;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Reflection;\r\n\r\n//3rd Party\r\nusing RatCow.MvcFramework;\r\n");
            code.AppendFormat("namespace {0}\r\n", tree.NamespaceName);
            code.AppendLine("{");

            StringBuilder code_s1 = new StringBuilder();

            if (flags.CreateEmptyNonDesignedFile)
            {
                //if we are creating a stub, we should put the inheritence in the stub, to allow it to be altered (e.g. modal)
                code_s1.AppendFormat("\tinternal partial class {1}{0}Controller\r\n", tree.ClassName, prefix);
            }
            else
            {
                code_s1.AppendFormat("\tinternal partial class {1}{0}Controller: BaseController<{0}>\r\n", tree.ClassName, prefix);
            }
            code_s1.AppendLine("\t{");

            //constructor
            code_s1.AppendFormat("\t\tpublic {1}{0}Controller() : base()\r\n", tree.ClassName, prefix);
            code_s1.AppendLine("\t\t{\r\n\t\t}\r\n");

            StringBuilder code_s2 = new StringBuilder();

            code_s2.AppendLine("\r\n#region GUI glue code\r\n");
            code_s2.AppendFormat("\tpartial class {1}{0}Controller\r\n", tree.ClassName, prefix);
            code_s2.AppendLine("\t{");

            if (flags.RestrictActions)
            {
                //load the actions file
                ViewActionMap map = (flags.UseDefaultActionsFile ? GetDefaultViewActionMap() : GetNamedViewActionMap(tree.ClassName, true));

                //we now have access to the controls
                foreach (var control in tree.Controls)
                {
                    //System.Console.WriteLine(" var {0} : {1} ", control.Name, control.GetType().Name);
                    //add the declaration to code_s2
                    code_s2.AppendFormat("\t\t[Outlet(\"{1}\")]\r\n\t\tpublic {0} {1} ", control.Value.FullName, control.Key); //add var
                    code_s2.AppendLine("{ get; set; }");

                    //this should find all known event types
                    AddMappedActions(tree.ClassName, control, code_s2, code_s1, flags, map);

                    //specific listView hooks
                    if (control.Value == typeof(System.Windows.Forms.ListView))
                    {
                        AddListViewHandler(control.Key, code_s2, code_s1, flags);
                    }
                }
            }
            else
            {
                //we now have access to the controls
                foreach (var control in tree.Controls)
                {
                    //System.Console.WriteLine(" var {0} : {1} ", control.Name, control.GetType().Name);
                    //add the declaration to code_s2
                    code_s2.AppendFormat("\t\t[Outlet(\"{1}\")]\r\n\t\tpublic {0} {1} ", control.Value.FullName, control.Key); //add var
                    code_s2.AppendLine("{ get; set; }");

                    //this should find all known event types
                    AddKnownActions(tree.ClassName, control, code_s2, code_s1, flags);

                    //specific listView hooks
                    if (control.Value == typeof(System.Windows.Forms.ListView))
                    {
                        AddListViewHandler(control.Key, code_s2, code_s1, flags);
                    }
                }
            }

            //some boiler plate code which helps set the data for a LisViewHelper

            code_s2.AppendLine("\t\tprotected void SetData<T>(ListViewHelper<T> helper, List<T> data) where T : class");
            code_s2.AppendLine("\t\t{\r\n\t\t\t//Auto generated call");

            code_s2.AppendLine("\t\t\tType t = helper.GetType();");
            code_s2.AppendLine("\t\t\tt.InvokeMember(\"SetData\", BindingFlags.Default | BindingFlags.InvokeMethod, null, helper, new object[] { data });");

            code_s2.AppendLine("\t\t}\r\n");

            code_s1.AppendLine("\t}"); //end of class declaration
            code.AppendLine(code_s1.ToString());

            code_s2.AppendLine("\t}"); //end of class declaration
            code_s2.AppendLine("#endregion /*GUI glue code*/");
            code.AppendLine(code_s2.ToString());

            code.AppendLine("}");

            return(code.ToString());
        }