Utility wizard for basic schematic datasets configuration
GenerateSchematicTemplate.cs
// Copyright 2012 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions at <your ArcGIS install location>/DeveloperKit10.0/userestrictions.txt.
// namespace SchematicCreateBasicSettingsAddIn

using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Schematic;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.ArcCatalogUI;
using ESRI.ArcGIS.ArcCatalog;
using ESRI.ArcGIS.Catalog;
using ESRI.ArcGIS.CatalogUI;
using ESRI.ArcGIS.ArcMap;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.NetworkAnalysis;
using System.Windows.Forms;
using ESRI.ArcGIS.esriSystem;

namespace SchematicCreateBasicSettingsAddIn
{
  public class GenerateSchematicTemplate : ESRI.ArcGIS.Desktop.AddIns.Button
  {
    #region Variables
    public frmDatasetTemplateName formNames;
    ESRI.ArcGIS.Geodatabase.IWorkspace m_pWS;
    String m_sfn;
    ESRI.ArcGIS.Schematic.ISchematicBuilder m_pB;
    ESRI.ArcGIS.Schematic.ISchematicDataset m_pSDS;
    ESRI.ArcGIS.Schematic.ISchematicStandardBuilder m_pSB;
    ESRI.ArcGIS.Schematic.ISchematicDiagramClass m_pSDT;

    ESRI.ArcGIS.Schematic.ISchematicDatasetImport m_pSDI;

    NameEvents templateInfo;
    public frmSelectItemsToReduce formReduce;
    private bool blnCancel;
    public frmAdvanced formAdvanced;
    private string strLayers;
    private string strNodeLayers;
    NameValueCollection m_myCol = new NameValueCollection();
    private IGxObject m_SelectedObject = null;
    #endregion Attributes

    public GenerateSchematicTemplate()
    {

    }

    private IEnumLayer GetLayers()
    {
      //now get the map document to parse out the feature classes
      GxDialog pGxDialog = new GxDialogClass();
      IEnumGxObject pEnumGxObject;
      bool pResult;

      pGxDialog.ObjectFilter = new GxFilterMapsClass();
      pGxDialog.Title = "Select a map document";
      try
      {
        pResult = pGxDialog.DoModalOpen(0, out pEnumGxObject);
        //check to see if the user canceled the dialog
        if (pResult == false) return null;
        IGxObject pGxObject = pEnumGxObject.Next();
        IMapReader pMapReader = new MapReaderClass();
        pMapReader.Open(pGxObject.FullName.ToString());
        IMap pMap = pMapReader.get_Map(0);
        ESRI.ArcGIS.esriSystem.UID pUID = new ESRI.ArcGIS.esriSystem.UIDClass();
        pUID.Value = "{40A9E885-5533-11D0-98BE-00805F7CED21}";  //feature layer

        IEnumLayer pLayers = pMap.get_Layers(pUID, true);
                return pLayers;
      }
      catch
      {
        //error getting layers
        return null;
      }

    }

    private Dictionary<string, IFeatureClass> ProcessFCs(IEnumFeatureClass fcComplexEdge, IEnumFeatureClass fcComplexNode, IEnumFeatureClass fcSimpleEdge, IEnumFeatureClass fcSimpleNode)
    {
      Dictionary<string, IFeatureClass> pDictionary = new Dictionary<string, IFeatureClass>();

      //handle complex edge
      IFeatureClass fc = fcComplexEdge.Next();
      if (fc != null)
      {
        do
        {
          try
          {
            pDictionary.Add(fc.AliasName, fc);
          }
          catch
          {
            //do nothing
          }
          fc = fcComplexEdge.Next();
        } while (fc != null);
      }

      //handle complex node
      fc = fcComplexNode.Next();
      if (fc != null)
      {
        do
        {
          try
          {
            pDictionary.Add(fc.AliasName, fc);
          }
          catch
          {
            //do nothing
          }
          fc = fcComplexNode.Next();
        } while (fc != null);
      }

      //handle simple edge
      fc = fcSimpleEdge.Next();
      if (fc != null)
      {
        do
        {
          try
          {
            pDictionary.Add(fc.AliasName, fc);
          }
          catch
          {
            //do nothing
          }
          fc = fcSimpleEdge.Next();
        } while (fc != null);
      }

      //handle simple node
      fc = fcSimpleNode.Next();
      if (fc != null)
      {
        do
        {
          try
          {
            pDictionary.Add(fc.AliasName, fc);
          }
          catch
          {
            //do nothing
          }
          fc = fcSimpleNode.Next();
        } while (fc != null);
      }
      return pDictionary;
    }

