Compile Time Changes

class PartProxy

The following functions were added to PartProxy in v16.5. These functions were added in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part.

New: extend public double basePrice(Part part, bool includeChildren=false, Space space=null, bool translatePrice=true) {}
New: extend public double optionPriceSum(Part part, bool includeChildren=false, Space space=null, bool translatePrice=true, bool invalidate=false) {}

class Part

Constructor Migration: List Price → Base Price + Option Price Sum

In v16.5, a new constructor has been introduced for Part to support the new pricing model. Previously, Part accepted a cached list price (listPrice) directly as a parameter. This behavior is now being phased out.

Old Constructor
  • constructor(Snapper snapper, str articleCode, str description, double listPrice, ...)
  • Relies on cached listPrice.
  • Marks Part with data._useNewPricing = false to use old pricing behavior.
New Constructor (preferred, introduced in 16.5)
  • constructor(Snapper snapper, str articleCode, str description, double basePrice, Double optionPriceSum, ...)
  • Accepts basePrice and optionPriceSum separately.
  • Marks Part with data._useNewPricing = true to activate new pricing behavior.
  • Double optionPriceSum Parameter
    • Nullable
    • If a value is provided → it is treated as the cached option price sum.
    • If null is provided → the option price sum will be generated on demand when required.
      • Recommended approach for most use cases.
      • See new pricing API section for generateOptionPriceSum() documentation
    • NOTE: cached option price sum value is removed in invalidateOptionPriceSum
Impact
  • Migrate to new constructor and split your values into basePrice and optionPriceSum.
  • All new core features and pricing rules will rely on the new constructor/pricing system.
  • The old constructor remains for backward compatibility
Example Old and New Constructor Usage
Old: new Part(snapper, "PART NUM", "PART DESC", listPrice=199.99);
New: new Part(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=49.99);
New: new Part(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=null);

Old Pricing API

The following functions are now part of the old pricing system. The new pricing API is introduced in v16.5 and documented in the next section. The old API will remain for backwards compatibility but is expected to be removed in a future version of CET.

extend public double customListPrice()
extend public Double upcharge()
extend public double customListPrice()
Old → New behavior

Old:

  • if applicable, returns PartProxy list price value
  • returns PartData cached list price value
  • overridable interface to customize list price value

New:

  • Same behavior within method.
Impact
  • Migrate to new pricing API and plan to remove all reliance on customListPrice()
  • See listPrice() and calculatedListPrice(..) documentation for more migration information
extend public Double upcharge()
Old → New behavior

Old:

  • upcharge() returns null.

New:

  • Replaced by optionPriceSum().
  • Still supported if useNewPricing() == false.
Impact
  • Migrate to new pricing API and plan to remove all reliance on upcharge()
  • See optionPriceSum(..) and calculatedListPrice(..) documentation for more migration information

New Pricing API (v16.5 and later)

The following functions were introduced as part of the new pricing system. They replace Old pricing methods that relied on a cached list price.

Added: final public bool useNewPricing() {}
Added: extend public double basePrice(bool includeChildren=false, Space space=null, bool translatePrice=true) {}
Added: extend public double optionPriceSum(bool includeChildren=false, Space space=null, bool translatePrice=true, bool invalidate=false) {}
Added: final public double calculatedListPrice(bool includeChildren=false, Space space=null) {}
Added: extend public Double generateOptionPriceSum() {}
Added: extend public void invalidateOptionPriceSum() {}
Added: extend public bool useNewPartPricing() {}

Indicates whether the new part pricing system should be used on the Part instance. An opt-in feature flag to the new pricing system.

Behavior
  • Returns cached value from PartData
  • Value is set during construction:
    • Using new constructor sets this value to true
    • Using old constructor sets this value to false
Impact
  • Acts as the feature flag for determining which pricing path is followed in constructors, listPrice, upcharge, basePrice, optionPriceSum, etc.
  • Developers should begin migrating logic to use base price + option price sum rather than raw list price.
