Skip to main content

Genogram Controller

The GenogramController manages data and layout for family trees, handling complex relationships like marriages, parental connections, and gender-based positioning.

Creating a Controller

final controller = GenogramController<Person>(
items: familyMembers,
idProvider: (person) => person.id.toString(),
fatherProvider: (person) => person.fatherId?.toString(),
motherProvider: (person) => person.motherId?.toString(),
spousesProvider: (person) => person.spouseIds?.map((id) => id.toString()).toList(),
genderProvider: (person) => person.isMale ? 0 : 1,
boxSize: const Size(150, 150),
spacing: 30,
runSpacing: 60,
);

Constructor Parameters

ParameterTypeDescription
itemsList<E>Data items to display in the family tree
idProviderString Function(E)Function to extract unique ID from an item
fatherProviderString? Function(E)Function to extract father's ID from an item
motherProviderString? Function(E)Function to extract mother's ID from an item
spousesProviderList<String>? Function(E)Function to extract spouse IDs from an item
genderProviderint Function(E)Function to determine gender (0=male, 1=female)
boxSizeSizeSize of each node box (default: Size(150, 150))
spacingdoubleHorizontal spacing between nodes (default: 30)
runSpacingdoubleVertical spacing between rows (default: 60)
orientationGraphOrientationLayout direction (default: topToBottom)

Key Methods

Family Relationship Methods

// Get root nodes (individuals with no parents)
List<Node<Person>> roots = controller.roots;

// Get children of specific individuals
List<Node<Person>> children = controller.getChildren([fatherNode, motherNode]);

// Get parents of an individual
List<Node<Person>> parents = controller.getParents(childNode);

// Get spouses of an individual
List<Node<Person>> spouses = controller.getSpouseList(personData);

// Gender helper methods
bool isMale = controller.isMale(personData);
bool isFemale = controller.isFemale(personData);

Layout Algorithm

The genogram controller implements a sophisticated layout algorithm that:

  1. Places couples (spouses) next to each other:

    • Husbands and wives are positioned side-by-side
    • Multiple spouses are arranged in sequence
  2. Groups children together:

    • Children of the same parents are positioned together
    • Half-siblings are ordered by their mother's position
  3. Positions generations hierarchically:

    • Oldest generation at the top/left (based on orientation)
    • Each subsequent generation below/right of their parents
  4. Centers parents above their children:

    • The algorithm balances the parent group to be centered above the child group

The positioning supports both orientations:

  • GraphOrientation.topToBottom: Parents above children
  • GraphOrientation.leftToRight: Parents to the left of children

Sibling Ordering

The controller has special logic to keep siblings visually grouped:

// The controller automatically sorts siblings by:
// 1. Children of the same father and mother stay together
// 2. Children with the same father are grouped by mother
// 3. Siblings are ordered based on their mother's position

Cache Optimization

For performance with large family trees, an internal cache is maintained:

// Access methods use caching for better performance
List<Node<Person>> spouses = controller.getSpouseList(person); // Uses cache

// Clear caches when data changes significantly
controller.items = updatedFamilyMembers; // Automatically clears caches