    private string CreateSchLayers(IEnumLayer pLayers)
    {
      if (pLayers == null) return "";
      ILayer pLayer = pLayers.Next();
      IFeatureLayer featureLayer;
      IFeatureClass featureClass;
      string pStrLayerNames = "";
      IDataset pDataset;
      System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;
      System.Windows.Forms.Cursor.Show();

      m_pSDS.DesignMode = true;
      m_pSDI = (ESRI.ArcGIS.Schematic.ISchematicDatasetImport)m_pSDS;

      Dictionary<string, IFeatureClass> myDictionary = new Dictionary<string, IFeatureClass>();
      IGeometricNetwork gn = null;
      do
      {
        featureLayer = (IFeatureLayer)pLayer;
        featureClass = featureLayer.FeatureClass;
        pDataset = (IDataset)featureClass;

        if (featureClass.FeatureType == esriFeatureType.esriFTSimpleJunction || featureClass.FeatureType == esriFeatureType.esriFTSimpleEdge || featureClass.FeatureType == esriFeatureType.esriFTComplexEdge || featureClass.FeatureType == esriFeatureType.esriFTComplexJunction)
        {

          //The FeatureType property of feature classes that implement this interface will be esriFTSimpleJunction, esriDTSimpleEdge, esriFTComplexJunction, or esriFTComplexEdge.
          INetworkClass networkClass = (INetworkClass)featureLayer.FeatureClass;

          if (networkClass.GeometricNetwork != null)
          {
            //we have a network class
            if ((gn == null) || (gn != networkClass.GeometricNetwork))
            {
              //need to process all the classes
              Dictionary<string, IFeatureClass> localDictionary = new Dictionary<string, IFeatureClass>();
              gn = networkClass.GeometricNetwork;
              IEnumFeatureClass fcComplexEdge = networkClass.GeometricNetwork.get_ClassesByType(esriFeatureType.esriFTComplexEdge);
              IEnumFeatureClass fcComplexNode = networkClass.GeometricNetwork.get_ClassesByType(esriFeatureType.esriFTComplexJunction);
              IEnumFeatureClass fcSimpleEdge = networkClass.GeometricNetwork.get_ClassesByType(esriFeatureType.esriFTSimpleEdge);
              IEnumFeatureClass fcSimpleNode = networkClass.GeometricNetwork.get_ClassesByType(esriFeatureType.esriFTSimpleJunction);
              localDictionary = ProcessFCs(fcComplexEdge, fcComplexNode, fcSimpleEdge, fcSimpleNode);
              if (myDictionary.Count == 0)  //just copy it
              {
                myDictionary = localDictionary;
              }
              else //merge
              {
                Dictionary<string, IFeatureClass>.KeyCollection keyColl = localDictionary.Keys;

                foreach (string s in keyColl)
                {
                  IFeatureClass fc;
                  bool bln = localDictionary.TryGetValue(s, out fc);
                  myDictionary.Add(s, fc);
                }
              }
            }
            //Build up the string that will go to the select items to reduce form
            pStrLayerNames += pDataset.Name.ToString();
            pStrLayerNames += ";";

            //Build up the string for just the node feature classes
            if (featureClass.FeatureType == esriFeatureType.esriFTSimpleJunction || featureClass.FeatureType == esriFeatureType.esriFTComplexJunction)
            {
              strNodeLayers += pDataset.Name.ToString();
              strNodeLayers += ";";
            }

            //create the fields collections to be used by the frmAdvanced form
            IFields pFields = featureClass.Fields;
            if (pFields.FieldCount > 0)
            {
              for (int i = 0; i < pFields.FieldCount; i++)
              {
                //don't mess with objectid or shape or GlobalID
                if ((pFields.get_Field(i).Name.ToString() != "OBJECTID") && (pFields.get_Field(i).Name.ToString() != "SHAPE") && (pFields.get_Field(i).Name.ToString() != "GlobalID") && (pFields.get_Field(i).Name.ToString() != featureClass.OIDFieldName.ToString()) && (pFields.get_Field(i).Name.ToString() != featureClass.ShapeFieldName.ToString()))
                {
                  m_myCol.Add(pDataset.Name.ToString(), pFields.get_Field(i).Name.ToString());
                }
              }
            }

            //remove the layer from the list of dictionary classes
            if (myDictionary.ContainsKey(featureClass.AliasName))
            {
              myDictionary.Remove(featureClass.AliasName);
            }

            m_pSDI.ImportFeatureLayer(featureLayer, m_pSDT, true, true, true);
          }
        }
        pLayer = pLayers.Next();
      } while (pLayer != null);

      //handle any feature classes that were not in the map
      if (myDictionary.Count > 0)
      {
        Dictionary<string, IFeatureClass>.KeyCollection keyColl = myDictionary.Keys;
        foreach (string s in keyColl)
        {
          IFeatureClass fc;
          bool bln = myDictionary.TryGetValue(s, out fc);
          IObjectClass o = (IObjectClass)fc;
          pDataset = (IDataset)fc;

          pStrLayerNames += pDataset.Name.ToString();
          pStrLayerNames += ";";

          //Build up the string for just the node feature classes
          if (fc.FeatureType == esriFeatureType.esriFTSimpleJunction || featureClass.FeatureType == esriFeatureType.esriFTComplexJunction)
          {
            strNodeLayers += pDataset.Name.ToString();
            strNodeLayers += ";";
          }

          //create the fields collections to be used by the frmAdvanced form
          IFields pFields = fc.Fields;
          if (pFields.FieldCount > 0)
          {
            for (int i = 0; i < pFields.FieldCount; i++)
            {
              //don't mess with objectid or shape or GlobalID
              if ((pFields.get_Field(i).Name.ToString() != "OBJECTID") && (pFields.get_Field(i).Name.ToString() != "SHAPE") && (pFields.get_Field(i).Name.ToString() != "GlobalID") && (pFields.get_Field(i).Name.ToString() != fc.OIDFieldName.ToString()) && (pFields.get_Field(i).Name.ToString() != fc.ShapeFieldName.ToString()))
              {
                m_myCol.Add(pDataset.Name.ToString(), pFields.get_Field(i).Name.ToString());
              }
            }
          }
          if ((fc.FeatureType == esriFeatureType.esriFTComplexJunction) || (fc.FeatureType == esriFeatureType.esriFTSimpleJunction))
          {
            //node
            m_pSDI.ImportObjectClass(o, m_pSDT, true, esriSchematicElementType.esriSchematicNodeType);
          }
          else
          {
            //link
            m_pSDI.ImportObjectClass(o, m_pSDT, true, esriSchematicElementType.esriSchematicLinkType);
          }
        }
      }

      m_pSDS.Save(ESRI.ArcGIS.esriSystem.esriArcGISVersion.esriArcGISVersionCurrent, true);
      m_pSDS.DesignMode = false;
      return pStrLayerNames;
    }

