Exemplo n.º 1
0
        public void TestMainMenuReading008()
        {
            String     content  = ReadResource(Resources.MainMenu_008);
            IBDocument document = IBDocument.LoadFromXml(content);

            CheckDocument(document);
        }
Exemplo n.º 2
0
        public void TestMyDocumentReading005()
        {
            String     content  = ReadResource(Resources.MyDocument_005);
            IBDocument document = IBDocument.LoadFromXml(content);

            CheckDocument(document);
        }
Exemplo n.º 3
0
        public override CodeCompileUnit Generate(ProjectFile xibFile, CodeDomProvider provider, CodeGeneratorOptions options)
        {
            var doc     = XDocument.Load(xibFile.FilePath);
            var ibDoc   = IBDocument.Deserialize(doc);
            var project = (DotNetProject)xibFile.Project;
            var ccu     = new CodeCompileUnit();
            var ns      = new CodeNamespace(project.GetDefaultNamespace(xibFile.FilePath));

            ccu.Namespaces.Add(ns);
            foreach (var ctd in GetTypes(ibDoc, provider, options))
            {
                ns.Types.Add(ctd);
            }
            return(ccu);
        }
Exemplo n.º 4
0
        public void TestMainMenuReading012()
        {
            String     content  = ReadResource(Resources.MainMenu_012);
            IBDocument document = IBDocument.LoadFromXml(content);

            CheckDocument(document);

            ClassDescriptionCollector collector = new ClassDescriptionCollector();

            document.Root.Accept(collector);
            Assert.AreEqual(3, collector.ClassNames.Count());
            Assert.IsTrue(collector.ClassNames.Contains("MainController"));
            IEnumerable <IBPartialClassDescription> classDescriptions = collector["MainController"];
            IEnumerable <IBOutletDescriptor>        outlets           = classDescriptions.SelectMany(d => d.Outlets);
            IEnumerable <IBActionDescriptor>        actions           = classDescriptions.SelectMany(d => d.Actions);

            Assert.AreEqual(3, outlets.Count());
            Assert.AreEqual(2, actions.Count());
        }
