Skip to content

Commit

Permalink
🎨: refactor layout-policy resizing and prevent feedbackloop via meta …
Browse files Browse the repository at this point in the history
…flag

Replaces old and not very well working control flows with a more sophisticated approach to determining sizing behavior of a styled morph within the context of various layouts.
According to the identified sizing behavior, the extent is applied in varying fashions. Also previously accidental re-execution of layouts would happen due to policies applying themselves, which lead to inefficient layout applications overall. This is now prevented with a meta flag.
  • Loading branch information
merryman authored and linusha committed Feb 5, 2025
1 parent 545b452 commit 65809a6
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 24 deletions.
49 changes: 25 additions & 24 deletions lively.morphic/components/policy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ export class StylePolicy {
* @returns { boolean | object } Wether or not size is controlled via layout and if so, the concrete policy.
*/
isResizedByLayout (aSubmorph) {
const layout = aSubmorph.owner && aSubmorph.owner.layout;
let layout = aSubmorph.owner && aSubmorph.owner.layout;
let heightPolicy = 'fixed'; let widthPolicy = 'fixed';
if (aSubmorph.isText) {
if (!aSubmorph.fixedHeight) heightPolicy = 'hug';
Expand All @@ -1306,6 +1306,19 @@ export class StylePolicy {
if (widthPolicy !== 'hug') widthPolicy = layout.getResizeWidthPolicyFor(aSubmorph);
if (heightPolicy === 'fill' || widthPolicy === 'fill') return { widthPolicy, heightPolicy };
}

layout = aSubmorph.layout;

if (layout?.hugContentsVertically ||
layout?.hugContentsHorizontally ||
widthPolicy === 'hug' ||
heightPolicy === 'hug') {
return {
widthPolicy: layout?.hugContentsHorizontally ? 'hug' : widthPolicy,
heightPolicy: layout?.hugContentsVertically ? 'hug' : heightPolicy
};
}

return false;
}

Expand Down Expand Up @@ -1498,8 +1511,17 @@ export class PolicyApplicator extends StylePolicy {
if (propName === 'position' && this.isPositionedByLayout(morphToBeStyled)) continue;
let resizePolicy;
if (propName === 'extent' && (resizePolicy = this.isResizedByLayout(morphToBeStyled))) {
if (resizePolicy.widthPolicy === 'fixed' && morphToBeStyled.width !== propValue.x) morphToBeStyled.width = propValue.x;
if (resizePolicy.heightPolicy === 'fixed' && morphToBeStyled.height !== propValue.y) morphToBeStyled.height = propValue.y;
morphToBeStyled.withMetaDo({ deferLayoutApplication: true }, () => {
if (resizePolicy.widthPolicy === 'fixed' && morphToBeStyled.width !== propValue.x) {
morphToBeStyled.width = propValue.x;
}
if (resizePolicy.heightPolicy === 'fixed' && morphToBeStyled.height !== propValue.y) {
morphToBeStyled.height = propValue.y;
}
if (morphToBeStyled.isText && (resizePolicy.widthPolicy === 'hug' || resizePolicy.heightPolicy === 'hug')) {
morphToBeStyled.withMetaDo({ doNotFit: false }, () => morphToBeStyled.fit());
}
});
continue;
}

Expand All @@ -1514,32 +1536,11 @@ export class PolicyApplicator extends StylePolicy {
if (propName === 'position') continue;
}

// FIXME: other special cases??
if (morphToBeStyled.isText && propName === 'extent') {
if (!morphToBeStyled.fixedWidth && !morphToBeStyled.fixedHeight) continue;
if (!morphToBeStyled.fixedWidth) propValue = propValue.withX(morphToBeStyled.width);
if (!morphToBeStyled.fixedHeight) propValue = propValue.withY(morphToBeStyled.height);
}

if (morphToBeStyled.isText && propName === 'width' && morphToBeStyled.lineWrapping !== 'no-wrap') {
if (!morphToBeStyled.fixedWidth) continue;
morphToBeStyled.width = propValue;
morphToBeStyled.withMetaDo({ doNotFit: false }, () => morphToBeStyled.fit());
}

if (['border', 'borderTop', 'borderBottom', 'borderRight', 'borderLeft'].includes(propName)) continue; // handled by sub props;

if (!obj.equals(morphToBeStyled[propName], propValue)) {
morphToBeStyled[propName] = propValue;
}

// we may be late for the game when setting these props
// se we need to make sure, we restore the morphs "intended extent"
// for this purpose we enforce the masterSubmorph extent
if (['fixedHeight', 'fixedWidth'].includes(propName) &&
morphToBeStyled._parametrizedProps?.extent) {
morphToBeStyled.extent = morphToBeStyled._parametrizedProps.extent;
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions lively.morphic/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,10 @@ export class TilingLayout extends Layout {
}

scheduleApply (submorph, animation, change = {}) {
if (change.meta?.deferLayoutApplication) {
return;
}

if (!change.meta?.isLayoutAction || !this.container?._yogaNode?.getParent()) {
this._alreadyComputed = false;
}
Expand Down

0 comments on commit 65809a6

Please sign in to comment.