The valueS()
function in DsiPDataOption
was updated to now return specialCode
if there is one.
// dsiPDataOption.cm Old: extend public str valueS() { if (_dataType.Character) return code; ... } New: extend public str valueS() { if (_dataType.Character) return specialCode ?? code; ... }
The generateSifOptionRows
function in DsPData
was updated to take a DsPart
as a parameter.
// dsPData.cm Old: final public void generateSifOptionRows(SifEnv env, Option o, DsiPDataOption pO, int level=0) : deprecated New: final public void generateSifOptionRows(SifEnv env, Option o, DsiPDataOption pO, DsPart part=null, int level=0)
The generateSifOptionRows
function in DsPData
was updated to export a CustomerOwnMaterial
code and description for
a DsiPDataOption
where appropriate.
The dsGenerateCOMPartsHook
was added as part of the rawPartListHooks
. It gathers CustomerOwnMaterial
s on DsPData
s and
generates child COMPart
s from these materials.
// hooks.cm /** * Append COMParts from Part. * (COMParts hook) */ package Part[] dsGenerateCOMPartsHook(Part[] parts, Space space) { for (part in parts) { Snapper snapper = part.owner; generateCOMParts(snapper, part); } return parts; }
Deprecated functions:
public void build() : deprecated
public void rebuild()
updates the dialogpublic void editTFCB() : deprecated
public void controlCb(Control c)
public void updateTF() : deprecated
public void update()
As mentioned under Compile Time Changes, MhFrameUpdateBayHeightFunction
has been renamed to MhFrameHeightChangeUpdateBayFunction
. This was changed to more accurately reflect the logic of the class.
Additionally, the function key associated with this function has already been changed:
Old: res << MhFrameUpdateBayHeightFunction("frameUpdateBayHeight"); New: res << MhFrameHeightChangeUpdateBayFunction("frameHeightChangeUpdateBay");
All calls of "frameUpdateBayHeight"
have been updated to "frameHeightChangeUpdateBay"
in the abstract, you will need to do the same as well in your extension.
The measurements()
method has had some of its code moved out into seperate methods getBayHeightMeasurements()
and getLevelHeightMeasurements()
.
/** * Get bay height measurements. */ extend public void getBayHeightMeasurements(<line, double, point>[] lines, MhSnapper owner, box b, double offset) { double lbh = owner.shapeBoundWithChildren(symbols=[sLevel, sUnitLoad]).h; double frameH = lbh; forChildren(snapper in owner.rootParent) if (snapper as MhSnapper) { // Frame Height lines << <line(b.p0, (b.p0.point2D, frameH)), offset, (0, 1, 0)>; } /** * Get level height measurements. */ extend public void getLevelHeightMeasurements(<line, double, point>[] lines, MhSnapper owner, box b, double offset) { double last = 0; double lastZ = 0; for (MhSnapper l in owner.getSortedChildren(), index=i) { if (l.isLevel) { // Level height (between levels). double curr = l.toSpaceTransform.pos.z; lines << <line((b.p1.x, b.p0.y, last), (b.p1.x, b.p0.y, curr)), offset, (0, -1, 0)>; last = curr; // Level height - frame height. box lb = l.shapeBound([sLevel, sLevelFrame]); double z = curr - lb.h; lines << <line((b.p1.x, b.p1.y, lastZ), (b.p1.x, b.p1.y, z)), offset, point0>; lastZ = l.localBoundWithChildren.p1.z + curr; } } }
Removed specific configuration behaviors as default behaviors for the bay, frame, and level spawners.
Affected spawners:
The field preview
has been moved down from MhRackingConfiguration
in the cm.abstract.materialHandling.storage.racking
package into MhStorageConfiguration
in the cm.abstract.materialHandling.storage
package.
public class MhStorageConfiguration extends MhSystemConfiguration { /** * Preview */ public MhStorageConfigurationPreview preview : copy=null, stream=null; }
You do not need to add any load code as this field is not streamed.
This class also now generates and returns a preview by default. If you do not wish to see a preview in your pre configurator, you will have to override the configurationPreview()
method.
Old: extend public MhStorageConfigurationPreview configurationPreview() { return null; } New: extend public MhStorageConfigurationPreview configurationPreview() { if (!preview) preview = MhStorageConfigurationPreview(); return preview; }
New method updateSystemsAfterExport added to engine manager that runs after export instead of after the initial export. alignAllSnapped of the rows is now done in updateSystemsAfterExport instead of updateSystemsAfterInitialExport.
New: extend public void updateSystemsAfterExport(MhSystemEngineEnvironment env, MhSystemCollection[] systems, Snapper{} snappers, MhEngine engine)
Currently when calling mhRunEngines()
, all collected engine runs will be ran. We have introduced the ability to only run specific engine runs by passing in a space
to MhRunEngineEnv
. If space
has been passed into the engine run env, when running engines, we will not execute any engine runs that do not match the engine related to the given space
.
public class MhEngineManager extends CoreObject { /** * Run all engines. */ extend public void runEngines(MhRunEngineEnv runEnv=null) { ... Space space = runEnv.space; for (e, list in engineRunList) { ... if (space and e != mhEngine(space, createIfNone=false)) continue; ... } ... } }
Here are the changes we made to now use space
when running engines:
public class MhStorageConfigurationPreview extends PropObj { /** * Populate the preview snappers. */ extend public void populatePreviewSnappers(MhStorageConfiguration config, MhStorageConfigurationItem item=null) { ... mhRunEngines(MhRunEngineEnv(space=previewSpace, blockFinalize=false, blockExport=true)); ... } /** * Spawn preview snappers. */ extend public void spawnPreviewSnappers(MhStorageConfiguration config) { ... mhRunEngines(MhRunEngineEnv(space=previewSpace, blockExport=false)); }
MhSnapper
validate event for sRunEngines
will now only run engine runs for the snapper's space.public class MhSnapper extends Snapper { /** * Validate 'k' (change to set). */ public void validate(symbol k, Object env=null) { ... switch (k) { case sRunEngines: { ... mhRunEngines(MhRunEngineEnv(space=space, blockFinalize=true, initiator=initiator)); ... } ... }
mhRunEngines()
call at every #endUndoStep
event viewed by MhEngineManagerEventViewer
has been changed to first collect all spaces related to the undo step and then call mhRunEngines()
for each collected space.public class MhEngineManagerEventViewer extends EventViewer { Old: /** * Event being fired. */ public bool event(symbol event, Object z, str->Object args) { if (event == #endUndoStep) { if (?UndoStep step = z) { ... mhRunEngines(MhRunEngineEnv(blockFinalize=false, blockExport=true)); } } ... } New: /** * Event being fired. */ public bool event(symbol event, Object z, str->Object args) { if (event == #endUndoStep) { if (?UndoStep step = z) { Space{} spaces(4); for (MhSnapper s in step.referred) { if (!s.isAlive) continue; spaces << s.space; ... } } for (s in spaces) mhRunEngines(MhRunEngineEnv(space=s, blockFinalize=false, blockExport=true)); } } ... } }
Tunnel graphics will no longer be shown during rendering. The line that removed the tunnel from the rendering is as below:
public class MhTunnelGfxBehavior extends MhGenericGfxBehavior { /** * Tunnel 3D. */ extend public Primitive3D tunnel3D(MhSnapper owner, FetchEnv3D env) { ... p.layer = not(#render); ... }
This change is made in tunnel3D()
from the MhTunnelGfxBehavior
class, located in behavior/mhTunnelGfxBehavior.cm
.
So any tunnel that uses this class and method will no longer be rendered, and this method will have to be overriden if you would still like the tunnel to be shown.
The method updateBayHeight()
has been updated to use logic similar to other storage extensions. It relies on the mhCalculatedBayHeightForConstruction()
function.
We do not expect shelving products to have floor levels and so have update MhShelvingBayEngineBehavior
to not generate floor levels by default.
public class MhShelvingBayEngineBehavior extends MhBayEngineBehavior { /** * Add floor level. */ public bool addFloorLevel(MhSnapper snapper) { return false; } /** * * Accepts function run. */ public bool acceptFunctionRun(MhSnapper snapper, MhEngineFunctionRun func, symbol event="", Object env=null) { str funcName = func.name; if (funcName == "bayEnsureFloor") return false; return super(..); } }
See "New pre configurator classes" about the new `MhShelvingConfiguration class which mentioned overridden logic to support no floor levels.
MhShelvingClearanceConfigurationItem
now returns a MhShelvingClearanceSpec
object by default for defaultClearance()
.
public class MhShelvingClearanceConfigurationItem extends MhClearanceCompartmentConfigurationItem { /** * Default clearance. */ public MhClearanceSpec defaultClearance() { return MhShelvingClearanceSpec(); } }
Selective racking extension now extends from generic Extension class.
Old: private class AbstractSelectiveRackingExtension extends AbsRackingExtension New: private class AbstractSelectiveRackingExtension extends Extension
Previously, if a sequence was declared as 'weak', it would also clear out null
values when the sequence is resized. This would cause the observed contents of the seqeunce to change at what would appear to be an arbitrary time. With this release, these sequences will no longer clean up null
values on resize.
When streaming a collection with weak values, the object loses the weak value attribute when being streamed back in. This functionally meant that all unstreamed collections would not have the weak value attribute, regardless of their state before streaming. As of this release, the weak value attribute will be respected when un-streaming.
A function to collect any additional child parts has been added to the OrderExporter
. This is to catch COMPart
s that are appended during rawPartsListHooks
.
// orderExporter.cm extend public void collectAdditionalChildParts(Part[] parts)
DwgBspEntry is now responsible for caching graph.bound
.
To utilize the cache, access the bound by calling DwgBspEntry::bound()
rather than DwgBspEntry::graph.bound()
. The latter will always return a freshly calculated bound, while the former is cached.
Also, be mindful that you do not mutate a Graph
owned by a DwgBspEntry
in a way that affects it bound after its initialization, as this does not automatically clear the cache.
Fixed a bug in gText.cm
where evaluatedSize()
did not properly respect the scale
argument. It only updated the font with the scale, bus assumed the scale for the actual size was 0.001.
You can ignore this if you do not manually call evaluatedSize
. If not, note that evaluatedSize
is now scaled up by a factor of scale / 0.001
compared to previous versions of CET.
The following changes were made to support development efforts of the new UI.
A new automatic caching system has been added for extension libraries, so any custom caching should be removed in order to not conflict with it.
UIHint
s now apply to children of the LibraryLimb
as well. This allows
applying the same hint to all child limbs without explicitly passing it in to
each one. You can still override the hint by applying a different hint to the
limb.
semiHidden()
is no longer a condition in isVisibleInMaterialList()
as a way of including child parts during exports.
// part.cm Old: public bool isVisibleInMaterialList(Part part, bool expand, bool child) { bool view; if (!part.visibleInMaterialList()) view = false; else if (part.zeroQuantity(true)) view = false; else if (part.canceled()) view = false; else if (part.semiHidden()) view = false; else view = true; return view; } New: public bool isVisibleInMaterialList(Part part, bool expand, bool child) { bool view; if (!part.visibleInMaterialList()) { view = false; } else if (part.zeroQuantity(true)) { view = false; } else if (part.canceled()) { view = false; } else { view = true; } return view; }
A method for building the columns for a PartInfoTree
was added. When a PartInfoTree
is being built in the CalculationGridWindow
, this method is called to build it's columns.
Added: extend public void buildColumns(CalculationGridWindow grid, int row, Space space) {
The toolbox card width has been updated when running CET in new UI. This matches our new design system for component tab libraries.
For existing libraries that are not adopting to newUI (i.e. useFacelift=false
):
For the best experience in new UI, consider adopting your component library for the new UI. https://dev-docs.configura.com/design-system/tutorial-adopting-the-new-ui-style-for-extension-libraries
For more information on what is possible with libraries in new UI: https://dev-docs.configura.com/design-system/component-tab-libraries
Developers could previously add hooks for updating toolbox style treeviews when a style is updated by appending to updateToolBoxHook
.
In addition to this, they would need to append a SelectWorldHooks
to rebuild the treeview when the world changes (as different worlds have different saved styles).
Developers should no longer add a SelectWorldHooks
to update toolbox drop downs, if they are already updated in hooks in updateToolBoxHook
. All updateToolBoxHook
are now called automatically when a new world is selected.
Updating via SelectWorldHooks
should not cause functional issues, but may impact performance, as the update will happen twice.
Added new field to cache already exported materials.
Added: private str->DwgMaterialData cachedMaterials();
The following changes were made to support development efforts of new UI.
The origin of parent Window
s will now be respected when doing operations like extendRight
, extendBottom
, extendBottomRight
, and any other positioning functions, which may affect the layout of your dialogs.
The new UI comes with a different larger font, which may affect the layout of your windows. This typically shows up in the various forms:
Some common classes that are affected:
Hidden cards no longer get size updates from their parent parent CardWindow
. This is to improve resizing performance. Instead, CardWindow will call parentClientBoundChanged
before your card is shown.
To handle custom layout logic, you may can override Card's parentClientBoundChanged
:
/** * Parent client bound changed. */ public void parentClientBoundChanged() { sizeI prevSize = size(); super(); if (size() != prevSize) updateLayout(); }
Card are no longer constructed with a hardcoded size of (100, 100) to improve performance.
Upon constructing a MenuBar, you need to perform a finalize()
method call.
CoolMenuBar menu(parent); buildFileMenu(menu); buildEditMenu(menu); buildManufacturersMenu(menu); menuBar.finalize();
The finalize method call performs the following:
Call
finalizeSubMenu
to ensure sub menu margins consistent.Perform an
autoSize
to calculates appropriate width and height.Resize and reposition
xControls
as required duringparentClientBoundChanged
The following classes no longer paint frames in repaintFrame.
ShrinkBox
ShrinkWindow
SubGroupBox
Subclasses of the above classes should migrate their repaintFrame overrides to repaint. In most cases a rename of the method signature would suffice.
Removed: public bool repaintFrame(mdc hdc, rectI r) Replace: public bool repaint(mdc hdc, rectI r)
If you have code that used to call repaintFrame()
, you should replace it with refreshFrame()
Old: repaintFrame(); New: refreshFrame();
In future releases, we will try to remove repaintFrame in more places.