    protected override void OnClick()
    {
      blnCancel = false;
      formNames = new frmDatasetTemplateName();
      formNames.cancelFormEvent += new EventHandler(formNames_cancelFormEvent);
      formNames.nextFormEvent += new EventHandler<NameEvents>(formNames_nextFormEvent);
      m_SelectedObject = ArcCatalog.ThisApplication.SelectedObject;

      if ((m_SelectedObject.Category == "Schematic Dataset")
          || (m_SelectedObject.Category.ToLower().Contains("database")))
      {
        if (m_SelectedObject.Category.ToLower().Contains("database"))
        {
          //get dataset and template names, then create the objects
          formNames.blnNewDataset = true;
        }
        else
        {
          //dataset, just get template names, then create objects
          formNames.blnNewDataset = false;
        }
        //show the first form of the wizard 
        if (formNames.ShowDialog() == DialogResult.Cancel)
        {
          formNames = null;
          return;
        }
      }
      else
      {
        //we are not on a database or a schematic dataset
        blnCancel = true;
      }

      if (blnCancel == true)
      {
        System.Windows.Forms.MessageBox.Show("The name of the dataset or template already exists.  Please try again with valid names.");
      }

      if (blnCancel != true)  //only true if the user cancels the first form formNames_cancelFormEvent 
      {
        System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;
        IEnumLayer pEnumLayer = GetLayers();
        if (pEnumLayer == null)
        {
          //should only happen if the user clicks cancel on the gxdialog
          blnCancel = true;
        }
        else
        {
          strLayers = CreateSchLayers(pEnumLayer);
                    if (strLayers.Length > 0) //make sure we get something back
                    {
                        //find out if we need to create node reduction rules
                        formReduce = new frmSelectItemsToReduce();
                        formReduce.doneFormEvent += new EventHandler<ReduceEvents>(formReduce_doneFormEvent);
                        formReduce.cancelFormEvent += new EventHandler(formReduce_cancelFormEvent);

                        formReduce.itemList = strNodeLayers;
                        System.Windows.Forms.Cursor.Current = Cursors.Default;
                        formReduce.ShowDialog();
                    }
                    else
                    {
                        //this can happen if the map document didn't have any
                        //layers corresponding to a geometric network
                        blnCancel = true;
                    }
        }
        System.Windows.Forms.Cursor.Current = Cursors.Default;
      }

      if (blnCancel != true)  //could have cancelled on either frmDatasetTemplateName or frmSelectItemsToReduce
      {
        //Advanced Form
        formAdvanced = new frmAdvanced();
        formAdvanced.doneFormEvent += new EventHandler<AdvancedEvents>(formAdvanced_doneFormEvent);
        formAdvanced.strLayers = this.strLayers;
        formAdvanced.strNodeLayers = this.strNodeLayers;
        formAdvanced.m_myCol = this.m_myCol;
        formAdvanced.ShowDialog();
      }

      ArcCatalog.ThisApplication.Refresh(m_sfn);
      try
      {
        ArcCatalog.ThisApplication.Location = m_SelectedObject.FullName.ToString();
      }
      catch { }

      cleanUp();
    }