Exemplo n.º 5
0
        IEnumerable <CodeTypeDeclaration> GetTypes(IBDocument doc, CodeDomProvider provider, CodeGeneratorOptions options)
        {
            object          outVar;
            UnknownIBObject objects;

            if (!doc.Properties.TryGetValue("IBDocument.Objects", out outVar) || (objects = outVar as UnknownIBObject) == null)
            {
                return(new CodeTypeDeclaration[0]);
            }

            //process the connection records
            NSMutableArray connectionRecords;

            if (!objects.Properties.TryGetValue("connectionRecords", out outVar) || (connectionRecords = outVar as NSMutableArray) == null)
            {
                return(new CodeTypeDeclaration[0]);
            }

            //group connection records by type ref ID
            var typeRecords = new Dictionary <int, List <IBConnectionRecord> > ();

            foreach (var record in connectionRecords.Values.OfType <IBConnectionRecord> ())
            {
                //get the type this member belongs in
                var ev     = record.Connection as IBActionConnection;
                var outlet = record.Connection as IBOutletConnection;
                if (outlet == null && ev == null)
                {
                    //not a recognised connection type. probably a desktop xib
                    continue;
                }
                int?typeIndex = ((IBObject)(ev != null
                                        ? ev.Destination.Reference
                                        : outlet.Source.Reference)).Id;
                if (typeIndex == null)
                {
                    throw new InvalidOperationException("Connection " + record.ConnectionId + " references null object ID");
                }
                List <IBConnectionRecord> records;
                if (!typeRecords.TryGetValue(typeIndex.Value, out records))
                {
                    typeRecords[typeIndex.Value] = records = new List <IBConnectionRecord> ();
                }
                records.Add(record);
            }

            //grab the custom class names, keyed by object ID
            var classNames          = new Dictionary <int, string> ();
            var flattenedProperties = (NSMutableDictionary)objects.Properties ["flattenedProperties"];

            foreach (var pair in flattenedProperties.Values)
            {
                string keyStr = (string)pair.Key;
                if (!keyStr.EndsWith(".CustomClassName"))
                {
                    continue;
                }
                int    key  = int.Parse(keyStr.Substring(0, keyStr.IndexOf('.')));
                string name = (string)pair.Value;

                //HACK: why does IB not generate partial classes for UIApplication or UIResponder? I guess we should suppress them too
                if (name == "UIApplication" || name == "UIResponder")
                {
                    continue;
                }

                classNames[key] = (string)pair.Value;
            }

            // it seems to be hard to figure out which objects we should generate classes for,
            // so take the list of classes that xcode would generate
            var             ibApprovedPartialClassNames = new HashSet <string> ();
            UnknownIBObject classDescriber;

            if (doc.Properties.TryGetValue("IBDocument.Classes", out outVar) && (classDescriber = outVar as UnknownIBObject) != null)
            {
                NSMutableArray arr;
                if (classDescriber.Properties.TryGetValue("referencedPartialClassDescriptions", out outVar) && (arr = outVar as NSMutableArray) != null)
                {
                    foreach (var cls in arr.Values.OfType <IBPartialClassDescription> ())
                    {
                        if (!String.IsNullOrEmpty(cls.ClassName))
                        {
                            ibApprovedPartialClassNames.Add(cls.ClassName);
                        }
                    }
                }
            }

            // construct the type objects, keyed by ref ID
            var objectRecords   = (IBMutableOrderedSet)objects.Properties ["objectRecords"];
            var customTypeNames = new Dictionary <int, string> ();
            var types           = new Dictionary <int, CodeTypeDeclaration> ();

            foreach (IBObjectRecord record in objectRecords.OrderedObjects.OfType <IBObjectRecord> ())
            {
                string name;
                int?   objId = ((IBObject)ResolveIfReference(record.Object)).Id;
                if (objId != null && classNames.TryGetValue(record.ObjectId, out name))
                {
                    customTypeNames[objId.Value] = name;

                    if (!ibApprovedPartialClassNames.Contains(name))
                    {
                        continue;
                    }

                    //HACK to avoid duplicate class definitions, which is not compilable
                    ibApprovedPartialClassNames.Remove(name);

                    var type = new CodeTypeDeclaration(name)
                    {
                        IsPartial = true
                    };
                    type.CustomAttributes.Add(
                        new CodeAttributeDeclaration("MonoTouch.Foundation.Register",
                                                     new CodeAttributeArgument(new CodePrimitiveExpression(name))));

                    //FIXME: implement proper base class resolution. I'm not sure where the info is - it might need some
                    // inference rules

                    var obj = ResolveIfReference(record.Object);
                    if (obj != null)
                    {
                        string baseType = "MonoTouch.Foundation.NSObject";
                        if (obj is IBProxyObject)
                        {
                            baseType = "MonoTouch.UIKit.UIViewController";
                        }
                        else if (obj is UnknownIBObject)
                        {
                            var uobj = (UnknownIBObject)obj;

                            //if the item comes from another nib, don't generate the partial class in this xib's codebehind
                            if (uobj.Properties.ContainsKey("IBUINibName") && !String.IsNullOrEmpty(uobj.Properties["IBUINibName"] as string))
                            {
                                continue;
                            }

                            baseType = GetTypeName(null, uobj) ?? "MonoTouch.Foundation.NSObject";
                        }
                        type.Comments.Add(new CodeCommentStatement(String.Format("Base type probably should be {0} or subclass", baseType)));
                    }

                    types.Add(objId.Value, type);
                }
            }

            foreach (KeyValuePair <int, List <IBConnectionRecord> > typeRecord in typeRecords)
            {
                CodeTypeDeclaration type;
                if (!types.TryGetValue(typeRecord.Key, out type))
                {
                    continue;
                }

                //separate out the actions and outlets
                var actions = new List <IBActionConnection> ();
                var outlets = new List <IBOutletConnection> ();
                foreach (var record in typeRecord.Value)
                {
                    if (record.Connection is IBActionConnection)
                    {
                        actions.Add((IBActionConnection)record.Connection);
                    }
                    else if (record.Connection is IBOutletConnection)
                    {
                        outlets.Add((IBOutletConnection)record.Connection);
                    }
                }

                //process the actions, grouping ones with the same name
                foreach (var actionGroup in actions.GroupBy(a => a.Label))
                {
                    //find a common sender type for all the items in the grouping
                    CodeTypeReference senderType = null;
                    foreach (IBActionConnection ev in actionGroup)
                    {
                        var sender  = ResolveIfReference(ev.Source) as IBObject;
                        var newType = new CodeTypeReference(GetTypeName(customTypeNames, sender) ?? "MonoTouch.Foundation.NSObject");
                        if (senderType == null)
                        {
                            senderType = newType;
                            continue;
                        }
                        else if (senderType == newType)
                        {
                            continue;
                        }
                        else
                        {
                            //FIXME: resolve common type
                            newType = new CodeTypeReference("MonoTouch.Foundation.NSObject");
                            break;
                        }
                    }

                    if (type.Members.Count == 0)
                    {
                        AddWarningDisablePragmas(type, provider);
                    }

                    //create the action method and add it
                    StringWriter actionStubWriter = null;
                    GenerateAction(type, actionGroup.Key, senderType, provider, options, ref actionStubWriter);
                    if (actionStubWriter != null)
                    {
                        type.Comments.Add(new CodeCommentStatement(actionStubWriter.ToString()));
                        actionStubWriter.Dispose();
                    }
                }

                foreach (var outlet in outlets)
                {
                    CodeTypeReference outletType;
                    //destination is widget, so get type
                    var widget = ResolveIfReference(outlet.Destination.Reference) as IBObject;
                    outletType = new CodeTypeReference(GetTypeName(customTypeNames, widget) ?? "System.Object");

                    if (type.Members.Count == 0)
                    {
                        AddWarningDisablePragmas(type, provider);
                    }
                    AddOutletProperty(type, outlet.Label, outletType);
                }
            }

            return(types.Values);
        }
