Overview

Icon Library Updates

Icon Library Updates

The icon library has been reorganized to improve consistency and make icons easier to find and maintain. Developers must update references to icons that were removed, moved, or renamed. References using outdated names or paths may no longer resolve, resulting in missing icons.

Renamed icons with their previous and new names

Old: Cut-Snip
New: Cut-snip

Old: Automatic-Dimension
New: Automatic-dimension

Old: Manual-Dimension
New: Manual-dimension

Old: List-Select
New: List-select

Old: Junction-2-Way-90
New: Junction-2-way-90

Old: Junction-2-Way-120
New: Junction-2-way-120

Old: Junction-3-Way
New: Junction-3-way

Old: Junction-4-Way
New: Junction-4-way

Old: Add-New-drawing
New: Add-new-drawing

Old: Query-history
New: Search-history

cm.abstract.dataSymInterface

External Reference Key (E-KEY) matching behavior update

From 17.5 onwards, we are adding support for both AND and OR matching condition when multiple External Reference Keys are used to match a Product's External Reference. As a result, the fundamental logic for finding matching External Reference using E-KEY is completely reworked.

Enabling DSI constraints logic

The new DSI constraints logic will be enabled by default in the 17.5 Major release. The logic has been rewritten to better support both CET and Stage, allowing them to share the same backend for improved consistency. There should be no behavioral differences between the old and new constraints logic. However, if you encounter any broken or unexpected behavior after enabling the new DSI constraints logic, please report it to Dev Support. As a temporary workaround, you can override the forceDsApplyLogic() method in the DsPData or DsPDataProxy class to fall back to the old constraints logic.

cm.abstract.draw

A few unused and legacy classes have been removed from this package to simplify the codebase and improve maintainability.

cm.abstract.ofdaXml

OFDA XML 04.02.00 Export Compatibility

OFDA XML exports now preserve part attribute notes and descriptions in separate elements that can be imported correctly by Spec. Several line-item, option, and specification elements have also been reordered for schema compatibility.

The export format is labeled 04.02.00, but the root Envelope continues to contain SchemaVersion="04.00.00". This is intentional for the 04.02.00 schema and is not the version displayed in the Calculations export menu.

cm.abstract.office

Extensible Type Elevation Merging

TypeElevation.mergeAll() previously searched specifically for PanelTypeElevation objects. As a result, merge did not work correctly for non-panel systems extending TypeElevation.

mergeAll() now delegates candidate selection to collectMergers(). This allows the base class to support non-panel type elevations while retaining panel-specific behavior in PanelTypeElevation.

cm.abstract.part

Query Dialog Sidebar and Model Import

The product-part Query implementation now supplies its import support through a specialized QueryPartImportTabBehavior. This keeps part file import and option drag/drop behavior while integrating it with the new Query dialog sidebar.

Part Dimensions and Special Creation

Physical dimensions, generic codes, and XML export hooks are being moved toward the common part APIs so non-data-symbol parts can participate in the same SIF and OFDA workflows. Product-part creators now share the option-processing implementation used for override and addition specials.

cm.abstract.part.query

Multiline Query and Article View Text

The option-special dialog now provides a multiline description area so long option descriptions can wrap instead of expanding the dialog horizontally. This complements the related part-special dialog and query tooltip changes in cm.core.part.query.

cm.application

Separate menu entries for horizontal and vertical split views

The Views menu now has separate entries for horizontal and vertical split layouts.

cm.core

PropInputSetting of "persistent"/"persistant" prop arg only applies on Insert Animation

The "persistent"/"persistant"=true prop arg in PropInputSetting was meant to be a quick implementation of setting the same value of a prop as the previous inserting same class Snapper.

Example:

  1. Press worksurface inserting button.
  2. Inserting 1st worksurface, default width is 60cm.
  3. Change width to 120cm.
  4. Click to actually place the worksurface.
  5. 2nd worksurface now inserting with 120cm width.

The "persistent"/"persistant" logic is also happening while stretching Snappers which makes no sense according to the original intent. Therefore "persistent"/"persistant" will now be executed only in insert animation (Previously happening to all animation properties).

Split-view Resource Label

The single label previously used for split views has been replaced with separate labels for horizontal and vertical layouts. This allows each split-view option to be clearly identified in the user interface.

Removal of Legacy 2D and 3D Contextual View-Switch Toolbar Models

The legacy contextual view-switch toolbar models have been removed as part of the split-view toolbar update.

Split-View Orientation and Divider Interface Changes

Split views now support both horizontal and vertical layouts. The split-view API has been updated so that horizontal consistently means views stacked top/bottom and vertical means views arranged left/right.

Preserving Part Adjustments When Resetting Item Tags

Resetting item tags on a TaggableSnapper now handles each part's user-modified Ind. Tag explicitly. If resetting those tags would change the keys of existing part adjustments, CET identifies the affected article codes and asks whether the adjustments should be preserved.

cm.core.calc

Multiline Query and Article View Text

Article-view information rows now honor the existing Use newline setting consistently, including text supplied by PartInfoColumn and BasicPartInfoTreeColumn implementations.

cm.core.part

Query Dialog Sidebar and Model Import

Query dialog side tools are now represented by QueryTabBehavior and QueryTabWindow objects managed by a QueryTabContainer. This replaces the single-purpose rightWindow and moves part-import behavior out of QueryDialogBehavior into QueryPartImportTabBehavior.

Extensions that customize the Query dialog can return additional tab behaviors from QueryDialogBehavior.tabBehaviors() or replace the standard part/model import behaviors by overriding the corresponding behavior factory method.

Part Owner Identification

In 17.0 sourceId was introduced at the core level to give parts a snapper specific unique identifier to help identify the owning object and ItemTag associated with the part. A gap was found from the changes where merged parts didn't have enough information to link changes from a part back to all ItemTags across all owners of the part. The main issue was that itemTagKey could be changed to not be the sourceId in a customization. To help solve this issue, PartSouceInfo was created as an object to own all the unique information that identifies the part. Currently this is Snapper owner, str sourceId, and str itemTagKey.

Preserving Part Adjustments When Resetting Item Tags

Resetting a user-modified Ind. Tag can change a part's adjustment key. CET now detects adjusted parts before the reset and can migrate their adjustments to the new key. This prevents price, quantity, and other part adjustments from unexpectedly becoming orphaned when an Ind. Tag returns to its default value.

cm.core.part.query

Multiline Query and Article View Text

Part-special descriptions are now edited in a multiline area. Long query-cell tooltips are also split into shorter lines so they remain readable without producing excessively wide tooltips.

cm.core3D

Improvements to 3D text spacing

3D text built through Text3D now gets character spacing from glyph advance data instead of deriving spacing from each character outline's maximum x extent.

In practice this makes 3D text spacing better match 2D text, especially for strings containing whitespace. The change is most noticeable in snappers that build meshes from text outlines, such as 3D Text.

3D Text Character Spacing

cm.std.draw3D

Many unused classes and functionality have been removed from this package to simplify the codebase and improve maintainability.

cm.std.print.template

Many unused classes and functionality have been removed from this package to simplify the codebase and improve maintainability.

Compile Time Changes

cet.runtime

Timeout changes for CET updates

mcCheckForUpdatesHandler.cm

Added new arguments to the abortTimedOutInstallation method in the MCCheckForUpdatesHandler class.

