(BUS 13) Samples of Some Key Project Documents
by Kenneth L. Hess
This document contains extracts from the key project
document for Banner Blue Software's program, Family Tree Maker
for Windows (referred to throughout as FTW, FTM was the DOS version
of the program). The first version of FTW was developed for Windows
3.1 during 1993.
Product Specific Objectives
These are the high-level objectives for the product
the team is to build. This is how the team stated the objectives
in 1993.
The following objectives are key to FTW's success:
Product Requirements Document
This document puts the project objectives into a
working format. It contains:
The FTW Product Requirements Document had a total
of thirty-two sections, two of which are extracted below. Every
item listed was required in the final product unless it was labeled
as "Desirable" or "Highly desirable." Since
an MS-DOS version of this program was already on the market, the
brief descriptions below sometimes imply a significant amount
of functionality. The readers of the document knew that unless
otherwise stated, everything about a feature in the MS-DOS version
would have to be replicated in FTW.
15.0 Ancestor Tree
15.1 FTM format.
Highly desirable: Allow (optionally) a space saving layout where y-axis space is closed up for
missing individuals. (Like R-Plot.)
15.2 Single page option. With limits on what can
print.
15.3 Multi-page option.
15.4 Print empty tree option.
15.5 Print empty branch option.
15.6 Option to print spouse (first, current) of
primary individual.
15.7 Ahnentafel numbering option.
15.8 Desirable: Cascading trees.
15.9 Desirable: Option to print siblings of primary
individual.
15.10 Desirable: Option to print siblings of all
individuals.
...
26.0 Basic Editing of Fields and Positions
Undo Minimum of one level.
Cut
Copy
Paste
Paste Special...
Find Individual...
Field Labels...
Typing Saver... Ditto last identical field, ditto last field, macro capability
Sort
...
Specifications
These are the blueprints. Software specifications
are often broken into the two pieces below: an external and an
internal spec.
External Product Specification
An External Product Specification is a detailed description
of how the product appears to the end user. Consultations with
customers, mock-ups, prototypes, and actual code should be used
as appropriate to verify key parts of a design as early in the
external specification process as possible.
Extracted below is a portion of the External Product
Specification for FTW, dealing with the requirement for a "Find
Individual" command called out in section 26.0 of the Product
Requirements Document above.
Find Individual
The philosophy of the Find Individual command is
to find too much rather than skip over what the user is looking
for. Find Individual is accessible (currently) from the Family
Page and the generic paginated views.
A key point is that this command is Find INDIVIDUAL.
Many aspects of the behavior relate to finding a (single) person.
For example, if several fields for one individual meet the criteria,
the command navigates to the person once, not to the fields in
succession.
The Answer Set
The program incrementally generates an answer set
from the search criteria, allowing the user to navigate through
the "found" items as they are located. Thus, if the
user changes something in the answer set such that the search
criteria is not met, it remains in the answer set until a new
search is started. On the other hand, if someone modifies an
individual not yet found so that they no longer meet the criteria,
then they are never found.
If someone is deleted, they are dropped from the
answer set. If a matching marriage or a matching object is deleted,
the involved individual(s) remain in the answer set. In the specific
case of a marriage, we would navigate back to the male, or the
female if the male is deleted. (If this causes special problems,
it's so obscure, it's not worth much work.)
If someone is added to the database during a search,
they are found (if they meet the criteria) and their IND hasn't
been searched yet. To the user, they may be found, they may not
be found.
A new search is defined by any editing of the search
criteria or by activation of the Restart button (which re-runs
the search with the existing criteria). The criteria are remembered
until explicitly cleared by the user. Thus, doing a search in
the Index of Individuals destroys any other ongoing search.
Search Types and Criteria
Info presentation will be the same as in FTM (move
to each Family Page or Album Page in order, or in the index, move
the highlight). A table below indicates what to highlight when
searching on a given item from a given location. The dialog box
hovers on screen until the user cancels. It moves out of the
way depending on what field is highlighted when found.
[The Change Item to Search dialog is list of fields
and other items as shown below. Dialog design TBD.]
NOTE: For version 1.0, case insensitivity for text searches will
not apply to Unicode above 0xFF. Upper and lower case will represent
different characters.
Name (text) fields have a restriction of between one and eight
words in the search criteria. If you search only on punctuation
in the name, you won't find anything.
If a shared object meets the criteria, every individual sharing
the object is found.
An empty picture frame and an empty Note may be treated equivalently.
Parentless, childless individuals (individuals w/o children
AND w/o parents) is a special search criterion. This is
to assist in finding "lost" souls and litter from detach
operations.
A "not within" search criteria is not required at this
time.
This table shows what field or screen area is highlighted when
an individual is found. Note that the view does not change when
an individual is found.
If two or more fields/objects meet the criteria for a single individual,
only the first (arbitrarily but consistently selected) is landed
on.
1) If Find Individual on the Family Page finds a marriage or
generic field where ther are two spouses, it will always put the
cursor on the names of the spouses rather than on the field.
2) If Find Individual on the Marriage Notes or Marriage Facts
finds an individual with no marriage or where the marriage has
two spouses, it will switch to the Family Page. Rule 1 then governs
where the cursor goes.
Once a field is landed on, any action by the user breaks out of
the search. For example, if the user switches from the Family
Page to the Ancestor Tree View during a search, the search dialog
disappears.
If going backwards in an answer set to an individual whose field
no longer matches, the default item is highlighted per the above
table.
Desirable: Kinship will also be available as a search criterion
(i.e. search for all first cousins of NAME).
Future: Multiple criteria search.
Future: Search on embedded or linked objects.
Field Name Type
Quantity per Person Search Type
Name 48 char alpha 1
Text aka 48 char alpha 1
Text Birth date Comment/event
1 Date Birth location Comment/event
1 Text Birth source information Source
1 Text Death date Comment/event
1 Date Death location Comment/event
1 Text Death source information Source
1 Text [In the actual specification, this table continued to describe 45 additional fields....]
Search Type Valid Search Criteria
Finds
Text Any alphanumeric character(s)
Any field containing the string (not case sensitive, not whole word)
!= All non-empty fields
= All empty fields
Text (special case for name) Additional restriction of 8 words max (if search is on "Any and all text fields", then only the first 8 words are applied to the name field)
Date M-D-Y Exact match & in range (abt, bef, aft, etc.)
M-Y Any day in M-Y & in range
M-D Any year with M-D & in range
M Any day or year with M & in range
Y Any day or month with Y & in range
? Entered as unknown
UNKNOWN Entered as unknown
EST <date> Exact match & in range
ABT <date> Exact match & in range
CIRCA <date> Exact match & in range
[In the actual specification, this table continued to describe approximately 25 additional conditions....]
Field Name Being Searched Searching From Family Page
Searching From Album Page (future) Searching From Index of Individuals
Default if field is erased or modified
Name field Title, Page 1 of n
Name
Name Name field Title, Page 1 of n
Name aka Name field Title, Page 1 of n
NA Birth date Birth date field
Title, Page 1 of n NA
Birth location Birth location field
Title, Page 1 of n NA
Birth source information Name field
Title, Page 1 of n NA
Death date Death date field
Title, Page 1 of n NA
Death location Death location field
Title, Page 1 of n NA
Death source information Name field
Title, Page 1 of n NA
[In the actual specification, this table continued to describe 45 additional fields....]
Internal Product Specification
The Internal Product Specification contains a detailed
description of the overall product architecture and coding techniques
to be applied for each feature. It is extremely important for
this specification to detail the handling of all boundary and
error conditions.
Extracted below is a portion of the Internal Product
Specification for FTW, dealing with the requirement for a "Find
Individual" command called out in section 26.0 of the Product
Requirements Document and the External Product Specification above.
It is far beyond the purposes of this note to describe what any
of the material below actually means! Note also that the converter
to put this on the Web totally botched the indentation and formatting
of this section -- only software engineers will notice the difference.
Find Individual
Overview
Strictly speaking, Find Individual is part of the
user interface, not the database. However, its workings are described
here.
The Find Individual system supports four different
dialogs: Find Individual, Add and Delete Individuals (for Individuals
to Include), and Find Picture/Object. Although all four dialogs
look and act differently, the code underneath is mostly shared.
The Find Individual and Find Picture/Object dialogs
operate as free-floating modeless dialogs which communicate asynchronously
via messages with the VIEW underneath them. They do not
"understand" which VIEW is currently being displayed;
in fact, for Find Individual, the VIEW can be changed dynamically.
Although only field-oriented VIEWs currently
accept input from Find Individual, eventually it could be used
to search through trees, kinship, etc..
It is the responsibility of each other VIEW/dialog
in FTW to inform the Find Individual dialog as to whether the
VIEW/dialog wants information from the Find Individual
dialog or not.
Most of the actual messages are hidden procedurally.
Interface
A FINDIND is the static structure stored in
the main data area of FTW within which the Find Individual dialog
stores its static values. The structure is referred to via LPFINDIND
and initialized via:
FindInt_InitStruct Performs the one-time initialization of a FINDIND structure.
Arguments: LPFINDIND lpfi
Return Type: -none-
Each VIEW (or the VIEW manager) should
make the following call:
FindInd_Status_Change Informs a Find Individual or Find Picture Object dialog as to its new parent window, database, and how it is to act. Also, the basic kind of the dialog should be passed in.
Arguments: LPFINDIND lpfi
HWND hwndParent
DB dbDataBase
FINDINDOPTS fioNewState
FINDDIALOGS fndDialog
Return Type: -none-
The possible FINDINDOPTS are:
typedef enum {
FINDIND_START, /* bring up the Find Individual dialog */
FINDIND_ENABLE, /* ok to bring up Individual dialog */
FINDIND_RESET, /* get rid of the dialog, reset it, but don't
touch bOkToShow */
FINDIND_HIDE, /* get rid of the Find Individual dialog
temporarily */
FINDIND_DESTROY /* get rid of the dialog and reset it for a new
database */
} FINDINDOPTS;
Typically, FINDIND_START is used when the dialog
is explicitly requested from the menu. When a VIEW is
entered that doesn't mind if the dialog remains visible and active,
it should set FINDIND_ENABLE; if it doesn't want the dialog to
be visible, it should instead use FINDIND_HIDE. When a VIEW
must cancel the dialog (perhaps because the temporary bits
are going to be used for another purpose), it should use FINDIND_HIDE.
Closing a DB should cause a FINDIND_DESTROY.
Possible FINDDIALOGS are:
typedef enum {
FINDDIALOG_FIND_INDIVIDUAL, /* Find Individual dialog */
FINDDIALOG_FIND_PICTURE_OBJECT /* Find Picture/Object
dialog */
FINDDIALOG_ADD_INDIVIDUALS /* under Individuals to
Include */
FINDDIALOG_DELETE_INDIVIDUALS /* under Individuals to
Include */
} FINDDIALOGS;
The dialog may need to know the IND/MRG
it is to work with. This is supplied via another function call:
FindInd_IndMrgInfo Informs a Find Individual dialog as to whom it is to search the ATTCHs for (in the case of FINDDIALOG_FIND_PICTURE_OBJECT) or whom the primary individual is (in the case of ancestor/descendant tree searches).
Arguments: LPFINDIND lpfi
IND ind
MRG mrg
Return Type: -none-
Once the above settings are established, the enabling
of the "Find Individual/Scrapbook" menu item comes from:
FindInd_Menu_Active Returns TRUE iff the menu item "Find Individual" should be active.
Arguments: LPFINDIND lpfi
Return Type: BOOL
To keep a Find Ind dialog out of the way of fields
being navigated through, VIEWs that use FINDIND_ENABLE
should call:
FindInd_MoveAside Keeps the Find Individual dialog as far away from the hwndAvoid window as possible, but still within the hwndConstrain window. If the Find Individual dialog is hidden or has been terminated, there is no effect.
Arguments: LPFINDIND lpfi
HWND hwndAvoid
HWND hwndConstrain
Return Type: -none-
When the user presses Find Previous, Find Next, or
Restart Search, the Find Individual dialog generally locates an
IND/MRG/ATTCH to go to. When it does, it sends a VWM_SWITCH_IND,
VWM_SWITCH_MRG_HUSBAND, VWM_SWITCH_MRG_WIFE, or VWM_SWITCH_ATTCH
message to the currently active VIEW. Typical message
handlers for these messages are:
XX_OnFindInd_Ind Handles the VWM_SWITCH_IND message sent to the VIEW. The VIEW should display the designated IND. The FIELDCODE does not always reflect the field found - however, per the EPS, the VIEW can decide which fields it is willing to move the focus to.
Arguments: HWND hwnd
FIELDCODE fc
IND ind
Return Type: -none-
XX_OnFindInd_Mrg Handles the VWM_SWITCH_MRG_HUSBAND and VWM_SWITCH_MRG_WIFE messages sent to the VIEW. The VIEW should display the designated IND who is the husband (if bHusband is TRUE) or wife (if bHusband is FALSE) of the MRG. The FIELDCODE does not always reflect the field found - however, per the EPS, the VIEW can decide which fields it is willing to move the focus to.
Arguments: HWND hwnd
FIELDCODE fc
MRG mrg
BOOL bHusband
Return Type: -none-
XX_OnFindInd_Attch Handles the VWM_SWITCH_ATTCH message sent to the VIEW. The VIEW should display the ATTCH with the designated index. The FIELDCODE does not always reflect the field found - however, per the EPS, the VIEW can decide which fields it is willing to move the focus to.
Arguments: HWND hwnd
FIELDCODE fc
DWORD ulIndex
Return Type: -none-
Standard message crackers are available:
#define HANDLE_VWM_SWITCH_IND(hwnd, wParam, lParam, fn) ...
#define HANDLE_VWM_SWITCH_MRG_HUSBAND(hwnd, wParam, lParam, fn) ...
#define HANDLE_VWM_SWITCH_MRG_WIFE(hwnd, wParam, lParam, fn) ...
#define HANDLE_VWM_SWITCH_ATTCH(hwnd, wParam, lParam,
fn) ...
The Find Picture/Object dialog must ask the VIEW
beneath it which ATTCH it is on. It uses the message:
VWM_WHICH_ATTCH Obtains the index of the current ATTCH from the Scrapbook View.
Arguments: HWND hwnd
Return Type: DWORD
As per the EPS, not all VIEWs can support
all ..SWITCH.. possibilities at all times. For example, a Marriage
Facts page should not show INDs who are married where the
spouse will also be found because of the ambiguity over which
person has been found. To switch to the family page under these
circumstances, the VIEW should call:
FindInd_SwitchViews Tells the Find Individual dialog to switch VIEWs (presumably back to the family page) as the current VIEW receiving a VWM_SWITCH_... message cannot display the desired person.
Arguments: LPFINDIND lpfndindFindInd
Return Type: -none-
Because the Find Individual dialog creates a set
of people who meet certain criteria, it must be told about deletions:
FindInd_DeletedInd Tells the Find Individual dialog that indToBeDeleted is about to be deleted. It is essential that this be called prior to the delete so that it can determine if the person was in the Find Individual set or not.
Arguments: LPFINDIND lpfndindFindInd
DB dbDataBase
IND indToBeDeleted
Return Type: -none-
[This section of the Internal Product Specification
goes on for an additional five pages, including a description
of relevant data structures.]
Stn_LCyc.doc
5/20/98