Exemplo n.º 6
0
        public override CodeCompileUnit Generate(ProjectFile xibFile, CodeDomProvider provider, CodeGeneratorOptions options)
        {
            var xibDoc = XDocument.Load(xibFile.FilePath);
            var ibDoc  = IBDocument.Deserialize(xibDoc);
            var ccu    = new CodeCompileUnit();

            object          outVar;
            UnknownIBObject classDescriber;

            if (!ibDoc.Properties.TryGetValue("IBDocument.Classes", out outVar) || (classDescriber = outVar as UnknownIBObject) == null)
            {
                return(ccu);
            }

            NSMutableArray arr;

            if (!classDescriber.Properties.TryGetValue("referencedPartialClassDescriptions", out outVar) || (arr = outVar as NSMutableArray) == null)
            {
                return(ccu);
            }

            var project   = (DotNetProject)xibFile.Project;
            var defaultNS = project.GetDefaultNamespace(xibFile.FilePath);
            var nsDict    = new Dictionary <string, CodeNamespace> ();

            foreach (var cls in arr.Values.OfType <IBPartialClassDescription> ())
            {
                if (string.IsNullOrEmpty(cls.ClassName))
                {
                    continue;
                }

                var si = cls.SourceIdentifier.Value;
                if (si == null || si.MajorKey != "IBUserSource")
                {
                    continue;
                }

                var type = new CodeTypeDeclaration(cls.ClassName)
                {
                    IsPartial = true,
                };
                type.CustomAttributes.Add(
                    new CodeAttributeDeclaration("MonoMac.Foundation.Register",
                                                 new CodeAttributeArgument(new CodePrimitiveExpression(cls.ClassName))));

                var sc = GetTypeReference(cls.SuperclassName ?? "id");
                type.Comments.Add(new CodeCommentStatement("Should subclass " + sc.BaseType));
                //type.BaseTypes.Add (sc);

                if (cls.Actions != null)
                {
                    foreach (var action in cls.Actions.Values)
                    {
                        AddWarningDisablePragmas(type, provider);
                        StringWriter actionStubWriter = null;

                        var sender = GetTypeReference((string)action.Value);
                        GenerateAction(type, (string)action.Key, sender, provider, options, ref actionStubWriter);

                        if (actionStubWriter != null)
                        {
                            type.Comments.Add(new CodeCommentStatement(actionStubWriter.ToString()));
                            actionStubWriter.Dispose();
                        }
                    }
                }

                if (cls.Outlets != null)
                {
                    foreach (var outlet in cls.Outlets.Values)
                    {
                        AddWarningDisablePragmas(type, provider);
                        AddOutletProperty(type, (string)outlet.Key, GetTypeReference((string)outlet.Value));
                    }
                }

                //FIXME: use _ as namespace separator
                var           ns = defaultNS;
                CodeNamespace cn;
                if (!nsDict.TryGetValue(ns, out cn))
                {
                    cn = new CodeNamespace(ns);
                    nsDict.Add(ns, cn);
                    ccu.Namespaces.Add(cn);
                }
                cn.Types.Add(type);
            }

            return(ccu);
        }
Exemplo n.º 7
0
 private static void CheckDocument(IBDocument document)
 {
     Assert.IsNotNull(document.Root);
 }