protected override void OnClick()
        {
            FileType ft = FileType.COGOToolbarTraverse; //start out assuming it is a cogo traverse file

            m_count = 1;
            ICadastralEditor            pCadEd         = (ICadastralEditor)ArcMap.Application.FindExtensionByName("esriCadastralUI.CadastralEditorExtension");
            ICadastralFabric            pCadFabric     = pCadEd.CadastralFabric;
            ICadastralExtensionManager2 pCadExtMan     = (ICadastralExtensionManager2)pCadEd;
            IParcelEditManager          pParcEditorMan = (IParcelEditManager)pCadEd;
            IParcelConstruction         pTrav          = pParcEditorMan.ParcelConstruction;

            if (!(pParcEditorMan.InTraverseEditMode) && !(pParcEditorMan.InConstructionEditMode))
            {//if this is not a construction or a new parcel, then get out.
                MessageBox.Show("Please create a new parcel or new construction first, and then try again.");
                return;
            }

            //Make sure the lines grid is selected
            Utilities UTILS = new Utilities();

            UTILS.SelectCadastralPropertyPage((ICadastralExtensionManager)pCadExtMan, "lines");

            IParcelConstruction3 pTrav3  = (IParcelConstruction3)pTrav;
            IGSParcel            pParcel = null;

            try
            {
                pParcel = pTrav.Parcel;
            }
            catch (COMException error)
            {
                MessageBox.Show(error.Message.ToString());
                return;
            }
            //go get a traverse file
            // Display .Net dialog for File selection.
            OpenFileDialog openFileDialog = new OpenFileDialog();

            // Set File Filter
            openFileDialog.Filter = "Traverse file (*.txt)|*.txt|Comma-delimited(*.csv)|*.csv|All Files|*.*";
            // Disable multi-select
            openFileDialog.Multiselect = false;
            // Don't need to Show Help
            openFileDialog.ShowHelp = false;
            // Set Dialog Title
            openFileDialog.Title       = "Load file";
            openFileDialog.FilterIndex = 2;
            // Display Open File Dialog
            if (openFileDialog.ShowDialog() != DialogResult.OK)
            {
                openFileDialog = null;
                return;
            }

            TextReader tr = null;

            try
            {
                tr = new StreamReader(openFileDialog.FileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            string sCourse = "";
            int    iCount  = 0;

            string[] sFileLine = new string[0]; //define as dynamic array
            //initialize direction units and format
            esriDirectionType  enumDirectionType  = esriDirectionType.esriDTQuadrantBearing;
            esriDirectionUnits enumDirectionUnits = esriDirectionUnits.esriDUDegreesMinutesSeconds;

            //initialize start and end points
            IPoint StartPoint     = new PointClass();
            IPoint EndPoint       = new PointClass();
            bool   IsLoopTraverse = false;

            //fill the array with the lines from the file
            while (sCourse != null)
            {
                sCourse = tr.ReadLine();
                try
                {
                    if (sCourse.Trim().Length >= 1) //test for empty lines
                    {
                        RedimPreserveString(ref sFileLine, 1);
                        sFileLine[iCount] = sCourse;
                    }
                    iCount++;
                    sCourse = sCourse.ToLower();
                    if (sCourse.Contains("dt"))
                    {
                        if (sCourse.Contains("qb"))
                        {
                            enumDirectionType = esriDirectionType.esriDTQuadrantBearing;
                        }
                        else if (sCourse.Contains("na"))
                        {
                            enumDirectionType = esriDirectionType.esriDTNorthAzimuth;
                        }
                        else if (sCourse.Contains("sa"))
                        {
                            enumDirectionType = esriDirectionType.esriDTSouthAzimuth;
                        }
                        else if (sCourse.Contains("p"))
                        {
                            enumDirectionType = esriDirectionType.esriDTPolar;
                        }
                    }
                    if (sCourse.Contains("du"))
                    {
                        if (sCourse.Contains("dms"))
                        {
                            enumDirectionUnits = esriDirectionUnits.esriDUDegreesMinutesSeconds;
                        }
                        else if (sCourse.Contains("dd"))
                        {
                            enumDirectionUnits = esriDirectionUnits.esriDUDecimalDegrees;
                        }
                        else if (sCourse.Contains("g"))
                        {
                            enumDirectionUnits = esriDirectionUnits.esriDUGons;
                        }
                        else if (sCourse.Contains("r"))
                        {
                            enumDirectionUnits = esriDirectionUnits.esriDURadians;
                        }
                    }
                    if (sCourse.Contains("sp"))
                    {//start point
                        string[] XY = sCourse.Split(' ');
                        double   x  = Convert.ToDouble(XY[1]);
                        double   y  = Convert.ToDouble(XY[2]);
                        StartPoint.PutCoords(x, y);
                    }

                    if (sCourse.Contains("ep"))
                    {//end point
                        string[] XY = sCourse.Split(' ');
                        double   x  = Convert.ToDouble(XY[1]);
                        double   y  = Convert.ToDouble(XY[2]);
                        EndPoint.PutCoords(x, y);
                    }

                    if (sCourse.Contains("tometricfactor"))
                    {//this handles the comma-separated file case
                        string[] sScaleFactor = sCourse.Split(',');
                        m_dScaleFactor = Convert.ToDouble(sScaleFactor[1]);
                    }
                }
                catch { }
            }
            tr.Close(); //close the file and release resources
            string sFileExt = System.IO.Path.GetExtension(openFileDialog.FileName.TrimEnd());

            if ((sFileExt.ToLower() == ".csv") && (sFileLine[0].Contains(",")))
            {//if it's a comma-delimited file
                ft = FileType.CommaDelimited;
            }

            //Test for loop traverse
            if (!(EndPoint.IsEmpty))
            {
                if (EndPoint.Compare(StartPoint) == 0)
                {
                    IsLoopTraverse = true;
                }
                else
                {
                    IsLoopTraverse = false;
                }
            }

            //get highest point id number in grid, and get the to point id on the last line.
            IGSLine pParcelLine     = null;
            int     iFirstToNode    = -1;
            int     iLastToNode     = -1;
            int     iHighestPointID = -1;

            for (int i = 0; i < pTrav.LineCount; i++)
            {
                if (pTrav.GetLine(i, ref pParcelLine))
                {
                    if (iFirstToNode < 0)
                    {
                        iFirstToNode = pParcelLine.ToPoint;
                    }
                    iLastToNode     = pParcelLine.ToPoint;
                    iHighestPointID = iHighestPointID < pParcelLine.ToPoint ? pParcelLine.ToPoint : iHighestPointID;
                    iHighestPointID = iHighestPointID < pParcelLine.FromPoint ? pParcelLine.FromPoint : iHighestPointID;
                }
            }

            ICadastralUndoRedo pCadUndoRedo = pTrav as ICadastralUndoRedo;

            pCadUndoRedo.StartUndoRedoSession("Load Lines From File");
            try
            {
                IGSLine  pLine        = null;
                int      iLinecount   = iCount - 1;
                ISegment pExitTangent = null;
                for (iCount = 0; iCount <= iLinecount; iCount++)
                {
                    if (ft == FileType.COGOToolbarTraverse)
                    {
                        {
                            pLine = null;

                            ICircularArc pCircArc;//need to use this in the test to handle curves greater than 180
                            pLine = CreateGSLine(sFileLine[iCount], enumDirectionUnits, enumDirectionType,
                                                 pExitTangent, out pExitTangent, out pCircArc);
                            //exit tangent from the previous course is the new entry tangent for the next course

                            if (pLine != null)
                            {
                                if (pCircArc == null)
                                {// straight line
                                    //if this is the last course then set the to point to 1
                                    if ((iCount == iLinecount) && IsLoopTraverse)
                                    {
                                        pLine.ToPoint = 1;
                                    }
                                    pTrav.InsertGridRow(-1, pLine);
                                }
                                else
                                {                                                               //some post-processing needed to figure out if a 180 curve needs to be split
                                    if (Math.Abs(pCircArc.CentralAngle) < (Math.PI - 0.000001)) //some tolerance for being close to 180
                                    {                                                           //this curve is OK
                                      //if this is the last course then set the to point to 1
                                        if ((iCount == iLinecount) && IsLoopTraverse)
                                        {
                                            pLine.ToPoint = 1;
                                        }
                                        pTrav.InsertGridRow(-1, pLine);
                                    }
                                    else
                                    {//curve is greater than or equal to 180, special treatment for GSE needed to split curve into 2 parts
                                        //first decrement the count
                                        m_count -= 1;
                                        ISegment pFullSegment = (ISegment)pCircArc; ISegment pFirstHalf; ISegment pSecondHalf;
                                        pFullSegment.SplitAtDistance(0.5, true, out pFirstHalf, out pSecondHalf);
                                        IConstructCircularArc2 pCircArcConstr1 = new CircularArcClass();
                                        ICircularArc           pCircArc1       = (ICircularArc)pCircArcConstr1;
                                        pCircArcConstr1.ConstructEndPointsRadius(pFirstHalf.FromPoint,
                                                                                 pFirstHalf.ToPoint, pCircArc.IsCounterClockwise, pCircArc.Radius, true);
                                        ILine2 pTangentLine = new LineClass();
                                        pCircArc1.QueryTangent(esriSegmentExtension.esriExtendTangentAtTo, 0, false, 100, pTangentLine);
                                        string sTangentBearing = PolarRadians_2_DirectionString(pTangentLine.Angle,
                                                                                                enumDirectionType, enumDirectionUnits);
                                        sTangentBearing = sTangentBearing.Replace(" ", "");
                                        string sHalfDelta = Radians_2_Angle(Math.Abs(pCircArc1.CentralAngle), enumDirectionUnits);
                                        string sSide      = pCircArc.IsCounterClockwise ? " L " : " R ";

                                        ISegment EntryTangent = (ISegment)pTangentLine;

                                        //construct the string for the first piece
                                        // looks similar to this: NC R 500 D 181-59-59 T N59-59-59W L
                                        string sFirstCurve = "NC R " + Convert.ToString(pCircArc.Radius)
                                                             + " D " + sHalfDelta + " T " + sTangentBearing + sSide;

                                        IGSLine pLineFirstCurve = CreateGSLine(sFirstCurve, enumDirectionUnits, enumDirectionType, pExitTangent,
                                                                               out pExitTangent, out pCircArc);
                                        pTrav.InsertGridRow(-1, pLineFirstCurve);

                                        ICircularArc pCircArc2 = (ICircularArc)pCircArcConstr1;
                                        pCircArcConstr1.ConstructEndPointsRadius(pSecondHalf.FromPoint,
                                                                                 pSecondHalf.ToPoint, pCircArc.IsCounterClockwise, pCircArc.Radius, true);
                                        pCircArc2.QueryTangent(esriSegmentExtension.esriExtendTangentAtTo, 0, false, 100, pTangentLine);
                                        sTangentBearing = PolarRadians_2_DirectionString(pTangentLine.Angle, enumDirectionType, enumDirectionUnits);
                                        sTangentBearing = sTangentBearing.Replace(" ", "");
                                        //construct the string for the second piece
                                        // looks similar to this: NC R 500 D 181-59-59 T N59-59-59W L
                                        string sSecondCurve = "NC R " + Convert.ToString(pCircArc.Radius)
                                                              + " D " + sHalfDelta + " T " + sTangentBearing + sSide;

                                        IGSLine pLineSecondCurve = CreateGSLine(sSecondCurve, enumDirectionUnits, enumDirectionType, pExitTangent,
                                                                                out pExitTangent, out pCircArc);
                                        //if this is the last course then set the to point to 1
                                        if ((iCount == iLinecount) && IsLoopTraverse)
                                        {
                                            pLine.ToPoint = 1;
                                        }
                                        pTrav.InsertGridRow(-1, pLineSecondCurve);
                                    }
                                }
                            }
                        }
                    }
                    else//this is comma-separated version of the grid, so do the following
                    {
                        pLine = null;
                        //apply a point id number offset if there are existing lines in the grid.
                        if (iHighestPointID > -1 && iCount >= 3)
                        {
                            string[] sTraverseCourse = sFileLine[iCount].Split(',');
                            if (iCount == 3)
                            {
                                sTraverseCourse[0] = iLastToNode.ToString();
                                sTraverseCourse[5] = (Convert.ToInt32(sTraverseCourse[5]) + iHighestPointID).ToString();
                            }
                            else if (iCount > 3)
                            {
                                sTraverseCourse[0] = (Convert.ToInt32(sTraverseCourse[0]) + iHighestPointID).ToString();
                                sTraverseCourse[5] = (Convert.ToInt32(sTraverseCourse[5]) + iHighestPointID).ToString();
                            }

                            sFileLine[iCount] = sTraverseCourse[0];
                            int iAttCount = sTraverseCourse.GetLength(0);
                            for (int j = 1; j < iAttCount; j++)
                            {
                                sFileLine[iCount] += "," + sTraverseCourse[j];
                            }
                        }

                        pLine = CreateGSLineFromCommaSeparatedString(sFileLine[iCount], enumDirectionUnits, enumDirectionType);

                        if (pLine != null)
                        {
                            pTrav.InsertGridRow(-1, pLine);
                        }
                    }
                }
                pTrav3.UpdateGridFromGSLines(false);
                IParcelConstruction2 pConstr2 = (IParcelConstruction2)pTrav3; //hidden interface
                pConstr2.RecalculatePoints();                                 //explicit recalculate needed on a construction
                pParcel.Modified();
                pParcEditorMan.Refresh();
                pCadUndoRedo.WriteUndoRedoSession(true);
                sFileLine      = null;
                openFileDialog = null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Load Lines From File");
                pCadUndoRedo.WriteUndoRedoSession(false);
            }
        }
        protected override void OnClick()
        {
            ICadastralEditor            pCadEd         = (ICadastralEditor)ArcMap.Application.FindExtensionByName("esriCadastralUI.CadastralEditorExtension");
            ICadastralFabric            pCadFabric     = pCadEd.CadastralFabric;
            ICadastralExtensionManager2 pCadExtMan     = (ICadastralExtensionManager2)pCadEd;
            IParcelEditManager          pParcEditorMan = (IParcelEditManager)pCadEd;
            IParcelConstruction         pTrav          = pParcEditorMan.ParcelConstruction;

            //Test for the visibility of the parcel details window
            IDockableWindowManager pDocWinMgr = (IDockableWindowManager)ArcMap.Application;
            UID pUID = new UIDClass();

            pUID.Value = "{28531B78-7C42-4785-805D-2A7EC8879EA1}";//ArcID.ParcelDetails
            IDockableWindow pParcelDet = pDocWinMgr.GetDockableWindow(pUID);

            if (!pParcelDet.IsVisible())
            {
                MessageBox.Show("The Parcel Details window is not visible. \r\nThere is no data to save.");
                return;
            }

            //Make sure the lines grid is selected
            Utilities UTILS = new Utilities();

            UTILS.SelectCadastralPropertyPage((ICadastralExtensionManager)pCadExtMan, "lines");

            //test to make sure there is data there to be saved
            IParcelConstruction3 pConstr = (IParcelConstruction3)pTrav;
            IGSParcel            pParcel = null;

            //
            try
            {
                pParcel = pTrav.Parcel;
            }
            catch (COMException err)
            {
                MessageBox.Show(err.Message + Environment.NewLine + "ERROR: Select a parcel or add lines to the grid. \r\nThere is no data to save. ");
                return;
            }
            //define the file that needs to be saved
            // Display .Net dialog for File saving.
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            // Set File Filter
            saveFileDialog.Filter           = "Comma-delimited(*.csv)|*.csv|All Files|*.*";
            saveFileDialog.FilterIndex      = 1;
            saveFileDialog.RestoreDirectory = true;
            // Warn on overwrite
            saveFileDialog.OverwritePrompt = true;
            // Don't need to Show Help
            saveFileDialog.ShowHelp = false;
            // Set Dialog Title
            saveFileDialog.Title = "Save file";

            // Display Open File Dialog
            if (saveFileDialog.ShowDialog() != DialogResult.OK)
            {
                saveFileDialog = null;
                return;
            }
            TextWriter tw = null;

            try
            {
                tw = new StreamWriter(saveFileDialog.FileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            try
            {
                IGSPlan pPlan = pTrav.Parcel.Plan;
                int     iDF   = (int)pPlan.DirectionFormat;
                switch (iDF)
                {
                case (int)esriDirectionType.esriDTNorthAzimuth:
                    tw.WriteLine("DT,NA");
                    break;

                case (int)esriDirectionType.esriDTPolar:
                    tw.WriteLine("DT,P");
                    break;

                case (int)esriDirectionType.esriDTQuadrantBearing:
                    tw.WriteLine("DT,QB");
                    break;

                case (int)esriDirectionType.esriDTSouthAzimuth:
                    tw.WriteLine("DT,SA");
                    break;

                default:
                    tw.WriteLine("DT,NA");
                    break;
                }

                int iAU = (int)pPlan.AngleUnits;
                switch (iAU)
                {
                case (int)esriDirectionUnits.esriDUDecimalDegrees:
                    tw.WriteLine("DU,DD");
                    break;

                case (int)esriDirectionUnits.esriDUDegreesMinutesSeconds:
                    tw.WriteLine("DU,DMS");
                    break;

                case (int)esriDirectionUnits.esriDUGons:
                case (int)esriDirectionUnits.esriDUGradians:
                    tw.WriteLine("DU,G");
                    break;

                case (int)esriDirectionUnits.esriDURadians:
                    tw.WriteLine("DU,R");
                    break;

                default:
                    tw.WriteLine("DU,R");
                    break;
                }

                ICadastralUnitConversion pUnitConv = new CadastralUnitConversionClass();
                double dMetricConversion           = pUnitConv.ConvertDouble(1, pPlan.DistanceUnits, esriCadastralDistanceUnits.esriCDUMeter);
                string sLU = Convert.ToString(dMetricConversion);

                tw.WriteLine("ToMetricFactor," + sLU);

                IEnumGSLines pGSLines = pTrav.GetLines();
                pGSLines.Reset();
                IGSLine   pGSLine   = null;
                IGSParcel pGSParcel = null;
                pGSLines.Next(ref pGSParcel, ref pGSLine);
                while (pGSLine != null)
                {
                    int iFromPt  = pGSLine.FromPoint;     //from point
                    int iToPt    = pGSLine.ToPoint;       //to point
                    int iLineCat = (int)pGSLine.Category; //line category
                    if (iLineCat == 4)
                    {
                        pGSLines.Next(ref pGSParcel, ref pGSLine);
                        continue;                            //ignore radial lines
                    }
                    int    iLineUserType = pGSLine.LineType; //line user type
                    int    iAccCat       = pGSLine.Accuracy; //accuracy
                    double dDistance     = pGSLine.Distance; //distance
                    double dChord        = pGSLine.Distance; //chord
                    double dRadius       = pGSLine.Radius;   //radius

                    string sLineCat      = Convert.ToString(iLineCat);
                    string sLineUserType = Convert.ToString(iLineUserType);

                    if (iLineUserType > 2140000000)
                    {
                        sLineUserType = "";
                    }

                    string sAccCat = Convert.ToString(iAccCat);
                    string sFromPt = Convert.ToString(iFromPt);//from point

                    //following need conversion
                    string sDirection = NorthAzRadians_2_DirectionString(pGSLine.Bearing, pPlan.DirectionFormat, pPlan.AngleUnits); //direction
                    string sDistance  = Convert.ToString(dDistance / dMetricConversion);                                            //distance
                    string sRadius    = "";
                    string sChord     = "";

                    if (dRadius != 123456789)
                    {                                                                //circular curve
                        sRadius   = Convert.ToString(dRadius / dMetricConversion);   //radius
                        sChord    = Convert.ToString(dDistance / dMetricConversion); //chord
                        sDistance = "";                                              //distance is replaced with the chord distance
                    }

                    string sToPt = Convert.ToString(iToPt);//to point
                    //write the line
                    tw.WriteLine(sFromPt + "," + sDirection + "," + sDistance + "," + sRadius + "," + sChord + "," + sToPt + ","
                                 + sLineCat + "," + sLineUserType + "," + sAccCat);

                    pGSLines.Next(ref pGSParcel, ref pGSLine);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                tw.Close();
                saveFileDialog = null;
            }
        }