Link to: header | source
code | source 2 | source
4 | tables
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Source Code
This class manages general breakdown tables for the Goldenseal accounting software,
small business management software, construction
project management software and
construction
accounting software.
/*********************************************************************************
FillDetailArray TCS 2/7/00 rev 1/4/00
fill in an array of detail ID's. Note that all items in the table should have
the same class ID. This method should not be called for tables that have
a mixture of transaction types
*********************************************************************************/
void CBreakdownTable::FillDetailArray(TObjectIDArray &selectArray,
const DBClass detailClass) const
{
DBid id;
DBClass classID;
for (TableIndexT row = 1; row <= LastRow(); row++)
{
id = GetDetailTransactionID(row);
if (id && detailClass) // if we were passed a class, include only matching items
{
classID = GetDetailTransactionClass(row);
if (classID == detailClass)
selectArray.Append(id);
}
else if (id) // for a single-class table we include everything
selectArray.Append(id);
}
}
/*********************************************************************************
FillDetailArray TCS 2/7/00
fill in an array of detail ID's. This form can be used even with a mixture
of class ID's in the table.
*********************************************************************************/
void CBreakdownTable::FillDetailArray(TObjectInfoArray &selectArray) const
{
SObjectInfo info;
info.transactionType = 0;
for (TableIndexT row = 1; row <= LastRow(); row++)
{
info.classID = GetDetailTransactionClass(row);
info.itemID = GetDetailTransactionID(row);
if (info.classID && info.itemID)
selectArray.Append(info);
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetColTagMoneyTotal TCS 5/17/02
return the sum of the basic amount column. Subclasses may override if
a different column tag is used
*********************************************************************************/
CMoney CBreakdownTable::GetColTagMoneyTotal(const TagType tag)
{
TableIndexT col = GetMemberCol(tag);
if (col)
return GetColumnMoneyTotal(col);
else
return 0;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
SetFindMode TCS rev 10/26/99, moved 12/13/01
We are going into or out of find mode
*********************************************************************************/
void CBreakdownTable::SetFindMode(const Boolean findMode)
{
// the superclass stores a boolean for current find mode status
THE_SUPERCLASS::SetFindMode(findMode);
if (findMode)
{ // Show a blank single row table so users can enter
// find criteria TCS rev 12/13/01
MakeSingleRowTable(cRedraw, true);
}
else
{
// leaving find mode, so clear the table. It will be refilled
// with data later TCS 12/13/01
SetNumRows(0);
}
}
/*********************************************************************************
GetFindSelectors TCS 12/13/01
return a set of selectors based on the current criteria entered
in the table.
Note that for tables, we return the search tag as a negative number.
When we do the actual record finding, that way we can distinguish between
table tags and regular field tags.
*********************************************************************************/
void CBreakdownTable::GetFindSelectors(CTCS_Array *selectorArray) const
{
CTextString cellText, highString, lowString;
CNeoSelect *selector = nil;
Boolean isRange;
// we loop through each cell and check for values
for (SInt32 col = 1; col <= LastCol(); col++)
{
// fetch member info for the column
SMemberInfo memberInfo;
TCS_ASSERTMsg(GetColMemberInfo(col, &memberInfo), TCS_GetErrString(errID_BadColumn));
// fetch the cell text
cellText = GetCellText(1, col);
if (cellText.Length())
{
// does the text include range markers?
isRange = cellText.StripRangeMarkers(lowString, highString);
if (isRange)
{
selector = GetRangeSelector(memberInfo, lowString, highString);
}
else
{
selector = GetSimpleSelector(memberInfo, col, cellText);
}
}
// if we found a selector, add it to the array, and then nil
// out the reference for the next go-round.
if (selector)
{
selectorArray->Append(&selector);
selector = nil;
}
}
}
/*********************************************************************************
GetSimpleSelector TCS 12/18/01
return a simple selector for a column in this table
*********************************************************************************/
DB_MemberSelector *CBreakdownTable::GetSimpleSelector(const SMemberInfo &memberInfo,
const TableIndexT col, const CTextString &cellText) const
{
CTextString matchString;
SInt32 value;
Boolean useExact, useContains;
NeoOrder order;
DB_MemberSelector *selector = nil;
// First process the text for find markers TCS 12/17/01
cellText.StripFindMarkers(useExact, useContains, order, matchString);
UInt8 fieldType = GetFieldType(1, col); // rev TCS 12/19/01
// create a selector and add it to the array.
// the type of selector depends on the cell type
switch (fieldType)
{
case fieldtype_checkbox: // checkmark col
if (cellText.StartsWith(cCheckMarkChar))
selector = NEW DB_BooleanSelector(memberInfo.tag, true);
else
selector = NEW DB_BooleanSelector(memberInfo.tag, false);
break;
case fieldtype_integer:
case fieldtype_posinteger:
case fieldtype_cv:
case fieldtype_mixcv:
value = GetCellValue(1, col);
selector = NEW DB_LongSelector(memberInfo.tag, value);
break;
case fieldtype_date:
selector = NEW DB_DateSelector(memberInfo.tag, CDate(matchString));
break;
case fieldtype_money:
case fieldtype_emoney:
case fieldtype_percent:
case fieldtype_number:
selector = NEW DB_MoneySelector(memberInfo.tag, CMoney(matchString));
break;
case fieldtype_string:
case fieldtype_mixstring:
selector = NEW DB_CStringSelector(memberInfo.tag, &matchString);
if (selector)
{
if (useExact) // rev TCS 12/19/01
selector->SetSelectType(select_exact);
else if (useContains)
selector->SetSelectType(select_contains);
else
selector->SetSelectType(select_startswith);
}
break;
default:
break;
}
// let the selector know about any order restrictions, e.g. > or <
if (selector)
{
selector->setOrder(order);
selector->SetIsFromTable();
}
return selector;
}
/*********************************************************************************
GetRangeSelector TCS 12/18/01
return a range selector for our current contents. This function should only be
called if the cell has been determined to contain the range selection find code.
*********************************************************************************/
DB_MemberSelector *CBreakdownTable::GetRangeSelector(const SMemberInfo &memberInfo,
const CTextString &lowString, const CTextString &highString) const
{
DB_MemberSelector *lowSelector = nil,
*highSelector = nil,
*rangeSelector = nil;
// create a selector and add it to the array.
// the type of selector depends on the cell type
switch (memberInfo.type)
{
case type_date:
lowSelector = NEW DB_DateSelector(memberInfo.tag, CDate(lowString));
highSelector = NEW DB_DateSelector(memberInfo.tag, CDate(highString));
break;
case type_money:
case type_emoney:
case type_number:
case type_percent:
lowSelector = NEW DB_MoneySelector(memberInfo.tag, CMoney(lowString));
highSelector = NEW DB_MoneySelector(memberInfo.tag, CMoney(highString));
break;
case type_cstring:
lowSelector = NEW DB_CStringSelector(memberInfo.tag, &lowString);
highSelector = NEW DB_CStringSelector(memberInfo.tag, &highString);
break;
default:
break;
}
// we got the top and bottom selectors, so create a range selector
// to use for the search. The range selector will be responsible
// for deleting the two sub-selectors when it's done. It also sets
// the proper search order for each of the sub-selectors
if (lowSelector && highSelector)
{
lowSelector->SetIsFromTable();
highSelector->SetIsFromTable();
rangeSelector = NEW DB_RangeSelector(memberInfo.tag, lowSelector, highSelector);
}
if (rangeSelector)
{
rangeSelector->SetIsFromTable();
return rangeSelector;
}
else
{
TCS_Forget(lowSelector);
TCS_Forget(highSelector);
return nil;
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
CreateNewCellCVField
create a cv field for the given cell
*********************************************************************************/
CTCS_CVField *CBreakdownTable::CreateNewCellCVField(const TableCellT &inCell,
const SPaneInfo &inPaneInfo)
{
// get the member info from the column
SMemberInfo memberInfo;
TCS_ASSERTMsg(GetColMemberInfo(COL(inCell), &memberInfo), TCS_GetErrString(errID_BadColumn));
// now based on the tag and type, return the appropriate cv
switch (memberInfo.tag)
{
/*case tag_costarea: // bug fix TCS 11/27/98 rev 3/19/99 rev 9/2/99 removed TCS 6/10/03
return NEW CCostAreaCV(inPaneInfo, mTextInfo, GetCellCVClassID(inCell), cHasPopup);
break;*/ // shouldn't be needed here-- it's a menu cv
case tag_location: // TCS 8/23/99
return NEW CShortLocationCV(inPaneInfo, mTextInfo);
break;
case tag_paymentmethod: // TCS 10/11/99
return NEW CShortPaymentMethodCV(inPaneInfo, mTextInfo);
break;
case tag_category:
case tag_subcategory:
case tag_costitem:
return DB_Clairvoyant::CreateCV(memberInfo, inPaneInfo,
mTextInfo, cHasPopup);
break;
default: // for other classes we create a table clairvoyant,
{ // which has a reference to the table
DB_TableClairvoyant *cv =
NEW DB_TableClairvoyant(inPaneInfo, mTextInfo, GetCellCVClassID(inCell), cHasPopup);
TCS_FailNILMsg(cv, TCS_GetErrString(errID_BadClairvoyant));
cv->SetTable(this);
return cv;
}
break;
}
}
/*********************************************************************************
CreateNewCellMenuCVField TCS 9/2/99
create a cv field for the given cell
*********************************************************************************/
CMenuCV *CBreakdownTable::CreateNewCellMenuCVField(const TableCellT &inCell,
const SPaneInfo &inPaneInfo)
{ // get the member info from the column
SMemberInfo memberInfo;
TCS_ASSERTMsg(GetColMemberInfo(COL(inCell), &memberInfo), TCS_GetErrString(errID_BadColumn));
// now based on the tag and type, return the appropriate menu cv
switch (memberInfo.tag)
{
case tag_costarea: // bug fix TCS 11/27/98 rev 3/19/99 rev 9/2/99
{
CCostAreaCV *cv = NEW CCostAreaCV(inPaneInfo, mTextInfo, GetMenuCVClassID(inCell), cHasPopup);
if (cv)
cv->SetOwnerClass(GetOwnerClass()); // rev TCS 6/10/03
return cv;
}
break;
default: // changed TCS 10/28/98 so we get DB_ShortClairvoyant
return THE_SUPERCLASS::CreateNewCellMenuCVField(inCell, inPaneInfo);
break;
}
}
/*********************************************************************************
PrepCellCVField TCS 5/6/98
do any prep needed for a cell cv field. This is used when fetching a display
value in SetCVCellValue.
*********************************************************************************/
void CBreakdownTable::PrepCellCVField(const TableIndexT row, const TableIndexT col,
CTCS_CVField *cellField)
{
TagType colTag = GetColTag(col);
if (colTag == tag_category)
{
// let's cast the field to a cat cv
CCategoryCV *catField = TCS_SAFE_CAST(cellField, CCategoryCV);
TCS_FailNILMsg(catField, TCS_GetErrString(errID_BadClairvoyant));
// now we can set its category system
catField->SetCatSystem(GetTableCatSystem());
}
else if (colTag == tag_subcategory) // subcat setup is handled elsewhere
{
// let's cast the field to a subcat cv
CSubcatCV *subcatField = TCS_SAFE_CAST(cellField, CSubcatCV);
TCS_FailNILMsg(subcatField, TCS_GetErrString(errID_BadClairvoyant));
// set its category system
subcatField->SetCatSystem(GetTableCatSystem());
// set its category reference
TableIndexT catCol= GetMemberCol(tag_category);
if (catCol)
subcatField->SetCatRef(GetCellValue(row, catCol));
else
subcatField->SetCatRef(0);
}
else if (colTag == tag_location)
{
// let's cast the field to a location cv
CLocationCV *locationField = TCS_SAFE_CAST(cellField, CLocationCV);
TCS_FailNILMsg(locationField, TCS_GetErrString(errID_BadClairvoyant));
// set its job type and location package
locationField->SetJobType(mJobType);
locationField->SetLocationPackage(mLocationPackage); // TCS 8/23/99
}
else if (colTag == tag_costitem) // TCS 12/24/98
{
// fetch the cost class
SInt32 classCol = GetMemberCol(tag_costarea);
DBid classID = 0;
if (classCol)
classID = GetCellValue(row, classCol);
// set its class ID (needed so text displays properly)
if (classID == costtype_allowance)
cellField->SetDisplayClassID(id_Allowance); // TCS 7/14/99
else if (classID == costtype_assembly || classID == costtype_assmlabor || classID == costtype_assmmaterial)
cellField->SetDisplayClassID(id_Assembly);
else if (classID == costtype_bid)
cellField->SetDisplayClassID(id_Bid);
else if (classID == costtype_changeorder)
cellField->SetDisplayClassID(id_ChangeOrder);
else if (classID == costtype_powo)
cellField->SetDisplayClassID(id_PurchaseWorkOrder); // TCS 2/28/02
else if (classID == costtype_reminder)
cellField->SetDisplayClassID(id_ProjectReminder);
else if (classID == costtype_tool)
cellField->SetDisplayClassID(id_Tool);
else
cellField->SetDisplayClassID(id_CostItem);
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
AllowNegatives
return whether negatives are allowed in this column
*********************************************************************************/
Boolean CBreakdownTable::AllowNegatives(TableIndexT col) const
{
// get the member info from the column
SMemberInfo memberInfo;
TCS_ASSERTMsg(GetColMemberInfo(col, &memberInfo), TCS_GetErrString(errID_BadColumn));
Boolean allowNegatives = CAN_USE_NEGATIVES(memberInfo);
return allowNegatives;
}
/*********************************************************************************
HasUncheckedRows TCS 10/24/01
return whether some rows are lacking checkmarks
*********************************************************************************/
Boolean CBreakdownTable::HasUncheckedRows() const
{
TagType checkTag = GetCheckmarkTestTag();
if (checkTag)
{
TableIndexT checkCol = GetMemberCol(checkTag);
if (checkCol)
{
for (TableIndexT row = 1; row <= LastRow(); row++)
{
if (!IsChecked(row, checkCol))
return true;
}
}
}
// if we get this far, nothing is unchecked
return false;
}
/*********************************************************************************
HasColumn TCS 1/5/03
return whether or not the table has a column for the given member
*********************************************************************************/
Boolean CBreakdownTable::HasColumn(const TagType tag) const
{
return GetMemberCol(tag);
}
/*********************************************************************************
CanAlwaysChange TCS 5/13/02
return whether we can change a cell. That's generally determined by the
'always change' bit in the MEMB resource.
*********************************************************************************/
Boolean CBreakdownTable::CanAlwaysChange(const TableCellT &cell) const
{
TableIndexT col = COL(cell);
if (col)
{
// get the member info from the column. We don't worry if it's
// not there, since this may be called early in the table's existence
// when the members may not exist yet.
SMemberInfo memberInfo;
if (GetColMemberInfo(col, &memberInfo))
{
Boolean canAlwaysChange = CAN_ALWAYS_CHANGE(memberInfo);
if (canAlwaysChange)
return true;
}
}
// if we get this far, pass it to the superclass
return THE_SUPERCLASS::CanAlwaysChange(cell);
} |