    void formReduce_cancelFormEvent(object sender, EventArgs e)
    {
      blnCancel = true;
      formReduce.Close();
    }

    void formAdvanced_doneFormEvent(object sender, AdvancedEvents e)
    {
      m_pSDS.DesignMode = true;
      formAdvanced.Cursor = System.Windows.Forms.Cursors.WaitCursor;
      //process the algorithm if there is one
      if (e.AlgorithmName != "")
      {
        ISchematicAlgoSmartTree a = new SchematicAlgoSmartTreeClass();
        if (e.AlgorithmParams.Count > 0)
        {
          Dictionary<string, string>.KeyCollection keys = e.AlgorithmParams.Keys;
          string strValue = "";
          foreach (string s in keys)
          {
            if (s == "Direction")
            {
              e.AlgorithmParams.TryGetValue(s, out strValue);

              if (strValue == "Top to Bottom")
              {
                a.Direction = esriSchematicAlgoDirection.esriSchematicAlgoTopDown;
              }
              else if (strValue == "Bottom to Top")
              {
                a.Direction = esriSchematicAlgoDirection.esriSchematicAlgoBottomUp;
              }
              else if (strValue == "Left to Right")
              {
                a.Direction = esriSchematicAlgoDirection.esriSchematicAlgoLeftRight;
              }
              else
              {
                a.Direction = esriSchematicAlgoDirection.esriSchematicAlgoRightLeft;
              }
            }
          }
          if (e.RootClass != "")
          {
            ISchematicElementClassContainer pECC = (ISchematicElementClassContainer)m_pSDS;
            ISchematicElementClass pEC = pECC.GetSchematicElementClass(e.RootClass);
            ESRI.ArcGIS.esriSystem.UID u = new ESRI.ArcGIS.esriSystem.UID();
            u.Value = "{3AD9D8B8-0A1D-4F32-ABB5-54B848A46F85}";

            ISchematicAttributeConstant pAttrConst = (ISchematicAttributeConstant)pEC.CreateSchematicAttribute("RootFlag", u);
            ISchematicAttributeManagement pAttrMgmt = (ISchematicAttributeManagement)pAttrConst;
            pAttrMgmt.StorageMode = esriSchematicAttributeStorageMode.esriSchematicAttributeFieldStorage;
            pAttrConst.ConstantValue = "-1";
          }
        }

        m_pSDT.SchematicAlgorithm = (ISchematicAlgorithm)a;

      }

      //check to see if we need to add associated fields
      if (e.FieldsToCreate != null)
      {
        if (e.FieldsToCreate.Count > 0)
        {
          ISchematicElementClassContainer pECC = (ISchematicElementClassContainer)m_pSDS;

          //create the associated field attributes
          string[] keys = e.FieldsToCreate.AllKeys;
          foreach (string s in keys)
          {
            //get the feature class
            ISchematicElementClass pEC = pECC.GetSchematicElementClass(s);
            if (pEC != null)
            {
              string strName = "";
              string[] values = e.FieldsToCreate.GetValues(s);
              foreach (string v in values)
              {
                //create the field
                ESRI.ArcGIS.esriSystem.UID u = new ESRI.ArcGIS.esriSystem.UID();
                u.Value = "{7DE3A19D-32D0-41CD-B896-37CA3AFBD88A}";

                IClass pClass = (IClass)pEC;
                //only handle names that don't already exist in the schematic tables
                if (pClass.FindField(v) == -1)
                {
                  strName = v.ToString();

                  ISchematicAttributeAssociatedField pFieldAttr = (ISchematicAttributeAssociatedField)pEC.CreateSchematicAttribute(strName, u);
                  pFieldAttr.AssociatedFieldName = v;
                  ISchematicAttributeManagement pAttrMgmt = (ISchematicAttributeManagement)pFieldAttr;
                  pAttrMgmt.StorageMode = esriSchematicAttributeStorageMode.esriSchematicAttributeFieldStorage;
                }
              }
            }
          }
        }
      }

      m_pSDS.Save(ESRI.ArcGIS.esriSystem.esriArcGISVersion.esriArcGISVersionCurrent, true);
      m_pSDS.DesignMode = false;
      formAdvanced.Cursor = System.Windows.Forms.Cursors.Default;
      formAdvanced.Close();
    }

