// Constructor public CListableName( CIndividualRecord ir, string surname, string firstname ) { m_ir = ir; m_sSurname = surname; m_sFirstName = firstname; base.Text = ToString(); }
// Constructor. public CMiniTreeMap( string sName, CIndividualRecord ir, bool bLinkable, int x1, int y1, int x2, int y2 ) { m_x1 = x1; m_y1 = y1; m_x2 = x2; m_y2 = y2; m_ir = ir; m_bLinkable = bLinkable; m_sName = sName; }
// Recursively visit all individuals connected to this one and record them by adding their xrefs as keys in m_htVisited public void PruneMarkConnected( CIndividualRecord ir ) { int nFamily; CFamilyRecord fr; if( ir.Visibility() == CIndividualRecord.EVisibility.Invisible ) { // Don't follow splits return; } // Mark individual m_htVisited[ ir.m_xref ] = true; // Mark all ancestors nFamily = 0; fr = null; while( (fr = GetFamilyByChild( ir, nFamily++ )) != null ) { CIndividualRecord irFather = GetHusband( fr ); if( irFather != null ) { if( !m_htVisited.ContainsKey( irFather.m_xref ) ) { PruneMarkConnected( irFather ); } } CIndividualRecord irMother = GetWife( fr ); if( irMother != null ) { if( !m_htVisited.ContainsKey( irMother.m_xref ) ) { PruneMarkConnected( irMother ); } } // If both parents are unknown, we can still navigate to the children. Parents appear in minitree as <unknown>, and children also appear. // If either mother or father is known, the marking will have happened above. if( irMother == null && irFather == null ) { int i = 0; CIndividualRecord irChild; while ((irChild = fr.GetChildByBirthDate(i)) != null) { i++; if( m_htVisited.ContainsKey( irChild.m_xref ) == false ) { PruneMarkConnected( irChild ); } } } } // Mark all descendants nFamily = 0; fr = null; while( (fr = GetFamilyBySpouse( ir, nFamily++ )) != null ) { int nChild = 0; CIndividualRecord irChild = null; while ((irChild = fr.GetChildByBirthDate(nChild++)) != null) { if( irChild == null || m_htVisited.ContainsKey( irChild.m_xref ) ) { continue; } PruneMarkConnected( irChild ); } // Mark all spouses CIndividualRecord irFather = GetHusband( fr ); if( irFather != ir && irFather != null && !m_htVisited.ContainsKey( irFather.m_xref ) ) { PruneMarkConnected( irFather ); } CIndividualRecord irMother = GetWife( fr ); if( irMother != ir && irMother != null && !m_htVisited.ContainsKey( irMother.m_xref ) ) { PruneMarkConnected( irMother ); } } }
// This is the main tree drawing method. // irSubject is the individual for whom the tree is based. // nTargeWidth is the width below which the layout is free to use up space to produce a nice tree. public ArrayList CreateMiniTree( CPaintbox paintbox, CIndividualRecord ir, string sFilename, int nTargetWidth, System.Drawing.Imaging.ImageFormat imageFormat ) { // First calculate size required for tree, by iterating through individuals and building a data structure CMiniTreeGroup mtgParent = CreateDataStructure(ir); // For each individual calculate size of box required for display using helper function // There must be a better way to get a graphics: Bitmap bmp = new Bitmap( 1, 1, System.Drawing.Imaging.PixelFormat.Format24bppRgb ); Graphics g = Graphics.FromImage( bmp ); Font f = paintbox.m_font; // Record what font windows actually used, in case it chose a different one MainForm.s_config.m_sTreeFontName = f.Name; MainForm.s_config.m_fTreeFontSize = f.Size; // Recursively calculate sizes of other groups mtgParent.CalculateSize( g, f ); g.Dispose(); bmp.Dispose(); // Now calculate sizes of each row // Total width includes irSubject, their spouses and their siblings. // Total height is always three generations // Now calculate how best to position each generation // Calculate the width of each generation // There are three cases : frParents widest, siblings widest, children widest // Plus two aims : minimise total width, get offspring centred under frParents. // If nTargetWidth is exceeded simply because of number of individuals in one row, that // row's width becomes the new target width. // If nTargetWidth is exceeded otherwise, minimising total width becomes the priority mtgParent.CalculateLayout( 0f, 0f ); mtgParent.Compress(); RectangleF rect = mtgParent.GetExtent(); m_sizeTotal = new SizeF( rect.Width, rect.Height ); mtgParent.Translate( -rect.Left, -rect.Top ); // Calculate offset for each row // Can't do this so create a new bitmap: bmp.Width = totalSize.Width; // Can't do this so create a new bitmap: bmp.Height = totalSize.Height; int nTotalWidth = (int)(m_sizeTotal.Width+1.0f); int nTotalHeight = (int)(m_sizeTotal.Height+1.0f); bmp = new Bitmap( nTotalWidth, nTotalHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb ); g = Graphics.FromImage( bmp ); // Do background fill if( MainForm.s_config.m_bFakeMiniTreeTransparency && paintbox.m_brushFakeTransparency != null ) { g.FillRectangle( paintbox.m_brushFakeTransparency, 0, 0, nTotalWidth, nTotalHeight ); } else if( imageFormat == ImageFormat.Gif && paintbox.m_brushBgGif != null ) { g.FillRectangle( paintbox.m_brushBgGif, 0, 0, nTotalWidth, nTotalHeight ); } ArrayList alMap = new ArrayList(); mtgParent.DrawBitmap( paintbox, g, alMap ); // Save the bitmap LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.eDL_Note, "Saving mini tree as " + sFilename ); if( System.IO.File.Exists( sFilename ) ) { // Delete any current file System.IO.File.SetAttributes( sFilename, System.IO.FileAttributes.Normal ); System.IO.File.Delete( sFilename ); } // Save using FileStream to try to avoid crash (only seen by customers) System.IO.FileStream fs = new System.IO.FileStream( sFilename, System.IO.FileMode.Create ); bmp.Save( fs, imageFormat ); fs.Close(); g.Dispose(); bmp.Dispose(); // For gifs we need to reload and set transparency colour if( imageFormat == ImageFormat.Gif && !MainForm.s_config.m_bFakeMiniTreeTransparency ) { Image imageGif; ColorPalette colorpalette; imageGif = Image.FromFile( sFilename ); colorpalette = imageGif.Palette; // Creates a new GIF image with a modified colour palette if (colorpalette != null ) { // Create a new 8 bit per pixel image Bitmap bm=new Bitmap(imageGif.Width,imageGif.Height,PixelFormat.Format8bppIndexed); // Get it's palette ColorPalette colorpaletteNew = bm.Palette; // Copy all the entries from the old palette removing any transparency int n=0; foreach(Color c in colorpalette.Entries) { colorpaletteNew.Entries[n++]=Color.FromArgb(255,c); } // Now to copy the actual bitmap data // Lock the source and destination bits BitmapData src = ((Bitmap)imageGif).LockBits(new Rectangle(0,0,imageGif.Width,imageGif.Height),ImageLockMode.ReadOnly,imageGif.PixelFormat); BitmapData dst = bm.LockBits(new Rectangle(0,0,bm.Width,bm.Height),ImageLockMode.WriteOnly,bm.PixelFormat); // Uses pointers so we need unsafe code. // The project is also compiled with /unsafe byte backColor = 0; unsafe { backColor = ((byte *)src.Scan0.ToPointer())[0]; // Assume transparent colour appears as first pixel. byte* src_ptr = ((byte *)src.Scan0.ToPointer()); byte* dst_ptr = ((byte *)dst.Scan0.ToPointer()); // May be useful: System.Runtime.InteropServices.Marshal.Copy(IntPtr source, byte[], destination, int start, int length) // May be useful: System.IO.MemoryStream ms = new System.IO.MemoryStream(src_ptr); int width = imageGif.Width; int src_stride = src.Stride - width; int dst_stride = dst.Stride - width; for(int y=0;y<imageGif.Height;y++) { // Can't convert IntPtr to byte[]: Buffer.BlockCopy( src_ptr, 0, dst_ptr, 0, width ); int x = width; while( x-- > 0 ) { *dst_ptr++ = *src_ptr++; } src_ptr += src_stride; dst_ptr += dst_stride; } } // Set the newly selected transparency colorpaletteNew.Entries[(int)backColor]=Color.FromArgb(0,Color.Magenta); // Re-insert the palette bm.Palette=colorpaletteNew; // All done, unlock the bitmaps ((Bitmap)imageGif).UnlockBits(src); bm.UnlockBits(dst); imageGif.Dispose(); // Set the new image in place imageGif=bm; colorpalette=imageGif.Palette; LogFile.TheLogFile.WriteLine( LogFile.DT_HTML, LogFile.EDebugLevel.eDL_Note, "Re-saving mini gif as " + sFilename ); imageGif.Save( sFilename, imageFormat ); } } return alMap; }
// Gets the n'th child in the fr, or returns the default individual if first child requested and no fr. private static CIndividualRecord GetChild(CFamilyRecord fr, int nChild, CIndividualRecord irDefault ) { CIndividualRecord irChild = null; if (fr != null) { // The ordering of children in the tree can be selected to be the same as it is in the GEDCOM file. This // is because the file should be ordered as the user chose to order the fr when entering the data in // their fr history app, regardless of actual birth dates. if (MainForm.s_config.m_bKeepSiblingOrder) { irChild = fr.GetChildByPositionInFile(nChild); } else { irChild = fr.GetChild(nChild); } } else { // Return the default individual as first and only child of fr. if (nChild == 0) { irChild = irDefault; } } return irChild; }
// Add a box for the individual to the specified group. private static CMiniTreeIndividual AddToGroup(CIndividualRecord ir, CMiniTreeGroup mtg, bool bSpouse) { CMiniTreeIndividual mti = null; if (Exists(ir)) { CBoxText boxtext = new CBoxText(ir); mti = mtg.AddIndividual(ir, boxtext.m_sFirstName, boxtext.m_sSurname, boxtext.m_sDate, true, false, false, boxtext.m_bConcealed, bSpouse); } else { mti = mtg.AddIndividual(null, "", MainForm.s_config.m_sUnknownName, " ", false, false, false, false, bSpouse); } return mti; }
// Attaches sub-items to a list item (before the list item is added to the list) private void SetIndividualSubItems(CListableBool lbItem, CIndividualRecord ir, bool bCheckBoxes) { // Save checkbox state because SubItems.Clear() clears item.Text and item.Checked as well, so replace old value after calling Clear(). bool bWasChecked = lbItem.Checked; string sItemText = lbItem.Text; lbItem.SubItems.Clear(); lbItem.Text = sItemText; lbItem.Checked = bWasChecked; // If the list view has check boxes, the item is for the checkbox. // Otherwise the item is for the name, and so the sub items won't include the name. if (bCheckBoxes) { string sSurname = ""; string sFirstName = ""; s_config.CapitaliseName(ir.Name, ref sFirstName, ref sSurname); if (ir.NameSuffix != null && ir.NameSuffix != "") { sFirstName += ", " + ir.NameSuffix; } lbItem.SubItems.Add(new CListableName(ir, sSurname, sFirstName)); } CPGQualifiedDate birthDate = ir.BirthDate; if (birthDate != null) { lbItem.SubItems.Add(new CListableYear(birthDate.m_date)); } else { lbItem.SubItems.Add(new CListableYear(null)); } CPGQualifiedDate deathDate = ir.DeathDate; if (deathDate != null) { lbItem.SubItems.Add(new CListableYear(deathDate.m_date)); } else { lbItem.SubItems.Add(new CListableYear(null)); } lbItem.SubItems.Add(new CListableString(ir.m_xref)); lbItem.SubItems.Add(new CListableString(ir.UserReferenceNumber(0))); int nVisiblePics = ir.CountVisibleMFRs(); int nTotalPics = ir.CountAllMFRs(); if (nVisiblePics != nTotalPics) { lbItem.SubItems.Add(new CListableNumber(nVisiblePics, String.Format("{0}/{1}", nVisiblePics, nTotalPics))); } else { lbItem.SubItems.Add(new CListableNumber(nTotalPics, String.Format("{0}", nTotalPics))); } }
// Creates link HTML for the individual e.g. <a href="indiI1.html">Fred Bloggs</a> protected static string MakeLink( CIndividualRecord ir ) { string sName = ir.Name; string sDummy = ""; if (sName == "") { sName = MainForm.s_config.m_sUnknownName; } else if ((ir.Visibility() != CIndividualRecord.EVisibility.Visible) && !MainForm.s_config.m_bUseWithheldNames) { sName = MainForm.s_config.m_sConcealedName; } else { sName = MainForm.s_config.CapitaliseName(sName, ref sDummy, ref sDummy); } return MakeLink( ir, sName ); }
// Constructor public CChild( int nPositionInFile, CIndividualRecord ir ) { m_nPositionInFile = nPositionInFile; m_ir = ir; }
// Gets the n'th family record that the given individual is a spouse in public CFamilyRecord GetFamilyBySpouse( CIndividualRecord ir, int n ) { if( ir.m_alSpouseToFamilyLinks == null ) { return null; } if( n < 0 || n >= ir.m_alSpouseToFamilyLinks.Count ) { return null; } CSpouseToFamilyLink sfl = (CSpouseToFamilyLink)(ir.m_alSpouseToFamilyLinks[ n ]); if( sfl == null ) { return null; } return GetFamilyRecord( sfl.m_xrefFam ); }
// Gets the n'th family record that the given individual is a child in public CFamilyRecord GetFamilyByChild( CIndividualRecord ir, int n ) { if( ir.m_alChildToFamilyLinks == null ) { return null; } if( n < 0 || n >= ir.m_alChildToFamilyLinks.Count ) { return null; } CChildToFamilyLink cfl = (CChildToFamilyLink)(ir.m_alChildToFamilyLinks[ n ]); if( cfl == null ) { return null; } return GetFamilyRecord( cfl.m_xrefFam ); }
// Returns an ordered array of all family records that the given individual was a spouse in public ArrayList GetFamilyArray( CIndividualRecord ir ) { if( ir == null ) { return null; } ArrayList alFamily = new ArrayList(); int nFamilies = 0; CFamilyRecord fr; while( (fr = GetFamilyBySpouse( ir, nFamilies )) != null ) { alFamily.Add( fr ); nFamilies++; } alFamily.Sort( new CFamilyRecord.FamilyComparer() ); return alFamily; }
// Restricts descendants, and if required, their spouses and their spouses ancestors. private void PruneDescendants( CIndividualRecord ir, bool bPruneSpouses, bool bExclude ) { int nFamily = 0; CFamilyRecord fr = null; while( (fr = GetFamilyBySpouse( ir, nFamily++ )) != null ) { int nChild = 0; CIndividualRecord irChild = null; while( (irChild = fr.GetChildByBirthDate( nChild++ )) != null ) { if( irChild == null || m_htVisited.ContainsKey( irChild.m_xref ) ) { continue; } if( bExclude ) { if( !irChild.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneExcluded++; } irChild.Restricted = true; } } else { if( irChild.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneIncluded++; } irChild.Restricted = false; } } m_htVisited[ irChild.m_xref ] = true; PruneDescendants( irChild, bPruneSpouses, bExclude ); } if( bPruneSpouses ) { CIndividualRecord irFather = GetHusband( fr ); if( irFather != ir && irFather != null && !m_htVisited.ContainsKey( irFather.m_xref ) ) { if( bExclude ) { if( !irFather.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneExcluded++; } irFather.Restricted = true; } } else { if( irFather.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneIncluded++; } irFather.Restricted = false; } } m_htVisited[ irFather.m_xref ] = true; PruneAncestors( irFather, bExclude ); PruneDescendants( irFather, false ); } CIndividualRecord irMother = GetWife( fr ); if( irMother != ir && irMother != null && !m_htVisited.ContainsKey( irMother.m_xref ) ) { if( bExclude ) { if( !irMother.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneExcluded++; } irMother.Restricted = true; } } else { if( irMother.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneIncluded++; } irMother.Restricted = false; } } m_htVisited[ irMother.m_xref ] = true; PruneAncestors( irMother, bExclude ); PruneDescendants( irMother, false ); } } } }
// Restricts their siblings and their ancestors and their ancestors spouses private void PruneAncestors( CIndividualRecord ir, bool bPruneSpouses, bool bExclude ) { int nFamily = 0; CFamilyRecord fr = null; while( (fr = GetFamilyByChild( ir, nFamily++ )) != null ) { CIndividualRecord irFather = GetHusband( fr ); if( irFather != null ) { if( !m_htVisited.ContainsKey( irFather.m_xref ) ) { PruneAncestors( irFather, bExclude ); } if( bExclude ) { if( !irFather.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneExcluded++; } irFather.Restricted = true; } } else { if( irFather.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneIncluded++; } irFather.Restricted = false; } } m_htVisited[ irFather.m_xref ] = true; } CIndividualRecord irMother = GetWife( fr ); if( irMother != null ) { if( !m_htVisited.ContainsKey( irMother.m_xref ) ) { PruneAncestors( irMother, bExclude ); } if( bExclude ) { if( !irMother.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneExcluded++; } irMother.Restricted = true; } } else { if( irMother.Restricted ) { if( MainForm.m_mainForm != null ) { MainForm.m_mainForm.m_nPruneIncluded++; } irMother.Restricted = false; } } m_htVisited[ irMother.m_xref ] = true; } } }
// Restricts presentation of sources connected with an individual (for when individual themselves are marked as restricted) public void RestrictAssociatedSources( CIndividualRecord ir ) { // Restrict sources connected with individual directly foreach( CSourceCitation sc in ir.m_alSourceCitations ) { RestrictSource( sc, true ); } // Restrict sources connected with name foreach( CPersonalNameStructure pns in ir.m_alPersonalNameStructures ) { if( pns.m_personalNamePieces != null ) { foreach( CSourceCitation sc in pns.m_personalNamePieces.m_alSourceCitations ) { RestrictSource( sc, true ); } } } // Restrict sources connected with events foreach( CIndividualEventStructure ies in ir.m_alIndividualEventStructures ) { if( ies.m_eventDetail != null ) { foreach( CSourceCitation sc in ies.m_eventDetail.m_alSourceCitations ) { RestrictSource( sc, true ); } } } // Restrict sources connected with m_ldsIndividualOrdinances foreach( CLdsOrdinance lo in ir.m_alLdsIndividualOrdinances ) { foreach( CSourceCitation sc in lo.m_alSourceCitations ) { RestrictSource( sc, true ); } } // Restrict sources connected with m_associationStructures foreach( CAssociationStructure ass in ir.m_alAssociationStructures ) { foreach( CSourceCitation sc in ass.m_alSourceCitations ) { RestrictSource( sc, true ); } } }
// Returns true if the given individual is the female parent in this family public bool IsWife(CIndividualRecord ir) { return (ir != null && m_xrefWife == ir.m_xref); }
// Returns a string to use as a sFilename for this individual's HTML page. // The string is just the sFilename, not a fully qualified path. protected static string GetIndividualHTMLFilename( CIndividualRecord ir ) { string sRelativeFilename = String.Concat( "indi", ir.m_xref, ".", MainForm.s_config.m_sHtmlExtension ); if( MainForm.s_config.m_bUserRecFilename ) { if( ir.m_alUserReferenceNumbers.Count > 0 ) { CUserReferenceNumber urn = (CUserReferenceNumber)ir.m_alUserReferenceNumbers[0]; string sFilenameUserRef = EscapeFilename(urn.m_sUserReferenceNumber); if( sFilenameUserRef.Length > 0 ) { sRelativeFilename = String.Concat( "indi", sFilenameUserRef, ".", MainForm.s_config.m_sHtmlExtension ); } } } return sRelativeFilename; }
// Parser public static CIndividualRecord Parse( CGedcom gedcom, int nLevel ) { CGedcomLine gedcomLine; bool bParsingFinished; // Temporary holders for class members. CPersonalNameStructure personalNameStructure; CIndividualEventStructure individualEventStructure; CLdsOrdinance ldsIndividualOrdinance; CChildToFamilyLink childToFamilyLink; CSpouseToFamilyLink spouseToFamilyLink; CAssociationStructure associationStructure; CNoteStructure noteStructure; CSourceCitation sourceCitation; CMultimediaLink multimediaLink; ArrayList alAliases = new ArrayList(); // Without an xref header, we can't continue if ((gedcomLine = gedcom.GetLine(nLevel, "INDI")) == null) { // Not one of us return null; } CIndividualRecord ir = new CIndividualRecord( gedcom ); ir.m_xref = gedcomLine.XrefID; gedcom.IncrementLineIndex(1); do { bParsingFinished = true; // Family Historian tag _FLGS if( (gedcomLine = gedcom.GetLine(nLevel+1, "_FLGS")) != null ) { gedcom.IncrementLineIndex(1); if( (gedcomLine = gedcom.GetLine(nLevel+2, "__LIVING")) != null ) { ir.m_sStillLiving = gedcomLine.LineItem; gedcom.IncrementLineIndex(1); } bParsingFinished = false; } // Let Record have a go at parsing the rest else if( ir.ParseRecord( gedcom, nLevel ) ) { bParsingFinished = false; continue; } else if( (gedcomLine = gedcom.GetLine( nLevel+1, "RESN" )) != null ) { ir.m_sRestrictionNotice = gedcomLine.LineItem; gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (personalNameStructure = CPersonalNameStructure.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alPersonalNameStructures.Add( personalNameStructure ); bParsingFinished = false; } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "SEX")) != null ) { ir.m_sSexValue = gedcomLine.LineItem; gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (individualEventStructure = CIndividualEventStructure.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alIndividualEventStructures.Add( individualEventStructure ); bParsingFinished = false; if( individualEventStructure.Type == "ADOP" ) { gedcom.m_alAdoptedIndividuals.Add( ir ); } } else if( (ldsIndividualOrdinance = CLdsOrdinance.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alLdsIndividualOrdinances.Add( ldsIndividualOrdinance ); bParsingFinished = false; } else if( (childToFamilyLink = CChildToFamilyLink.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alChildToFamilyLinks.Add( childToFamilyLink ); bParsingFinished = false; } else if( (spouseToFamilyLink = CSpouseToFamilyLink.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alSpouseToFamilyLinks.Add( spouseToFamilyLink ); bParsingFinished = false; } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "SUBM")) != null ) { ir.m_alXrefSubms.Add( gedcomLine.LinePointer ); gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (associationStructure = CAssociationStructure.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alAssociationStructures.Add( associationStructure ); bParsingFinished = false; } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ALIA")) != null ) { if( gedcomLine.LinePointer != null ) { ir.m_alXrefAlias.Add( gedcomLine.LinePointer ); gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( gedcomLine.LineItem != null && gedcomLine.LineItem.Length > 0 ) { alAliases.Add( gedcomLine.LineItem ); gedcom.IncrementLineIndex(1); bParsingFinished = false; } } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "ANCI")) != null ) { ir.m_alXrefAncis.Add( gedcomLine.LinePointer ); gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "DESI")) != null ) { ir.m_alXrefDesis.Add( gedcomLine.LinePointer ); gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "RFN")) != null ) { ir.m_sPermanentRecordFileNumber = gedcomLine.LineItem; gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (gedcomLine = gedcom.GetLine(nLevel+1, "AFN")) != null ) { ir.m_sAncestralFileNumber = gedcomLine.LineItem; gedcom.IncrementLineIndex(1); bParsingFinished = false; } else if( (sourceCitation = CSourceCitation.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alSourceCitations.Add( sourceCitation ); bParsingFinished = false; } else if( (multimediaLink = CMultimediaLink.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alMultimediaLinks.Add( multimediaLink ); bParsingFinished = false; } else if( (noteStructure = CNoteStructure.Parse( gedcom, nLevel+1 )) != null ) { ir.m_alNoteStructures.Add( noteStructure ); bParsingFinished = false; } else if( ( gedcomLine = gedcom.GetLine()).Level > nLevel ) { LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, "Unknown tag :" ); LogFile.TheLogFile.WriteLine( LogFile.DT_GEDCOM, LogFile.EDebugLevel.Warning, gedcomLine.ToString() ); gedcom.IncrementLineIndex(1); bParsingFinished = false; } } while( !bParsingFinished ); // Workaround for GEDCOM that incorrectly contains this: ALIA Fred /Bloggs/ (instead of ALIA @I12@) if( alAliases.Count > 0 ) { foreach( string sAlias in alAliases ) { sAlias.Trim(); if( sAlias.Length > 0 ) { CPersonalNameStructure pns = new CPersonalNameStructure(gedcom); pns.m_sNamePersonal = sAlias; ir.m_alPersonalNameStructures.Add( pns ); } } } return ir; }
// Creates link HTML for the individual e.g. <a href="indiI1.html">Next Child</a>. Uses name provided by caller. protected static string MakeLink( CIndividualRecord ir, string sName ) { string sLink; if( ir.Visibility() == CIndividualRecord.EVisibility.Invisible ) { // TODO: Why are we linking to invisible people? sLink = CCreator.EscapeHTML(sName, true); } else { sLink = String.Concat("<a href=\"", GetIndividualHTMLFilename(ir), "\">", CCreator.EscapeHTML(sName, false), "</a>"); } return sLink; }
// Constructor public CCreatorRecordIndividual( CGedcom gedcom, IProgressCallback progress, string sW3cfile, CIndividualRecord ir, CCreatorIndexIndividuals indiIndexCreator, CPaintbox paintbox ) : base(gedcom, progress, sW3cfile) { m_ir = ir; m_indiIndexCreator = indiIndexCreator; m_paintbox = paintbox; m_htFirstFoundEvent = new Hashtable(); m_sBirthdaySourceRefs = ""; m_sDeathdaySourceRefs = ""; m_sNameTitle = ""; m_bUnknownName = false; m_sName = m_ir.Name; m_sNameSuffix = m_ir.NameSuffix; m_sFirstName = ""; m_sSurname = ""; m_sOccupation = ""; m_bConcealed = m_ir.Visibility() == CIndividualRecord.EVisibility.Restricted; m_alEventList = new ArrayList(); m_alAttributeList = new ArrayList(); m_alReferenceList = new ArrayList(); m_alOccupations = new ArrayList(); m_sPreviousChildLink = ""; m_sNextChildLink = ""; m_alOtherNames = new ArrayList(); m_qdateInferredBirthday = null; m_dateActualBirthday = null; m_qdateInferredDeathday = null; m_dateActualDeathday = null; m_alParents = new ArrayList(); }
// Constructor public CMiniTreeIndividual( CIndividualRecord ir, string sFirstNames, string sSurname, string sDate, bool bCreateLink, bool bCreateStalk, bool bHighlight, bool bConcealed, bool bShade, bool bConserveWidth ) { m_ir = ir; m_sFirstnames = sFirstNames; m_sSurname = sSurname; m_sDate = sDate; m_bLinkable = bCreateLink; m_bHighlight = bHighlight; m_bConcealed = bConcealed; m_bChild = bCreateStalk; m_bShade = bShade; m_fFirstnamesPad = 0f; m_fSurnamePad = 0f; m_fDatePad = 0f; m_bConserveWidth = bConserveWidth; m_sizeText = new Size(); }
// Adds the marriage associated with the fr record to the list of events. Also adds irSubject death if within this person's lifetime. private void AddMarriage( CIndividualRecord spouse, string spouseLink, CFamilyRecord fr ) { // Find wedding date if (spouse != null) { string sourceRefs = AddSpouseDeath(spouse, spouseLink); CPGDate marriageDate; string marriageNote; string marriagePlace; sourceRefs = AddMarriageEvent(fr, sourceRefs, out marriageDate, out marriageNote, out marriagePlace); marriageNote = BuildMaritalStatusNote(fr, marriageNote); // Add fr record notes to marriage event if (fr.m_alNoteStructures != null) { foreach (CNoteStructure ns in fr.m_alNoteStructures) { if (ns.Text != null && ns.Text.Length > 0) { if (marriageNote != "") { marriageNote += "\n"; } if (MainForm.s_config.m_bObfuscateEmails) { marriageNote += ObfuscateEmail(ns.Text); } else { marriageNote += ns.Text; } } } } string marriedString = "married "; if (fr.WereTheyReallyMarried() == false) { marriedString = "partner of "; } if (marriageDate != null) { CIEvent iEvent = new CIEvent(marriageDate, "_MARRIAGE", String.Concat(marriedString, spouseLink, marriagePlace, ".", sourceRefs), "", marriageNote, true, MainForm.s_config.m_bCapitaliseEventDescriptions); m_alEventList.Add(iEvent); } // else its an attribute. else { CIEvent iEvent = new CIEvent(marriageDate, "_MARRIAGE", String.Concat(marriedString, spouseLink, marriagePlace, ".", sourceRefs), "", marriageNote, true, MainForm.s_config.m_bCapitaliseEventDescriptions); // Marriages go at the front of the list so that they appear first in "Other facts" m_alAttributeList.Insert(0, iEvent); } } // end if (irSubject != null ) }
// Calculate size required for tree by iterating through individuals and building a data structure. protected CMiniTreeGroup CreateDataStructure( CIndividualRecord irSubject ) { // Add subject's frParents CFamilyRecord frParents = m_gedcom.GetFamilyByChild(irSubject, 0); CMiniTreeGroup mtgParents = new CMiniTreeGroup(); CMiniTreeIndividual mtiFather = null; if( frParents != null ) { mtiFather = AddToGroup(frParents.m_xrefHusband, mtgParents, false); } // Create a group for the subejct and their siblings. CMiniTreeGroup mtgSiblings = new CMiniTreeGroup(); // Keeps count of subject's siblings (including subject) int nSiblings = 0; // Keeps track of last added sibling, to hook up to next added sibling. CMiniTreeIndividual mtiRightmostSibling = null; // Keeps track of last added child, to hook up to next added child. CMiniTreeIndividual mtiRightmostChild = null; // For each sibling (including the subject) for(;;) { CIndividualRecord irSibling = GetChild(frParents, nSiblings, irSubject); if (null == irSibling) { break; } if (irSibling == irSubject) { // Add spouses and children of subject, (and subject too, if we need to put wife after them.) CMiniTreeGroup mtgOffspring = null; bool bAddedSubject = false; int nSpouses = 0; CMiniTreeGroup.ECrossbar ecbCrossbar = CMiniTreeGroup.ECrossbar.eCB_Solid; ArrayList alFamily = m_gedcom.GetFamilyArray(irSubject); foreach( CFamilyRecord fr in alFamily ) { CIndividualRecord irSpouse = fr.GetSpouse(irSubject); if (!fr.IsHusband(irSubject)) { mtiRightmostSibling = AddToGroup(irSpouse, mtgSiblings, true); // Subject is female so all but last husband have dotted bars ecbCrossbar = CMiniTreeGroup.ECrossbar.eCB_DottedLeft; } else if (Exists(irSubject) && !bAddedSubject) { // Subject is male, so need to put them in now, before their children. // (Otherwise they get added as a regular sibling later) CBoxText boxtext = new CBoxText(irSubject); mtiRightmostSibling = mtgSiblings.AddIndividual(irSubject, boxtext.m_sFirstName, boxtext.m_sSurname, boxtext.m_sDate, false, frParents != null, true, boxtext.m_bConcealed, false); // To stop subject being added as regular sibling. bAddedSubject = true; } int nGrandchildren = 0; CIndividualRecord irGrandchild = null; // If we have already added an offspring box (from previous marriage) need connect this box to it as its right box. if (mtgOffspring != null) { mtgOffspring.RightBox = mtiRightmostSibling; } // Create a box for the offspring of this marriage mtgOffspring = new CMiniTreeGroup(); // Set crossbar that joins subject to spouse according to whether this is subject's first spouse. mtgOffspring.m_ecCrossbar = ecbCrossbar; // Add children by this spouse CMiniTreeIndividual mtiChild = null; while(true) { // The ordering of children in the tree can be selected to be the same as it is in the GEDCOM file. This // is because the file should be ordered as the user chose to order the fr when entering the data in // their fr history app, regardless of actual birth dates. if (MainForm.s_config.m_bKeepSiblingOrder) { irGrandchild = fr.GetChildByPositionInFile(nGrandchildren); } else { irGrandchild = fr.GetChild(nGrandchildren); } if (irGrandchild == null) { break; } if( Exists(irGrandchild) ) { CBoxText boxtext = new CBoxText(irGrandchild); mtiChild = mtgOffspring.AddIndividual(irGrandchild, boxtext.m_sFirstName, boxtext.m_sSurname, boxtext.m_sDate, true, true, false, boxtext.m_bConcealed, false); // Hook this up to any children by previous spouses. if( nGrandchildren==0 && mtiRightmostChild != null ) { mtiRightmostChild.RightObjectAlien = mtiChild; mtiChild.LeftObjectAlien = mtiRightmostChild; } } nGrandchildren++; } // If we added anything, record it as the right-most child ready to hook to children by next spouse. if( mtiChild != null ) { mtiRightmostChild = mtiChild; } // Add the subjects children to the siblings group mtgSiblings.AddGroup( mtgOffspring ); // Hook the offspring group to the previous sibling if( mtgOffspring != null ) { mtgOffspring.LeftBox = mtiRightmostSibling; } // If subject is husband then we need to add their wife now. if (fr.IsWife(irSpouse)) { ecbCrossbar = CMiniTreeGroup.ECrossbar.eCB_DottedRight; // Hook up to previous rightmost sibling and set this as new rightmost sibling. mtiRightmostSibling = AddToGroup(irSpouse, mtgSiblings, true); // Hook the wife up as box on right of offspring box. if( mtgOffspring != null ) { mtgOffspring.RightBox = mtiRightmostSibling; } } nSpouses++; } if (!bAddedSubject) { CBoxText boxtext = new CBoxText(irSubject); CMiniTreeIndividual mtiWife = mtgSiblings.AddIndividual(irSubject, boxtext.m_sFirstName, boxtext.m_sSurname, boxtext.m_sDate, false, frParents != null, true, boxtext.m_bConcealed, false); if (mtgOffspring != null) { mtgOffspring.m_ecCrossbar = CMiniTreeGroup.ECrossbar.eCB_Solid; mtgOffspring.RightBox = mtiWife; } } } else if( Exists(irSibling) ) { // A sibling (not the subject). CBoxText boxtext = new CBoxText(irSibling); mtgSiblings.AddIndividual(irSibling, boxtext.m_sFirstName, boxtext.m_sSurname, boxtext.m_sDate, true, frParents != null, false, boxtext.m_bConcealed, false); } nSiblings++; } // End: for each child in frParents. // Add siblings group after subject's father mtgParents.AddGroup( mtgSiblings ); // Hook up to subject's father mtgSiblings.LeftBox = mtiFather; // Add subject's mother if( frParents != null ) { CMiniTreeIndividual mtiMother = AddToGroup(frParents.m_xrefWife, mtgParents, false); mtgSiblings.RightBox = mtiMother; } // Return the parents group (which contains the other family groups). return mtgParents; }
// Extracts the data from the DEAT event for the given individual and adds it if it was an event in the current individual's lifetime. private string AddSpouseDeath( CIndividualRecord spouse, string spouseLink ) { string sourceRefs = ""; string place = ""; if (spouse.Visibility() == CIndividualRecord.EVisibility.Visible) { // Record death of irSubject if within this person's lifetime CPGDate spouseDeathDate = null; foreach (CIndividualEventStructure ies in spouse.m_alIndividualEventStructures) { if (ies.Type == "DEAT") { if (ies.m_eventDetail != null) { spouseDeathDate = ies.m_eventDetail.m_dateValue; if (spouseDeathDate != null) { if (m_qdateInferredDeathday == null || m_qdateInferredDeathday.m_date == null || spouseDeathDate.CompareTo(m_qdateInferredDeathday.m_date) <= 0) { if (ies.m_eventDetail.m_placeStructure != null) { if (ies.m_eventDetail.m_placeStructure.m_sPlaceName != "") place = String.Concat(" ", MainForm.s_config.m_sPlaceWord, " ", EscapeHTML(ies.m_eventDetail.m_placeStructure.m_sPlaceName, false)); } sourceRefs = AddSources(ref m_alReferenceList, ies.m_eventDetail.m_alSourceCitations); if (spouseDeathDate != null) { CIEvent iEvent = new CIEvent(spouseDeathDate, "_SPOUSEDIED", String.Concat("death of ", spouseLink, place, ".", sourceRefs), "", null, false, MainForm.s_config.m_bCapitaliseEventDescriptions); m_alEventList.Add(iEvent); } // else its an attribute. else { CIEvent iEvent = new CIEvent(null, "_SPOUSEDIED", String.Concat("death of ", spouseLink, place, ".", sourceRefs), "", null, false, MainForm.s_config.m_bCapitaliseEventDescriptions); m_alAttributeList.Add(iEvent); } } break; } } } } } return sourceRefs; }
// Returns true if the individual record should be added to the tree private static bool Exists( CIndividualRecord ir ) { return (ir != null && ir.Visibility() != CIndividualRecord.EVisibility.eV_Invisible); }
// Gets the parent who isn't the given individual public CIndividualRecord GetSpouse(CIndividualRecord ir) { CIndividualRecord irSpouse = null; if (ir != null) { if (m_xrefHusband == ir.m_xref) { irSpouse = Gedcom.GetIndividualRecord(m_xrefWife); } else { irSpouse = Gedcom.GetIndividualRecord(m_xrefHusband); } } return irSpouse; }
public CBoxText(CIndividualRecord ir) { m_sFirstName = ""; m_sSurname = ""; m_bConcealed = (ir.Visibility() == CIndividualRecord.EVisibility.eV_Restricted); if (m_bConcealed && !MainForm.s_config.m_bUseWithheldNames) { m_sFirstName = ""; m_sSurname = m_sName = MainForm.s_config.m_sConcealedName; } else { if (ir.Name != "") { m_sName = MainForm.s_config.CapitaliseName(ir.Name, ref m_sFirstName, ref m_sSurname); } else { m_sFirstName = ""; m_sSurname = m_sName = MainForm.s_config.m_sUnknownName; } } if (m_bConcealed) { m_sDate = ""; } else { m_sDate = ir.LifeYears; } }
// Returns true if the given individual is the male parent in this family public bool IsHusband(CIndividualRecord ir) { return (ir != null && m_xrefHusband == ir.m_xref); }
// Creates a CMiniTreeIndividual for the individual specified and adds it to the group. // Informs neighbouring boxes about this box. // bCreateLink decides whether to make this box a clickable link in the HTML. public CMiniTreeIndividual AddIndividual( CIndividualRecord ir, string sFirstnames, string sSurname, string sDate, bool bCreateLink, bool bCreateStalk, bool bHighlight, bool bConcealed, bool bShade ) { CMiniTreeIndividual mti = new CMiniTreeIndividual( ir, sFirstnames, sSurname, sDate, bCreateLink, bCreateStalk, bHighlight, bConcealed, bShade, MainForm.s_config.m_bConserveTreeWidth ); if( m_alMembers == null ) { m_alMembers = new ArrayList(); } m_alMembers.Add( mti ); m_uIndividuals++; if( bCreateStalk ) { m_uStalkedIndividuals++; } mti.LeftObject = m_mtoLastAddedObject; if( m_mtoLastAddedObject != null ) { m_mtoLastAddedObject.RightObject = mti; } m_mtoLastAddedObject = mti; return mti; }
// Restricts descendants only public void PruneDescendants( CIndividualRecord ir, bool bExclude ) { m_htVisited[ ir.m_xref ] = true; PruneDescendants( ir, false, bExclude ); }