/*
Using pseudo enumerations to implement category and sub-category
attribute values.
Dialog displays two choice elements.
The first contains choices for the main category.
The second contains choices for the sub-category.
The choices available for the sub-category are dependant on the
selected main category.
This script assumes the existance of two ordinary string attributes,
the names of which are defined below.
Enumeration values are defined in a string array.
Tony Goodman.
*/
/******************************************************************************
Attribute Names
These must exist - no check is made.
******************************************************************************/
const string ATTR_MAIN_CATEGORY = "Category"
const string ATTR_SUB_CATEGORY = "Sub Category"
/******************************************************************************
Indices into string array of enumeration values
By defining these here we can change the number of categories without
changing the rest of the code.
******************************************************************************/
const int NUM_MAIN_CATEGORIES = 3
const int NUM_SUB_CATEGORIES = 10
const int NUM_ENTRIES = NUM_MAIN_CATEGORIES + (NUM_MAIN_CATEGORIES * NUM_SUB_CATEGORIES)
const int MAIN_CATEGORY_OFFSET = NUM_SUB_CATEGORIES + 1
/******************************************************************************
"Enumeration" Values
First entry on the left is the main category. This is followed by the
sub category values.
It is important that there are exactly the same number entries in this
array for each category.
Empty strings are ignored - this allows us to have a varying number of
sub categories for each category.
******************************************************************************/
const string CATEGORIES[NUM_ENTRIES] = {
"Cheeses", "Brie", "Cheddar", "Stilton", "Camembert", "Edam", "", "", "", "", "",
"Meats", "Chicken", "Lamb", "Beef", "Pork", "", "", "", "", "", "",
"Fruits", "Orange", "Banana", "Apple", "Mango", "", "", "", "", "", ""
}
/******************************************************************************
Dialog elements
******************************************************************************/
DB dbMain = null
DBE dbeLabel = null
DBE dbeMainCategory = null
DBE dbeSubCategory = null
/******************************************************************************
Global variables
******************************************************************************/
Module currModule = null
Object currObject = null
/******************************************************************************
isMainCategory
returns true if the index to the string array is a main category.
e.g. if the number of sub-categories is 10, then main categories
are at indices 0, 11, 22, 33 ...
******************************************************************************/
bool isMainCategory(int i)
{
return(i % MAIN_CATEGORY_OFFSET == 0)
}
/******************************************************************************
getMainChoiceIndex
given the choice selected in the dialog, returns the index to the string
array.
******************************************************************************/
int getMainChoiceIndex(string mainCategory)
{
int i = 0
for (i = 0; i < NUM_MAIN_CATEGORIES; i++)
{
if (CATEGORIES[i * MAIN_CATEGORY_OFFSET] == mainCategory)
{
return(i)
}
}
return(-1)
}
/******************************************************************************
getSubChoiceIndex
given the choices selected in the dialog, returns the index to the string
array for the selected sub category.
******************************************************************************/
int getSubChoiceIndex(int mainSelection, string subCategory)
{
int i = 0
int startIndex = 0
int endIndex = 0
// convert into index to string array
startIndex = mainSelection + 1
endIndex = startIndex + NUM_SUB_CATEGORIES
// find matching sub category
for (i = startIndex; i < endIndex; i++)
{
if (CATEGORIES[i] == subCategory)
{
return(i - startIndex)
}
}
return(-1)
}
/******************************************************************************
printCategories
******************************************************************************/
void printCategories()
{
int i = 0
for (i = 0; i < NUM_ENTRIES; i++)
{
if (isMainCategory(i))
{
print("\nCategory: " CATEGORIES[i] "\n")
}
else
{
print("\t" CATEGORIES[i] "\t")
}
}
}
/******************************************************************************
initSubCategoryChoices
initialise the choices displayed in the sub category DBE.
If the current object has a value for this attribute then this value
is selected, but only if it is a legal choice based on the current main
category.
******************************************************************************/
void initSubCategoryChoices()
{
int i = 0
int mainSelection = 0
string subCategory = ""
empty(dbeSubCategory)
mainSelection = get(dbeMainCategory)
// if there is no selection in the main category DBE
// then leave this DBE empty.
if (mainSelection < 0)
{
return
}
// convert into index to string array
mainSelection = mainSelection * MAIN_CATEGORY_OFFSET
// extract string values from array
for (i = mainSelection + 1; i < mainSelection + NUM_SUB_CATEGORIES; i++)
{
if (CATEGORIES[i] == "")
{
break
}
insert(dbeSubCategory, noElems(dbeSubCategory), CATEGORIES[i])
}
// check current object for current atribute value
subCategory = currObject.ATTR_SUB_CATEGORY ""
set(dbeSubCategory, getSubChoiceIndex(mainSelection, subCategory))
}
/******************************************************************************
initMainCategoryChoices
initialise the choices displayed in the main category DBE.
If the current object has a value for this attribute then this value
is selected.
The sub category DBE is also updated.
******************************************************************************/
void initMainCategoryChoices()
{
int i = 0
string mainCategory = ""
// populate main category DBE
for (i = 0; i < NUM_ENTRIES; i += MAIN_CATEGORY_OFFSET)
{
insert(dbeMainCategory, noElems(dbeMainCategory), CATEGORIES[i])
}
// check current object for current atribute value
mainCategory = currObject.ATTR_MAIN_CATEGORY ""
// convert mainCategory to choice index and set selection in DBE
set(dbeMainCategory, getMainChoiceIndex(mainCategory))
// initialise sub category choices based on setting of main category
initSubCategoryChoices()
}
/******************************************************************************
doEditCategory
Callback when user clicks OK button.
******************************************************************************/
void doEditCategory(DB db)
{
int mainSelection = 0
int subSelection = 0
// get user selections from dialog elements
mainSelection = get(dbeMainCategory)
subSelection = get(dbeSubCategory)
// enforce selection of main category
if (mainSelection < 0)
{
infoBox("Please select main category")
return
}
// enforce selection of sub category
if (subSelection < 0)
{
infoBox("Please select sub category")
return
}
// adjust selections for for real index into string array
mainSelection = mainSelection * MAIN_CATEGORY_OFFSET
subSelection = mainSelection + subSelection + 1
// set object attributes
currObject.ATTR_MAIN_CATEGORY = CATEGORIES[mainSelection]
currObject.ATTR_SUB_CATEGORY = CATEGORIES[subSelection]
// refresh display to show changes
refresh(currModule)
// we are finished
hide(dbMain)
destroy(dbMain)
dbMain = null
}
/******************************************************************************
doSelectMainCategory
Callback when user makes a selection in the main category DBE.
Call function to update the choices available for sub category.
******************************************************************************/
void doSelectMainCategory(DBE dbe)
{
initSubCategoryChoices()
}
/******************************************************************************
MAIN
******************************************************************************/
currModule = current Module
if (null currModule)
{
infoBox("This utility can only be run from a module")
halt
}
currObject = current Object
if (null currObject)
{
infoBox("No current object.")
halt
}
dbMain = create(currModule, "Edit Category")
dbeLabel = label(dbMain,
"Description of edit category utility.\n")
dbeMainCategory = choice(dbMain, "Main Category: ", dummy, 0)
dbeSubCategory = choice(dbMain, "Sub Category: ", dummy, 0)
apply(dbMain, "OK", doEditCategory)
set(dbeMainCategory, doSelectMainCategory)
realize(dbMain)
initMainCategoryChoices()
show(dbMain)
sitemap