    private Boolean CreateTemplate(NameEvents templateInfo)
    {
      //need to get everything first
      IGxDatabase pDatabase = null;
      ISchematicDiagramClassContainer pDiagramClassContainer = null;

      if (m_SelectedObject.Category == "Schematic Dataset")
      {
        pDatabase = (IGxDatabase)m_SelectedObject.Parent;
      }
      else  //on the database already
      {
        pDatabase = (IGxDatabase)m_SelectedObject;
      }
      m_pWS = pDatabase.Workspace;

      ESRI.ArcGIS.Schematic.ISchematicWorkspaceFactory pSWF = new SchematicWorkspaceFactory();
      ESRI.ArcGIS.Schematic.ISchematicWorkspace pSW = pSWF.Open(m_pWS);

      m_pSDS = pSW.get_SchematicDatasetByName(templateInfo.DatasetName);

      //check to see if the template name already exists
      pDiagramClassContainer = (ISchematicDiagramClassContainer)m_pSDS;
      m_pSDT = pDiagramClassContainer.GetSchematicDiagramClass(templateInfo.TemplateName.ToString());
      if (m_pSDT != null) return false;

      //create the schematic template
      m_pSDT = m_pSDS.CreateSchematicDiagramClass(templateInfo.TemplateName);

      if ((templateInfo.AutoCreate == true) || (templateInfo.UseVertices == true))
      {
        m_pB = (ESRI.ArcGIS.Schematic.ISchematicBuilder)m_pSDT;
        m_pSB = (ESRI.ArcGIS.Schematic.ISchematicStandardBuilder)m_pSDT.SchematicBuilder;
        m_pSB.InitializeLinksVertices = templateInfo.UseVertices;
        m_pSB.AutoCreateElementClasses = templateInfo.AutoCreate;
      }
      m_pSDS.Save(ESRI.ArcGIS.esriSystem.esriArcGISVersion.esriArcGISVersion10, false);
      return true;
    }

    private Boolean CreateDataset(NameEvents templateInfo)
    {
      try
      {
        IGxDatabase pDatabase = (IGxDatabase)m_SelectedObject;

        m_pWS = pDatabase.Workspace;

        ESRI.ArcGIS.Schematic.ISchematicWorkspaceFactory pSWF = new SchematicWorkspaceFactory();
        ESRI.ArcGIS.Schematic.ISchematicWorkspace pSW = pSWF.Open(m_pWS);
        //check to see if this dataset name is already used
        m_pSDS = pSW.get_SchematicDatasetByName(templateInfo.DatasetName.ToString());
        if (m_pSDS != null) return false;

        m_pSDS = pSW.CreateSchematicDataset(templateInfo.DatasetName, "");
        return true;
      }
      catch
      {
        //nothing
        return false;
      }
    }