Added: extend public double basePrice(bool includeChildren=false, Space space=null, bool translatePrice=true) {}
Parameters
  • bool includeChildren (optional)
    • default false
    • if true, recursively adds child part base prices to returned value
  • Space space (optional)
    • default null
    • utitlized for calling translatePrice
  • bool translatePrice (optional)
    • default true
    • if true, translates price value to current currency for space
Old → New behavior

Old:

  • basePrice() is implemented in cm.abstract.part.AbsPart
    • returns list price by default
    • does not utilize cached base price
    • does not utilize PartProxy
    • does not implement the core specials system
    • overridden in DsPart to return catalog base price

New:

  • basePrice() is implemented in cm.core.part.Part
    • if applicable, returns special amount if a PartSpecial is found
    • if applicable, returns PartProxy base price value
    • returns PartData cached base price
    • Supports:
      • Including child part base prices.
      • Optional currency translation via space.
      • Accounting for specials (PartSpecial).
Impact
  • Utilize the new constructor to set the cached basePrice for the Part
  • Replace usage of raw listPrice with basePrice where you need only the product’s inherent cost
Added: extend public double optionPriceSum(..)
Parameters
  • bool includeChildren (optional)
    • default false
    • if true, recursively adds child part option price sums to returned value
  • Space space (optional)
    • default null
    • utitlized for calling translatePrice
  • bool translatePrice (optional)
    • default true
    • if true, translates price value to current currency for space
  • bool invalidate (optional)
    • defaults false
    • if true, invalidates cached option price sum value, triggering regeneration
Old → New behavior

Old:

  • upcharge() is implemented in cm.abstract.part.AbsPart
    • returns null by default
    • does not utilize cached value
    • does not utilize PartProxy
    • does not utilize core specials system

New:

  • optionPriceSum() is implemented in cm.core.part.Part
    • if useNewPricing is false, returns upcharge()
    • if applicable, returns PartProxy option price sum value
    • returns PartData cached option price sum
      • if cached value is null (or invalidate=true), value is regenerated automatically with generateOptionPriceSum()
    • Supports:
      • Including child part option price sums.
      • Optional currency translation via space.
      • Accounting for specials (PartSpecial)
Impact
  • Replace calls to upcharge() with optionPriceSum()
  • If your code updates Part options dynamically, call invalidateOptionPriceSum() before recalculation.
Added: final public double calculatedListPrice(..)
Parameters
  • bool includeChildren (optional)
    • default false
    • if true, recursively adds child part list prices to returned value
  • Space space (optional)
    • default null
    • utilized for calling translatePrice
  • bool translatePrice (optional)
    • default true
    • if true, translates price value to current currency for space
  • bool invalidateOptionPriceSum (optional)
    • default false
    • if true, invalidates option price sum value for regeneration
Old → New behavior

Old:

  • customListPrice(..) is primary source of list price value
    • if applicable, returns PartProxy list price value
    • returns PartData cached list price value
    • overridable interface to customize list price value
    • Used by listPrice() when useNewPricing == false

New:

  • calculatedListPrice(..) is primary source of list price in new pricing model
    • no longer relies on a cached list price value
    • returns calculated list price value (basePrice(..) + optionPriceSum(..))
    • not an overridable interface
    • Used by listPrice() when useNewPricing == true
Impact
  • If your system overrides customListPrice(..) to customize list price, migrate this logic into:
    • basePrice(..) (for foundational Part price)
    • and/or optionPriceSum(..)/generateOptionPriceSum() (for option pricing logic).
  • listPrice() will automatically call calculatedListPrice(..) if useNewPricing is enabled.
Added: extend public Double generateOptionPriceSum()
Old → New behavior

Old:

  • Not applicable.

New:

  • Returns the newly generated option price total.
  • Default implementation returns null.
  • Extended Part classes should override this method to compute option pricing correctly for their system.
    • Overridden in ProdPart and DsPart
Impact
  • If you have custom option price logic, override generateOptionPriceSum() in your extended Part class.
  • Invalidate the cache (invalidateOptionPriceSum()) when option state changes to trigger regeneration.

Added: extend public void invalidateOptionPriceSum()

Old → New behavior

Old:

  • Not applicable.

New:

  • Invalidates cached optionPriceSum value to trigger regeneration
  • Call invalidateOptionPriceSum() whenever Part configuration changes (options, children, etc.)
Impact
  • Add invalidateOptionPriceSum() after any Part modifications that may affect option pricing.

New Part API

The following functions were added or changed in Part in v16.5. The new pricing model API is documented above and not included in this section.

translatePrice functions were modified to remove unused includeChildren parameter.

Added: extend public double totalBasePrice(bool includeChildren=false, Space space=null) {}
Added: extend public double totalOptionPriceSum(bool includeChildren=false, Space space=null) {}

Old: final public double translatePrice(double price, bool includeChildren=false, Space space=null) {
New: final public double translatePrice(double price, Space space=null) {

Old: final public double translatePrice(double price, currencyId currency, bool includeChildren=false, Space space=null) {
New: final public double translatePrice(double price, currencyId currency, Space space=null) {

New Lead Time Interface

As of 16.5, a new interface for lead time has been added to core Part. It's value is displayed in the new LeadTimeColumn implemented in cm/core/init/leadTimeColumn.cm.

In cm/core/part/part.cm

/**
 * Get lead time string.
 * Ex. 20 days, 3 weeks, etc.
 */
extend public str leadTime() {
	return "";
}

class WorldPart

Constructor Migration: List Price → Base Price + Option Price Sum

In v16.5, a new constructor has been introduced for WorldPart to support the new pricing model. Previously, WorldPart accepted a cached list price (listPrice) directly as a parameter. This behavior is now being phased out.

Old Constructor
  • constructor(World world, str articleCode, str description, double listPrice, ...)
  • Accepts a total listPrice value to cache.
  • See documentation in compile-time section for cm.core.part.Part for more info
New Constructor (preferred, introduced in 16.5)
  • constructor(World world, str articleCode, str description, double basePrice, Double optionPriceSum, ...)
  • Accepts basePrice and optionPriceSum separately for caching.
  • See documentation in compile-time section for cm.core.part.Part for more info
Impact
  • Migrate to new constructor and split your values into basePrice and optionPriceSum.
  • All new core features and pricing rules will rely on the new constructor/pricing system.
  • The old constructor remains for backward compatibility
Example Old and New Constructor Usage
Old: new WorldPart(snapper, "PART NUM", "PART DESC", listPrice=199.99);
New: new WorldPart(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=49.99);
New: new WorldPart(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=null);

class PartSpecialHolder

Added: public str[] specialKeys();

  • Stores an ordered sequence of special keys
  • Allows for tracking of order of insertion of added custom specials
Behavior
  • Appended to during put
  • Removed from during remove
  • Cleared during removeAll

class PartAnnotationHolder

See cm.core.part.attributes section in 16.5 New Features migration guide for new PartAnnotationHolder class documentation.

class PartData

New Interface

The following functions were added to PartData in v16.5. These functions were added in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part.

// FUNCTIONS
New: extend public bool useNewPricing() {}
New: extend public double basePrice() : abstract {}
New: extend public void setBasePrice(double v) : abstract {}
New: extend public Double optionPriceSum() : abstract {}
New: extend public void setOptionPriceSum(Double v) : abstract {}

class PartAnnotation

See cm.core.part.attributes section in 16.5 New Features migration guide for new PartAnnotation class documentation.

class BasicPartData

Constructor Migration: List Price → Base Price + Option Price Sum

In v16.5, a new constructor has been introduced for BasicPartData to support the new pricing model. Previously, BasicPartData accepted a cached list price (listPrice) directly as a parameter. This behavior is now being phased out.

Old Constructor
  • constructor(Snapper snapper, str articleCode, str description, double inPrice=0, double outPrice=0, ...)
  • Accepts a total outPrice (list price) value to cache.
  • Marks _useNewPricing as false to use old pricing behavior.
New Constructor (preferred, introduced in 16.5)
  • constructor(Snapper snapper, str articleCode, str description, double basePrice=0, Double optionPriceSum=null, ...)
  • Accepts basePrice and optionPriceSum separately for caching.
  • Marks _useNewPricing as true to activate new pricing behavior.
  • Sets _outPrice field to (basePrice + optionPriceSum)
    • This field is unused in the new pricing model
  • Double optionPriceSum Parameter
    • See new pricing API section in cm.core.part.Part for documentation
Impact
  • Migrate to new constructor and split your values into basePrice and optionPriceSum.
  • All new core features and pricing rules will rely on the new constructor/pricing system.
  • The old constructor remains for backward compatibility
Example Old and New Constructor Usage
Old: new BasicPartData(snapper, "PART NUM", "PART DESC", outPrice=199.99);
New: new BasicPartData(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=49.99);
New: new BasicPartData(snapper, "PART NUM", "PART DESC", basePrice=150, optionPriceSum=null);

New BasicPartData Interface

The following functions and fields were added to BasicPartData in v16.5. These functions were added in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part.

// FIELDS
New: package bool _useNewPricing;
New: public double _basePrice;
New: public Double _optionPriceSum;

// OVERRIDDEN FUNCTIONS (from PartData)
New: public bool useNewPricing() {}
New: public double basePrice() {}
New: public void setBasePrice(double v) {}
New: public Double optionPriceSum() {}
New: public void setOptionPriceSum(Double v) {}

Runtime/Behavior Changes

Invisible Pricing Propagation Behavior

The following functions were added or modified in cm/core/part/parts.cm in v16.5. These functions were modified in support of the new pricing model which is documented in the compile-time section for cm.core.part.Part.

Changed: private void propagatePrice(Part p) {}
Added: private void propagatePriceNew(Part parent) {}

Changed: private void propagatePrice(Part p)

With the introduction of the new pricing system, the behavior of propagatePrice in cm/core/part/parts.cm has undergone changes.

Old → New behavior

Old:

  • Propagation used cached listPrice only.
  • When a child Part had invisiblePricing() == true:
    • Its totalListPrice() was divided by the parent’s quantity and added to the parent’s list price.
    • The child’s listPrice was set to 0.
    • Currency conversion was handled manually during this aggregation.

NEW:

  • propagatePrice now branches on the parent’s pricing model:
    • If the parent uses new pricing:
      • propagatePriceNew(..) is called
  • NOTE: Child parts are assumed to be utilizing the same pricing model as their parent Part

Added: private void propagatePriceNew(Part parent) {}

If the parent Part has useNewPricing() set to true, the new propagation system is utilized on the parent and child Parts. With the new pricing model, invisible pricing propagation is split into two: base price and option price sum.

Old → New behavior

Old:

  • Propagation is done in propagatePrice(..) and utilizes cached listPrice only.

NEW:

  • propagatePrice now branches on the parent’s pricing model:
    • If the parent uses new pricing:
      • Propagation is split into two dimensions:
        • Base price (totalBasePrice)
        • Option price sum (totalOptionPriceSum)
      • Each is separately aggregated from invisible children and divided by the parent’s quantity
      • Child data values are cleared
      • The parent’s cached data values are incremented accordingly
      • Currency conversion is no longer done here
        • Price getters now have translatePrice flag which is set to false during aggregation
  • NOTE: Child parts are assumed to be utilizing the same pricing model as their parent Part

class PartSpecial

Added: extend public void copy(PartSpecial special) {}

  • Allows for copying values from one PartSpecial instance to another
Behavior
  • Sets values on this to values from passed in special
  • Fields transferred:
    • str partNum
    • str descr
    • bool priceReplace
    • double amount

class PartGridBuilder

Constructor Change

Old → New behavior

Old:

  • Simply assigned the provided env.
  • If env was null, the instance had no default environment.
Old:
public constructor(PartGridBuilderEnv env=null) {
    this.env = env;
}

New:

  • If no environment is passed, it now creates a default PartGridBuilderEnv with buildTotalsRow = true.
  • Ensures a baseline configuration is always available, even without explicit input.
New:
public constructor(PartGridBuilderEnv env=null) {
    this.env = env ?? PartGridBuilderEnv(buildTotalsRow:true);
}

Added: extend public void populateGridWindow(Object data, GridWindow grid, PartGridBuilderEnv env=null) {}

  • High-level entry point to populate a GridWindow with arbitrary data.
Behavior
  • If no grid is provided → safely returns
  • If no env is passed → falls back to cached `this.env
  • Calls two helpers:
    • populateColumns(grid, env)
    • populateRows(data, grid, env)
  • Net effect: Wraps the column + row population into a single call.

Added: extend public void populateRows(Object data, GridWindow grid, PartGridBuilderEnv env=null)

  • Populates rows in a GridWindow from different types of input collections.
Behavior
  • If no grid → safely returns.
  • Falls back to cached this.env if no env is given.
  • Supports two input types:
    • Seq : Iterates and calls populateRow(obj, grid, env) for each.
    • Set: Same iteration and per-object row population.
  • Skips null objects
  • If env.buildTotalsRow == true, appends a totals row after populating all others.

class Part

Modified Pricing Behavior (v16.5 and later)

The following functions were modified with the introduction of the new pricing system (documented in cm.core.part.Part compile-time section).

Changed: final public double listPrice(bool includeChildren=false, Space space=null) {}
Changed: final public double listPrice(..)
Old → New behavior

Old:

  • If applicable, returns list price adjusted value
  • Otherwise, returns customListPrice(..)

New:

  • If applicable, returns list price adjusted value
  • Otherwise, checks useNewPricing() to determine pricing behavior
    • Returns calculatedListPrice(..) when useNewPricing is true
    • Returns customListPrice(..) when useNewPricing is false
Impact
  • See new pricing API documentation in cm.core.part.Part compile-time section for migration tips

Modified PartSpecials Behavior (v16.5 and later)

Retrieval and modification of PartSpecials on Part has been updated to account for flattened parts and to allow optional invalidation of world price.

Added: extend public PartSpecial getSpecial(str id, PropObj s=null) {}
Old → New behavior

Old:

  • Only supported fetching a PartSpecial using the implicit specialsKey().

New:

  • Adds an overload to get a special by an explicit id.
  • If no id is provided (empty string), it safely returns null.
  • Broadens lookup options: you can now fetch by specialsKey() or a direct identifier.
Changed: extend public bool containsSpecial(PropObj s=null) {}
Old → New behavior

Old:

  • Checked only the current owner for a special by calling getSpecial(s)

New:

  • Still checks the current owner
  • Additionally iterates through all owners, returning true if any owner has a special.
  • Result: containsSpecial now considers both self and inherited/related owners instead of just one.
Changed: putSpecial functions
Old: extend public void putSpecial(PartSpecial special, PropObj s=null) {}
New: extend public void putSpecial(PartSpecial special, PropObj s=null, bool invalidateWorldPrice=true) {}
New: extend public void putSpecial(str id, PartSpecial special, PropObj s=null, bool invalidateWorldPrice=true) {} 
Old → New behavior

Old:

  • Simple: placed a PartSpecial in the current owner’s PartSpecialHolder keyed by specialsKey()
  • Always invalidated world price.

New:

  • Signature extended with bool invalidateWorldPrice = true
  • Now supports two ways of saving:
    • If the passed in PropObj s=null parameter is not null → s.putSpecial(...)
    • Otherwise → iterates over all owners and updates them.
  • Actively propagates invalidateWorldPrice flag.
  • Ensures consistency across multiple owners, not just the direct one.
Changed: removeSpecial functions
Old: extend public void removeSpecial(PropObj s=null) {}
New: extend public void removeSpecial( PropObj s=null, bool invalidateWorldPrice=true) {}
New: extend public void removeSpecial(str id, PropObj s=null, bool invalidateWorldPrice=true) {
Old → New behavior

Old:

  • Removed a special only from the current owner using specialsKey()
  • Always invalidated world price

New:

  • Two overloads:
    • One that removes by explicit id
    • One that removes by the derived specialsKey()
  • Both propagate the invalidateWorldPrice flag
  • Iterates through all owners, not just the direct owner
  • More robust cleanup — ensures that the special is removed everywhere it might exist

Other Part Changes

Added: extend public str annotationFlattenableKey() {}

With the addition of the new part attribute description/notes system, Parts now need to be differentiable/split by their attribute values.

The following helper function to generate the flattenable key for attributes has been made. It is appended to the flattenable key in flattenableKey():

/**
 * Flattened annotation note/descs key.
 * @return str of flattenable key of PartAnnotation(s)
 */
extend public str annotationFlattenableKey() {
	StrBuf buf();
	bool first = true;
	for (annotation in getAnnotations()) {
		if (first) first = false;
		else buf << ',';
		buf << annotation.key();
	}
	return buf.retireToS();
}
Changed: extend public str flattenableKey() {}

With the addition of the new part attribute description/notes system, Parts now need to be differentiable/split by their attribute values.

The following change has been made in flattenableKey to account for this:

/**
 * Flattenable key.
 */
extend public str flattenableKey() {
	StrBuf key;
	
	...
	
New:	key << annotationFlattenableKey();
	
	return key.any() ? key.retireToS() : articleCode();
}
Changed: extend public Object valueOf(PartColumn column) {}

With the addition of the new part attribute description and note columns in Calculations, the valueOf(..) function has been updated in Part to provide values for these columns.

This is mainly useful for the Excel order export and exporting a single, comma-delimited, str value for PartAttributeColumns.

/**
 * Normally returned from value method in 'column', this is a change to override it from part.
 */
extend public Object valueOf(PartColumn column) {
	if (column as PartAttributeColumn) {
		?str[] colVals = column.value(this, null);
		if (!colVals) return null;

		StrBuf valuesBuf();
		bool first = true;
		for (val in colVals) {
			if (first) first = false;
			else valuesBuf << ", ";
			valuesBuf << val;
		}

		return valuesBuf.retireToS();
	}
	return null;
}

Changed: extend public void updateItemTags() {}

With the addition of the new str articleCodeText field on ItemTagInfo, Part now sets this value during updateItemTags() if it is not already set. This ensures that the field has a value and that the new Control Panel setting for toggling article codes for Ind Tags is functional in most cases.

/**
 * Update the Item tags.
 */
extend public void updateItemTags() {
	...
	
	if (owner and acceptItemTags()) {
		if (ItemTags tags = owner.itemTags()) {
			if (ItemTag tag = tags.get(itemTagKey())) {
				...
	
New:			if (tag.info and !tag.info.articleCodeText) {
New:				tag.info.articleCodeText = articleCode();
New:				invalidate = true;
				}
				
				...
				return;
			}
		}
		...
	}
}

class FlattenedPartData

New Part-To-Owner Interface

A new interface, partToOwnerKeys, has been added to FlattenedPartData. These keys are str values that are unique for each Part within a single owner. Their purpose is to distinguish between multiple Parts on the same Snapper owner that may share the same flattenableKey but originate from different creators.

Example

Consider a table Snapper with four legs:

  • When processed, the table generates one Part for the tabletop and four Parts for the legs.
  • During part merging, if all four legs are identical, they may be flattened into a single leg Part.
  • The resulting FlattenedPartData contains an owners sequence pointing only to the table Snapper.
Previous Limitation

In this scenario, the flattened part had no way to reference the four individual leg parts that were merged together—it only knew about the shared owner.

New Behavior

The partToOwnerKeys interface resolves this gap by assigning unique keys for each contributing Part. This allows the flattened part to retain identifiers for the individual parts that generated it, ensuring traceability even after merging.

FlattenedPartData Modifications

To accomplish this, FlattenedPartData has a new field where the keys are stored (private str{} _partToOwnerKeys), a new accessor function (final public str{} partToOwnerKeys()), and a change in appendSimilar to build the keys. The appendSimilar function's purpose is to append a new Part to the flattened part info. It increases quantity, appends owners, and changes the level of the flattened part. It now also appends the passed in Part parts partToOwnerKey into the _partToOwnerKeys sequence.

In cm/core/part/flattenedPartData.cm 


New: private str{} _partToOwnerKeys;
New: final public str{} partToOwnerKeys() {}

Changed:
/**
 * Append a similar part.
 */
final public void appendSimilar(Part part, double multiplier) {
	appendOwnersFrom(part.data);

New:	if (!_partToOwnerKeys) init _partToOwnerKeys();
New:	_partToOwnerKeys << part.partToOwnerKey();

	_quantity += part.quantity()*multiplier;

	level = min(level, part.level());

	#if (!builtInReleaseMode) assert(_allowOtherParent == part.data.allowOtherParent);
}

class PartAnnotationHolder

See cm.core.part.attributes section in 16.5 New Features migration guide for new PartAnnotationHolder class documentation.

class PartGridBuilderEnv

Added: extend public Brush getCellBrush(Object data, int columnIdx) {}

  • Allows for customization of a row and columns cell background
  • Parameters:
    • Object data: Data for row to get cell brush for
    • int columnIdx: Column index to get cell brush for
Behavior
  • Returns whiteBrush by default

Added: extend public GridCell getDefaultCell(Object data, int columnIdx) {}

  • Gets default cell for row and column
  • Parameters:
    • Object data: Data for row to get default cell for (can be null)
    • int columnIdx: Column index to get default cell for
Behavior
  • Returns ColorNameGridCell("", bgColor=getCellBrush(..).color) by default

Added: extend public GridCell getPartRowCell(Part part, int columnIdx) {}

  • Gets part row cell for Part and column
  • Parameters:
    • Part part: Part for row to get cell for (can be null)
    • int columnIdx: Column index to get cell for
Behavior
  • If Part is null or column index is out of bounds, returns getDefaultCell(..)
  • Otherwise, returns a cell for the Part data associated with the column index
    • Assigns a background color to the cell by calling getCellBrush(..)

Changed: extend public GridCell[] getPartRowCells(Part part) {}

Old → New behavior

Old:

  • Directly returned a sequence of GridCells

New:

  • Loops through columns, calling getPartRowCell for each column and appending it to the returned GridCell sequence
  • Allows for more flexibility when building row cells

class PartAnnotation

See cm.core.part.attributes section in 16.5 New Features migration guide for new PartAnnotation class documentation.

cm/core/part/functions.cm Special functions

  • The parameter bool invalidateWorldPrice=true has been added to special functions
    • Gives the option to invalidate world price upon making changes to specials
    • Previously, world price was invalidated on every special change
Old: public void removeSpecialHolder(PropObj s) {}
New: public void removeSpecialHolder(PropObj s, bool invalidateWorldPrice=true) {}

Old: public void putSpecial(PropObj s, str key, PartSpecial special) {}
New: public void putSpecial(PropObj s, str key, PartSpecial special, bool invalidateWorldPrice=true) {}

Old: public void removeSpecial(PropObj s, str key) {}
New: public void removeSpecial(PropObj s, str key, bool invalidateWorldPrice=true) {}

Old: public void removeAllSpecials(PropObj s) {}
New: public void removeAllSpecials(PropObj s, bool invalidateWorldPrice=true) {}