Old: final public void abortTimedOutInstallation() {
New: final public void abortTimedOutInstallation(bool failed=false) {

Also some interfaces were updated in the cm.extension package. Please refer to the documentation for those changes as well.

cm.abstract.conveyors

Interface name changes

We have updated most of the public classes in this package to start with the same prefix of "AC". We have also updated public globals and functions to include "ac" or "AC" in their names.

Classes:

OldNew
ACConvSeqPropDefsVisitorACConveyorSeqPropDefsVisitor
AbsConvChargeCTACConveyorChargeCT
AbsConvDischargeCTACConveyorDischargeCT
AbsConvSideChannelCTACConveyorSideChannelCT
AbsConvDivertCTACConveyorDivertCT
AbsConvCenterLineCTACConveyorCenterLineCT
AbsConvMergeCTACConveyorMergeCT
AbsConvTakeawayCTACConveyorTakeawayCT
AbsConvEndCTACConveyorEndCT
AbsConvTransferCenterLineCTACConveyorTransferCenterLineCT
AbsConvTransferCTACConveyorTransferCT
ConvComponentVisitorACConveyorComponentVisitor
ConvBedLocalBoundVisitorACConveyorBedLocalBoundVisitor
ConvCollectBedsVisitorACConveyorCollectBedsVisitor
ConvWidthObserverACWidthObserver
ConveyorBedACConveyorBed
ConveyorBedSequencerACConveyorBedSequencer
ConveyorBeltACConveyorBelt
ConveyorComponentACConveyorComponent
ConveyorCurvedBedACConveyorCurvedBed
ConveyorGraphicsEnvACConveyorGraphicsEnv
ConveyorMergeBedACConveyorMergeBed
ConveyorGenericPartColumnACConveyorGenericPartColumn
ConveyorElevationChangePartColumnACConveyorElevationChangePartColumn
ConveyorChargeElevationPartColumnACConveyorChargeElevationPartColumn
ConveyorDischargeElevationPartColumnACConveyorDischargeElevationPartColumn
ConveyorPitchPartColumnACConveyorPitchPartColumn
ConveyorRedPickerACConveyorRedPicker
ConveyorRollersACConveyorRollers
ConveyorStraightBedACConveyorStraightBed
ConveyorTakeAwayBedACConveyorTakeAwayBed
ConveyorTransferBedACConveyorTransferBed
ConveyorWedgeBedACConveyorWedgeBed
DetailPropertiesFactoryACDetailPropertiesFactory
DetailPropsButtonsPropertyFactoryACDetailPropsButtonsPropertyFactory
DetailPropertiesUIACDetailPropertiesUI
DetailPropsDialogACDetailPropsDialog
AcShape2DLinePrimitiveACShape2DLinePrimitive
HingedBedACConveyorHingedBed
ConvObserverACObserver
ConvStretchEnvACConveyorStretchEnv
CutRuleFactoryACCutRuleFactory
UnitClassACUnitClass
LengthUnitACLengthUnit
LengthUnitMACLengthUnitM
LengthUnitCMACLengthUnitCM
LengthUnitMMACLengthUnitMM
LengthUnitInchACLengthUnitInch
LengthUnitFeetACLengthUnitFeet
SpeedUnitACSpeedUnit
SpeedUnitMpSACSpeedUnitMpS
SpeedUnitFpMACSpeedUnitFpM
SpeedUnitMpMACSpeedUnitMpM

Fields & Methods:

public class ACConveyorBehavior {
Old: extend public SpeedUnit speed(Snapper z) {
New: extend public ACSpeedUnit speed(Snapper z) {

Old: extend public <range, SpeedUnit>[] speeds(Snapper z) {
New: extend public <range, ACSpeedUnit>[] speeds(Snapper z) {
}


public class ConveyorBed extends ConveyorComponent {
Old: extend public ConveyorBedSequencer seqr(Snapper z) {
New: extend public ACConveyorBedSequencer seqr(Snapper z) {

Old: extend public ConveyorBed next(Snapper z) {
New: extend public ACConveyorBed next(Snapper z) {

Old: extend public ConveyorBed previous(Snapper z) {
New: extend public ACConveyorBed previous(Snapper z) {

Old: extend public void appendRoller2D(PropObj owner, GInstance gs, ConveyorRollers rollers) {
New: extend public void appendRoller2D(PropObj owner, GInstance gs, ACConveyorRollers rollers) {

Old: extend public void appendBeltTopSidePath(APath2D path, ConveyorBed prev, ConveyorBed next, Snapper owner) {
New: extend public void appendBeltTopSidePath(APath2D path, ACConveyorBed prev, ACConveyorBed next, Snapper owner) {

Old: extend public ConveyorBedSequencer newSectionSequencer(ConveyorBedSequencer parent=null) {
New: extend public ACConveyorBedSequencer newSectionSequencer(ACConveyorBedSequencer parent=null) {
}


public class ConveyorBedSequencer extends CorePropObj {
Old: extend public ConveyorBed operator<<(ConveyorBed bed) {
New: extend public ACConveyorBed operator<<(ACConveyorBed bed) {

Old: extend public void _append(ConveyorBed bed) {
New: extend public void _append(ACConveyorBed bed) {

Old: extend public void _insert(int i, ConveyorBed bed) {
New: extend public void _insert(int i, ACConveyorBed bed) {

Old: extend public void _remove(ConveyorBed bed) {
New: extend public void _remove(ACConveyorBed bed) {

Old: extend public void append(Snapper z, ConveyorBed bed, bool addZone=false) {
New: extend public void append(Snapper z, ACConveyorBed bed, bool addZone=false) {

Old: extend public void insert(Snapper z, int i, ConveyorBed bed, bool addZone=false) {
New: extend public void insert(Snapper z, int i, ACConveyorBed bed, bool addZone=false) {

Old: extend public void remove(Snapper z, ConveyorBed bed) {
New: extend public void remove(Snapper z, ACConveyorBed bed) {

Old: extend public void seqrEvent(symbol event, ConveyorBed bed, Snapper z) {
New: extend public void seqrEvent(symbol event, ACConveyorBed bed, Snapper z) {

Old: extend public ConveyorBed next(Snapper z, ConveyorBed bed) {
New: extend public ACConveyorBed next(Snapper z, ACConveyorBed bed) {

Old: extend public ConveyorBed prev(Snapper z, ConveyorBed bed) {
New: extend public ACConveyorBed prev(Snapper z, ACConveyorBed bed) {

Old: extend public ConveyorBed chargeBed(Snapper z) {
New: extend public ACConveyorBed chargeBed(Snapper z) {

Old: extend public ConveyorBed dischargeBed(Snapper z) {
New: extend public ACConveyorBed dischargeBed(Snapper z) {

Old: extend public ConveyorBed[] sortedBeds(Snapper z) {
New: extend public ACConveyorBed[] sortedBeds(Snapper z) {

Old: extend public ConveyorBed bed(Snapper z, str key) {
New: extend public ACConveyorBed bed(Snapper z, str key) {

Old: extend public ConveyorBed bed(Snapper z, int i) {
New: extend public ACConveyorBed bed(Snapper z, int i) {

Old: extend public point nextBedConnectPos(Snapper z, ConveyorBed bed ) {
New: extend public point nextBedConnectPos(Snapper z, ACConveyorBed bed ) {

Old: extend public ConveyorBed centerBed(Snapper z) {
New: extend public ACConveyorBed centerBed(Snapper z) {

Old: extend public ACZone nextZone(Snapper z, ConveyorBed bed) {
New: extend public ACZone nextZone(Snapper z, ACConveyorBed bed) {

Old: extend public ACZone newZone(Snapper owner, ConveyorBed bed, bool force=false) {
New: extend public ACZone newZone(Snapper owner, ACConveyorBed bed, bool force=false) {

Old: extend public bool needsNewZone(Snapper owner, ConveyorBed bed) {
New: extend public bool needsNewZone(Snapper owner, ACConveyorBed bed) {

Old: extend public void applyStretchEnv(ConvStretchEnv stretchEnv, symbol event=null, Snapper z=null) {
New: extend public void applyStretchEnv(ACConveyorStretchEnv stretchEnv, symbol event=null, Snapper z=null) {

Old: extend public void applyStretchEnvs(ConvStretchEnv[] stretchEnvs, symbol event=null, Snapper z=null) {
New: extend public void applyStretchEnvs(ACConveyorStretchEnv[] stretchEnvs, symbol event=null, Snapper z=null) {

Old: extend public CutRuleFactory cutRuleFactory() {
New: extend public ACCutRuleFactory cutRuleFactory() {
}


public class ConveyorComponent extends Component {
Old: extend public ConveyorBedSequencer seq(PropObj owner) {
New: extend public ACConveyorBedSequencer seq(PropObj owner) {
}


public class ConveyorGraphicsEnv extends PropObj {
Old: public ConveyorBedSequencer seq;
New: public ACConveyorBedSequencer seq;

Old: public constructor(Snapper z, ConveyorBedSequencer seq) {
New: public constructor(Snapper z, ACConveyorBedSequencer seq) {
}


public class ConveyorRollers extends ConveyorComponent {
Old: extend public void appendRollers2D(GInstance gs, ConveyorBed bed) {
New: extend public void appendRollers2D(GInstance gs, ACConveyorBed bed) {

Old: extend public void appendStraightBedRollers2D(GInstance gs, ConveyorStraightBed bed) {
New: extend public void appendStraightBedRollers2D(GInstance gs, ACConveyorStraightBed bed) {

Old: extend public void appendRollers3D(FetchEnv3D env, Snapper z, ConveyorBed bed, Primitive3D[] prims) {
New: extend public void appendRollers3D(FetchEnv3D env, Snapper z, ACConveyorBed bed, Primitive3D[] prims) {

Old: extend public void appendWedgeBedRollers3D(FetchEnv3D env, Snapper z, ConveyorWedgeBed bed, Primitive3D[] prims) {
New: extend public void appendWedgeBedRollers3D(FetchEnv3D env, Snapper z, ACConveyorWedgeBed bed, Primitive3D[] prims) {

Old: extend public void appendStraightBedRollers3D(FetchEnv3D env, Snapper z, ConveyorStraightBed bed, Primitive3D[] prims) {
New: extend public void appendStraightBedRollers3D(FetchEnv3D env, Snapper z, ACConveyorStraightBed bed, Primitive3D[] prims) {

Old: extend public void appendCurvedBedRollers3D(FetchEnv3D env, Snapper z, ConveyorCurvedBed bed, Primitive3D[] prims) {
New: extend public void appendCurvedBedRollers3D(FetchEnv3D env, Snapper z, ACConveyorCurvedBed bed, Primitive3D[] prims) {
}


public class ConveyorStraightBed extends ConveyorBed {
Old: extend public void appendHeightChangeLines(GInstance gs, ConveyorGraphicsEnv env, Snapper z, point[] fillPositions) {
New: extend public void appendHeightChangeLines(GInstance gs, ACConveyorGraphicsEnv env, Snapper z, point[] fillPositions) {
}


public class ACZone extends CorePropObj {
Old: extend public ConveyorBed bed(Snapper z, str key) {
New: extend public ACConveyorBed bed(Snapper z, str key) {

Old: extend public ConveyorBed[] zoneSortedBeds(Snapper owner) {
New: extend public ACConveyorBed[] zoneSortedBeds(Snapper owner) {

Old: extend public ConveyorBedSequencer seqr(Snapper z) {
New: extend public ACConveyorBedSequencer seqr(Snapper z) {

Old: extend public void applyStretchEnv(ConvStretchEnv zoneEnv, symbol event=null, Snapper z=null) {
New: extend public void applyStretchEnv(ACConveyorStretchEnv zoneEnv, symbol event=null, Snapper z=null) {

Old: extend public ConvStretchEnv zoneStretchEnv(Snapper z) {
New: extend public ACConveyorStretchEnv zoneStretchEnv(Snapper z) {

Old: extend public void updateBed(ConveyorBed bed, ConveyorBed prevBed, Snapper z, Object env=null)  {
New: extend public void updateBed(ACConveyorBed bed, ACConveyorBed prevBed, Snapper z, Object env=null)  {

Old: extend public void setBedLengths(Snapper z, double[] lengths, ConveyorBed[] changeBeds) {
New: extend public void setBedLengths(Snapper z, double[] lengths, ACConveyorBed[] changeBeds) {

Old: extend public void conveyorAddOrRemoveBed(Snapper z, double[] lengths, ConveyorBed[] changeBeds, int firstChangeBed, int insertIdx) {
New: extend public void conveyorAddOrRemoveBed(Snapper z, double[] lengths, ACConveyorBed[] changeBeds, int firstChangeBed, int insertIdx) {
}


public class ConvStretchEnv extends PropObj {
Old: public ConveyorBedSequencer seqr;
New: public ACConveyorBedSequencer seqr;

Old: public ConveyorBed[] changeBeds();
New: public ACConveyorBed[] changeBeds();

Old: public CutRuleFactory factory;
New: public ACCutRuleFactory factory;

Old: public constructor(Snapper z, double targetL, ACZone zone, ConveyorBedSequencer seqr=null, CutRuleFactory factory=null, str{} keepIntact=null) {
New: public constructor(Snapper z, double targetL, ACZone zone, ACConveyorBedSequencer seqr=null, ACCutRuleFactory factory=null, str{} keepIntact=null) {
}


public class UnitClass {
Old: public constructor(UnitClass c) {
New: public constructor(ACUnitClass c) {

Old: final public UnitClass operator+(UnitClass c) {
New: final public ACUnitClass operator+(ACUnitClass c) {

Old: final public UnitClass operator-(UnitClass c) {
New: final public ACUnitClass operator-(ACUnitClass c) {

Old: final public UnitClass operator=(UnitClass c) {
New: final public ACUnitClass operator=(ACUnitClass c) {

Old: extend public bool same(UnitClass c) {
New: extend public bool same(ACUnitClass c) {
}

Functions:

Old: public ConveyorGenericPartColumn acGenericPartColumn(str attr) {
New: public ACConveyorGenericPartColumn acGenericPartColumn(str attr) {


Old: public ConveyorBed[] convSortedBedComponents(Snapper z) {
New: public ACConveyorBed[] convSortedBedComponents(Snapper z) {


Old: public SubSet acCalcZone2DLengthDomain(Snapper z, ConveyorBedSequencer sqr=null, double step=5mm) {
New: public SubSet acCalcZone2DLengthDomain(Snapper z, ACConveyorBedSequencer sqr=null, double step=5mm) {


Old: public bool acIncorrectElevCh(double length, ConveyorStraightBed bed) {
New: public bool acIncorrectElevCh(double length, ACConveyorStraightBed bed) {

Enums:

The enum absConveyourTransDir has been renamed to acConveyorTransDir.

Globals:

OldNew
absSuperRollerRefinementacSuperRollerRefinement
absHighRollerRefinementacHighRollerRefinement
absMediumRollerRefinementacMediumRollerRefinement
cAcElevPKcACElevPK
cAcLengthPKcACLengthPK
cAcLength2DPKcACLength2DPK
cAcBFPKcACBFPK
cAcEndElevPKcACEndElevPK
cBeforeBedRemovecACBeforeBedRemove
cBedRemovedcACBedRemoved
cBedAppendedcACBedAppended
cBedInsertedcACBedInserted
cBedPosChangedcACBedPosChanged
cBedLengthChangedcACBedLengthChanged
cBedElevationChangecACBedElevationChange
cAcConvBFChangecACConvBFChange
cConvBedSequencerKeycACConvBedSequencerKey
absConvChargeRuleacConvChargeRule
absConvDischargeRuleacConvDischargeRule
absConvEndRuleacConvEndRule
absConvWedgeRuleacConvWedgeRule
absConvCenterLineRuleacConvCenterLineRule
absConvSideRuleacConvSideRule
absConvSupportRuleacConvSupportRule
absConvTransferRuleacConvTransferRule
absConvCenterLineTransferRuleacConvCenterLineTransferRule

For the connect rule globals modified above, we did not change the connect rule IDs.

Catalog-excel compilation changes

The class ACCatalogDialog has been removed as it was a work-in-progress dialog, and has been replaced with ACLocalCatalogCreatorDialog that has a design UI design.

Updated interface for function Url[] acUserCompileEssentialCatalog(Window parent, Url url=null, bool singleUnit=false, bool recurseDir=false) with a new Class fileOpClass=null argument.

Old:
public Url[] acUserCompileEssentialCatalog(Window parent, Url url=null, bool singleUnit=false, bool recurseDir=false)

New:
public Url[] acUserCompileEssentialCatalog(Window parent, Url url=null, bool singleUnit=false, bool recurseDir=false, Class fileOpClass=null)

Side accessory connectors

The connect rule absConvSideAccessoryRule has been removed and replaced with acConvSideAccessoryRule.

Old: absMhLibConvSideSnapRule = makeConnectRule("absMhLibConvSideSnapRule", ACConveyorSideChannelCT, null, pkg=(#"cm.abstract.mhLibrary"));
Replaced: acConvSideAccessoryRule = makeConnectRule("absConvSideAccessoryRule", ACConveyorSideChannelCT, null);

cm.abstract.dataSymInterface

class DsiPData

The following method is modified, as getting matching External References with matching E-KEY from a single option is no longer accurate.

Old: extend public ExternalRefType[] optionExternalsFromExtKeys(Option option, str{} usageTypes=null) {
New: extend public <ExternalRefType, str>[] optionExternalsFromExtKeys(str{} usageTypes=null) {

The following method is renamed:

Old: extend public Bool dbg_forceDsApplyLogic() {
New: extend public Bool forceDsApplyLogic() {

class DsiApplyConstraintsEnv

The following field and method in DsiApplyConstraintsEnv is removed as they are no longer used:

// Field
Removed: public str[] syncGroupIds;

// method
Removed: final public void appendSyncGroupId(str id) {

Changes to DataObj class uniqueKey

In 17.0 Minor, a new method collectExportUniqueKey() was added as part of the improvements to catalogue DB3 format saving. The main intentions were to :

  • Collect uniqueKeys more efficiently and reduce memory usage.
  • Generate a shorter and more accurate unique string identifier for DataObj. These changes has improved performance during the DB3 saving process.

However, this resulted in two different unique key implementations for each DataObj subclass. Hence, we are consolidating both methods into a single source of truth.

When is migration required?

Migration is required if you have a custom DataObj subclass (e.g., DsPData) that overrides the uniqueKey() method. The migration steps are:

  • Move the uniqueKey generation logic from uniqueKey() to writeUniqueKey().
  • Respect the includeClassId flag if the class is part of the unique key. It is recommended to use class.id as it is usually shorter than class.name or class.toS.
  • Remove the uniqueKey() method from the class as it is no longer overridable.

Important note: Do not call uniqueKey() within writeUniqueKey() directly/indirectly and vice versa, as this will result in recursion.

If you encounter a compile error related to uniqueKey() calls, add the following use statement to package.cm.

use cm.abstract.dataSymInterface.catalog;

Interface changes related to uniqueKey

The following field in DsTableDataG2 class is renamed due to ambiguous naming:

Old: public str uniqueKey;
New: public str tableUniqueKey;

collectExportUniqueKey() in DataObj has been renamed to writeUniqueKey(), and is now an abstract method.

Old: extend public void collectExportUniqueKey(StrBuf b, bool includeClassId=true) { }
New: extend public void writeUniqueKey(StrBuf b, bool includeClassId=true) : abstract { }

For DataObj class and its subclasses:

  • collectExportUniqueKey() is now renamed to writeUniqueKey().
  • uniqueKey() is no longer abstract and is now final. It always generates and returns the unique key using writeUniqueKey().
  • uniqueKey() method is removed in all DataObj subclasses
Old: extend public str uniqueKey() : null="null", abstract {
New: final public str uniqueKey() : null="null" {

// In cm/abstract/dataSymInterface/catalog/dataObj.cm:

    /**
     * Unique key.
     * A unique key is used to uniquely identify this object from other objects.
     * 
     * (It's known to be used to prevent duplicate append to SQLite databases)
     */
    final public str uniqueKey() : null="null" {
		static StrBuf buf();
		buf.clear();
		writeUniqueKey(buf);
		return buf.toS();
    }


// cm.abstract.dataSymInterface.catalog
public class DsiAddProductRefType extends DsBaseCodeType {
public class DsAliasType extends DsBaseCodeType : unstreamable {
public class ApplicationAreaType extends DsBaseCodeType : unstreamable {
public class DsBaseCodeType extends DataObj : abstract {
public class DsBaseExternalRefType extends DsBaseCodeType : abstract {
public class DsBaseNameType extends DsBaseCodeType {
public class DsCardConfig extends DsBaseCodeType : unstreamable {
public class DsClassificationRefType extends DsBaseCodeType {
public class DsClassificationType extends DsBaseCodeType : unstreamable {
public class DsConnectorType extends DsBaseCodeType : unstreamable {
public class DsConnectorRefType extends DataObj : unstreamable {
public class DsConstraintTable extends DsBaseTableG2 {
public class DsCustomOptionType extends DsBaseCodeType {
public class DsCustomInquiryType extends DsBaseCodeType {
public class DsCustomProdDataTable extends DsBaseTableG2 {
public class DsCustomTable extends DsBaseTableG2 {
public class DsVersionPolicy extends DataObj : unstreamable {
public class DsWire extends DsBaseCodeType {
public class DsExternalRefKeyType extends DataObj : inherit constructors {
public class ExternalRefType extends DataObj : unstreamable {
public class PrdExternalRefType extends ExternalRefType {
public class OptExternalRefType extends ExternalRefType {
public class DsiFeatureRefType extends DsBaseCodeType {
public class SFeature extends DsProductType : unstreamable {
public class DsiLayoutDomainType extends DataObj {
public class DsiLayoutType extends DsProductType {
public class DsLeadTimeProgramType extends DsBaseCodeType : unstreamable {
public class MaterialQtyType extends DataObj : unstreamable {
public class SMaterial extends DsBaseExternalRefType : unstreamable {
public class DsMeasureParamType extends DsBaseExternalRefType {
public class MeasurementType extends DataObj : unstreamable {
public class MtrlApplication extends DataObj : unstreamable {
public class NamedPoint extends DataObj {
public class DsNoteType extends DataObj {
public class OFDAHeaderData extends DsBaseNameType : unstreamable {
public class OFDAHeaderData extends DsBaseNameType : unstreamable {
public class DsiCodeRangeType extends DataObj {
public class DsiOptionRangeType extends DsBaseCodeType {
public class Option extends DsProductType : unstreamable {
public class PlacementOriginType extends DataObj : unstreamable {
public class PlacementType extends DataObj : unstreamable {
public class PriceTypeSeq extends DataObj : unstreamable {
public class PriceType extends DataObj : unstreamable {
public class PricelistType extends DsBaseCodeType : unstreamable {
public class ProductCatalog extends DsBaseNameType : unstreamable {
public class ProductLevel extends DsBaseExternalRefType : unstreamable {
public class DsProductType extends DsBaseExternalRefType : unstreamable {
public class DsiRangeType extends DsBaseCodeType {
public class DsRuleType extends DsBaseCodeType {
public class DsSectionConfig extends DsBaseCodeType : unstreamable {
public class DsTableDataG2 extends DataObj {
public class DsTableType extends DsBaseCodeType {
public class DsTableHeadType extends DataObj {
public class DsTableRowType extends DataObj {
public class UsageType extends DataObj : unstreamable {
public class VersionType extends DataObj : unstreamable {

// cm.abstract.dataSymInterface
public class DataCatalog extends DataObj : unstreamable {
public class DataCatalogs extends DataObj : unstreamable {
public class DsiPData extends DataObj {
public class DsiPDataOption extends DataObj {
package class DsiPDataCustomOption extends DataObj : abstract {

// cm.abstract.dataSymbol.ui.libraryBuilder
public class DsCustomLibrary extends DataObj : unstreamable {
public class DsLibBuildDataObjSeq extends DataObj {
package class DsCustomLibraryType extends DsLibBuildDataObj : unstreamable {
public class DsLibNewLDataObj extends DsLibBuildDataObj {
public class DsLibBuildShrinkType extends DsCustomLibraryType {
public class DsLibBuildMultiMemBtnType extends DsLibBuildDataObj {
public class DsLibBuildMemBtnType extends DsLibBuildDataObj {
public class DsLibDisplayType extends DsLibBuildDataObj {
public class DsLibImageDisplayType extends DsLibBuildDataObj {
public class DsLibDataCatalogType extends DsLibBuildDataObj {
public class DsSymbolInfo extends DataObj {
public class DsLibraryData extends DataObj : unstreamable {
public class DsLibrarySearchData extends DataObj : unstreamable {
package class DsLibraryFavLibData extends DataObj : unstreamable {

// cm.abstract.materialHandling.data
public class MhPData extends DsPData : replacing load {

The following debug flag is removed as it is no longer relevant after the uniqueKey changes:

In cm/abstract/dataSymInterface/database/dsSqlExport.cm:

Removed: public bool dsiOptimizeDb3Export() {
Removed: public void dsiSetOptimizeDb3Export(bool v) {

Remove uninstalled catalogs

The following interface changes have been made to facilitate the functionality to remove related catalog files when an extension is uninstalled.

cm.abstract.dataSymInterface.registerCatalogs.cm

Old: public void extensionRegCatDB3File(int cid, str dbFileName, str catCode,
					function(Object o) completeCB=null,
					function(Object o) outOfDateCB=null) {
New: public void extensionRegCatDB3File(int cid, str dbFileName, str catCode,
					function(Object o) completeCB=null,
					function(Object o) outOfDateCB=null,
					symbol sourcePkg=#:package : caller eval) {
Old: public void dsiRegisterEmbeddedCatalog(int cid, str dbFile, str{} offlinePrdCatalogs=null, bool offlineTurnOnAll=false) {
New: public void dsiRegisterEmbeddedCatalog(int cid, str dbFile, str{} offlinePrdCatalogs=null, bool offlineTurnOnAll=false, symbol sourcePkg=#:package : caller eval) {
Old: public void dsiRegisterEmbeddedCatalog(int cid, str dbFile, str{} offlinePrdCatalogs=null,
					    bool offlineTurnOnAll=false, bool ignoreSyncCycle=false) {
New: public void dsiRegisterEmbeddedCatalog(int cid, str dbFile, str{} offlinePrdCatalogs=null,
					    bool offlineTurnOnAll=false, bool ignoreSyncCycle=false,
					    symbol sourcePkg=#:package : caller eval) {

Also some interfaces were updated in the cm.abstract.dataSymbol and cm.extension packages as part of this change. Please refer to the documentation for those changes as well.

Performance improvement for loading db3 files in catalog creator

We have updated the sql import functionality in catalog creator to leverage more caching to improve load performance.

The following interfaces have changed to facilitate this.

class DataCatalogDBWrapper

Old: extend public void recreateCollection(DataObj oh, int ownerID, Field f) {
New: extend public void recreateCollection(DataObj oh, int ownerID, Field f, str[] bufList) {
Old: extend public void recreateUnaryColl(UnaryCollection coll, Field f, DataObj oh, str refTable, int ownerID) {
New: extend public void recreateUnaryColl(UnaryCollection coll, Field f, DataObj oh, str refTable, int ownerID, str[] bufList) {
Old: extend public void recreateMap(BinaryCollection m, Field f, DataObj oh, str refTable, int ownerID) {
New: extend public void recreateMap(BinaryCollection m, Field f, DataObj oh, str refTable, int ownerID, str[] bufList) {

cm.abstract.dataSymbol

Part Measurements and Generic Codes

DsPrdMeasurementColumn now stores its measurement type as a string:

Old: public dsMeasurementType mType
Old: public str mTypeS
New: public str mType

Replace mTypeS reads with mType. Code that requires dsMeasurementType should convert the string with dsiStrToDsMeasurementTypeEnum().

Both constructors have a new optional package argument:

Old: public constructor(str mType)
New: public constructor(str mType, symbol pkg=null)

Old: public constructor(dsMeasurementType mType)
New: public constructor(dsMeasurementType mType, symbol pkg=null)

Added: public double dsUnitConvertFactor(distanceUnit distUnit, str mTypeS)

class DsPData

The following methods have been removed in DsPData class as they were deprecated or no longer in use.

Removed: public str->(str->(< double, double>)) propagateStretchInfo: copy=null, stream=null, deprecated;

Removed: public void postApplyConstraints(DsiApplyConstraintsEnv env) {
Removed: extend public void verifySyncGroupContainer(): deprecated {
Removed: extend public void specOption(DsSpecOption[] sOptions, Space space, Option o, DsPDataOption pDataOption, int level, bool choosableInCalculation) {
Removed: extend public bool trySetDsProp(Snapper snapper, SetSnapperPropertyEnv env) {
Removed: public str graphicalSpecialCacheKey(Object obj) {
Removed: extend public void generateAdditionalOptionRows(DsiPDataOption dataOpt|, DsPart part, SifEnv env, Space space, bool recurse=true) : deprecated {
Removed: extend public void generateOptionalNoOptionRows(SifEnv env, SFeature f, DsiPDataOption selOpt) {
Removed: extend public void generateOptionalSelOptionRows(SifEnv env, SFeature f, DsiPDataOption selOpt) : deprecated {
Removed: final public void generateSifOptionRows(SifEnv env, Option o, DsiPDataOption pO, int level=0) : deprecated {
Removed: extend public void clearPropagateStretchInfo() : deprecated {
Removed: extend public void updatePropagateStretchValue(str key, str stretchMeasureParam, double length, double delta) : deprecated {
Removed: extend public double propagateStretchValue(str key, str stretchMeasureParam) : deprecated {
Removed: extend public bool symStretch(SymHandle handle, PreCorePropObj owner, str measParam, bool stretchEP, point p, AnimationMouseInfo mi) {
Removed: extend public void apply(DsPData data) {

The following method has been renamed in DsPData class as part of the constraint changes in 17.5.

Modified:
Old: public Bool dbg_forceDsApplyLogic() {
New: public Bool forceDsApplyLogic() {

class DataSymbol

The following methods have been removed in DataSymbol class as they were deprecated or no longer in use. The method completeBuild() is now replaced by buildConnectors().

Removed: extend package DsConnector[] nodeConnectors() {
Removed: extend public bool nodeConnectorExists(point pos) {
Removed: extend public bool completeBuild(bool defaultMats=true) {

Some connector-related interfaces are now changed to public. Certain unused method arguments are also removed.

Old: extend public void buildConnectors(point{} pos, bool updateSpace) {
New: extend public void buildConnectors(bool updateSpace) {

Old: extend public void buildConnectors(point{} pos) {
New: extend public void buildConnectors() {

Remove uninstalled catalogs

The following interface changes have been made to facilitate the functionality to remove related catalog files when an extension is uninstalled.

cm.abstract.dataSymbol.registerCatalogs.cm

Old: public void registerDsEmbeddedCatalog(int cid, str dbFile, str{} offlinePrdCatalogs=null) {
New: public void registerDsEmbeddedCatalog(int cid, str dbFile, str{} offlinePrdCatalogs=null, symbol sourcePkg=#:package : caller eval) {

Also some interfaces were updated in the cm.abstract.dataSymInterface and cm.extension packages as part of this change. Please refer to the documentation for those changes as well.

cm.abstract.draw

The following legacy classes have been removed. We recommend migrating to one of the more recent measure animation classes such as CoreStraitDrawMeasureInsertAnimation, ChainDrawInsertAnimation or ChainDrawInsertAnimationStart.

If migration is not feasible, you will need to maintain your own local copies of the removed classes.

Removed: class CoreMeasureLineInsertAnimation
Removed: class CoreMeasureLineInsertAnimationLast
Removed: class CoreMeasureLineInsertAnimationStart
Removed: class CoreMeasureLineInsertVessel
Removed: class DrawChainMeasureInsertAnimation
Removed: class SingleChainDimInsertAnimation

class DrawMeasure

The forcedAngle parameter of the following methods has changed from Angle to Orientation. Existing calls that pass an angle value (for example, 5deg) still work: it is converted to an orientation around yaw. Update overrides, typed function references, and callers that need pitch or roll to use Orientation.

Old: extend public void setSpaceP0(point p, Angle forcedAngle=null, bool updateD=true) {
New: extend public void setSpaceP0(point p, Orientation forcedAngle=null, bool updateD=true) {
Old: extend public void setSpaceP1(point p, Angle forcedAngle=null) {
New: extend public void setSpaceP1(point p, Orientation forcedAngle=null) {

cm.abstract.materialHandling

MhPopupToolbarModelItem moved to core

The following classes have been moved from cm.abstract.materialHandling.ui to cm.core and have been renamed.

Old: MhPopupToolbarModelItem
New: PopupToolbarModelItem

Old: MhMultiTogglePopupInfo
New: MultiTogglePopupInfo

Old: MhMultiTogglePopup
New: MultiTogglePopupWindow

Old: MhMultiTogglePopupToolbarModelItem
New: MultiTogglePopupToolbarModelItem

Additionally, there have been several interface changes made to the classes within the class hierarchy. PopupToolbarModelItem has had any fields and logic related to on/off images moved down to the child class MhMultiTogglePopupToolbarModelItem. It is also no longer an abstract class.

Old:
public class MhPopupToolbarModelItem extends ToolbarModelItem : abstract {


New:
public class PopupToolbarModelItem extends ToolbarModelItem {
    Removed: private Image _onImage : copy=reference, public readable;
    Removed: private Image _offImage : copy=reference, public readable;


Old:
    extend public void showPopup(ContextualViewToolbarModel model) : abstract { }
New:
    extend public void showPopup(ContextualViewToolbarModel model) { }


Removed:
    extend public void syncImageToState(ContextualViewToolbarModel model) { }


Removed:
    extend public Image onImage() {


Removed:
    extend public Image offImage() {
}


public class MultiTogglePopupToolbarModelItem extends PopupToolbarModelItem {
    Added: private Image _onImage : copy=reference, public readable;
    Added: private Image _offImage : copy=reference, public readable;


    Old: public function(ToolbarModelItem, ContextualViewToolbarModel):MhMultiTogglePopupInfo[] infosCallback;
    New: public function(ToolbarModelItem, ContextualViewToolbarModel):MultiTogglePopupInfo[] infosCallback;


Added:
    extend public void syncImageToState(ContextualViewToolbarModel model) {


Added:
    final public Image onImage() {
    extend public Image defaultOnImage() {


Added:
    extend public Image offImage() {
    extend public Image defaultOffImage() {
}

MultiTogglePopup has had an unused constructor removed.

public class MultiTogglePopup extends Control {

Removed:
    public constructor(Window parent,
                       MhMultiTogglePopupInfo[] infos |, 
                       // Inherited arguments.
                       Font font=controlFont,
                       Brush brush=whiteBrush,
                       FrameStyle frameStyle=noFrame,
                       frame3DState frameState=frameStateDown,
                       pointI origin=(0, 0),
                       bool selectable=true,
                       pointI pos=(0, 0),
                       sizeI size=(0, 0),
                       pointI margins=(0, 0),
                       alignment align=middle,
                       ControlGroup group=null,
                       bool popup=true,
                       bool shadow=true,
                       str key=null,
                       SrcRef src=#:src) {
}


Replace with:
    public constructor(Window parent,
                       MultiTogglePopupInfo[] infos,
                       MultiTogglePopupToolbarModelItem item |, 
                       // Inherited arguments.
                       Font font=controlFont,
                       Brush brush=whiteBrush,
                       FrameStyle frameStyle=noFrame,
                       frame3DState frameState=frameStateDown,
                       pointI origin=(0, 0),
                       bool selectable=true,
                       pointI pos=(0, 0),
                       sizeI size=(0, 0),
                       pointI margins=(0, 0),
                       alignment align=middle,
                       ControlGroup group=null,
                       bool popup=true,
                       bool shadow=true,
                       str key=null,
                       SrcRef src=#:src) {

MhStorageConfiguration changes

Removed a duplicate UnitLoad unitLoad() method. Replace overrides to it with UnitLoad unitLoad(Object env=null) instead.

public class MhStorageConfiguration extends MhSystemConfiguration {

Removed:
    extend public UnitLoad unitLoad() {
        return getValue(cMhUnitLoadPK).?UnitLoad;
    }


Replace with:
    extend public UnitLoad unitLoad(Object env=null) {
        UnitLoad res = getValue(cMhUnitLoadPK, env=env).?UnitLoad;
        if (res) return res;

        for (compType in orderedCompartmentTypes()) {
            if (UnitLoad ul = compType.compProps.unitLoad) {
                return ul;
            }
        }

        return null;
    }
}

MhShelvingBayAdoptionBehavior changes

Updated interface for bool validLevelPosition(point2D levelPos) with a new Snapper owner argument.

public class MhShelvingBayAdoptionBehavior extends MhAdoptionBehavior {

Old:
    extend public bool validLevelPosition(point2D levelPos) {
New:
    extend public bool validLevelPosition(Snapper owner, point2D levelPos) {
}

MhSystemExportFunction changes

Updated interface for bool exportFailed(MhEngineEntry entry, box exportedBound) with a new StrBuf error=null argument.

public class MhSystemExportFunction extends MhSystemEngineFunction {

Old:
    public bool exportFailed(MhEngineEntry entry, box exportedBound) {
New:
    public bool exportFailed(MhEngineEntry entry, box exportedBound, StrBuf error=null) {
}

Unit load population changes

Changes have been made to support modifying the population direction of unit loads. MhUnitLoadConstructionalPopulateFunction has a new field Point populateOffset that can be passed in as an argument, using this field value in vector populateVector() if there is any. This field previously existed in the subclass MhDeepstorageUnitLoadConstructionalPopulateFunction but has now been moved here.

Point unitLoadPopulateVector is also a new field in MhEngineLevelConstructionEntryInfo so each level can have a different direction. MhLevelConstructionalPopulateFunction has been updated to check for this value of each level entry info and pass it into "unitLoadConstruction".

Multi-racking framework changes

In 17.0 Minor we added a new package cm.abstract.materialHandling.storage.multi that is meant to contain most of the code related to the multi-racking framework that utilizes multi-bays and multi-frames. In 17.5 Major we are further expanding on the framework as well as moving multi-racking related code from other packages into the multi package. This section mainly cover interface changes made to improve the multi-racking framework. For new features related to this, see the "Multi-racking framework changes" section in the New Features pages.

1. Moved code

The following classes have been moved from cm.abstract.materialHandling.storage to cm.abstract.materialHandling.storage.multi:

Behaviors:
MhMultiBayEngineBehavior
MhMultiBayStretchEngineBehavior
MhMultiSplitRowAnimationEngineBehavior

Engine:
MhMultiEntryArrangeFunction
MhMultiEntryUpdateShapeFunction
MhMultiEntryUpdateClassificationFunction

2. Engine functions changes

The following engine function keys have been modified. If you have implemented multi-racking, ensure you search your codebase for the following old keys and replace them.

Old: multiBayPopulate
New: multiBayConstruction
Now associated with class MhMultiBayConstructionalPopulateFunction

Old: frameConstruction
New: multiFrameConstruction
Now associated with class MhMultiFrameConstructionalPopulateFunction

MhMultiBayConstructionFunction has been renamed to MhMultiBayConstructionalPopulateFunction.

MhMultiBayConstructionalFunction has been removed. It is to be replaced with MhMultiBayConstructionalPopulateFunction.

MhMultiFrameConstructionFunction has been renamed to MhMultiFrameConstructionalPopulateFunction.

MhMultiFrameConstructionalFunction has been removed. It is to be replaced with MhMultiFrameConstructionalPopulateFunction.

Removed method in MhMultiFrameEntryConstructionArrangement double calculateSpacerZSpacing(MhSpacingItem spacingItem). This logic is now handled in MhSpacingItem method double calcZSpacing(double frameHeight).

3. Other changes

For MhMultiRowConfiguration, the implementation of calcDepthFromAisles(MhRowAnimationInfo info, int numAisles) has been moved into the method that was calling it, calcWidthFromAisles(MhRowAnimationInfo info, int numAisles).

public class MhMultiRowConfiguration extends MhStorageRowConfiguration {

Removed:
    extend public double calcDepthFromAisles(MhRowAnimationInfo info, int numAisles) {


Updated:
    public double calcWidthFromAisles(MhRowAnimationInfo info, int numAisles) {
        // need to reset from previous time rowLayout.current was used
        rowLayout.current = 0;

        double aisleW = info.aisleWidth;
        if (aisleW == 0) aisleW = aisleWidth().safeDouble;

        double firstRowDepth = rowDepth(rowLayout, first=true);
        double lastRowDepth = rowDepth(rowLayout, last=true);
        double overhang = rearOverhang().safeDouble;
        double systemD = (aisleW + firstRowDepth + lastRowDepth +
                          info.offsetLeft + info.offsetRight + overhang*2);

        if (numAisles > 1) {
            double middleRowDepth = rowDepth(rowLayout, middle=true);
            for (x in 1..numAisles - 1) {
                systemD += aisleW;
                systemD += middleRowDepth;
            }
        }

        return systemD + 0.01;
    }
}

MhSpacingItem has a new argument for its constructor used to set the frame spacer count.

public class MhSpacingItem extends MhFramelinePatternItem {

Old:
    public constructor(MhSystemConfiguration config, Double d=null) {
        ...
        frameSpacerCount = config.getValue(translateKey(cMhFrameSpacerCountPK)).?int;
    }


New:
    public constructor(MhSystemConfiguration config, Double d=null, Int spacerCount=null) {
        ...
        if (spacerCount) frameSpacerCount = spacerCount.v;
        else frameSpacerCount = config.getValue(translateKey(cMhFrameSpacerCountPK)).?int;
    }
}

Multi-bays are now also intended to hold the "bottom level" (level at z=0) to allow for unit load insertion on the floor. We updated bay config logic to work better with this. In bay config behavior, reduced the cases where false is returned for shouldPutConfigToManager. Previously for a child-bay, as long as the parent multi-bay had a level child it would not put the child-bay config into the manager. We have omitted the case where the parent multi-bay has a bottom level with no unit loads so child-bays will still be config owners for this case.

public class MhBayConfigBehavior extends MhStorageConfigBehavior {

Old:
    public bool shouldPutConfigToManager(MhSnapper z) {
        ?MhSnapper parent = z.parent;
        while (parent) {
            if (parent.getChildren(levelFilter).any) return false;
            ?parent = parent.parent;
        }
        if (!z.getChildren(levelFilter).any) return false;
        return super(..);
    }

New:
    public bool shouldPutConfigToManager(MhSnapper z) {
        // Check if parent has level (false if yes).
        ?MhSnapper parent = z.parent;
        while (parent) {
            Snapper{} children = parent.getChildren(levelFilter);
            for (child in children) {
                if (child.isBottom) { // If parent has bottom level with loads.
                    if (child as MhSnapper) {
                        if (child.snapperInfos.any or child.getChildren().any) {
                            return false;
                        }
                    }
                } else { // If parent has any other (non-bottom) level.
                    return false;
                }
            }
            ?parent = parent.parent;
        }

        // Check if bay has levels (false if no).
        if (!z.getChildren(levelFilter).any) {
            return false;
        }
        return super(..);
    }
}

Engine function key update

A typo has been fixed in a function key. If using the key systemColumGrouping in your codebase, ensure this is updated to systemColumnGrouping.

Old: systemColumGrouping
New: systemColumnGrouping

MhBayShape changes

Removed method void appendLevelBracketPrimitives(CollisionPrimitive{} prims, Transform t=null).

public class MhBayShape extends MhBoxSnapperShape {

Old:
    public CollisionPrimitive collisionPrimitive(MhCollisionFetchEnv env) {
        ...
        appendLevelBracketPrimitives(geos, env.?transform);
        appendTopApproachPrimitives(geos, env);
        return set;
    }

New:
    public CollisionPrimitive collisionPrimitive(MhCollisionFetchEnv env) {
        ...
        appendTopApproachPrimitives(geos, env);
        return set;
    }


Removed:
    extend public void appendLevelBracketPrimitives(CollisionPrimitive{} prims, Transform t=null) { // FIXME 17.5 remove
        /* CUT THIS OUT  Thu Apr 30 13:29:18 2026 /kenng
        // Dont let the level brackets go past first hole
        Layer bracketLayer = geometryLayer(owner, sLevelBracket);
        box bracketBound(rect(point2D0, w, d).grown(0.01), 0, holeStartZ - holePitch/2);
        CollisionPrimitive bracketPrim = mhGetBoxCollisionPrimitive(bracketBound, bracketLayer, t);
        prims <<? bracketPrim;//mhInstanceCollisionPrim(bracketPrim, null);
        * CUT THIS OUT /kenng */
    }
}

MhRowShape changes

Removed method bool buildRowEntryLayoutCheckExactMatch.

public class MhRowShape extends MhSnapperShape {

Removed:
    extend public bool buildRowEntryLayoutCheckExactMatch() {
        return false;
    }
}

MhBasePropsSchemeData changes

The class MhBasePropsSchemeData has been moved from cm.abstract.materialHandling.behavior to cm.abstract.materialHandling.storage.

Feature snapping changes

The class MhFSGridFeatureSearchSnapAlternative has been renamed to MhFeatureSearchSnapAlternative as it is no longer just used by MhFSGridRectInsertAnimationG2. It is now also used by MhRowInsertAnimation and MhRowInsertToolAnimationG2.

The class MhFSGridSpaceVolumeSnapperFilter has been renamed to MhActiveSpaceVolumeSnapperFilter.

These changes are to allow racking insert animation to feature snap to unmovable snappers as well as to set the animation's elevation to the feature points elevation.

Old: public class MhFSGridFeatureSearchSnapAlternative extends FeatureSearchSnapAlternative {
New: MhFeatureSearchSnapAlternative

Old: public class MhFSGridSpaceVolumeSnapperFilter extends ActiveSpaceVolumeSnapperFilter {
New: public class MhActiveSpaceVolumeSnapperFilter extends ActiveSpaceVolumeSnapperFilter {

MhSnapperAbsMezzEngineEntry changes

Removed method void removeSnapper(AbsMezzEngineEnvironment env, Snapper{} removed, Space space) as it was a duplicate method of a base class. Replace with bool removeSnapper(AbsMezzEngineEnvironment env, Space space).

public class MhSnapperAbsMezzEngineEntry extends AbsMezzForeignEngineEntry {

Removed:
    extend public void removeSnapper(AbsMezzEngineEnvironment env,
                                     Snapper{} removed,
                                     Space space) {}
}

Configuration tooltip changes

There were two methods for generating property tooltips for configuration tabs so we have combined them. MhStorageConfigurationItem method str getToolTip(PropObj propertyOwner, str key) has been removed and MhSystemConfigurationItem method str toolTip(str key, PropObj owner) has been renamed to str getToolTip(str key, PropObj owner). You should be overriding str getToolTip(str key, PropObj owner) for tooltip implementations.

public class MhSystemConfigurationItem extends CoreObject {

Old:
    extend public str toolTip(str key, PropObj owner) {
        return null;
    }

New:
    extend public str getToolTip(str key, PropObj owner) {
        return null;
    }
}

public class MhStorageConfigurationItem extends MhSystemConfigurationItem {

Removed:
    extend public str getToolTip(PropObj propertyOwner, str key) {
        return toolTip(key, propertyOwner);
    }
}

Catalog-excel compilation changes

Updated interfaces in MhExcelCatalogFactory. The creation of ToC and population of features have been decoupled from the writing of db file. MhExcelCatalogFactory is also now an abstract class.

public class MhExcelCatalogFactory : abstract {

Old:
    extend public void process(bool showProgress=true,
                               str startingSheetName=null,
                               bool createToC=false,
                               StrBuf error=null) {
                    ...
                    populateCatalog();
                    createDb(createToC);
    }


New:
    extend public void process(bool showProgress=true,
                               str startingSheetName=null,
                               bool writeDb=true,
                               bool createToC=false,
                               StrBuf error=null) {
                    ...
                    populateCatalog();
                    populateFeatures();
                    cat.updateDependencies();
                    if (createToC) finalizeToC();
                    if (writeDb) createDb();
    }


Old:
    extend public void createDb(bool createToC=false) {


New:
    extend public void createDb() {
}

Debugging

We have consolidated most of the existing MH debug dialogs into a single dialog. Each of the old dialogs now exist as a window (tab) in the new Debug Dialog.

See "MH Debug tools revamp" in the New Features page for more info.

The following public interfaces have been modified.

Old: void showMhDebugDialog(Window parent=null)
New: void showMhDebugDialog(Window parent=null, str selectToolsCardKey=null)

Added: MhDebugDialog mhDebugDialog()

If showMhDebugDialog is passed in a selectToolsCardKey, it will open the dialog to that specific tab. Any existing code to open a specific debug dialog should be updated to use this function instead. For example, replace dbg_showDebugBehaviorsDialog() with showMhDebugDialog(selectToolsCardKey=cDbgBehaviorStoreKey).

These are the list of keys we use for the debug windows described below.

public const str cDbgEngineTrackerKey = "dbgEngineTracker";
public const str cDbgEngineVisualiserKey = "dbgEngineVisualiser";
public const str cDbgClassViewerKey = "dbgClassViewer";
public const str cDbgBehaviorStoreKey = "dbgBehaviorStore";
public const str cDbgConfigManagerTrackerKey = "dbgConfigManagerTracker";
public const str cDbgLinkedNeighborsKey = "dbgLinkedNeighbors";
public const str cDbgConfigurationsKey = "dbgConfigurations";
  1. Behavior Debug

The following public interfaces have been modified.

Old: class DebugBehaviorsDialog
New: class MhDebugBehaviorStoreWindow

Removed: void dbg_showDebugBehaviorsDialog()
Removed: void showDebugBehaviorsDialog(Window parent=null)

Added: MhDebugBehaviorStoreWindow mhDebugBehaviorStoreWindow()

The TreeView used to represent the behavior debug window has been revamped. The TreeViewItems now have a shared base class MhDebugObjectItem that has a field Object obj to contain a reference object for the item to have a reference to the relevant object, similar to the previous MyObjectItem. For behaviors, the referenced object will now be MhBehaviorController instead of the Behavior object and assortments will now be MhAssortmentController.

Old: class MyBehaviorGroupItem
New: class MhDebugBehaviorGroupItem

Old: class MyObjectItem
New: class MhDebugObjectItem

Old: class MySpawnerItem
New: class MhDebugObjectItem

Old: class MyBehaviorItem
New: class MhDebugBehaviorItem

Removed: class MyEngineFunctionItem
  1. Class Viewer

The previously named "Debug Functions/Behaviors" is now the Class Viewer tab of the Debug Dialog.

The following public interfaces have been modified.

Old: class MhDebugMaterialHandlingDialog
New: class MhDebugClassViewerWindow

Removed: void dbg_showDebugMaterialHandlingDialog()

Added: MhDebugClassViewerWindow mhDebugClassViewerWindow()
  1. Config Tracker

The config tracker was a private class that has now been made public.

The following public interfaces have been modified.

Old: private class MhConfigManagerTrackerDialog
New: public class MhDebugConfigManagerTrackerWindow

Old: MhConfigManagerTrackerDialog mhConfigManagerTrackerWindow 
New: MhDebugConfigManagerTrackerWindow mhDebugConfigManagerTrackerWindow()

Removed: void showConfigManagerTracker()
  1. Configurations

Previously the Debug Configurations dialog had public interfaces to open it but was never added to the debug library. It is now a tab in the Debug Dialog.

The following public interfaces have been modified.

Old: class DebugConfigurationsDialog
New: class MhDebugConfigurationWindow

Old: class MyConfigurationGroupItem
New: class MhDebugConfigurationGroupItem

Old: class MyConfigurationItem
New: class MhDebugConfigurationItem

Removed: void dbg_showDebugConfigurationsDialog()
Removed: void showDebugConfigurationsDialog(Window parent=null)

Added: MhDebugConfigurationWindow mhDebugConfigurationWindow()
  1. Engine Tracker

This has been moved from cm.abstract.materialHandling.engine to cm.abstract.materialHandling.debug.

The following public interfaces have been modified.

Old: class MhEngineTrackerWindow
New: class MhDebugEngineTrackerWindow

Old: void updateEngineTrackers()
New: void mhDebugUpdateEngineTrackers(str event)

Removed: void showEngineTracker()

Added: str->MhDebugEngineFunctionTracker dbgEngineFunctionTrackers()
Added: void dbgRegisterEngineFunctionTracker(MhDebugEngineFunctionTracker eft)
Added: void dbgUnregisterEngineFunctionTracker(str key)
Added: MhDebugEngineTrackerWindow mhDebugEngineTrackerWindow

Old: class MhEngineFunctionTracker
New: class MhDebugEngineFunctionTracker
  1. Engine Visualiser

This has been moved from cm.abstract.materialHandling.engine to cm.abstract.materialHandling.debug.

The engine visualiser was a private class that has now been made public.

The following public interfaces have been modified.

Old: private class EngineVisualiserDialog
New: public class MhDebugEngineVisualiserWindow

Removed: void showEngineVisualiser()
Removed: void showEngineVisualiserFunctionSelectorWindow()

Old: void updateEngineVisualiser()
New: void updateEngineVisualiser(str event)

Old: DebugCollisionPrimitiveVisualizer
New: MhDebugCollisionPrimitiveVisualizer

Removed: MhEngineVisPopulatorData dbg_getPopulatorData()
Removed: void dbg_resetPopulatorData()

For updating populator data to be displayed in the visualiser, we no longer use dbg_getPopulatorData() and dbg_resetPopulatorData(). Instead a new cache MhDebugEngineVisEngineFuncDataCache dbg_getEngineVisFuncDataCache() has been introduced and this cache now holds the populator data. Use the below interfaces instead. This cache is also intended to hold other data related to engine functions for visualisation purposes, currently the other type of data being entries that failed to export.

Added: MhDebugEngineVisEngineFuncDataCache dbg_getEngineVisFuncDataCache()

Added: void dbg_resetEnginVisFuncDataCache()

Added:
public class MhDebugEngineVisEngineFuncDataCache {

    extend public MhDebugEngineVisPopulatorData getPopulatorData(Vector direction=null) {
        if (direction) {
            if (!populatorData) {
                populatorData = MhDebugEngineVisPopulatorData(direction.v);
            } else if (populatorData.populatorDirection != direction.v) {
                populatorData.populatorDirection = direction.v;
                populatorData.steps.?clear();
            }
        }
        return populatorData;
    }


    extend public void appendPopulatorData(Vector direction, MhDebugEngineVisStepData stepData) {
        getPopulatorData(direction).add(stepData);
    }
}
  1. Linked Neighbors

The global dbg_snapperLinks to enable snapper link 3D graphics drawn by the MhDebugLinksBehavior is now toggled whenever you open or close the Debug Dialog.

The following public interfaces have been modified.

Old: class DebugLinkDialog
New: class MhDebugLinkWindow

Removed: void dbg_showDebugLinkDialog()

Removed: void showDebugLinkDialog(Window parent=null)

Added: MhDebugLinkWindow mhDebugLinkWindow()

Old: class MyObjectItem
New: class MhDebugLinkItem

Aside from the new debug dialog, there are some other interface changes reltaed to debugging.

Removed global bool dbg_statelessCollCache and replaced with bool _spawnerBehaviorCollCacheEnabled. This is now exposed to the debug library toolbox as the toggle "Enable Spawner Behavior Collection Cache".

Removed: bool dbg_statelessCollCache
Added: bool mhSpawnerBehaviorCollCacheEnabled()
Added: bool mhEnableSpawnerBehaviorCollCache(bool v)

cm.abstract.mezzanine

AbsMezzEngineEntry changes

The function bool removeSnapper(AbsMezzEngineEnvironment env, Space space) has been moved from subclass AbsMezzConstructionEngineEntry to base class AbsMezzEngineEntry.

public class AbsMezzEngineEntry {

Added:
    extend public bool removeSnapper(AbsMezzEngineEnvironment env,
                                     Space space) {
        return false;
    }
}

AbsMezzStructureLinesGenerator changes

Removed deprecated methods.

public class AbsMezzStructureLinesGenerator {

Removed:
    extend public bool shouldOnlyGenerateSecondary(AShape2D shape) {
        if (env.engineEntries.empty) return false;

        AShape2D sh = shape.toPolyline();
        RectConcat rc();
        for (e in env.engineEntries) if (e) rc << e.bound.transformed(-env.spaceTransform).rect;
        rect r = rc.bound;
        
        rect sb = sh.bound();
        return sb.coveredBy(r);
    }


Removed:
    final public void generateOuterLines(line[] res, AShape2D shape, angle dir, double extLength=0, double offset=0, double threshold=0) : inline {
        APolyline2D[] shapes = mezzToPolyline2D(shape);

        bool clockwise = shape.clockwise;
        for (sh in shapes) {
            if (first) clockwise = sh.clockwise;

            AShape2D osh = sh.mezzGrow(clockwise xor !sh.clockwise ? -offset : offset);
            AGeometry2D[] geos = osh.explode();
            line2D refLn = line2D((0, 0), dir, 1);

            //bool outline = clockwise == sh.clockwise;
            for (ALine2D g in geos) {
                line2D ln = g.v;
                if (ln.isParallel(refLn)) {
                    if (angle(ln.direction()) != dir) swap(ln.p0, ln.p1);
                    if (accepts(res, ln, threshold)) res << line(ln, 0);
                }
            }
        }
    }
}

Renamed constant

The constant cAbsMezzTransverse has been renamed to cMezzTransverse.

Removed class MezzXDistanceSnapperFilter

The class MezzXDistanceSnapperFilter has been removed.

cm.abstract.mhLibrary

class MhLibDataSymbol

The following method is modified followed by changes in DataSymbol class.

Old: public void buildConnectors(point{} pos, bool updateSpace) {
New: public void buildConnectors(bool updateSpace) {

Removed constant

Removed constant absMhLibConvSideSnapRule. Replace with acConvSideAccessoryRule from cm.abstract.conveyors.

cm.abstract.office

Extensible Type Elevation Merging

The change is additive, so most subclasses require no source updates. A subclass that already declares a member named collectMergers may now conflict with or override the inherited method. If the method is intended to customize merging, update it to the compatible signature:

extend public void collectMergers(TypeElevation{} mergers)

Otherwise, rename the existing member to avoid the inherited interface.

cm.abstract.part

Query Dialog Sidebar and Model Import

The part import window has been renamed and now derives from the tab-window API:

Old: public class ProdPartQueryImportWindow extends QueryImportWindow
New: public class QueryProdPartImportTabWindow extends QueryPartImportTabWindow

Update references and subclasses to use QueryProdPartImportTabWindow.

Part import customization has moved from ProdPartQueryDialogBehavior to the new QueryProdPartImportTabBehavior:

Added: public QueryProdPartImportTabBehavior prodPartImportTabBehavior()
Added: public class QueryProdPartImportTabBehavior extends QueryPartImportTabBehavior

Removed: public SubWindow initImportWindow(QueryDialog dialog, Url url=null) // from ProdPartQueryDialogBehavior
Added: public QueryPartImportTabBehavior queryPartImportTabBehavior() //  to ProdPartQueryDialogBehavior

Overrides of getImporterEnv(), beginGridDragAnimation(), or getValidDragRanges() must move to a QueryProdPartImportTabBehavior subclass. Return that behavior from an overridden ProdPartQueryDialogBehavior.queryPartImportTabBehavior().

Part Dimensions and Special Creation

The following physical-measurement methods are now defined on AbsPart:

Added: extend public double volume()
Added: extend public double depth()
Added: extend public double height()
Added: extend public double width()

These methods return meters and are distinct from the renamed Part.maxDepth() hierarchy method documented under cm.core.part.

ProdPartCreator has a new optional constructor argument and extension points:

Old: public constructor(PartData data, PartOption[] options=null)
New: public constructor(PartData data, PartOption[] options=null,
                        customizationType optionHandling=customizationType.none)

Added: public customizationType optionHandling
Added: extend public void processOverrideOptions(ProdPart part)
Added: extend public void processAdditionOptions(ProdPart part)
Added: extend public CustomOptionSpecial createCustomOptionSpecial(Part part, PartOptionItem opt)
Added: public bool containsAnySpecials(PropObj s)

ProdPartQueryDialogBehavior.queryPartImportTabBehavior() now requires a QueryDialog argument, matching the corresponding cm.core.part.query API.

cm.abstract.unitLoad

Unit load interface changes

Removed deprecated functions.

public color[] wongColorPallet() : deprecated {
    return wongColorPalette();
}


public color[] tolColorPallet() : deprecated {
    return tolMutedColorPalette();
}

Removed unused constant cMhJPPalletGroupKey. Replaced with cMhAPACPalletGroupKey.

Removed deprecated method in UnitLoad. Use str cacheKey3D(Object owner, FetchEnv3D env) instead.

public class UnitLoad extends CoreObject {

Removed:
    extend public Object[] cacheKey3DArgs(Object owner, FetchEnv3D env) : deprecated {
        Object[] args();
        args << env.detail;
        args << env.reason;
        //args << gid;
        for (k, v in getPropsWithAttribute(#gfx)) args << v;
        return args;
    }
}

Removed deprecated method in UnitLoadDialog. Use CoreObject{} getAffectedObjects(UnitLoad[] unitLoads) and bool usesLoad(CoreObject obj, UnitLoad[] unitLoads) instead.

public class UnitLoadDialog extends DialogWindow {

Removed:
    extend public CoreObject{} getAffectedObjects() : deprecated {
        return getAffectedObjects(null);

        /* CUT THIS OUT  Wed Oct 30 11:31:42 2024 /kenng
        CoreObject{} affected();
        for (s in mainWorld.?spaces) {
            forSnappersAndChildren (snapper in s) {
                if (!snapper.isSystemSnapper and snapper.isComponentSnapper) {
                    if (hasLoad(snapper)) affected << snapper;
                }
            }

            for (v in s.vessels) if (hasLoad(v)) affected << v;
        }
        
        return affected;
        * CUT THIS OUT /kenng */
    }

Removed:
    extend public bool hasLoad(CoreObject obj) : deprecated {
        return hasUnitLoad(obj);
    }
}

Removed deprecated method in UnitLoadPallet. use Primitive3D outerBoards3D(Object owner, FetchEnv3D env, double th) instead.

public class UnitLoadPallet extends UnitLoad {

Removed:
    extend public Primitive3D outerBoards3D(Object owner, FetchEnv3D env) : deprecated {
        return outerBoards3D(.., topBoardTh/2);
    }
}

cm.core

Split-view Resource Label

The $twoViewsMenuLabel resource has been removed. Use $horizontalViewsMenuLabel or $verticalViewsMenuLabel according to the layout.

Removal of Legacy Contextual View-Switch Toolbar Models

Legacy 2D and 3D toolbar model classes were removed, and split-view switching now requires an explicit layout orientation.

cm.core.contextual2DViewToolbarModel

The following class has been removed as part of Removal of Legacy 2D and 3D Contextual View-Switch Toolbar Models effort:

Removed: public class ContextualMultiViewSettingsModel extends ViewSettingsToolbarModel
Removed: public class ContextualMultiPopupViewSettingsModel extends ViewSettingsToolbarModel
Removed: public class Contextual2DViewSettingsModel extends ViewSettingsToolbarModel

actualSwitchToSplitView() now requires the desired orientation:

Old: actualSwitchToSplitView()
New: actualSwitchToSplitView(multiViewState.horizontal); // 2D above 3D
New: actualSwitchToSplitView(multiViewState.vertical);   // 2D left of 3D

cm.core.contextual3DViewToolbarModel

The following class has been removed as part of Removal of Legacy 2D and 3D Contextual View-Switch Toolbar Models effort:

Removed: Contextual3DViewSettingsModel

View changes should instead be initiated through MultiViewArea.switchState(..) or actualSwitchToSplitView(..) as appropriate.

Split-View Orientation and Divider Interface Changes

Split-view enum values and divider fields were updated to support distinct horizontal and vertical layouts, while deprecated view states were removed.

cm.core.multiViewArea

Previously, the existing top/bottom layout was represented by multiViewState.vertical, which caused confusion about whether the name described the divider or the arrangement of the views. The naming has now been standardized and any code using multiViewState.vertical for the original top/bottom layout must be updated to multiViewState.horizontal. If the desired view state is left/right, then multiViewState.vertical should be used.

The existing split-view enum and divider field were renamed to identify them explicitly as horizontal-layout interfaces:

Old: drawingViewType.viewSplit
New: drawingViewType.viewHorizontalSplit

Old: MultiViewArea.dragDivider
New: MultiViewArea.horizontalDragDivider

Use the new drawingViewType.viewVerticalSplit value and MultiViewArea.verticalDragDivider field when working with the left/right layout.

The following deprecated multiViewState enum values have been removed and have no direct replacement:

Removed: multiViewState.verticalPaper2D
Removed: multiViewState.verticalPaper3D
Removed: multiViewState.vertical3D
Removed: multiViewState.horizontal3D

cm.core.spaceVolume

Combined functions of the name spaceVolumeUpdateObjects. Use the function spaceVolumeUpdateObjects(Snapper z, vector u, SnapperFilter filter=null, bool undoable=true, Snapper{} visited=new Snapper{}, bool force=false) that has an additional SnapperFilter filter=null argument.

Old:
public void spaceVolumeUpdateObjects(Snapper z, vector u, bool undoable=true,
				     Snapper{} visited=new Snapper{}, bool force=false) {
    spaceVolumeUpdateObjects(z, u, filter=null, undoable=undoable, visited=visited, force=force);

Old:
public void spaceVolumeUpdateObjects(Snapper z, vector u, SnapperFilter filter, bool undoable=true,
				     Snapper{} visited=new Snapper{}, bool force=false) {

New:
public void spaceVolumeUpdateObjects(Snapper z, vector u, SnapperFilter filter=null, bool undoable=true,
				     Snapper{} visited=new Snapper{}, bool force=false) {
}

Preserving Part Adjustments When Resetting Item Tags

The following public interfaces have been added:

Added: extend public Part[] Snapper.rawParts()
Added: extend public bool Snapper.resetPartItemTagInfos()
Added: public bool TaggableSnapper.resetPartItemTagInfos()
Added: public int askUserAdjustedPartMigration(Part[] adjustedParts)

Snapper.resetPartItemTagInfos() returns true by default. Custom snappers can override it to perform their own part-tag reset preparation or return false to cancel the surrounding item-tag reset.

cm.core.part

Query Dialog Sidebar and Model Import

QueryDialog no longer exposes a generic right-side window. Use the tab API instead:

Removed: public SubWindow rightWindow;
Removed: extend public SubWindow rightWindow();

Added: public QueryTabContainer tabContainer;
Added: extend public str activeTabKey();
Added: extend public QueryTabWindow activeTab();
Added: extend public void openTab(str key);
Added: extend public void closeActiveTab();

The old import window has been renamed and now participates in the tab framework:

Old: public class QueryImportWindow extends QuerySubWindow
New: public class QueryPartImportTabWindow extends QueryTabWindow

Old: extend public void setImportFileUrl(Url url)
New: extend public void setImportFileUrl(Url url, bool invokeCb=true)

The constructor no longer accepts an initial Url. Pass fileFilters when constructing the tab, then call setImportFileUrl() if an initial file is needed.

Part-import methods formerly overridden on QueryDialogBehavior have moved to QueryPartImportTabBehavior. This includes file-filter and importer factories, validation and cleanup, file-change handlers, and grid drag/drop handling. Migrate custom overrides to a QueryPartImportTabBehavior subclass and return it from queryPartImportTabBehavior():

public class MyPartImportTabBehavior extends QueryPartImportTabBehavior {
    public <str, str>[] getImportFileLabelsAndSuffixes() {
        return super(..) + [<"My Parts", "*.myparts">];
    }
}

public class MyQueryDialogBehavior extends QueryDialogBehavior {
    public QueryPartImportTabBehavior queryPartImportTabBehavior() {
        return MyPartImportTabBehavior();
    }
}

The following QueryDialogBehavior entry points have been replaced by the tab API:

Removed: extend public SubWindow initImportWindow(QueryDialog dialog, Url url=null)
Removed: extend public void initImportWindowEvents(SubWindow importWindow)
Removed: extend public SubWindow rightWindow(QueryDialog dialog)

Added: extend public QueryTabBehavior[] tabBehaviors()
Added: extend public QueryPartImportTabBehavior queryPartImportTabBehavior()
Added: extend public QueryModelImportTabBehavior queryModelImportTabBehavior()
Added: extend public SubWindow activeTab(QueryDialog dialog)

QueryControlWindow.importButton and its importBtnClicked event have been removed. Open the part-import tab with dialog.openTab(corePartImportTabBehavior().key()), or provide the desired tabs through QueryDialogBehavior.tabBehaviors().

The QuerySubWindow constructor now exposes the standard window arguments. Calls that passed a brush positionally must switch to a named argument because the second positional argument is now Font:

Old: QuerySubWindow(parent, myBrush)
New: QuerySubWindow(parent, brush=myBrush)

QuerySubWindow now calls the new overridable initEvents() method during construction. Subclasses should override that method for event wiring and call super(..) where appropriate.

Part Hierarchy Depth and Physical Dimensions

The recursive hierarchy-depth method on Part has been renamed so AbsPart.depth() can represent a physical measurement:

Old: final public int Part.depth()
New: final public int Part.maxDepth()

Replace calls that inspect the deepest child level with maxDepth(). Do not replace physical-dimension calls: AbsPart.depth() is a separate double value measured in meters.

Generic Part Codes and Export Data

The following interfaces have been added:

Added: public str BasicPartData._genericCode
Added: public str BasicPartData.genericCode()
Added: public void BasicPartData.setGenericCode(str value)
Added: extend public str PartData.genericCode()
Added: extend public void PartData.setGenericCode(str value)
Added: extend public str Part.genericCode(Space space=null)
Added: extend public str Part.adjustedGenericCode(Space space=null)
Added: extend public str PartProxy.genericCode(Part part)
Added: extend public PartTag Part.tag(str categoryLbl, World world=null, bool ignoreCase=false)

The OFDA hooks xmlMeasurements(str prefix, XmlStreamBuf buf) and xmlUserDefined(str prefix, XmlStreamBuf buf) have moved from ProdPart to the base Part class. A new xmlMeasurement() helper writes a measurement value and its type, system, and unit attributes.

Query Dialog API Follow-up

Query tab factories now receive their owning dialog. Update overrides and direct calls:

Old: extend public QueryTabBehavior[] tabBehaviors()
New: extend public QueryTabBehavior[] tabBehaviors(QueryDialog dialog)

Old: extend public QueryPartImportTabBehavior queryPartImportTabBehavior()
New: extend public QueryPartImportTabBehavior queryPartImportTabBehavior(QueryDialog dialog)

Old: extend public QueryModelImportTabBehavior queryModelImportTabBehavior()
New: extend public QueryModelImportTabBehavior queryModelImportTabBehavior(QueryDialog dialog)

The first argument to alignCenterY() is now the reference window rather than part of the rest sequence:

Old: public void alignCenterY(rest: Window[] controls)
New: public void alignCenterY(Window this, rest: Window[] controls)
Added: public void alignCenterX(Window this, rest: Window[] controls)
Added: public void alignCenter(Window this, rest: Window[] controls)

Part Owner Identification

BasicPartData

Old: public Snapper snapper : copy=reference;
New: private PartSourceInfo _sourceInfo : copy=reference;
Old: public void setOwner(Snapper z) 
New: public void setSourceInfo(PartSourceInfo info) {
Old: public Snapper owner()
New: public PartSourceInfo sourceInfo()
Old: public Snapper{} owners()
New: public PartSourceInfo{} sourceInfos() 

All direct access of the snapper field have been changed to owner method.

FlattenedPartData

Old: public Snapper{} snappers : copy=shallow;
Old: private str{} _sourceIds;
New: private PartSourceInfo{} _sourceInfos;
Old: public Snapper{} owners()
Old: final public str{} sourceIds()
New: public PartSourceInfo{} sourceInfos()
Old: final private void appendOwnersFrom(PartData data)
New: final private void appendSourceInfosFrom(PartData data)

Part

Removed:  private str _sourceId; // sourceId is stored on PartData now.
Added: extend public PartSourceInfo{} sourceInfos()

PartData

Added: extend public void setSourceInfo(PartSourceInfo info) : abstract
Added: extend public PartSourceInfo sourceInfo() : abstract
Added: extend public PartSourceInfo{} sourceInfos() : abstract
Added: extend public void setSourceId(str id)
Added: extend public str sourceId()
Added: extend public str{} sourceIds() 

The following methods have been updated to use PartSourceInfo and are no longer abstract

extend public void setOwner(Snapper z)
extend public Snapper owner()
extend public Snapper{} owners() 

Preserving Part Adjustments When Resetting Item Tags

The following public interfaces have been added:

Added: public bool Part.blockAdjustmentMigration
Old: final public void Part.migrateAdjusmentKeys(str oldKey)
New: final public void Part.migrateAdjusmentKeys(str oldKey, bool markOldPending=false)
Added: final public str Part.userItemTagInfoKey()
Added: extend public ItemTagInfo Part.userItemTagInfo()
Added: extend public ItemTagInfo Part.defaultItemTagInfo(bool putToWorld=false)
Added: final public bool SinglePartAdjustment.pendingSilentRemoval()
Added: final public void SinglePartAdjustment.markPendingSilentRemoval(bool value)
Added: public str untokenizedArticleCodeStr(Part[] parts, str breakS)
Added: public Part[] adjustedParts(Part[] parts, bool updatePartTags=true, Space space=null)
Added: public Part[] indTagModifiedParts(Part[] parts)

Existing one-argument calls to migrateAdjusmentKeys() remain valid. Pass markOldPending=true when the old adjustment may still be used by another flattened part; CET will remove it silently once it is no longer active.

cm.core.part.query

Multiline Query and Article View Text

The public description control on PartMakeSpecialDialog has changed type:

Old: public FormattedTextField descrTF;
New: public FormattedTextArea descrTF;

Code that replaces, stores, or passes descrTF as a FormattedTextField must use FormattedTextArea or a compatible common control type. For example, subclasses that replace the control should migrate their initialization:

Old: descrTF = FormattedTextField(this,
                                  font=smallSystemFont,
                                  frameStyle=flatFrame);

New: descrTF = FormattedTextArea(this,
                                 font=smallSystemFont,
                                 frameStyle=flatFrame,
                                 lineBreak=true);

cm.extension

Timeout changes for CET updates

bgInstallHost.cm

Added new arguments to the abortAfterTimeout method in the BgInstallHost class.

Old: final public void abortAfterTimeout() {
New: final public void abortAfterTimeout(bool failed=false) {

Also some interfaces were updated in the cet.runtime package. Please refer to the documentation for those changes as well.

Remove uninstalled catalogs

The following interface changes have been made to facilitate the functionality to remove related catalog files when an extension is uninstalled.

class EmbeddedCatalogHost

Old: extend public EmbeddedCatalogInfo dequeueCatalogToRegister() {
New: extend public <symbol, EmbeddedCatalogInfo> dequeueCatalogToRegister() {

Also some interfaces were updated in the cm.abstract.dataSymInterface and cm.abstract.dataSymbol packages as part of this change. Please refer to the documentation for those changes as well.

cm.format.xml

XML Short-Tag Attributes

The XmlStreamBuf.shortTag() overloads now accept optional XML attributes:

Old: final public void shortTag(str tag, str value)
New: final public void shortTag(str tag, str value, <str, str>[] args=null)

Old: final public void shortTag(str tag, int value)
New: final public void shortTag(str tag, int value, <str, str>[] args=null)

Old: final public void shortTag(str tag, double value)
New: final public void shortTag(str tag, double value, <str, str>[] args=null)

Each tuple in args is written as an attribute name and value. Existing two-argument calls retain their previous output.

Example:

buf.shortTag("Measurement", 1.25,
             [<"type", "width">, <"unit", "meter">]);

cm.recovery

More specific error reports

The following interfaces have been changed to facilitate better categorization and more information for crash reports now.

cm.recovery.recoveryBits.cm

Old: public void sendBitsBugReport(str subject=null, Url drawing=null, Window parent=null) {
New: public void sendBitsBugReport(ErrorDialogArgs args=null, str subject=null,
			      Url drawing=null, Window parent=null,
			      str stackTrace=null, CallStack callStack=null) {
Old: public void sendFeedbackReport(ErrorDialogArgs errorDialogArgs=null, bool forceCrash=false) {
New: public void sendFeedbackReport(ErrorDialogArgs errorDialogArgs=null) {

For crash reports use sendBitsCrashReport reports instead.

cm.statistics

statsPartsDB.cm

Added new arguments for the PartEntryOption constructor to support part anlytics for Material Portal Textile manufacturers.

Old: public constructor(str code, str description, str groupDescription=null, int level=1) {
New: public constructor(str code, str description, str groupDescription=null, int level=1,
			str mMatPortalCompanyId=null, str mMatPortalCompanyCode=null,
			str matPortalSku=null) {

Also some interfaces were updated in the cm.win package as part of this change. Please refer to the documentation for those changes as well.

cm.std.draw3D

The following classes have been removed because they are no longer used in the base repository. Most were legacy implementations or experimental code and were not intended for public use.

If your project depends on any of these classes, you will need to maintain your own local copies.

Removed: class AFaceAnonymousOwner
Removed: class AFaceConeOwner
Removed: class AFaceCylinderOwner
Removed: class AFaceDoubleOwner
Removed: class AFaceFaceOwner
Removed: class AFaceNurbOwner
Removed: class AFaceOwner
Removed: class AFaceSphereOwner
Removed: class AOwnedQuadeFace
Removed: class AOwnedTriFace
Removed: class AngleDraw3DMeasureInsertAnimation
Removed: class BaselineDimensionInsertAnimationG2
Removed: class ChainDraw3DMeasureFilter
Removed: class ChainDrawRemoverAnimation
Removed: class DiagonalDraw3DMeasureInsertAnimation
Removed: class Draw3DBox
Removed: class Draw3DConvertToSolid
Removed: class Draw3DEdgeMeshHelper
Removed: class Draw3DFace
Removed: class Draw3DFaceMeshHelper
Removed: class Draw3DMeasureLineChainInsertAnimation
Removed: class Draw3DMeshEditor
Removed: class Draw3DMeshHelper
Removed: class Draw3DMeshStretchAnimation
Removed: class Draw3DMixedLine
Removed: class Draw3DNurbs
Removed: class Draw3DNurbsCPConnector
Removed: class Draw3DPolyMixedLineInsertAnimation
Removed: class Draw3DProfile
Removed: class Draw3DProfileArcTangent
Removed: class Draw3DProfileEditor
Removed: class Draw3DProfileEditorAdd
Removed: class Draw3DProfileEditorMove
Removed: class Draw3DProfileEditorRemove
Removed: class Draw3DProfileEditorToggle
Removed: class Draw3DProfileGrab
Removed: class Draw3DProfileGrabEdge
Removed: class Draw3DProfileGrabVertex
Removed: class Draw3DProfileSnapper
Removed: class Draw3DProfileSnapperFilter
Removed: class Draw3DRevisionCloudInsertAnimation
Removed: class Draw3DRevisionCloudPaperInsertAnimation
Removed: class Draw3DSolid
Removed: class Draw3DSolidData
Removed: class Draw3DSolidStretchBox
Removed: class Draw3DSolidStretchObject
Removed: class Draw3DVertexMeshHelper
Removed: class DrawBoxEdgeDepthInsertAnimation
Removed: class HorizontalDraw3DMeasureInsertAnimation
Removed: class MeshSolidData
Removed: class ProfileSnapperFilter
Removed: class SolidSnapperFilter
Removed: class StaticHorizontalDraw3DMeasure
Removed: class StaticHorizontalVerticalDraw3DMeasure
Removed: class StaticHorzVertDrawMeasureInsertAnimation
Removed: class StaticVerticalDraw3DMeasure
Removed: class SweepSolidData
Removed: class ThickProfileSolidData
Removed: class VerticalDraw3DMeasureInsertAnimation

The following classes have been deprecated because they are no longer used in the base repository. They will be removed in a future release.

public class DiagonalDraw3DMeasure extends Draw3DMeasure : deprecated {
public class Draw3DMeasureLine extends Draw3DMeasureBase : deprecated {
public class Draw3DMeasureLineChain extends Draw3DMeasureLine : deprecated {
public class Draw3DMeasureLineEndSnap extends Draw3DMeasureLineSnap : deprecated {
public class Draw3DMeasureLineStartSnap extends Draw3DMeasureLineSnap : deprecated {
public class SingleChainDraw3DMeasure extends ChainDraw3DMeasure : deprecated {

The following class interfaces have had their visibility limited.

Old: public class Draw3DMeasureLineAnimation extends DrawStretchAnimation {
New: private class Draw3DMeasureLineStretchAnimation extends DrawStretchAnimation {
Old: public class Draw3DMeasureLineStartSnap extends Draw3DMeasureLineSnap {
New: package class Draw3DMeasureLineStartSnap extends Draw3DMeasureLineSnap : deprecated {
Old: public class Draw3DMeasureLineEndSnap extends Draw3DMeasureLineSnap {
New: package class Draw3DMeasureLineEndSnap extends Draw3DMeasureLineSnap : deprecated {

The following functions have been removed because they are no longer used in the base repository.

Removed: public AFaceOwner getOwner(AFace z) {
Removed: public Draw3DProfile profile(Snapper z) {
Removed: public Transform transform(Snapper z, line mouseLine) {
Removed: public point intersectP(Snapper z, line mouseLine, Transform it=null) {

The following variables have been removed because they are no longer used in the base repository

Removed: public bool transparentSolids = false;

class StaticDraw3DMeasure

Renamed some interfaces to make them applyable to both 2D and 3D.

Old: public bool isUpdateAssoc2D : copy=null, stream=null, ignore modify notice;
New: private bool _assocPosInvalidated : copy=null, stream=null, public readable, ignore modify notice;
Added: final public void invalidateAssocPos() { _assocPosInvalidated = true; }
Old: extend public void updateAssoc2D(bool force=false) {
New: extend public void invalidateGraphicsAfterAssocChange(bool force=false) {

StaticDraw3DMeasure now uses dimensionAlignment instead of the old dimAlignType property to indicate direction and what to measure. The old type only described 2D layout as horizontal, vertical, or diagonal. dimensionAlignment also works for 3D dimensions.

A dimensionAlignment value has two parts: what the dimension measures, and which direction the dimension legs extend in. For the old 2D values, use these replacements:

dimAlignType.diagonal -> dimensionAlignment.euclideanLocalY
dimAlignType.horizontal -> dimensionAlignment.deltaXGlobalY
dimAlignType.vertical -> dimensionAlignment.deltaYGlobalX

Some references to the old type still exist on ChainDraw3DMeasure for backwards compatibility, but the underlying static-measure mechanism now uses dimensionAlignment.

The following definitions were removed or replaced:

Removed: extend public void updateRot(dimAlignType value) {
Removed: extend public void setMinLegLength(double length) {
Old: quick property `dimAlignType "dimAlign"`
New: quick property `dimensionAlignment "dimensionAlignment"`
Added: extend public dimensionAlignment currentDimensionAlignment() {

Calls or overrides of updateRot(dimAlignType) and setMinLegLength must be updated. For association changes, replace setting isUpdateAssoc2D with invalidateAssocPos(), and replace calls to updateAssoc2D() with invalidateGraphicsAfterAssocChange() at the prior refresh point. There is no public readable replacement for isUpdateAssoc2D.

class DimensionInsertAnimation

The standard dimension insertion path now uses DimensionInsertAnimation for both 2D and 3D. Code that checks for subclasses or configures the old static/two-click insertion animations should be reviewed. The old TwoClickMeasureInsertAnimationStart class remains available for compatibility, but the standard toolbox and key bindings now start DimensionInsertAnimation with numClicks=2 or numClicks=3.

The new common animation inserts StaticDraw3DPowerMeasure by default. If an extension derives a dimension class and uses this insertion path, override instantiateNewDimension() in a derived animation so that a new dimension of the extension's class is created:

public DrawMeasure instantiateNewDimension() {
    MyDimension dim();
    dim.d = getInitialLineLength();
    return dim;
}

library.cm

Removed unused function.

Removed: public Library stdDraw3DLibrary() {

cm.std.print.template

The following classes have been removed because they are no longer used in the base repository. Most DrawTemplate<..> classes were near-identical duplicates of the corresponding Draw<..> classes in cm.std.draw3D, and we recommend using those instead. For example, replace DrawTemplate3DArc with Draw3DArc.

If migration is not feasible, you will need to maintain your own local copies of the removed classes.

Removed: class DiagonalDrawTemplate3DMeasure
Removed: class Draw2DRefPointVessel
Removed: class DrawStretchablePolylineInsertAnimationG2
Removed: class DrawTemplate3D2SidedDoubleRect
Removed: class DrawTemplate3D2SidedDoubleRectEdgeDepthInsertAnimation
Removed: class DrawTemplate3D2SidedRect
Removed: class DrawTemplate3D2SidedRectEdgeDepthInsertAnimation
Removed: class DrawTemplate3D3SidedDoubleRect
Removed: class DrawTemplate3D3SidedDoubleRectEdgeDepthInsertAnimation
Removed: class DrawTemplate3D3SidedRect
Removed: class DrawTemplate3D3SidedRectEdgeDepthInsertAnimation
Removed: class DrawTemplate3DArc
Removed: class DrawTemplate3DArc2LineInsertAnimation
Removed: class DrawTemplate3DArc3PointsInsertAnimation
Removed: class DrawTemplate3DArcRadiusAngleInsertAnimation
Removed: class DrawTemplate3DArcTangentAngleInsertAnimation
Removed: class DrawTemplate3DBackgroundRect
Removed: class DrawTemplate3DBackgroundRectEdgeDepthInsertAnimation
Removed: class DrawTemplate3DBackgroundRectEdgeDiagonalInsertAnimation
Removed: class DrawTemplate3DBox
Removed: class DrawTemplate3DCircle
Removed: class DrawTemplate3DCircleDiameterInsertAnimation
Removed: class DrawTemplate3DCircleRadiusInsertAnimation
Removed: class DrawTemplate3DDoubleArc
Removed: class DrawTemplate3DDoubleArc2LineInsertAnimation
Removed: class DrawTemplate3DDoubleArc3PointsInsertAnimation
Removed: class DrawTemplate3DDoubleArcTangentAngleInsertAnimation
Removed: class DrawTemplate3DDoubleLine
Removed: class DrawTemplate3DDoubleLineInsertAnimation
Removed: class DrawTemplate3DDoubleRect
Removed: class DrawTemplate3DDoubleRectEdgeDepthInsertAnimation
Removed: class DrawTemplate3DDoubleRectEdgeDiagonalInsertAnimation
Removed: class DrawTemplate3DDoubler
Removed: class DrawTemplate3DHelpLine
Removed: class DrawTemplate3DHelpLineInsertAnimation
Removed: class DrawTemplate3DMeasure
Removed: class DrawTemplate3DMeetDoubler
Removed: class DrawTemplate3DMeeter
Removed: class DrawTemplate3DMixedLine
Removed: class DrawTemplate3DNurbs
Removed: class DrawTemplate3DNurbsCPConnector
Removed: class DrawTemplate3DPolyHelpLineInsertAnimation
Removed: class DrawTemplate3DPolyLineInsertAnimation
Removed: class DrawTemplate3DPolyMixedLineInsertAnimation
Removed: class DrawTemplate3DRectEdgeDiagonalInsertAnimation
Removed: class DrawTemplate3DRectRevisionCloudInsert
Removed: class DrawTemplate3DReferencePoint
Removed: class DrawTemplate3DReferencePointInsertAnimation
Removed: class DrawTemplate3DRevisionCloud
Removed: class DrawTemplate3DRevisionCloudInsertAnimation
Removed: class DrawTemplate3DSurface2DSearch
Removed: class DrawTemplate3DTrimmer
Removed: class DrawTemplateBackgroundDragAnimation
Removed: class DrawTemplateBoxEdgeDepthInsertAnimation
Removed: class DrawTemplateHelpLineInsertAnimationG2
Removed: class DrawTemplateHelpLineInsertAnimationG2
Removed: class DrawTemplateHelpLineInsertAnimationG2Vessel
Removed: class DrawTemplateLineInsertAnimationG2
Removed: class DrawTemplateLineInsertAnimationG2Vessel
Removed: class DrawTemplatePolyHelpLineInsertAnimationG2
Removed: class DrawTemplatePolyHelpLineInsertAnimationG2Vessel
Removed: class DrawTemplatePolyLineInsertAnimationG2
Removed: class DrawTemplatePolyLineInsertAnimationG2Vessel
Removed: class DrawTemplatePolyRefPointsInsertAnimationG2
Removed: class DrawTemplatePolyRefPointsInsertAnimationG2Vessel
Removed: class DrawTemplateRefPointInsertAnimationG2
Removed: class DrawTemplateRefPointInsertAnimationG2Vessel
Removed: class HorizontalDrawTemplate3DMeasure
Removed: class RefPointCursorVessel
Removed: class VertDist
Removed: class VerticalDrawTemplate3DMeasure

The following classes have been deprecated because they are no longer used in the base repository. They may be removed in future releases.

public class PrintRect extends DrawRect : deprecated {

The following function have been removed because it is no longer used in the base repository.

Removed: public void startRepeatTemplateLineAnimation() {

Instead use:

Added: public void startRepeatLineAnimation() {

cm.win

UrlField button background brush

The following overridable method has been added to UrlField:

Added: extend public Brush buttonBgBrush()

Most UrlField subclasses require no source changes. However, a subclass that already declares a member named buttonBgBrush may now conflict with or override the inherited method. If that member is intended to customize the URL button, ensure it has the compatible Brush buttonBgBrush() signature and access. Otherwise, rename it to avoid the inherited interface.

The open file name functions have been cleaned up:

  • Removed getOpenFileNameEx and getOpenFileNameMultipleEx
  • Removed argument pointI position as it was unused
  • Renamed argument str[] filters to str[] filter
Old: public Url getOpenFileNameEx(Window parent, Url initUrl, str[] filters,
                                  bool fileMustExist=true, Int filterIndex=null) {
Old: public Url getOpenFileNameEx(Window parent, Url initUrl, str[] filters, pointI position,
                                  bool fileMustExist=true, Int filterIndex=null) {
New: public Url getOpenFileName(Window parent, Url initUrl, str[] filter,
                                bool fileMustExist=true, Int filterIndex=null) {

Old: public Url[] getOpenFileNameMultipleEx(Window parent, Url initUrl, str[] filters,
                                            bool fileMustExist=true, Int filterIndex=null) {
Old: public Url[] getOpenFileNameMultipleEx(Window parent, Url initUrl, str[] filters, pointI position,
                                            bool fileMustExist=true, Int filterIndex=null) {
New: public Url[] getOpenFileNameMultiple(Window parent, Url initUrl, str[] filter,
                                          bool fileMustExist=true, Int filterIndex=null) {

Old: public Url getOpenFileName(Window parent, Url initUrl, str[] filter, pointI position,
                                bool fileMustExist=true, Int filterIndex=null) {
New: public Url getOpenFileName(Window parent, Url initUrl, str[] filter,
                                bool fileMustExist=true, Int filterIndex=null) {

The save file name functions have been cleaned up:

  • Removed getSaveFileNameEx
  • Removed argument pointI position as it was unused
  • Renamed argument str[] filters to str[] filter
Old: public Url getSaveFileNameEx(Window parent, Url initUrl, str[] filters,
                                  Int filterIndex=null, bool overwriteWarning=true) {
Old: public Url getSaveFileNameEx(Window parent, Url initUrl, str[] filters, pointI position,
                                  Int filterIndex=null, bool overwriteWarning=true) {
New: public Url getSaveFileName(Window parent, Url initUrl, str[] filter,
                                Int filterIndex=null, bool overwriteWarning=true) {

Old: public Url getSaveFileName(Window parent, Url initUrl, str[] filter, pointI position,
                                Int filterIndex=null, bool overwriteWarning=true) {
New: public Url getSaveFileName(Window parent, Url initUrl, str[] filter,
                                Int filterIndex=null, bool overwriteWarning=true) {

The browse folder functions have been renamed:

Old: public Url browseForFolderEx(Window parent, str title, Url initUrl=null) {
New public Url browseForFolder(Window parent, str title, Url initUrl=null) {

The following functions have been removed:

public void applySaveFilterOldReplaceStyle(Url url, str[] filters, int index) {
public void applySaveFilterOldReplaceStyle(Url url, str filter) {

Added argument str loc=callerLoc() for various progress related classes and functions.

# InfiniteProgressBarDialog
Old: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=null,
                        pointI pos=(0, 0),
                        sizeI size=(280, 64),
                        bool initVisible=true,
                        bool resident=false,
                        // extended args
                        bool spinning=false,
                        bool center=true,
                        bool modal=true,
                        bool cancel=false,
                        function(ProgressDialog d) abortCallback=null) {
New: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=null,
                        pointI pos=(0, 0),
                        sizeI size=(280, 64),
                        bool initVisible=true,
                        bool resident=false,
                        // extended args
                        bool spinning=false,
                        bool center=true,
                        bool modal=true,
                        bool cancel=false,
                        function(ProgressDialog d) abortCallback=null,
                        str loc=callerLoc()) {

# ProgressEnv
Old: public constructor(Window frame, int steps=100,
                        str label=null,
                        bool cancel=true,
                        bool center=true,
                        bool modal=false,
                        function(ProgressDialog d) abortCallback=null,
                        bool infinite=false,
                        bool spinning=false,
                        bool initVisible=true,
                        str infoLabel=null,
                        str statusLabel=null) {
New: public constructor(Window frame, int steps=100,
                        str label=null,
                        bool cancel=true,
                        bool center=true,
                        bool modal=false,
                        function(ProgressDialog d) abortCallback=null,
                        bool infinite=false,
                        bool spinning=false,
                        bool initVisible=true,
                        str infoLabel=null,
                        str statusLabel=null,
                        str loc=callerLoc()) {

Old: public ProgressDialog beginProgress(Window frame, int steps=100,
                                         str label=null,
                                         bool cancel=true,
                                         bool center=true,
                                         bool modal=true,
                                         function(ProgressDialog d) abortCallback=null,
                                         bool infinite=false,
                                         bool spinning=false,
                                         bool initVisible=true,
                                         str infoLabel=null,
                                         str statusLabel=null) {
New: public ProgressDialog beginProgress(Window frame, int steps=100,
                                         str label=null,
                                         bool cancel=true,
                                         bool center=true,
                                         bool modal=true,
                                         function(ProgressDialog d) abortCallback=null,
                                         bool infinite=false,
                                         bool spinning=false,
                                         bool initVisible=true,
                                         str infoLabel=null,
                                         str statusLabel=null,
                                         str loc=callerLoc()) {

Added argument str loc=callerLoc() into the non modal dialogs classes and functions.

# NonModalMessageBox
Old: public constructor(Window parent, str message,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label="Message",
                        str buttonLabel=null,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        function(Object arg) callback=null,
                        Object callbackArg=null) {
New: public constructor(Window parent, str message,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label="Message",
                        str buttonLabel=null,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        function(Object arg) callback=null,
                        Object callbackArg=null,
                        str loc=callerLoc()) {

Old: public void makeNonModalMessageBox(Window parent, str message) {
New: public void makeNonModalMessageBox(Window parent, str message, str loc=callerLoc()) {

Old: public void makeNonModalMessageBox(Window parent, str id, str message) {
New: public void makeNonModalMessageBox(Window parent, str id, str message, str loc=callerLoc()) {

Old: public NonModalMessageBox makeNonModalMessageBox(Window parent, str id, str label, str message, str buttonLabel=null,
                                                      function(Object arg) callback=null,
                                                      Object callbackArg=null) {
New: public NonModalMessageBox makeNonModalMessageBox(Window parent, str id, str label, str message, str buttonLabel=null,
                                                      function(Object arg) callback=null,
                                                      Object callbackArg=null,
                                                      str loc=callerLoc()) {

# NonModalWarningDialog
Old: public constructor(Window parent, str message,
                        Image warningIcon=null,
                        pointI messageOffset=(20, 10),
                        str buttonLabel=null,
                        Brush textFieldBrush=almostWhiteBrush,
                        function(Control) buttonCallback=null,
                        str checkBoxMessage=null,
                        function(Control) checkBoxCallback=null|,
                       
                        // Inhertited
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        FrameStyle frameStyle=lightGrayPenFrame,
                        frame3DState frameState=frameStateUp,
                        str label="Dialog",
                        pointI pos=(-1, -1),
                        sizeI size=(500, 200),
                        bool initVisible=true,
                        bool noBorder=false,
                        bool noCaptionStyle=false,
                        bool shadow=false,
                        bool addMinimize=false,
                        bool addMaximize=false,
                        bool resident=false,
                        bool forceShowInTaskbar=false) {
                        bool forceShowInTaskbar=false,
                        str loc=callerLoc()) {
New: public constructor(Window parent, str message,
                        Image warningIcon=null,
                        pointI messageOffset=(20, 10),
                        str buttonLabel=null,
                        Brush textFieldBrush=almostWhiteBrush,
                        function(Control) buttonCallback=null,
                        str checkBoxMessage=null,
                        function(Control) checkBoxCallback=null|,
                       
                        // Inhertited
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        FrameStyle frameStyle=lightGrayPenFrame,
                        frame3DState frameState=frameStateUp,
                        str label="Dialog",
                        pointI pos=(-1, -1),
                        sizeI size=(500, 200),
                        bool initVisible=true,
                        bool noBorder=false,
                        bool noCaptionStyle=false,
                        bool shadow=false,
                        bool addMinimize=false,
                        bool addMaximize=false,
                        bool resident=false,
                        bool forceShowInTaskbar=false,
                        str loc=callerLoc()) { 

# FormattedTextNonModalMessageBox
Old: public constructor(Window parent, str header, FormattedText content,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label="Message",
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool framed=false,
                        bool initVisible=true) {
New: public constructor(Window parent, str header, FormattedText content,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label="Message",
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool framed=false,
                        bool initVisible=true,
                        str loc=callerLoc()) {

Old: public void makeFormattedTextNonModalMessageBox(Window parent, str message,
                                                     FormattedText content, bool framed=false) {
New: public void makeFormattedTextNonModalMessageBox(Window parent, str message,
                                                     FormattedText content, bool framed=false,
                                                     str loc=callerLoc()) {

Old: public void makeFormattedTextNonModalMessageBox(Window parent, str id, str message,
                                                     FormattedText content, bool framed=false) {
New: public void makeFormattedTextNonModalMessageBox(Window parent, str id, str message,
                                                     FormattedText content, bool framed=false,
                                                     str loc=callerLoc()) {

Old: public void makeFormattedTextNonModalMessageBox(Window parent, str id, str label, str message,
                                                     FormattedText content, bool framed=false) {
New: public void makeFormattedTextNonModalMessageBox(Window parent, str id, str label, str message,
                                                     FormattedText content, bool framed=false,
                                                     str loc=callerLoc()) {

Changed argument SrcRef src=#:src to str loc=callerLoc() for the following message box functions:

Old: public void makeMessageBox(Window parent, str message,
                                dialogIcon icon=dialogIcon.none,
                                function(Window dialog) positionCallback=null,
                                SrcRef src=#:src) {
New: public void makeMessageBox(Window parent, str message,
                                dialogIcon icon=dialogIcon.none,
                                function(Window dialog) positionCallback=null,
                                str loc=callerLoc()) {

Old: public void makeMessageBox(Window parent, str label, str message,
                                dialogIcon icon=dialogIcon.none,
                                function(Window dialog) positionCallback=null,
                                SrcRef src=#:src) {
New: public void makeMessageBox(Window parent, str label, str message,
                                dialogIcon icon=dialogIcon.none,
                                function(Window dialog) positionCallback=null,
                                str loc=callerLoc()) {

Old: public void makeMessageBox(Window parent, str label, str message,
                                function(Control c) doNotShowAgainCB=null,
                                dialogIcon icon=dialogIcon.none,
                                function(Window dialog) positionCallback=null,
                                SrcRef src=#:src) {
New: public void makeMessageBox(Window parent, str label, str message,
                                function(Control c) doNotShowAgainCB=null,
                                dialogIcon icon=dialogIcon.none,
                                function(Window dialog) positionCallback=null,
                                str loc=callerLoc()) {

Old: public void makeFormattedMessageBox(Window parent, str label, str message,
                                         function(Control c) doNotShowAgainCB=null,
                                         dialogIcon icon=dialogIcon.none,
                                         function(Window dialog) positionCallback=null,
                                         SrcRef src=#:src) {
New: public void makeFormattedMessageBox(Window parent, str label, str message,
                                         function(Control c) doNotShowAgainCB=null,
                                         dialogIcon icon=dialogIcon.none,
                                         function(Window dialog) positionCallback=null,
                                         str loc=callerLoc()) {

Added argument str loc=callerLoc() into the the following message box functions:

# LinkedOneButtonBox
Old: public constructor(Window parent, str message, str preLinkMsg,
                        str linkLabel, str link, str btnLabel=$okButtonLabel,
                        dialogIcon icon=dialogIcon.none,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$messageDialogCaption,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true) {
New: public constructor(Window parent, str message, str preLinkMsg,
                        str linkLabel, str link, str btnLabel=$okButtonLabel,
                        dialogIcon icon=dialogIcon.none,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$messageDialogCaption,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str loc=callerLoc()) {

Old: public void makeLinkedMessageBox(Window parent, str label, str message, str preLinkMsg, str linkLabel, str link, str btnLabel=$okButtonLabel, dialogIcon icon=dialogIcon.none) {
New: public void makeLinkedMessageBox(Window parent, str label, str message,
                                      str preLinkMsg, str linkLabel, str link,
                                      str btnLabel=$okButtonLabel,
                                      dialogIcon icon=dialogIcon.none,
                                      str loc=callerLoc()) {

Old: public void makeMessageBoxPostLoad(Window parent, str message, FormattedText content, bool framed=false, bool readOnly=true, str label=null) {
New: public void makeMessageBoxPostLoad(Window parent, str message, FormattedText content,
                                        bool framed=false, bool readOnly=true, str label=null,
                                        str loc=callerLoc()) {

Old: public void makeMessageBoxPostLoad(Window parent, str message, bool framed=false, bool readOnly=true, str label=null) {
New: public void makeMessageBoxPostLoad(Window parent, str message, bool framed=false,
                                        bool readOnly=true, str label=null, str loc=callerLoc()) {


Old: public void makeMessageBoxPostLoad(Window parent, str label, str content, bool framed=false, bool readOnly=true) {
New: public void makeMessageBoxPostLoad(Window parent, str label, str content,
                                        bool framed=false, bool readOnly=true, str loc=callerLoc()) {

Removed argument SrcRef src=#:src from the the following two button box functions:

Old: public int makeTwoButtonBox(Window parent, str question, str select1, str select2,
                                 int defaultButtonNo=1,
                                 dialogIcon icon=dialogIcon.none,
                                 function(Window dialog) positionCallback=null,
                                 str loc=callerLoc(),
                                 SrcRef src=#:src) {
New: public int makeTwoButtonBox(Window parent, str question, str select1, str select2,
                                 int defaultButtonNo=1,
                                 dialogIcon icon=dialogIcon.none,
                                 function(Window dialog) positionCallback=null,
                                 str loc=callerLoc()) {

Changed argument SrcRef src=#:src to str loc=callerLoc() for the following two button box functions:

Old: public int makeTwoButtonBox(Window parent, str label, str question, str select1, str select2,
                                 int defaultButtonNo=1,
                                 dialogIcon icon=dialogIcon.none,
                                 function(Window dialog) positionCallback=null,
                                 SrcRef src=#:src) {
New: public int makeTwoButtonBox(Window parent, str label, str question, str select1, str select2,
                                 int defaultButtonNo=1,
                                 dialogIcon icon=dialogIcon.none,
                                 function(Window dialog) positionCallback=null,
                                 str loc=callerLoc()) {

Added argument str loc=callerLoc() into the the following two button box functions:

# TwoButtonImageBox
Old: public constructor(Window parent,
                        str question,
                        str select1,
                        str select2,
                        function(int z) callback,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$questionDialogCaption,
                        Image image1=null,
                        Image image2=null,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true) {
New: public constructor(Window parent,
                        str question,
                        str select1,
                        str select2,
                        function(int z) callback,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$questionDialogCaption,
                        Image image1=null,
                        Image image2=null,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str loc=callerLoc()) {

Old: public int makeTwoButtonImageBox(Window parent, str question,
                                      str select1, str select2,
                                      Image image1, Image image2, int defaultButtonNo=1) {
New: public int makeTwoButtonImageBox(Window parent, str question,
                                      str select1, str select2,
                                      Image image1, Image image2,
                                      int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeTwoButtonImageBox(Window parent, str label, str question,
                                      str select1, str select2,
                                      Image image1, Image image2, int defaultButtonNo=1) {
New: public int makeTwoButtonImageBox(Window parent, str label, str question,
                                      str select1, str select2,
                                      Image image1, Image image2,
                                      int defaultButtonNo=1, str loc=callerLoc()) {

# YesNoDialog
Old: public constructor(Window parent, str label, str question, function(int z) callback, int defaultButtonNo=1) {
New: public constructor(Window parent, str label, str question, function(int z) callback, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeYesNoDialog(Window parent, str question, int defaultButtonNo=1) {
New: public int makeYesNoDialog(Window parent, str question, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeYesNoDialog(Window parent, str label, str question, int defaultButtonNo=1) {
New: public int makeYesNoDialog(Window parent, str label, str question, int defaultButtonNo=1, str loc=callerLoc()) {

# YesCancelDialog
Old: public constructor(Window parent, str label, str question, function(int z) callback, int defaultButtonNo=1) {
New: public constructor(Window parent, str label, str question, function(int z) callback, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeYesCancelDialog(Window parent, str question, int defaultButtonNo=1) {
New: public int makeYesCancelDialog(Window parent, str question, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeYesCancelDialog(Window parent, str label, str question, int defaultButtonNo=1) {
New: public int makeYesCancelDialog(Window parent, str label, str question, int defaultButtonNo=1, str loc=callerLoc()) {

# OkExitDialog
Old: public constructor(Window parent, str label, str question, function(int z) callback, int defaultButtonNo=1) {
New: public constructor(Window parent, str label, str question,
                        function(int z) callback, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeOkExitDialog(Window parent, str question, int defaultButtonNo=1) {
New: public int makeOkExitDialog(Window parent, str question, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeOkExitDialog(Window parent, str label, str question, int defaultButtonNo=1) {
New: public int makeOkExitDialog(Window parent, str label, str question, int defaultButtonNo=1, str loc=callerLoc()) {

# OkCancelDialog
Old: public constructor(Window parent, str label, str question, function(int z) callback, int defaultButtonNo=1, bool initVisible=true) {
New: public constructor(Window parent, str label, str question,
                        function(int z) callback, int defaultButtonNo=1, bool initVisible=true,
                        str loc=callerLoc()) {

Old: public int makeOkCancelDialog(Window parent, str question, int defaultButtonNo=1) {
New: public int makeOkCancelDialog(Window parent, str question, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeOkCancelDialog(Window parent, str label, str question, int defaultButtonNo=1) {
New: public int makeOkCancelDialog(Window parent, str label, str question, int defaultButtonNo=1, str loc=callerLoc()) {

# FormattedTextYesNoDialog
Old: public int makeFormattedTextYesNoDialog(Window parent, str label, str header,
                                             FormattedText content, bool framed=false) {
New: public int makeFormattedTextYesNoDialog(Window parent, str label, str header,
                                             FormattedText content, bool framed=false, str loc=callerLoc()) {

# FormattedTextTwoButtonBox
Old: public constructor(Window parent,
                        str label,
                        str header,
                        FormattedText content,
                        function(int z) callback,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str select1=null,
                        str select2=null,
                        bool framed=false) {
New: public constructor(Window parent,
                        str label,
                        str header,
                        FormattedText content,
                        function(int z) callback,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str select1=null,
                        str select2=null,
                        bool framed=false,
                        str loc=callerLoc()) {

Old: public int makeFormattedTextTwoButtonBox(Window parent, str label, str header,
                                              FormattedText content, str select1, str select2, bool framed=false, int defaultButtonNo=1) {
New: public int makeFormattedTextTwoButtonBox(Window parent, str label, str header,
                                              FormattedText content, str select1, str select2,
                                              bool framed=false, int defaultButtonNo=1, str loc=callerLoc()) {

Old: public int makeFormattedTextOkReportDialog(Window parent, str label, str header,
                                                FormattedText content, bool framed=false) {
New: public int makeFormattedTextOkReportDialog(Window parent, str label, str header,
                                                FormattedText content, bool framed=false, str loc=callerLoc()) {

Old: public int makeFormattedTextOkCancelDialog(Window parent, str header,
                                                FormattedText content, bool framed=false) {
New: public int makeFormattedTextOkCancelDialog(Window parent, str header,
                                                FormattedText content, bool framed=false,
                                                str loc=callerLoc()) {

Old: public int makeFormattedTextOkCancelDialog(Window parent, str id, str header,
                                                FormattedText content, bool framed=false) {
New: public int makeFormattedTextOkCancelDialog(Window parent, str id, str header,
                                                FormattedText content, bool framed=false,
                                                str loc=callerLoc()) {

Old: public int makeFormattedTextOkCancelDialog(Window parent, str id, str label, str header,
                                                FormattedText content, bool framed=false) {
New: public int makeFormattedTextOkCancelDialog(Window parent, str id, str label, str header,
                                                FormattedText content, bool framed=false,
                                                str loc=callerLoc()) {

# ExitCancelDialog
Old: public constructor(Window parent, str label, str question, function(int z) callback) {
New: public constructor(Window parent, str label, str question, function(int z) callback, str loc=callerLoc()) {

Old: public int makeExitCancelDialog(Window parent, str question) {
New: public int makeExitCancelDialog(Window parent, str question, str loc=callerLoc()) {

Old: public int makeExitCancelDialog(Window parent, str label, str question) {
New: public int makeExitCancelDialog(Window parent, str label, str question, str loc=callerLoc()) {

Added argument str loc=callerLoc() into the the following three button box functions:

# ThreeButtonBox
Old: public constructor(Window parent,
                        str question,
                        str select1,
                        str select2,
                        str select3,
                        Image image1=null,
                        Image image2=null,
                        Image image3=null,
                        function(int z) callback=null,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$questionDialogCaption,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true) {
New: public constructor(Window parent,
                        str question,
                        str select1,
                        str select2,
                        str select3,
                        Image image1=null,
                        Image image2=null,
                        Image image3=null,
                        function(int z) callback=null,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$questionDialogCaption,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str loc=callerLoc()) {

Old: public constructor(Window parent,
                        str question,
                        str select1,
                        str select2,
                        str select3,
                        Image image1=null,
                        Image image2=null,
                        Image image3=null,
                        function(str z) callback=null,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$questionDialogCaption,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true) {
New: public constructor(Window parent,
                        str question,
                        str select1,
                        str select2,
                        str select3,
                        Image image1=null,
                        Image image2=null,
                        Image image3=null,
                        function(str z) callback=null,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=$questionDialogCaption,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str loc=callerLoc()) {

# FormattedTextThreeButtonBox
Old: public constructor(Window parent,
                        str label,
                        str header,
                        FormattedText content,
                        function(int z) callback,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str select1=null,
                        str select2=null,
                        str select3=null,
                        Image image1=null,
                        Image image2=null,
                        Image image3=null,
                        bool framed=false) {
New: public constructor(Window parent,
                        str label,
                        str header,
                        FormattedText content,
                        function(int z) callback,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str select1=null,
                        str select2=null,
                        str select3=null,
                        Image image1=null,
                        Image image2=null,
                        Image image3=null,
                        bool framed=false,
                        str loc=callerLoc()) {

Old: public int makeFormattedTextThreeButtonBox(Window parent, str label, str header, FormattedText content,
                                                str select1, str select2, str select3,
                                                Image image1=null,
                                                Image image2=null,
                                                Image image3=null,
                                                bool framed=false,
                                                int defaultButtonNo=1) {
New: public int makeFormattedTextThreeButtonBox(Window parent, str label, str header, FormattedText content,
                                                str select1, str select2, str select3,
                                                Image image1=null,
                                                Image image2=null,
                                                Image image3=null,
                                                bool framed=false,
                                                int defaultButtonNo=1,
                                                str loc=callerLoc()) {

Changed argument SrcRef src=#:src to str loc=callerLoc() for the following three button box functions:

Old: public int makeThreeButtonBox(Window parent, str question,
                                   str select1, str select2, str select3,
                                   Image image1=null, Image image2=null, Image image3=null,
                                   int defaultButtonNo=1,
                                   dialogIcon icon=dialogIcon.none,
                                   function(Window dialog) positionCallback=null,
                                   SrcRef src=#:src) {
New: public int makeThreeButtonBox(Window parent, str question,
                                   str select1, str select2, str select3,
                                   Image image1=null, Image image2=null, Image image3=null,
                                   int defaultButtonNo=1,
                                   dialogIcon icon=dialogIcon.none,
                                   function(Window dialog) positionCallback=null,
                                   str loc=callerLoc()) {

Old: public int makeThreeButtonBox(Window parent, str question, str caption,
                                   str select1, str select2, str select3,
                                   Image image1=null, Image image2=null, Image image3=null,
                                   int defaultButtonNo=1,
                                   dialogIcon icon=dialogIcon.none,
                                   function(Window dialog) positionCallback=null,
                                   SrcRef src=#:src) {

New: public int makeThreeButtonBox(Window parent, str question, str caption,
                                   str select1, str select2, str select3,
                                   Image image1=null, Image image2=null, Image image3=null,
                                   int defaultButtonNo=1,
                                   dialogIcon icon=dialogIcon.none,
                                   function(Window dialog) positionCallback=null,
                                   str loc=callerLoc()) {

Changed argument SrcRef src=#:src to str loc=callerLoc() for the following four button box functions:

Old: public int makeFourButtonBox(Window parent, str question,
                                  str select1, str select2, str select3, str select4,
                                  Image image1=null, Image image2=null, Image image3=null, Image image4=null,
                                  int defaultButtonNo=1,
                                  dialogIcon icon=dialogIcon.none,
                                  function(Window dialog) positionCallback=null,
                                  SrcRef src=#:src) {
New: public int makeFourButtonBox(Window parent, str question,
                                  str select1, str select2, str select3, str select4,
                                  Image image1=null, Image image2=null, Image image3=null, Image image4=null,
                                  int defaultButtonNo=1,
                                  dialogIcon icon=dialogIcon.none,
                                  function(Window dialog) positionCallback=null,
                                  str loc=callerLoc()) {

Old: public int makeFourButtonBox(Window parent, str question, str caption,
                                  str select1, str select2, str select3, str select4,
                                  Image image1=null, Image image2=null, Image image3=null, Image image4=null,
                                  int defaultButtonNo=1,
                                  dialogIcon icon=dialogIcon.none,
                                  function(Window dialog) positionCallback=null,
                                  SrcRef src=#:src) {
New: public int makeFourButtonBox(Window parent, str question, str caption,
                                  str select1, str select2, str select3, str select4,
                                  Image image1=null, Image image2=null, Image image3=null, Image image4=null,
                                  int defaultButtonNo=1,
                                  dialogIcon icon=dialogIcon.none,
                                  function(Window dialog) positionCallback=null,
                                  str loc=callerLoc()) {

Added argument str loc=callerLoc() into the the following functions:

# IntInputDialog
Old: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=null,
                        pointI pos=(-1, -1),
                        sizeI size=sizeI(250, 150),
                        bool initVisible=true,
                        str text=null,
                        Int initValue=null) {
New: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label=null,
                        pointI pos=(-1, -1),
                        sizeI size=sizeI(250, 150),
                        bool initVisible=true,
                        str text=null,
                        Int initValue=null,
                        str loc=callerLoc()) {

Old: public Int makeIntInputDialog(Window parent, str label=null, str text=null, Int initValue=null) {
New: public Int makeIntInputDialog(Window parent, str label=null, str text=null, Int initValue=null, str loc=callerLoc()) {

# RadioButtonBox
Old: public constructor(Window parent,
                        str question,
                        str[] keys,
                        str[] labels,
                        str selectedKey,
                        str caption=$questionDialogCaption,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true) {
New: public constructor(Window parent,
                        str question,
                        str[] keys,
                        str[] labels,
                        str selectedKey,
                        str caption=$questionDialogCaption,
                        int defaultButtonNo=1,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(-1, -1),
                        sizeI size=(280, 80),
                        bool initVisible=true,
                        str loc=callerLoc()) {

Old: public str makeRadioButtonBox(Window parent,
                                   str question,
                                   str[] keys,
                                   str[] labels,
                                   str selectedKey,
                                   str caption=$questionDialogCaption,
                                   function(Window dialog) positionCallback=null) {
New: public str makeRadioButtonBox(Window parent,
                                   str question,
                                   str[] keys,
                                   str[] labels,
                                   str selectedKey,
                                   str caption=$questionDialogCaption,
                                   function(Window dialog) positionCallback=null,
                                   str loc=callerLoc()) {

Old: public int makeYesAllNoCancelDialog(Window parent, str question,
                                         dialogIcon icon=dialogIcon.none,
                                         function(Window dialog) positionCallback=null) {
New: public int makeYesAllNoCancelDialog(Window parent, str question,
                                         dialogIcon icon=dialogIcon.none,
                                         function(Window dialog) positionCallback=null,
                                         str loc=callerLoc()) {

Old: public int makeYesAllNoCancelDialog(Window parent, str label, str question,
                                         dialogIcon icon=dialogIcon.none,
                                         function(Window dialog) positionCallback=null) {
New: public int makeYesAllNoCancelDialog(Window parent, str label, str question,
                                         dialogIcon icon=dialogIcon.none,
                                         function(Window dialog) positionCallback=null,
                                         str loc=callerLoc()) {

# ResizableDialogWindow
Old: public constructor(Window parent, 
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        FrameStyle frameStyle=noFrame,
                        frame3DState frameState=frameStateUp,
                        str label="Dialog",
                        pointI pos=(-1, -1),
                        sizeI size=(300, 200),
                        bool initVisible=true,
                        bool noBorder=false,
                        bool noCaptionStyle=false,
                        bool shadow=false,
                        bool addMinimize=false,
                        bool addMaximize=false,
                        bool resident=false,
                        bool forceShowInTaskbar=false,
                        str key=null,
                        sizeI minSize=(-1, -1),
                        sizeI maxSize=(-1, -1)) {
New: public constructor(Window parent, 
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        FrameStyle frameStyle=noFrame,
                        frame3DState frameState=frameStateUp,
                        str label="Dialog",
                        pointI pos=(-1, -1),
                        sizeI size=(300, 200),
                        bool initVisible=true,
                        bool noBorder=false,
                        bool noCaptionStyle=false,
                        bool shadow=false,
                        bool addMinimize=false,
                        bool addMaximize=false,
                        bool resident=false,
                        bool forceShowInTaskbar=false,
                        str key=null,
                        sizeI minSize=(-1, -1),
                        sizeI maxSize=(-1, -1),
                        str loc=callerLoc()) {

Old: public constructor(Window parent,
                        TitleBarConfig tbConfig,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label="Dialog",
                        pointI pos=(-1, -1),
                        sizeI size=(300, 200),
                        bool initVisible=true,
                        bool resident=false,
                        bool forceShowInTaskbar=false,
                        str key=null,
                        sizeI minSize=(-1, -1),
                        sizeI maxSize=(-1, -1)) {
New: public constructor(Window parent,
                        TitleBarConfig tbConfig,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        str label="Dialog",
                        pointI pos=(-1, -1),
                        sizeI size=(300, 200),
                        bool initVisible=true,
                        bool resident=false,
                        bool forceShowInTaskbar=false,
                        str key=null,
                        sizeI minSize=(-1, -1),
                        sizeI maxSize=(-1, -1)) {
                        str loc=callerLoc()) {

eventLogG3.cm

The access modifier for the valid method for G3UserEvent has been changed from public to package:

Old: final public bool valid(G3InvalidList list) {
New: final package bool valid(G3InvalidList list) {

Added new arguments for the G3ManufacturerId constructor to support part anlytics for Material Portal Textile manufacturers. statsManufacturerType.cil is for CIL manufacturers while statsManufacturerType.mpCompanyId are for Textile manufacturers using the material portal moving forward.

Old: public constructor(str mPMEnterprise) {
New: public constructor(str enterprise, statsManufacturerType mType=statsManufacturerType.cil) {

Also some interfaces were updated in the cm.statistics package as part of this change. Please refer to the documentation for those changes as well.

custom.accessories.office.catalogues

class OfficeSnapper (custom/accessories/office/catalogues/officeSnapper.cm)

Renamed the following method followed by changes in DataSymbol class.

Old: extend public void buildConnectors() {
New: extend public void buildLocalConnectors() {

custom.dataCatalog

Variants Table in Catalog Creator is no longer editable

As catalog has moved towards using constraints tables instead, we are deprecating support for variants tables. They will no longer be editable from the catalog creator and will be read only from 17.5 onwards. The user can migrate their variant tables to constraint tables using the migrate button in catalog creator.

The following methods have in the custom.dataCatalog.build.variantsTables package been removed:

class DcVariantsTableCard

Removed: method public bool dropFiles(DropFiles drop)
Removed: method extend public void importXLS()

class DcVariantsTableGridSubWindow

Removed: field public DsButton replaceBtn;
Removed: method extend public bool nameTxtEvent(str msg, Object value=null)
Removed: extend public bool importBtnEvent(str msg, Object value=null)

class DcVariantsTableToolboxSubWindow

Removed: field public DsButton importBtn;
Removed: field public DsButton newBtn;
Removed: field public DsButton deleteBtn;
Removed: method extend public bool importBtnEvent(str msg=null, Object value=null)
Removed: method extend public bool deleteBtnEvent(str msg=null, Object value=null)
Removed: method extend public bool newBtnEvent(str msg=null, Object value=null)

Performance improvement for loop detection in additional products and features

Previous when additional products and/or catalog features were deeply nested, there were sometimes performance issues when adding additional products and/or features in the catalog creator. We have updated the algorithm to be more efficient to improve such performance issues.

functions.cm

The following interfaces have changed in custom.dataCatalog.functions.cm

Old: public bool dcFeatureLoop(DsProductType prod, DataCatalog catalog, str[] soFar=null,
			       str{} validated=null, bool useCache=true) {
new: public bool dcFeatureLoop(DsProductType prod, DataCatalog catalog,
			       str{} visiting=null, str{} validated=null) {
Old: public bool dcFeatureLoop(DsProductType prod, DataCatalog catalog, str[] soFar=null,
			       str{} validated=null, bool useCache=true) {
new: public bool dcFeatureLoop(DsProductType prod, DataCatalog catalog,
			       str{} visiting=null, str{} validated=null) {
Old: public bool dcAdditionalProductLoop(DsProductType prod, DataCatalog catalog, str[] features=null, str[] products=null, str{} validatedFeatures=null, str{} validatedProducts=null, bool useCache=true) {
New: public bool dcAdditionalProductLoop(DsProductType prod, DataCatalog catalog, time timelimit=time(0)) {
Removed: public bool dcAdditionalProductLoop(DsProductType prod, DataCatalog catalog, time timelimit,
				    str[] features=null, str[] products=null,
				    str{} validatedFeatures=null, str{} validatedProducts=null,
				    bool useCache=true) {

Performance improvements when copy/paste/delete/undo material applications in the Options grid window

Fixed an issue where CET would get stuck when performing copy/paste/delete/undo actions in the material application column in the Options grid window.

The following interfaces have changed in custom.dataCatalog

** class DcDBBuilderEditFeaturesCard**

Old: extend public void triggerUpdate(Option opt) {
New: extend public void triggerUpdate(Option opt, bool synchronize=true) {

custom.dataCatalog.builder

class DcMenuSubWindow

Changed catalogue creator menu bar buttons from CoolGradientDropDownMenuButton to DsButton type for creator facelift.

Old: public CoolGradientDropDownMenuButton fileMenuBtn; 
New: public DsButton fileMenuBtn; 

Old: public CoolGradientDropDownMenuButton editMenuBtn; 
New: public DsButton editMenuBtn; 

Old: public CoolGradientDropDownMenuButton toolsMenuBtn; 
New: public DsButton toolsMenuBtn; 

Old: public DsCoolGradientDropDownMenuButton switchMenuBtn; 
New: public DsButton switchMenuBtn; 

custom.dataCatalog.builder.ui

class DcHelpButton

Added 1 new parameter hoverImage to set button image on hover, added defaults for stdBrush, hoverBrush, mouseDownBrush.

Old: public constructor(Window parent,
		                Window helpDialogParent,
		                Brush stdBrush,
		                Brush hoverBrush,
                        Brush mouseDownBrush,
                        Image helpImage,
                        str helpText,
                        str onlineLink=null,
                        // inherited key arguments
                        Font font=controlFont,
                        FrameStyle frameStyle=noFrame,
                        frame3DState frameState=frameStateUp,
                        pointI pos=(0, 0),
                        sizeI size=sizeI(-1, -1),
                        pointI margins=(6, 4),
                        alignment align=middle,
                        str key=null,
                        str label="",
                        color labelColor=color(0, 0, 0),
                        color pressedLabelColor=color(colorType.none),
                        alignment textSide=undefinedAlignment,
                        Image image=null,
                        Image disabledImage=null,
                        color color=nocolor,
                        function(Control button) callback=null,
                        SrcRef src=#:src)
New: public constructor(Window parent,
                        Window helpDialogParent,
                        str helpText,
                        Brush stdBrush=noBrush,
                        Brush hoverBrush=noBrush,
                        Brush mouseDownBrush=noBrush,
                        Image helpImage=null,
                        str onlineLink=null,
                        // inherited key arguments
                        Font font=controlFont,
                        FrameStyle frameStyle=noFrame,
                        frame3DState frameState=frameStateUp,
                        pointI pos=(0, 0),
                        sizeI size=sizeI(-1, -1),
                        pointI margins=(2, 1),
                        alignment align=middle,
                        str key=null,
                        str label="",
                        color labelColor=color(0, 0, 0),
                        color pressedLabelColor=color(colorType.none),
                        alignment textSide=undefinedAlignment,
                        Image image=null,
                                Image hoverImage=null,
                        Image disabledImage=null,
                        color color=nocolor,
                        function(Control button) callback=null,
                        SrcRef src=#:src)

custom.dataCatalog.builder.core

class dcShrinkWindow.cm

Removed parameters for addHelpButton, dcHelpButton signature has changed.

Old: extend public void addHelpButton(Image helpImage, Image helpIcon=null,
				                      Brush hoverBrush=null,
				                      Brush downBrush=null,
			                          FrameStyle fs=thinCoolButtonFrame)
New: extend public void addHelpButton()

custom.dataCatalog.builder.geometry

class DcDBBuilderGeometryCard

Added new arguments to removePrdExtRefKeys to skip visited products and features when removing External Reference Keys.

Old: final public DcDBBuilderUpdateEnv removePrdExtRefKeys(DsProductType prd, str->str{} etkToBeRemoved, str featureKey=null) {
New: final public DcDBBuilderUpdateEnv removePrdExtRefKeys(DsProductType prd, str->str{} etkToBeRemoved, str featureKey=null, str{} visitedPrds=null, str{} visitedFeats=null) {

class DcPreviewDataSymbol

The following method is modified followed by changes in DataSymbol class.

Old: public void buildConnectors(point{} pos) {
New: public void buildConnectors() {

class DcModularCard

Removed: extend public void buildFilterTextFieldSection()
Removed: extend public void buildIconFilterDD(DcTreeViewModule module, FrameStyle frameStyle=dsRoundedFrame)

custom.dataCatalog.ui.catalogTreeView

The following class methods are removed/modified:

class CatalogTreeView

Removed: extend public bool isTviDropped() {
Removed: extend public void incrTviDropCount(bool force=false) {
Removed: extend public void decrTviDropCount() {

Old: extend public void populateFromFeaturesContainExtRefKey(Object key, CatalogTreeViewEnv env=null) {
New: extend public void populateFromFeaturesContainExtRefKeys(Object key, CatalogTreeViewEnv env=null) {

Old: extend public void populateFromProductsContainExtRefKey(Object key, CatalogTreeViewEnv env=null) {
New: extend public void populateFromProductsContainExtRefKeys(Object key, bool includeFeature=true, CatalogTreeViewEnv env=null) {

Old: extend public bool findExtRefKey(str[] featureKeys, <str, str> key, CatalogTreeViewEnv env, str{} visited=null) {
New: extend public bool findExtRefKeys(str[] featureKeys, str->str{} sourceEKeyMap, CatalogTreeViewEnv env, str{} visited=null

class ExtRefKeyTreeViewItem

Old: extend public void showUses(str usesType) {
New: extend public void showUses(str usesType, str->str{} extRefKeysMap) {

Runtime/Behavior Changes

cet.runtime

Timeout changes for CET updates

We've added better timeout handling for CET updates. Previously when the CET update timed out due to unexpected errors, CET would only show that the update timed out but would not stop until the user aborted the update. We have changed this so that the update process tries to detect if the update process has terminated due to unexpected error and report the failure to the user now.

putIgnoreDir() changes in cm.extension

The rescursive behavior of putIgnoreDir() has been corrected in 17.5. To minimize migration effort, the recursive parameter now defaults to false, preserving the previous behavior for existing code.

Previously, only the specified directory was added to the ignore list due to an implementation issue. In the recursive case, instead of adding each discovered subdirectory, the method repeatedly adds the original directory to the ignore list, producing duplicate entries and failing to add the subdirectories into the ignore list.

Existing code that calls putIgnoreDir() without specifying the recursive parameter should continue to behave as before. Code that explicitly specifies subdirectories individually is also unaffected.

The corrected recursive behavior makes it possible to ignore an entire directory tree by calling putIgnoreDir(dir, recursive=true), which now registers both the specified directory and all of its subdirectories into the ignore list.

cm.abstract.dataSymInterface

class MtrlApplication

The _uniqueKey field in MtrlApplication was added to speed up unique key generation for certain environment. However, this field was also mistakenly streamed into DB3 format, resulting in unintended data entry being saved to the file. From 17.5 onwards, this field will be excluded from DB3 saving. The saved DB3 in 17.5 should remain compatible when opened in both older and newer versions of CET.

External Reference Key (E-KEY) matching behavior changes

The changes to External Reference Key (E-KEY) matching behavior are made for two main reasons:

  • Introducing AND condition to align with the E-KEY behavior defined in the OFDA schema.
  • Ensure OR condition is still achievable to avoid breaking existing catalogue implementation

Old Behavior

Prior to 17.5, the E-KEY matching was evaluated independently for each selected option, using an OR condition across all keys. If any E-KEY on a selected option matched an E-KEY on the Product's External Reference, it was considered a match.

New Behavior

The optionExternals and optionExternalsFromExtKeys methods in the DsiPData class have been changed so that the matching logic is evaluated using the combined set of E-KEYs from all selected options. The new matching logic is descriped as follow:

  • AND across types: If an External Reference contains multiple E-KEY types, at least one E-KEY from each type must match.
  • OR within a type: If an External Reference contains multiple E-KEYs of the same type, matching any one of those E-KEYs satisfies that type.
  • Matching E-KEYs can come from different selected options. They are combined when evaluating whether the External Reference matches.

For example, given the following E-KEYs on an External Reference (E-KEY format: Type/Value):

E-KEYs in a Product's External Reference: X/A, X/B, Y/C

The matching condition is: (X/A OR X/B) AND Y/C

This means the selected options must contain either X/A or X/B, as well as Y/C, for the External Reference to match.

When is migration required?

Existing catalogues using multiple E-KEY types should be reviewed, as different E-KEY types are now evaluated using an AND condition. All E-KEY types defined on an External Reference must be satisfied by the selected options for it to match.

The migration work is mainly required on the catalogue side. For more details on how to migrate the catalogue, please refer to this page.

Remove uninstalled catalogs

We have updated the functionality for the "Keep catalogue files after uninstalling catalogue" option in the control panel under the "Catalogues" tab. Previously this functionality was intended to remove the files in the portfolio (cid) folder after all the catalogs in the portfolio were turned off (this state was known as the portfolio uninstalled state). However this did not work correctly.

We have fixed this functionality to work correctly now so that when the option is unchecked, all the catalogs under the portfolio have been turned off, the portfolio folder in the catalog directory will be removed now. Additionally when an extension is uninstalled when the option is unchecked, we remove all related portfolio folders that were registered by that extension. This removal is done silently and over time to minimize interruptions to the user experience.

cm.abstract.dataSymbol

Part Measurements and Generic Codes

Configura SIF rows generated for data-symbol parts now include VO (volume), WD (width), DP (depth), and HT (height). A value from Part.genericCode() is written as CG; TAG2 supplies CG only when the part has no generic code.

OFDA measurement values are now emitted through Part.xmlMeasurement(). The type, measurement system, and unit remain XML attributes, while numeric values are normalized through the shared conversion helper.

OFDA XML 04.02.00 Export Compatibility

DsPart.xmlOptions() now writes OmitOnOrder before the option price. This changes the order of elements in exported OFDA XML without changing their values. Extensions or integrations that compare or parse option elements positionally must update for the 04.02.00 ordering. See the cm.abstract.ofdaXml migration notes for the other OFDA XML output changes.

cm.abstract.draw

class DrawMeasure

The documentation for d has been corrected. It used to say that d was the shortest leg length among p0 and p1. Existing dimension values are not changed, but d should now be interpreted as the extension length from p0.

If your code needs the shortest leg length, call minLegLength() instead.

cm.abstract.engine.ofml

Apply OFML block mapping to its UV mapping

Updated OFML graphics so that it applies the block mapping and rotate parameter to its UV mapping.

cm.abstract.materialHandling

MhPrimPopulatorStepper now includes previous collision primitive when calculating next step

Previously in MhPrimPopulatorStepper.nextStep(MhPopulator populator, Object obj) the steps returned only contained the CollisionPrimitive of the passed in obj. It did not contain the CollisionPrimitive of the steps that came before it, meaning that when checking for collision with the previousStep, it does not check for collision with the primitives of the steps that came before it. We have updated this method to include primitives from the previous steps as well in each returned step.

public class MhPrimPopulatorStepper extends MhLimitPopulatorStepper {

Old:
    public MhPopulatorStep nextStep(MhPopulator populator, Object obj) {
                ...
                prim = mhInstanceCollisionPrim(prim, moveTransform(dp.v));
                if (!(endPrim and primConflicts(prim, endPrim))) {
                    return MhPopulatorStep(l, stepSize, prim);
                }
    }


New:
    public MhPopulatorStep nextStep(MhPopulator populator, Object obj) {
                ...
                MhCollisionPrimitiveSet set(null, null);
                set << mhInstanceCollisionPrim(prim, moveTransform(dp.v));
                if (lastStep) set << lastPrim;
                prim = set;

                if (!(endPrim and primConflicts(prim, endPrim))) {
                    return MhPopulatorStep(l, stepSize, prim);
                }
    }
}

unitLoad lookup fallbacks

As part of our efforts to support having no unit loads generated for levels, we've added some fallback lookups to minimize cases where unit loads are not generated when they actually should be, such as trying to insert a unit load from the toolbox when the configuration is currently set to no unit load.

MhStorageConfiguration.unitLoadKey() has been updated to also check unitLoad() if there is no value for the unitLoadKey property. unitLoad() has also been updated to work with compartment types.

public class MhStorageConfiguration extends MhSystemConfiguration {

Old:
    extend public Str unitLoadKey() {
        return getValue(cMhUnitLoadKeyPK).?Str;
    }


New:
    extend public Str unitLoadKey() {
        Str res = getValue(cMhUnitLoadKeyPK).?Str;
        if (res) return res;

        if (UnitLoad ul = unitLoad()) {
            return ul.gid.hex;
        }

        return null;
    }


Old:
    extend public UnitLoad unitLoad(Object env=null) {
        return getValue(cMhUnitLoadPK, env=env).?UnitLoad;
    }


New:
    extend public UnitLoad unitLoad(Object env=null) {
        UnitLoad res = getValue(cMhUnitLoadPK, env=env).?UnitLoad;
        if (res) return res;

        for (compType in orderedCompartmentTypes()) {
            if (UnitLoad ul = compType.compProps.unitLoad) {
                return ul;
            }
        }

        return null;
    }
}

MhUnitLoadSpawner.shapeCreationProps() has a small change to find first unitLoadKey from domain if configuration does not return a unitLoadKey.

public class MhUnitLoadSpawner extends MhStorageSpawner {

Old:
    public str->Object shapeCreationProps() {
            ...
            if (!ul) {
                SubSet ss = config.getDomain(cMhUnitLoadKeyPK);
                if (ss.any) ?key = ss.next(key);
            }

            return props { unitLoadKey=key };
        }
    }


New:
    public str->Object shapeCreationProps() {
            ...
            if (!ul) {
                SubSet ss = config.getDomain(cMhUnitLoadKeyPK);
                if (ss.any) {
                    if (!key.any) ?key = ss.first();
                    if (?str next = ss.next(key)) key = next;
                }
            }

            return props { unitLoadKey=key };
        }
    }
}

Behavior changes for spawners

MhRackFrameSpawner was mistakenly missing a behavior mhRowChildCopyPasteBehavior in its method override of MhBehavior[] customOtherBehaviors(). This has now been added so if you are also overriding customOtherBehaviors() to add this behavior in after super(), that can now be removed.

public class MhRackFrameSpawner extends MhFrameSpawner {

Updated:
    public MhBehavior[] customOtherBehaviors() {
        ...
        res << mhRowChildCopyPasteBehavior;
        return res;
    }
}

MhFrameSpawner now has an override for customDebugBehaviors() to use mhDebugLinksBehavior.

public class MhFrameSpawner extends MhStorageSpawner {

    public MhBehavior[] customDebugBehaviors() {
        return [MhBehavior: mhDebugLinksBehavior];
    }
}

MhSpacerSpawner has removed mhDebugLinksBehavior from customOtherBehaviors() and moved it to customDebugBehaviors().

public class MhSpacerSpawner extends MhStorageSpawner {

Old: public MhBehavior[] customOtherBehaviors() { ... res << mhDebugLinksBehavior; return res; }

New: public MhBehavior[] customOtherBehaviors() { ... return res; }

New: public MhBehavior[] customDebugBehaviors() { return [MhBehavior: mhDebugLinksBehavior]; } }

MhUnitLoadSpawner has removed mhDebugResolverPrimitivesBehavior from customOtherBehaviors() and moved it to customDebugBehaviors().

public class MhUnitLoadSpawner extends MhStorageSpawner {

Old:
    public MhBehavior[] customOtherBehaviors() {
        ...
        res << mhDebugResolverPrimitivesBehavior;
        return res;
    }

New:
    public MhBehavior[] customOtherBehaviors() {
        ...
        return res;
    }


New:
    public MhBehavior[] customDebugBehaviors() {
        return [MhBehavior: mhDebugResolverPrimitivesBehavior];
    }
}

MhSnapperInfo changes

When a MhSnapperInfo is appended to MhSnapperBehavior, we no longer suppress the removeChild and setParent snapper functions if it was a silent append. They will now be called with the silent flag passed into them, allowing the ChildSnapperNode family to be appropriately updated.

public class MhSnapperBehavior extends MhBehavior {

Old:
    extend public void append(MhSnapper snapper, bool silent) {
        init? infos();
        MhSnapperInfo info = createSnapperInfo(snapper);
        infos << info;
        
        if (!silent) {
            snapper.parent.?removeChild(snapper);
            snapper.setParent(null);
        }
    }


New:
    extend public void append(MhSnapper snapper, bool silent) {
        init? infos();
        MhSnapperInfo info = createSnapperInfo(snapper);
        infos << info;
        
        snapper.parent.?removeChild(snapper, silent=silent);
        snapper.setParent(null, silent=silent);
    }
}

Master link changes

The function MhMasterLinkFinalizeFunction has had it's multiChildrenLink functionality modified. In linkSiblingAndCousin(MhEngine engine, MhEngineEntry entry, Transform rootParentTransform), it now only links bays and frames. This change was made to avoid linking levels together with anything, as it was linking spanning levels with frames and bays.

public class MhMasterLinkFinalizeFunction extends MhSystemEngineFunction {

    extend public MhEngineEntry[] getAllowedMultiLinkChildren(MhEngineEntry[] children) {
        MhEngineEntry[] res(children.count);
        MhEngineEntryFilter filter = multiLinkChildrenFilter();
        for (child in children) {
            if (filter.accepts(child)) {
                res << child;
            }
        }

        return res;
    }


    extend public MhEngineEntryFilter multiLinkChildrenFilter() {
        return mhFrameOrBayEntryFilter;
    }
}

cm.abstract.mezzanine

Gates new property

AbsMezzGate has a new property openRatio that is visible by default in quick properties that is meant to represent the degree to which the gate graphics is open. If you wish to utilize this property, you'll have to update your get3D methods to offset the graphics by openRatio. Otherwise hiding this property is also an option.

cm.abstract.ofdaXml

Generic Codes and Base Part XML Export

OfdaXMLOrderLineProxy.xmlSpecItemDataFromPart() now calls Part.xmlMeasurements() and Part.xmlUserDefined() by default. OfdaXMLOrderLineProdProxy writes product options and then delegates to this base behavior. Custom proxies that override xmlSpecItemDataFromPart() without calling super() will not receive the new common measurement and generic-code output.

DiscountCategory is populated from Part.genericCode(). The UserDefined generic-code value uses the same interface and falls back to the TAG2 label when no generic code is available. Integrations should account for these newly populated elements.

OFDA XML 04.02.00 Export Compatibility

OfdaXMLOrderLineProxy.xmlGeneratePartAttributes() now writes one Comment per part attribute. The previous combined value:

<Comment>
  <Type>LineNote</Type>
  <Value>Note : Description</Value>
</Comment>

is replaced by separate note and description values:

<Comment>
  <Type>OtherType</Type>
  <OtherType>Note</OtherType>
  <Description>Description</Description>
</Comment>

Code that consumes, validates, compares, or transforms exported OFDA XML must account for the new attribute structure. In particular, consumers should no longer expect the note and description to be combined in a Value element.

Element ordering has also changed:

  • Line-item pricing is written before comments and part attributes.
  • Part attributes are written before individual tags and specification-item data.
  • Product options are written before measurements.
  • OmitOnOrder is written before option pricing.

XML consumers and snapshot/reference files that depend on element order must be updated.

getOfdaXMLProxy(Part part) now searches the part's complete class hierarchy for the first registered package proxy. The previous search stopped after 15 inheritance levels. Deeply inherited part classes may therefore resolve a proxy where they previously returned null; extensions should verify that the nearest registered package proxy is appropriate for those classes.

cm.abstract.office

Extensible Type Elevation Merging

Calling mergeAll() on a non-panel TypeElevation now collects split TypeElevation objects and removes them before inserting the merged elevation. This replaces the previous panel-only search.

The base implementation can collect split elevations belonging to other TypeElevation subclasses in the same space. Extensions whose elevation objects must only merge with the same product, system, or subclass should override collectMergers() and append only compatible objects to the supplied set. PanelTypeElevation already does this to retain panel-only merging.

cm.abstract.part

Part Dimensions and Special Creation

ProdPartCreator now copies the supplied option sequence. Later changes to the caller's original sequence no longer change the creator's options.

ProdPart.internal_generateConfiguraSifRows() now includes weight, volume, width, depth, height, source/package code, and generic code. A stored or adjusted generic code is emitted as CG; TAG2 is used for CG only when no generic code is available.

ProdPartAddition and ProdPartOverride now select their behavior through ProdPartCreator.optionHandling. Existing streamed instances that lack this field are migrated to addition or override respectively when loaded.

cm.abstract.part.query

Multiline Query and Article View Text

OptionMakeSpecialDialog now creates optDescTF as a FormattedTextArea with line breaking. The control is 100 pixels high and enables automatic scrolling after its size has been established.

Old: optDescTF = FormattedTextField(this,
                                    font=smallSystemFont,
                                    frameStyle=flatFrame);

New: optDescTF = FormattedTextArea(this,
                                   font=smallSystemFont,
                                   frameStyle=flatFrame,
                                   lineBreak=true);
New: optDescTF.h = 100;
New: optDescTF.autoScroll = true;

Custom layouts or UI automation that depend on the previous single-line control or dialog dimensions should be updated for the taller description area.

cm.application

Separate menu entries for horizontal and vertical split views

The single split-view menu item has been replaced with separate menu items for horizontal and vertical split layouts:

cm.application.menuStdViews

// Menu item keys
Old: views#twoViews
New: views#horizontalSplitViews
New: views#verticalSplitViews

cm.core

Handling quarantine of root parents when child snappers crash

Crash isolation has been improved for parent-child snapper hierarchies.

Previously, when a child snapper crashed, only that child was converted into an ExceptionProxySnapper. During restoration, the child snapper could be restored independently and attempt to enter the space without its parent, causing CET to crash because child snappers cannot exist directly in a space.snappers.

To prevent this, the runtime now quarantines the root parent whenever any snapper in the hierarchy crashes. This ensures the entire parent-child hierarchy is isolated and later restored together.

As a result:

  • The root parent and all of its descendants become ExceptionProxySnapper.
  • The entire hierarchy is restored as a single unit (could be seen from the drawing).
  • Parent-child relationships are preserved throughout isolation and restoration.
  • Child snappers are never restored directly into a space without their parent.

Implementation

Before calling isolateCrashingSnapper(..), the runtime now resolves the crashing snapper's root parent, ensuring parent-child hierarchies are quarantined first before restoring them as one ExceptionProxySnapper.

Files affected

  • cm/core/ExceptionProxySnapper.cm
  • cm/core/stream/load.cm
  • cm/core/space.cm
  • cm/core/view2D.cm
  • cm/core/view3D.cm
  • cm/core/snapAlternative.cm

For more implementation details, refer to this merge request !44030.

Split-view Resource Label

The single split-view resource label has been replaced with separate labels for horizontal and vertical split layouts:

Old: $twoViewsMenuLabel
New: $horizontalViewsMenuLabel
New: $verticalViewsMenuLabel

Split-View Orientation and Divider Interface Changes

The meanings of the remaining split multiViewState values are now orientation-based:

  • multiViewState.horizontal displays the 2D view above the 3D view.
  • multiViewState.vertical displays the 2D view to the left of the 3D view.

Review conditionals that use these values even if they still compile. Also review any code that persists or exchanges their integer representations: horizontal is now 3, while vertical remains 2 but represents the left/right layout.

Preserving Part Adjustments When Resetting Item Tags

TaggableSnapper.resetItemTags() now calls resetPartItemTagInfos() before removing displayed item tags. The reset is canceled if that hook returns false.

For adjusted parts with user-modified Ind. Tags, the default implementation asks the user whether to preserve adjustments. Choosing Yes migrates each adjustment to the key produced by the default tag; choosing No resets the tags without migrating adjustments; closing the prompt cancels the entire reset. User tag information unrelated to the snapper's raw parts is no longer cleared as a side effect.

PsLayoutEditLabelDialog is now fixed size

Changed PsLayoutEditLabelDialog to be a fixed size now.

cm.core.calc

Multiline Query and Article View Text

When ArticleViewSnapper has Use newline enabled, information-row text returned by PartInfoColumn or BasicPartInfoTreeColumn is now passed through ArticleViewSnapperGText.breakLinesViaFormatter(). Long values can therefore wrap onto multiple lines and increase the row height in article-view previews and output.

New: gText = gText(indent # output, c.alignment);
New: if (useNewline) gText.breakLinesViaFormatter();

Custom information columns, visual comparisons, or layouts that assume one line per information row should account for the wrapped output.

cm.core.part

Query Dialog Sidebar and Model Import

Only one Query sidebar tab is expanded at a time. A tab's window is cached while the Query dialog remains open, so switching tabs preserves its contents; closing the dialog discards that state.

Applying an imported model creates or updates the queried snapper's graphical special after the user confirms the alignment options. Revert removes that graphical special and restores the owner's current graphics in the preview.

QuerySubWindow now initializes with stdLightFrame/frameStateDown defaults and invokes initEvents() automatically. Subclasses that require an unframed window must pass frameStyle=noFrame, and subclasses that previously wired events outside construction should avoid registering the same observers twice.

Generic Part Codes and Export Data

Generic-code lookup now prefers an adjusted value, then allows PartProxy.genericCode() to provide a value, and otherwise uses the value stored on PartData. Flattening a part preserves the stored generic code. Importing part data now stores item.genericCode directly instead of converting it into an adjusted value.

The Generic Code calculation column uses Part.genericCode() first and retains TAG2 as a fallback. Extensions that previously treated TAG2 as the only generic-code source should use the new interface.

Part Special Handling Helpers

containsSpecial(PropObj) now returns true only when the object's PartSpecialHolder contains data, rather than merely when a holder exists. Code that used an empty holder as a presence flag must use a different check.

applyCustomParts() now returns immediately for a null part sequence, applies additions, and then applies overrides through the two new helper functions.

Query Dialog API Follow-up

QueryButton.press() now invokes the inherited Button.press() before its onClick event. A constructor callback and an onClick observer can therefore both run for one press; verify that handlers do not perform the same action twice.

QueryTabWindow.setVisible(true) no longer calls alignControls() automatically. Custom tab windows that depend on realignment when shown must do so from their visibility handler or another appropriate lifecycle method.

The model-import preview now restores its initial camera location and recenters the extents whenever the preview is refreshed.

Part Owner Identification

Part

PartSourceInfo will be set during construction of a Part. The itemTagKey field on PartSourceInfo for a given Part after first setting the sourceId and when sourceId changes.

setUserItemTagInfo(str text) has been updated to use loop over PartSourceInfos instead of Snapper owners.

WorldPart

Added loaded0 call to initialize empty partSourcInfo.

Preserving Part Adjustments When Resetting Item Tags

Part.resetItemTagInfo() now restores the default ItemTagInfo across every owner, clears the cached final key, and returns the default info. Code that relied on the returned object representing the former user-modified info must be updated.

When an adjustment key changes, migrateAdjusmentKeys() now copies the adjustment to the new key instead of changing the existing adjustment in place. With markOldPending=true, the old adjustment remains available while it is active on another part and is silently removed after it becomes inactive rather than appearing as an orphan adjustment.

Refreshing a SinglePartAdjustment no longer replaces a previously stored adjustment currency with null. A non-null currency from the current part still takes precedence.

cm.core.part.query

Multiline Query and Article View Text

PartMakeSpecialDialog now initializes its part-number and description controls from the owning Part, rather than from the existing PartSpecial:

Old: partNumTF.setText(original.partNum);
Old: descrTF.setText(original.descr);

New: partNumTF.setText(part.articleCode());
New: descrTF.setText(part.description());

When an existing special is edited, the controls therefore start with the owning part's current article code and description. The description control is now 100 pixels high, supports line breaking, and enables automatic scrolling after layout. Update custom layouts, UI automation, or workflows that rely on the previous single-line control or on the special's stored values being prefilled.

EditGridCell now stores tooltip text through setToolTipText(), inserting a newline after every 100 characters. This applies both to the default outS() tooltip and to text explicitly supplied by extensions. Code that compares or reuses toolTipText() should account for the inserted newline characters.

New: public void setToolTipText(str text) {
         text = insertNewLines(text);
         super(..);
     }

cm.core.propsScheme.layout

PsLayoutPropsScheme groupName fixes

The groupName has been adjusted to remove "www." prefix and remove trailing ".com". This affects visual display of schemes in Schemes Explorer and the title bar.

cm.core3D

Improvements to 3D text spacing

3D text created through Text3D or meshFromText(...) may get a different final width and character layout than before.

This also affects existing content when older drawings are opened in 17.5.

If code depends on previous text extents, alignment, or placement based on the old spacing behavior, those cases may need to be reviewed.

cm.extension

putIgnoreDir() changes in cm.extension

The recursive behavior of putIgnoreDir() has been corrected in 17.5. To minimize migration effort, the recursive parameter now defaults to false, preserving the previous behavior for existing code.

Previously, only the specified directory was added to the ignore list due to an implementation issue. In the recursive case, instead of adding each discovered subdirectory, the method repeatedly adds the original directory to the ignore list, producing duplicate entries and failing to add the subdirectories into the ignore list.

Existing code that calls putIgnoreDir() without specifying the recursive parameter should continue to behave as before. Code that explicitly specifies subdirectories individually is also unaffected.

The corrected recursive behavior makes it possible to ignore an entire directory tree by calling putIgnoreDir(dir, recursive=true), which now registers both the specified directory and all of its subdirectories into the ignore list.

Use int64 instead for tracking file sizes related to extension archives and check for sufficient hard disk space during updates

Previously there was a bug related to the filesize of the ExtensionInfo file whereby it used a 32-bit integer to keep track of the extension's size. This caused it to overflow when the extension archive became larger than 2GB. To fix this we added int64 versions of the various filesizes we use to keep track of the extension sizes in 17.5 onwards. We stil maintain the 32-bit version for backwards compatibility. However please note this value might be inaccurate.

Also we added a hard disk space check for CET updates as sometimes there were issues where CET updates would fail when the user ran out of hard disk space during CET updates. We now do a minimum size check during CET updates where we check if the user has enough hard disk space to install an extension.

As sometimes other processes like downloader and Windows updates might end up filling up the hard disk while the CET updates are running, we still allow the user to proceed with the CET updates anyway. They will now receive a notification where they can choose to continue with the update or cancel it when CET detects there might not be sufficient hard disk space. However if the disk space ever drops below 1GB, we mark the update as having failed.

cm.recovery

More specific error reports

We have made some updates to the error reporting dialog to have better categorization and more information for crash reports. The following interface now sends reports as bug reports.

cm.recovery.errorDialog.cm

public void addReportErrorButton(FlexDialog d, ErrorDialogArgs errorDialogArgs) {

To send reports as feedback or crash, use the following interfaces instead.

Feedback: public void addReportFeedbackButton(FlexDialog d, ErrorDialogArgs errorDialogArgs) {
Crash: public void addReportCrashButton(FlexDialog d, ErrorDialogArgs errorDialogArgs) {

Also crash reports require a stack trace string or call stack now so that crash locations are now traceable and will trigger a devassert if the stack traces are empty (sendBitsCrashReport or addReportCrashButton).

cm.std.draw3D

class StaticDraw3DMeasure

StaticDraw3DMeasure now supports 3D and can be inserted in 3D through DimensionInsertAnimation.

This is intended to replace the old 3D dimension class, Draw3DMeasureDimension.

StaticDraw3DMeasure now has the viewVis property with values only2D, only3D, and both. Rendering, hit testing, connector visibility, and association graphics invalidation are filtered using this value. Custom overrides of contains, isVisibleIn2D, isVisibleIn3D, build2D, or get3D should respect the selected view.

DimensionInsertAnimation initializes a new dimension as only2D when inserted in a 2D view and only3D when inserted in a 3D view.

Dimensions loaded from drawings saved before this change are initialized as visible in 2D-only by the loadFailed handling code. Extensions that expect legacy dimensions to remain visible in 3D should explicitly migrate or initialize viewVis to both or only3D.

A new enableRender property controls whether 3D dimensions are shown in renderings or not. It is only available when the dimension is visible in 3D.

class ChainDraw3DMeasure

ChainDraw3DMeasure now explicitly denies 3D graphics, since the base class now has 3D graphics and chain dimensions do not support that behavior.

If your extension overrides get3D on ChainDraw3DMeasure to show custom 3D graphics, also override deny3D to return false.

For example:

public bool deny3D() {
    return false;
}

cm.test.cmunit.testInstructions

class PutAnimationPropInstruction

PutAnimationPropInstruction now works better with CoreAnimations, and should behave closer to editing the same property in the animation input window.

If PutAnimationPropInstruction cannot find a supported animation property to update, it now reports an error instead of continuing with a less clear failure.

class ClickConnectorInstruction

ClickConnectorInstruction now verifies that the connector's parent snapper is alive and not suspended before trying to click it. This makes tests fail closer to the real user-visible problem when a connector can be found internally but cannot actually be clicked.

Pass ensureConnectorSnapperAlive=false to the constructor for tests that intentionally click connectors whose parent snapper is not in a normal alive state.

cm.win

UrlField button background brush

UrlField.drawUrlButton() now obtains the button fill from buttonBgBrush() instead of reading skin.control directly. The default implementation returns skin.control, so unmodified fields retain their previous appearance.

Existing UrlField subclasses that already implement buttonBgBrush() will now have that method called whenever the browse button is drawn. Verify that the returned brush is appropriate for every enabled button state. Subclasses that override drawUrlButton() without calling super() are unaffected by this new hook.

win_drawGlyphOutline improvements

win_drawGlyphOutline now advances text using glyph advance (gmCellIncX) instead of advancing from the maximum x extent of each emitted glyph outline. This improves 3D text spacing, especially for whitespace characters, but may change the final width and appearance of text generated from outline data.

Changes to callerLoc

Separator for `callerLoc()`` has been changed from '.' to '::' to make it easier to extract the package name.

Manufacturer prefix for dialogs

Starting in 17.5 Major, subclasses of DialogWindow in an extension will show the manufacturer prefix in the title bar. This is to aid users to identify the source of a dialog.

The same behavior of showing manufacturer prefix also applies to the following classes:

  • FlexDialogWindow
  • ModalDialog
  • NonModalMessageBox
  • NonModalWarningDialog
  • ProgressDialog

res.images

Several icons have been moved to the icon library (res/iconLibrary/) and are now available through the cetIconLib() function.

Note: You can find icons by running the CET Facelift Test Tools extension and searching the CET Icon Library toolbox.

  • icon("res/images/architectural/carpetCircle2.png") should be replaced with cetIconLib("Tools/Circle-tool-blue_Color_24")
  • icon("res/images/architectural/carpetCustomShape2.png") should be replaced with cetIconLib("Tools/3D-custom-shape-blue_Color_24")
  • icon("res/images/architectural/carpetRect2.png") should be replaced with cetIconLib("Tools/3D-rectangle-blue_Color_24")
  • icon("res/images/architectural/levelAddPoint.png") should be replaced with cetIconLib("Tools/Add-point_Color_24")
  • icon("res/images/architectural/levelCircle.png") should be replaced with cetIconLib("Tools/Circle-tool_Color_24")
  • icon("res/images/architectural/levelCurve.png") should be replaced with cetIconLib("Tools/Switch-straight-curved_Color_24")
  • icon("res/images/architectural/levelCustomShape.png") should be replaced with cetIconLib("Tools/3D-custom-shape_Color_24")
  • icon("res/images/architectural/levelInsertWall.png") should be replaced with cetIconLib("Tools/Insert-wall-edge_Color_24")
  • icon("res/images/architectural/levelRect.png") should be replaced with cetIconLib("Tools/3D-rectangle_Color_24")
  • icon("res/images/architectural/levelRemovePoint.png") should be replaced with cetIconLib("Tools/Remove-point_Color_24")
  • icon("res/images/architectural/levelSlice.png") should be replaced with cetIconLib("Tools/Slice-shape_Color_24")
  • icon("res/images/architectural/levelStretch.png") should be replaced with cetIconLib("Tools/Stretch-level_Color_24")
  • icon("res/images/draw3D/doublerFacelift.png") should be replaced with cetIconLib("Tools/Show-double-line_Color_24")
  • icon("res/images/draw3D/helpLineFacelift.png") should be replaced with cetIconLib("Tools/Help-line_Color_24")
  • icon("res/images/draw3D/meeterFacelift.png") should be replaced with cetIconLib("Tools/Measure_Color_24")
  • icon("res/images/draw3D/mirrorHorizontalFacelift.svg") should be replaced with cetIconLib("Tools/Flip-horizontally_Color_24")
  • icon("res/images/draw3D/mirrorLineFacelift.svg") should be replaced with cetIconLib("Tools/Mirror-across-line_Color_24")
  • icon("res/images/draw3D/mirrorVerticalFacelift.svg") should be replaced with cetIconLib("Tools/Flip-vertically_Color_24")
  • icon("res/images/draw3D/referencePointFacelift.png") should be replaced with cetIconLib("Tools/Help-point_Color_24")
  • icon("res/images/draw3D/trimmerFacelift.png") should be replaced with cetIconLib("Tools/Trim-line_Color_24")
  • icon("res/images/facelift2023/tbDrawingPaper.png") should be replaced with cetIconLib("Tools/Drawing-paper_Color_24")
  • icon("res/images/facelift2023/tbDrawingPaper.svg") should be replaced with cetIconLib("Tools/Drawing-paper_Color_24")
  • icon("res/images/icons/removerFacelift.png") should be replaced with cetIconLib("Tools/Remove-snapper_Color_24")
  • icon("res/images/tools/addPoint.png") should be replaced with cetIconLib("Tools/Add-point_Color_24")
  • icon("res/images/tools/angleDimension.png") should be replaced with cetIconLib("Tools/Angle-dimension_Line_24")
  • icon("res/images/tools/arc3Points.png") should be replaced with cetIconLib("Tools/Arc-three-point_Color_24")
  • icon("res/images/tools/arcInside2Tangents.png") should be replaced with cetIconLib("Tools/Arc-two-tagnent_Color_24")
  • icon("res/images/tools/arcRadiusAngle.png") should be replaced with cetIconLib("Tools/Arc-radius-angle_Color_24")
  • icon("res/images/tools/arcTangentAngle.png") should be replaced with cetIconLib("Tools/Arc-tangent-angle_Color_24")
  • icon("res/images/tools/arrow2Lines.png") should be replaced with cetIconLib("Tools/Arrow-two-line_Color_24")
  • icon("res/images/tools/arrowNormal.png") should be replaced with cetIconLib("Tools/Arrow-default_Color_24")
  • icon("res/images/tools/baseline.png") should be replaced with cetIconLib("Tools/Baseline_Color_24")
  • icon("res/images/tools/baselineDimension.png") should be replaced with cetIconLib("Tools/Baseline-dimension_Color_24")
  • icon("res/images/tools/cadZeroPoint.png") should be replaced with cetIconLib("Tools/CAD-zero-point_Color_24")
  • icon("res/images/tools/calcAreaAddPoint.png") should be replaced with cetIconLib("Tools/Add-point_Color_24")
  • icon("res/images/tools/calcAreaCurve.png") should be replaced with cetIconLib("Tools/Switch-straight-curved_Color_24")
  • icon("res/images/tools/calcAreaCustomShape.png") should be replaced with cetIconLib("Tools/3D-custom-shape_Color_24")
  • icon("res/images/tools/calcAreaMoveLine.png") should be replaced with cetIconLib("Tools/Move-line_Color_24")
  • icon("res/images/tools/chainDimension.png") should be replaced with cetIconLib("Tools/Chain-dimension_Line_24")
  • icon("res/images/tools/circle.png") should be replaced with cetIconLib("Tools/Circle-tool_Color_24")
  • icon("res/images/tools/circleDiameter.png") should be replaced with cetIconLib("Tools/Circle-diameter-tool_Color_24")
  • icon("res/images/tools/circleEllipse.png") should be replaced with cetIconLib("Tools/Ellipse-tool_Color_24")
  • icon("res/images/tools/circleRadius.png") should be replaced with cetIconLib("Tools/Circle-tool_Color_24")
  • icon("res/images/tools/columnBalloon.png") should be replaced with cetIconLib("Tools/Column-balloon_Color_24")
  • icon("res/images/tools/curve.png") should be replaced with cetIconLib("Tools/Switch-straight-curved_Color_24")
  • icon("res/images/tools/customShape.png") should be replaced with cetIconLib("Tools/3D-custom-shape_Color_24")
  • icon("res/images/tools/dataField.png") should be replaced with cetIconLib("Tools/Data-field_Color_24")
  • icon("res/images/tools/doubleArc3Points.png") should be replaced with cetIconLib("Tools/Arc-three-point-double_Color_24")
  • icon("res/images/tools/doubleArcInside2Tangents.png") should be replaced with cetIconLib("Tools/Arc-two-tagnent-double_Color_24")
  • icon("res/images/tools/doubleArcTangentAngle.png") should be replaced with cetIconLib("Tools/Arc-tangent-angle-double_Color_24")
  • icon("res/images/tools/doubleLine.png") should be replaced with cetIconLib("Tools/Double-line_Color_24")
  • icon("res/images/tools/doubleRectangle2Sided.png") should be replaced with cetIconLib("Tools/3D-rectangle-two-sided_Color_24")
  • icon("res/images/tools/doubleRectangle3Sided.png") should be replaced with cetIconLib("Tools/3D-rectangle-three-sided_Color_24")
  • icon("res/images/tools/doubleRectangleDefault.png") should be replaced with cetIconLib("Tools/3D-rectangle_Color_24")
  • icon("res/images/tools/doubleRectangleEdgeDiagonal.png") should be replaced with cetIconLib("Tools/3D-rectangle-diagonal_Color_24")
  • icon("res/images/tools/faceliftPrintableArticleView.png") should be replaced with cetIconLib("Systemwide/Print_Line_16")
  • icon("res/images/tools/faceliftViewClip2D.png") should be replaced with cetIconLib("Systemwide/View-clip-2D_Color_16")
  • icon("res/images/tools/faceliftViewClipEmpty.png") should be replaced with cetIconLib("Systemwide/View-clip-empty_Color_16")
  • icon("res/images/tools/faceliftViewport3D.png") should be replaced with cetIconLib("Systemwide/View-clip-3D_Color_16")
  • icon("res/images/tools/helpLine.png") should be replaced with cetIconLib("Tools/Help-line_Color_24")
  • icon("res/images/tools/helpPoint.png") should be replaced with cetIconLib("Tools/Help-point_Color_24")
  • icon("res/images/tools/hideEntities.png") should be replaced with cetIconLib("Tools/Hide-entities_Color_24")
  • icon("res/images/tools/hideLayers.png") should be replaced with cetIconLib("Tools/Hide-layers_Color_24")
  • icon("res/images/tools/incrementer.png") should be replaced with cetIconLib("Tools/Incrementer_Color_24")
  • icon("res/images/tools/insertWall.png") should be replaced with cetIconLib("Tools/Insert-wall-edge_Color_24")
  • icon("res/images/tools/label.png") should be replaced with cetIconLib("Tools/Label_Color_24")
  • icon("res/images/tools/leader.png") should be replaced with cetIconLib("Tools/Leader_Color_24")
  • icon("res/images/tools/line.png") should be replaced with cetIconLib("Tools/Line_Color_24")
  • icon("res/images/tools/lineDimension.png") should be replaced with cetIconLib("Tools/Dimension_Line_24")
  • icon("res/images/tools/lineDimensionPaper.png") should be replaced with cetIconLib("Tools/Dimension_Line_24")
  • icon("res/images/tools/loadImage.png") should be replaced with cetIconLib("Tools/Import-image_Color_24")
  • icon("res/images/tools/measureAndScale.png") should be replaced with cetIconLib("Tools/Measure-and-scale_Color_24")
  • icon("res/images/tools/meetAtAngle.png") should be replaced with cetIconLib("Tools/Meet-at-angle_Color_24")
  • icon("res/images/tools/northArrow.png") should be replaced with cetIconLib("Tools/North-arrow_Color_24")
  • icon("res/images/tools/offsetLine.png") should be replaced with cetIconLib("Tools/Offset-line_Color_24")
  • icon("res/images/tools/pen.png") should be replaced with cetIconLib("Tools/Pen_Color_24")
  • icon("res/images/tools/photolabImage.png") should be replaced with cetIconLib("Tools/Image_Color_24")
  • icon("res/images/tools/polygonHelpLine.png") should be replaced with cetIconLib("Tools/Help-line_Color_24")
  • icon("res/images/tools/polygonHelpPoint.png") should be replaced with cetIconLib("Tools/Help-point_Color_24")
  • icon("res/images/tools/polygonLine.png") should be replaced with cetIconLib("Tools/Grouped-single-line_Color_24")
  • icon("res/images/tools/polygonLineArrow.png") should be replaced with cetIconLib("Tools/Arrow-multiple-line_Color_24")
  • icon("res/images/tools/polygonLineArrowConnected.png") should be replaced with cetIconLib("Tools/Arrow-group-line_Color_24")
  • icon("res/images/tools/polygonLineConnected.png") should be replaced with cetIconLib("Tools/Grouped-group-line_Color_24")
  • icon("res/images/tools/quickChainDimension.png") should be replaced with cetIconLib("Tools/Chain-dimension_Line_24")
  • icon("res/images/tools/radialDimension.png") should be replaced with cetIconLib("Tools/Radius-dimension_Line_24")
  • icon("res/images/tools/rectangle2Sided.png") should be replaced with cetIconLib("Tools/3D-rectangle-two-sided_Color_24")
  • icon("res/images/tools/rectangle3Sided.png") should be replaced with cetIconLib("Tools/3D-rectangle-three-sided_Color_24")
  • icon("res/images/tools/rectangleDefault.png") should be replaced with cetIconLib("Tools/3D-rectangle_Color_24")
  • icon("res/images/tools/rectangleEdgeDiagonal.png") should be replaced with cetIconLib("Tools/3D-rectangle-diagonal_Color_24")
  • icon("res/images/tools/removePoint.png") should be replaced with cetIconLib("Tools/Remove-point_Color_24")
  • icon("res/images/tools/replicateCircular.png") should be replaced with cetIconLib("Tools/Replicate-circular_Color_24")
  • icon("res/images/tools/replicateLinear.png") should be replaced with cetIconLib("Tools/Replicate-linear_Color_24")
  • icon("res/images/tools/replicateRectangular.png") should be replaced with cetIconLib("Tools/Replicate-rectangular_Color_24")
  • icon("res/images/tools/revisionCloudCircular.png") should be replaced with cetIconLib("Tools/Revision-cloud-circle_Color_24")
  • icon("res/images/tools/revisionCloudCustom.png") should be replaced with cetIconLib("Tools/Revision-cloud-custom_Color_24")
  • icon("res/images/tools/revisionCloudLasso.png") should be replaced with cetIconLib("Tools/Revision-cloud-lasso_Color_24")
  • icon("res/images/tools/revisionCloudRectangular.png") should be replaced with cetIconLib("Tools/Revision-cloud-rectangular_Color_24")
  • icon("res/images/tools/show.png") should be replaced with cetIconLib("Systemwide/Show_Line_24")
  • icon("res/images/tools/slice.png") should be replaced with cetIconLib("Tools/Slice-shape_Color_24")
  • icon("res/images/tools/spreadsheet.png") should be replaced with cetIconLib("Tools/Spreadsheet_Color_24")
  • icon("res/images/tools/square.png") should be replaced with cetIconLib("Tools/3D-rectangle_Color_24")
  • icon("res/images/tools/text.png") should be replaced with cetIconLib("Tools/Text_Color_24")
  • icon("res/images/tools/trimLine.png") should be replaced with cetIconLib("Tools/Trim-line_Color_24")
  • icon("res/images/tools/twoClickDimensionLarge.png") should be replaced with cetIconLib("Tools/Dimension_Line_24")
  • icon("res/images/wall/3DTextOnWallsFacelift.png") should be replaced with cetIconLib("Extension-specific/3D-text-on-walls_Color_24")
  • icon("res/images/wall/arcWallByRadiusAndAngleFacelift.png") should be replaced with cetIconLib("Extension-specific/Arc-wall-radius-angle_Color_24")
  • icon("res/images/wall/arcWallInsideTwoTangentLinesFacelift.png") should be replaced with cetIconLib("Extension-specific/Arc-wall-two-tangent-lines_Color_24")
  • icon("res/images/wall/arcWallThroughTangentAndAngleFacelift.png") should be replaced with cetIconLib("Extension-specific/Arc-wall-tangent-angle_Color_24")
  • icon("res/images/wall/ceilingDividedCenterFacelift.png") should be replaced with cetIconLib("Extension-specific/Ceiling-divided-center_Color_24")
  • icon("res/images/wall/ceilingDividedLeftFacelift.png") should be replaced with cetIconLib("Extension-specific/Ceiling-divided-left_Color_24")
  • icon("res/images/wall/ceilingDividedRightFacelift.png") should be replaced with cetIconLib("Extension-specific/Ceiling-divided-right_Color_24")
  • icon("res/images/wall/columnFacelift.png") should be replaced with cetIconLib("Extension-specific/Column_Color_24")
  • icon("res/images/wall/continuousWallFacelift.png") should be replaced with cetIconLib("Extension-specific/Continuous-wall_Color_24")
  • icon("res/images/wall/curtainsFacelift.png") should be replaced with cetIconLib("Extension-specific/Curtains_Color_24")
  • icon("res/images/wall/drainFacelift.png") should be replaced with cetIconLib("Extension-specific/Drain_Color_24")
  • icon("res/images/wall/explodeToThinStraightWallsFacelift.png") should be replaced with cetIconLib("Extension-specific/Explode-to-thin-walls_Color_24")
  • icon("res/images/wall/glassPartition.png") should be replaced with cetIconLib("Extension-specific/Glass-partition_Color_24")
  • icon("res/images/wall/glassPartitionDoor.png") should be replaced with cetIconLib("Extension-specific/Glass-partition-door_Color_24")
  • icon("res/images/wall/imageOnWallFacelift.png") should be replaced with cetIconLib("Extension-specific/Image-on-wall_Color_24")
  • icon("res/images/wall/panelCurtainFacelift.png") should be replaced with cetIconLib("Extension-specific/Panel-curtain_Color_24")
  • icon("res/images/wall/panelCurtainRodFacelift.png") should be replaced with cetIconLib("Extension-specific/Panel-curtain-rod_Color_24")
  • icon("res/images/wall/pilasterFacelift.png") should be replaced with cetIconLib("Extension-specific/Pilaster_Color_24")
  • icon("res/images/wall/plainCeilingFacelift.png") should be replaced with cetIconLib("Extension-specific/Plain-ceiling_Color_24")
  • icon("res/images/wall/radiatorFacelift.png") should be replaced with cetIconLib("Extension-specific/Radiator_Color_24")
  • icon("res/images/wall/rollerDoorFacelift.png") should be replaced with cetIconLib("Extension-specific/Roller-door_Color_24")
  • icon("res/images/wall/sectionalDoorFacelift.png") should be replaced with cetIconLib("Extension-specific/Sectional-door_Color_24")
  • icon("res/images/wall/slidingDoorFacelift.png") should be replaced with cetIconLib("Extension-specific/Sliding-door_Color_24")
  • icon("res/images/wall/straightMediumWallFacelift.png") should be replaced with cetIconLib("Extension-specific/Straight-medium-wall_Color_24")
  • icon("res/images/wall/straightThickWallFacelift.png") should be replaced with cetIconLib("Extension-specific/Straight-thick-wall_Color_24")
  • icon("res/images/wall/straightThinWallFacelift.png") should be replaced with cetIconLib("Extension-specific/Straight-thin-wall_Color_24")
  • icon("res/images/wall/surfaceTilesFacelift.png") should be replaced with cetIconLib("Extension-specific/Surface-tiles_Color_24")
  • icon("res/images/wall/triPilasterFacelift.png") should be replaced with cetIconLib("Extension-specific/Tri-pilaster_Color_24")
  • icon("res/images/wall/valveFacelift.png") should be replaced with cetIconLib("Extension-specific/Valve_Color_24")
  • icon("res/images/wall/venetianBlindsFacelift.png") should be replaced with cetIconLib("Extension-specific/Venetian-blinds_Color_24")
  • icon("res/images/wall/verticalBlindsFacelift.png") should be replaced with cetIconLib("Extension-specific/Vertical-blinds_Color_24")
  • icon("res/images/wall/wallDoorFacelift.png") should be replaced with cetIconLib("Extension-specific/Wall-door_Color_24")
  • icon("res/images/wall/wallDoubleDoorFacelift.png") should be replaced with cetIconLib("Extension-specific/Wall-double-door_Color_24")
  • icon("res/images/wall/wallModificationHoleFacelift.png") should be replaced with cetIconLib("Extension-specific/Wall-modification-hole_Color_24")
  • icon("res/images/wall/windowFacelift.png") should be replaced with cetIconLib("Extension-specific/Window_Color_24")
  • icon("res/images/wall/windowSillFacelift.png") should be replaced with cetIconLib("Extension-specific/Window-sill_Color_24")
  • icon("res/images/xclip/faceliftAlwaysReadableCompanion.png") should be replaced with cetIconLib("Tools/Rotate-always-readable-text_Line_24")
  • icon("res/images/xclip/faceliftApplyTemplate.png") should be replaced with cetIconLib("Tools/Apply-template_Color_24")
  • icon("res/images/xclip/faceliftBlackWhiteCompanion.png") should be replaced with cetIconLib("Tools/Show-only-black-and-white_Line_24")
  • icon("res/images/xclip/faceliftCollomBallonCompanion.png") should be replaced with cetIconLib("Tools/Column-balloon_Color_24")
  • icon("res/images/xclip/faceliftDebugCompanion.png") should be replaced with cetIconLib("Tools/Debug-information_Line_24")
  • icon("res/images/xclip/faceliftEllipses.png") should be replaced with cetIconLib("Tools/Ellipse-tool_Color_24")
  • icon("res/images/xclip/faceliftFrameCompanion.png") should be replaced with cetIconLib("Tools/Add-a-frame_Color_24")
  • icon("res/images/xclip/faceliftPartTagPlotStyleCompanion.png") should be replaced with cetIconLib("Drawing/Tag_Color_24")
  • icon("res/images/xclip/faceliftScalableTextCompanion.png") should be replaced with cetIconLib("Tools/Custom-scale-for-text-in-view-clip_Line_24")
  • icon("res/images/xclip/faceliftScaleCompanion.png") should be replaced with cetIconLib("Tools/Show-scale_Color_24")

Miscellaneous

cm.core

class Space

Space now exposes the overridable method isElevationSpace(), which returns false by default. Custom elevation-space implementations should override it to return true. Dimension view-visibility editing uses this method to distinguish elevation spaces from ordinary spaces.