    void formNames_cancelFormEvent(object sender, EventArgs e)
    {
      //user is canceling the wizard
      formNames.Close();
      formNames = null;
      blnCancel = true;
    }

    void formReduce_doneFormEvent(object sender, ReduceEvents e)
    {
      //user click the done button on the reduce form
      ISchematicBuilderRule pIsbr;
      ISchematicBuilderRuleContainer pIsbrc = (ISchematicBuilderRuleContainer)m_pSDT;
      ISchematicBuilderRuleContainerEdit pIsbrce = (ISchematicBuilderRuleContainerEdit)pIsbrc;

      formReduce.Cursor = System.Windows.Forms.Cursors.WaitCursor;
      string[] selectedItems = e.SelectedObjects;
      m_pSDS.DesignMode = true;
      foreach (string s in selectedItems)
      {
        //setup rule properties
        ISchematicNodeReductionRuleByPriority pRule = new SchematicNodeReductionRuleByPriorityClass();
        pRule.NodeDegreeConstraint = true;
        pRule.ReduceNodeDegree0 = true;
        pRule.ReduceNodeDegree2 = true;
        pRule.ReduceNodeDegree1 = false;
        pRule.ReduceNodeDegreeSup3 = false;

        //set the name and class to reduce
        ISchematicNodeReductionRule pNR = (ISchematicNodeReductionRule)pRule;
        pNR.Description = "Remove " + s.ToString();
        pNR.NodeClassName = s.ToString();

        //add it to the template
        pIsbr = pIsbrce.AddSchematicBuilderRule();
        pIsbr.SchematicRule = (ISchematicRule)pRule;
      }

      //save and close
      m_pSDS.Save(ESRI.ArcGIS.esriSystem.esriArcGISVersion.esriArcGISVersion10, false);
      m_pSDS.DesignMode = false;
      formReduce.Cursor = System.Windows.Forms.Cursors.Default;
      formReduce.Close();
    }

    void formNames_nextFormEvent(object sender, NameEvents e)
    {
      Boolean blnCheck = false;
      //check if we need to create a new dataset
      templateInfo = new NameEvents(e.NewDataset, e.DatasetName, e.TemplateName, e.UseVertices);
      formNames.Cursor = System.Windows.Forms.Cursors.WaitCursor;

      if (templateInfo.NewDataset == true)
      {
        blnCheck = CreateDataset(templateInfo);
        if (blnCheck == false)
        {
          //name already exists
          blnCancel = true;
        }
        else
        {
          blnCheck = CreateTemplate(templateInfo);
          if (blnCheck == false)
          {
            //name already exists
            blnCancel = true;
          }
        }
      }
      else //just create a new template
      {
        blnCheck = CreateTemplate(templateInfo);
        if (blnCheck == false)
        {
          //name already exists
          blnCancel = true;
        }
      }
      formNames.Cursor = System.Windows.Forms.Cursors.Default;
      formNames.Close();
    }

    protected override void OnUpdate()
    {
      Enabled = ArcCatalog.Application != null;
      if ((ArcCatalog.ThisApplication.SelectedObject.Category == "File Geodatabase")
          || (ArcCatalog.ThisApplication.SelectedObject.Category == "Personal Geodatabase")
          || (ArcCatalog.ThisApplication.SelectedObject.Category == "Schematic Dataset")
          || (ArcCatalog.ThisApplication.SelectedObject.Category == "Spatial Database Connection"))
      {
        Enabled = true;
      }
      else
      {
        Enabled = false;
      }

    }

    void cleanUp()
    {
      //m_pWSF = null;
      m_pWS = null;
      m_pSDT = null;
      m_pSDS = null;
      m_pSB = null;
      m_pB = null;
      m_SelectedObject = null;
      templateInfo = null;
      m_pSDI = null;
      formNames = null;
      formReduce = null;
      m_sfn = "";
      blnCancel = false;
      strLayers = "";
      strNodeLayers = "";
    }

  }
}