private void LinkComponent(CyPhyML.Component component, MgaFCO selectedCADModel)
 {
     try
     {
         bool createNewComponent = false;
         CyPhyMetaLink.CyPhyMetaLinkAddon.CreoOpenMode creoMode = CyPhyMetaLink.CyPhyMetaLinkAddon.CreoOpenMode.OPEN_EMPTY;
         var createOrEdit = new CreateOrEditComponent();
         createOrEdit.btnCreateNewComponent.Click += (o, e) =>
         {
             createNewComponent        = true;
             creoMode                  = CyPhyMetaLink.CyPhyMetaLinkAddon.CreoOpenMode.OPEN_COMPONENT;
             createOrEdit.DialogResult = DialogResult.OK;
             createOrEdit.Close();
         };
         createOrEdit.btnEditExistingComponent.Click += (o, e) =>
         {
             createNewComponent        = false;
             creoMode                  = CyPhyMetaLink.CyPhyMetaLinkAddon.CreoOpenMode.OPEN_COMPONENT;
             createOrEdit.DialogResult = DialogResult.OK;
             createOrEdit.Close();
         };
         createOrEdit.btnEmptyCreoOpen.Click += (o, e) =>
         {
             createNewComponent        = false;
             creoMode                  = CyPhyMetaLink.CyPhyMetaLinkAddon.CreoOpenMode.OPEN_EMPTY;
             createOrEdit.DialogResult = DialogResult.OK;
             createOrEdit.Close();
         };
         DialogResult result = createOrEdit.ShowDialog(new NativeWindowWrapper(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle));
         if (result != DialogResult.Cancel)
         {
             if (creoMode == CyPhyMetaLink.CyPhyMetaLinkAddon.CreoOpenMode.OPEN_COMPONENT)
             {
                 metalinkAddon.StartEditingComponent(component, selectedCADModel, createNewComponent);
             }
             else
             {
                 metalinkAddon.StartCreoEmpyMode();
             }
         }
     }
     catch (IOException e) // e.g. manifest.project.json not found
     {
         GMEConsole.Error.WriteLine(e.ToString());
     }
     return;
 }
        public void InvokeEx(MgaProject project, MgaFCO currentobj, MgaFCOs selectedobjs, int param)
        {
            if (!enabled)
            {
                return;
            }

            try
            {
                GMEConsole = GMEConsole.CreateFromProject(project);
                MgaGateway = new MgaGateway(project);


                propagateAddon = GetPropagateAddon(project);
                if (propagateAddon == null)
                {
                    GMEConsole.Error.WriteLine("CyPhyMLSync: Unable to contact CyPhyMLPropagate.");
                    return;
                }
                if (propagateAddon.bridgeClient.IsConnectedToBridge() == false)
                {
                    ConnectToMetaLinkBridge(project, param);
                }

                string currentobjKind = null;
                MgaFCO selectedCADModel = null;
                string componentVersion = null;
                MgaGateway.PerformInTransaction(delegate
                {
                    if (currentobj != null)
                    {
                        currentobjKind = currentobj.Meta.Name;
                        if (currentobjKind == "CADModel")
                        {
                            selectedCADModel = currentobj;
                            currentobj = (MgaFCO)currentobj.ParentModel;
                            currentobjKind = currentobj.Meta.Name;
                        }
                        else
                        {
                            Func<MgaFCO, bool> isCADCreoModel = fco => fco.Meta.Name == "CADModel"
                                && CyPhyMLClasses.CADModel.Cast(fco).Attributes.FileFormat == CyPhyMLClasses.CADModel.AttributesClass.FileFormat_enum.Creo;
                            selectedCADModel = (selectedobjs ?? (System.Collections.IEnumerable)(new List<MgaFCO>())).Cast<MgaFCO>()
                                .FirstOrDefault(isCADCreoModel);
                            if (selectedCADModel == null && currentobj.ObjType == GME.MGA.Meta.objtype_enum.OBJTYPE_MODEL)
                            {
                                // TODO: show dialog instead of picking one at random
                                selectedCADModel = ((MgaModel)currentobj).ChildFCOs.Cast<MgaFCO>().FirstOrDefault(isCADCreoModel);
                            }
                        }
                        if (currentobj != null && currentobj.Meta.Name == typeof(CyPhyMLClasses.Component).Name)
                        {
                            componentVersion = CyPhyMLClasses.Component.Cast(currentobj).Attributes.Version;
                        }
                    }
                }, transactiontype_enum.TRANSACTION_GENERAL, abort: false);
                if (currentobjKind != null && currentobjKind != "Component" && currentobjKind != "CADModel" && currentobjKind != "ComponentAssembly")
                {
                    System.Windows.Forms.MessageBox.Show("Please open a Component or a Component Assembly");
                    return;
                }
                if (currentobjKind == "Component")
                {
                    CyPhyML.Component component = CyPhyMLClasses.Component.Cast(currentobj);
                    if (selectedCADModel == null)
                    {
                        GMEConsole.Error.WriteLine("This component has no CADModels to edit.");
                        return;
                    }
                    bool connected = true;
                    if (propagateAddon.bridgeClient.IsConnectedToBridge() == false)
                    {
                        connected = ConnectToMetaLinkBridge(project, param);
                    }
                    if (connected)
                    {
                        LinkComponent(component, selectedCADModel);
                    }
                    return;
                }

                if (currentobjKind == null)
                {
                    propagateAddon.StartCreoEmpyMode();
                    return;
                }

                //GMEConsole.Out.WriteLine("Running CyPhySync interpreter...");

                if (propagateAddon.AssemblyID != null)
                {
                    GMEConsole.Warning.WriteLine("A ComponentAssembly is already synced");
                }
                else
                {
                    bool connected = propagateAddon.bridgeClient.IsConnectedToBridge();
                    if (connected == false)
                    {
                        GMEConsole.Info.WriteLine("Connecting to MetaLink Bridge ...");

                        connected = ConnectToMetaLinkBridge(project, param);
                    }

                    if (connected)
                    {
                        StartAssemblySync(project, currentobj, param);
                    }
                }

                //GMEConsole.Out.WriteLine("End of CyPhySync interpreter...");
            }
            finally
            {
                MgaGateway = null;
                project = null;
                currentobj = null;
                selectedobjs = null;
                GMEConsole = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }
        public void InvokeEx(MgaProject project, MgaFCO currentobj, MgaFCOs selectedobjs, int param)
        {
            if (!enabled)
            {
                return;
            }

            try
            {
                GMEConsole       = GMEConsole.CreateFromProject(project);
                MgaGateway       = new MgaGateway(project);
                ProjectDirectory = Path.GetDirectoryName(project.ProjectConnStr.Substring("MGA=".Length));


                metalinkAddon = GetMetaLinkAddon(project);
                if (metalinkAddon == null)
                {
                    GMEConsole.Error.WriteLine("MetaLink: Unable to find CyPhyMetaLinkAddon. Was it disabled under Tools>Register Components?");
                    return;
                }
                ConnectToMetaLinkBridge(project, param);

                string currentobjKind   = null;
                string currentobjName   = null;
                MgaFCO selectedCADModel = null;
                string componentVersion = null;
                Guid   currentobjGuid   = Guid.Empty;
                if (currentobj != null)
                {
                    MgaGateway.PerformInTransaction(delegate
                    {
                        currentobjKind = currentobj.Meta.Name;
                        currentobjName = currentobj.Name;
                        currentobjGuid = CyPhyMLClasses.DesignElement.Cast(currentobj).Guid;
                        if (currentobjKind == "CADModel")
                        {
                            selectedCADModel = currentobj;
                            currentobj       = (MgaFCO)currentobj.ParentModel;
                            currentobjKind   = currentobj.Meta.Name;
                            currentobjName   = currentobj.Name;
                            currentobjGuid   = CyPhyMLClasses.DesignElement.Cast(currentobj).Guid;
                        }
                        else
                        {
                            Func <MgaFCO, bool> isCADCreoModel = fco => fco.Meta.Name == "CADModel" &&
                                                                 CyPhyMLClasses.CADModel.Cast(fco).Attributes.FileFormat == CyPhyMLClasses.CADModel.AttributesClass.FileFormat_enum.Creo;
                            selectedCADModel = (selectedobjs ?? (System.Collections.IEnumerable)(new List <MgaFCO>())).Cast <MgaFCO>()
                                               .FirstOrDefault(isCADCreoModel);
                            if (selectedCADModel == null && currentobj.ObjType == GME.MGA.Meta.objtype_enum.OBJTYPE_MODEL)
                            {
                                // TODO: show dialog instead of picking one at random
                                selectedCADModel = ((MgaModel)currentobj).ChildFCOs.Cast <MgaFCO>().FirstOrDefault(isCADCreoModel);
                            }
                        }
                        if (currentobj != null && currentobj.Meta.Name == typeof(CyPhyMLClasses.Component).Name)
                        {
                            componentVersion = CyPhyMLClasses.Component.Cast(currentobj).Attributes.Version;
                        }
                    }, transactiontype_enum.TRANSACTION_NON_NESTED, abort: false);
                }
                if (currentobjKind != null && currentobjKind != "Component" && currentobjKind != "CADModel" && currentobjKind != "ComponentAssembly")
                {
                    System.Windows.Forms.MessageBox.Show("Please open a Component or a Component Assembly");
                    return;
                }
                if (currentobjKind == "Component")
                {
                    CyPhyML.Component component = CyPhyMLClasses.Component.Cast(currentobj);
                    if (selectedCADModel == null)
                    {
                        GMEConsole.Error.WriteLine("This component has no CADModels to edit.");
                        return;
                    }
                    bool connected = true;
                    ConnectToMetaLinkBridgeTask.Wait();
                    connected = ConnectToMetaLinkBridgeTask.Result;
                    if (connected)
                    {
                        LinkComponent(component, selectedCADModel);
                    }
                    return;
                }

                if (currentobjKind == null)
                {
                    bool connected = true;
                    ConnectToMetaLinkBridgeTask.Wait();
                    connected = ConnectToMetaLinkBridgeTask.Result;
                    if (connected)
                    {
                        metalinkAddon.StartCreoEmpyMode();
                    }
                    return;
                }

                //GMEConsole.Out.WriteLine("Running CyPhySync interpreter...");

                if (metalinkAddon.AssemblyID != null)
                {
                    if (currentobjGuid == Guid.Parse(metalinkAddon.AssemblyID))
                    {
                        metalinkAddon.assemblySyncPaused = !metalinkAddon.assemblySyncPaused;
                        if (metalinkAddon.assemblySyncPaused)
                        {
                            GMEConsole.Info.WriteLine(String.Format("Pausing MetaLink for {0}", SecurityElement.Escape(currentobjName)));
                        }
                        else
                        {
                            GMEConsole.Info.WriteLine(String.Format("Resuming MetaLink for {0}", SecurityElement.Escape(currentobjName)));
                            if (metalinkAddon.assembliesToRestart.Count > 0)
                            {
                                MgaGateway.PerformInTransaction(delegate
                                {
                                    // n.b. end of current transaction will trigger MetaLinkAddon RestartAssemblySync
                                });
                            }
                        }
                    }
                    else
                    {
                        GMEConsole.Warning.WriteLine("A different ComponentAssembly is already synced");
                    }
                }
                else
                {
                    StartAssemblySync(project, currentobj, param);
                }

                //GMEConsole.Out.WriteLine("End of CyPhySync interpreter...");
            }
            catch (AggregateException e)
            {
                foreach (var exception in e.InnerExceptions)
                {
                    GMEConsole.Error.WriteLine(exception.Message);
                }
                throw new ApplicationException(e.InnerException.Message, e.InnerException);
            }
            finally
            {
                MgaGateway   = null;
                project      = null;
                currentobj   = null;
                selectedobjs = null;
                GMEConsole   = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }