Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 37 additions & 91 deletions src/framework/components/scrollbar/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { ElementDragHelper } from '../element/element-drag-helper.js';
/**
* @import { EventHandle } from '../../../core/event-handle.js'
* @import { Entity } from '../../entity.js'
* @import { ScrollbarComponentSystem } from './system.js'
*/

/**
Expand Down Expand Up @@ -69,6 +68,15 @@ class ScrollbarComponent extends Component {
*/
static EVENT_SETVALUE = 'set:value';

/** @private */
_orientation = ORIENTATION_HORIZONTAL;

/** @private */
_value = 0;

/** @private */
_handleSize = 0;

/**
* @type {Entity|null}
* @private
Expand All @@ -87,35 +95,6 @@ class ScrollbarComponent extends Component {
*/
_evtHandleEntityChanges = [];

/**
* Create a new ScrollbarComponent.
*
* @param {ScrollbarComponentSystem} system - The ComponentSystem that created this Component.
* @param {Entity} entity - The Entity that this Component is attached to.
*/
constructor(system, entity) {
super(system, entity);
this._toggleLifecycleListeners('on');
}

/**
* Sets the enabled state of the component.
*
* @type {boolean}
*/
set enabled(arg) {
this._setValue('enabled', arg);
}

/**
* Gets the enabled state of the component.
*
* @type {boolean}
*/
get enabled() {
return this.data.enabled;
}

/**
* Sets whether the scrollbar moves horizontally or vertically. Can be:
*
Expand All @@ -127,7 +106,15 @@ class ScrollbarComponent extends Component {
* @type {number}
*/
set orientation(arg) {
this._setValue('orientation', arg);
if (this._orientation === arg) {
return;
}

this._orientation = arg;

if (this._handleEntity?.element) {
this._handleEntity.element[this._getOppositeDimension()] = 0;
}
Comment on lines 108 to +117
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed - this is a real (pre-existing) bug. ElementDragHelper captures its axis at construction, so flipping orientation at runtime leaves drags constrained to the old axis and can stop value updates from happening. Fixed in 6016d61bf as part of #8694: the orientation setter now rebuilds the drag helper and calls _updateHandlePositionAndSize() when a handle element is already attached. Regression test included.

}

/**
Expand All @@ -136,7 +123,7 @@ class ScrollbarComponent extends Component {
* @type {number}
*/
get orientation() {
return this.data.orientation;
return this._orientation;
}

/**
Expand All @@ -145,7 +132,11 @@ class ScrollbarComponent extends Component {
* @type {number}
*/
set value(arg) {
this._setValue('value', arg);
if (Math.abs(arg - this._value) > 1e-5) {
this._value = math.clamp(arg, 0, 1);
this._updateHandlePositionAndSize();
this.fire('set:value', this._value);
}
}

/**
Expand All @@ -154,7 +145,7 @@ class ScrollbarComponent extends Component {
* @type {number}
*/
get value() {
return this.data.value;
return this._value;
}

/**
Expand All @@ -165,7 +156,10 @@ class ScrollbarComponent extends Component {
* @type {number}
*/
set handleSize(arg) {
this._setValue('handleSize', arg);
if (Math.abs(arg - this._handleSize) > 1e-5) {
this._handleSize = math.clamp(arg, 0, 1);
this._updateHandlePositionAndSize();
}
}

/**
Expand All @@ -174,7 +168,7 @@ class ScrollbarComponent extends Component {
* @type {number}
*/
get handleSize() {
return this.data.handleSize;
return this._handleSize;
}

/**
Expand Down Expand Up @@ -208,12 +202,6 @@ class ScrollbarComponent extends Component {
if (this._handleEntity) {
this._handleEntitySubscribe();
}

if (this._handleEntity) {
this.data.handleEntity = this._handleEntity.getGuid();
} else if (isString && arg) {
this.data.handleEntity = arg;
}
}

/**
Expand All @@ -225,26 +213,6 @@ class ScrollbarComponent extends Component {
return this._handleEntity;
}

/** @ignore */
_setValue(name, value) {
const data = this.data;
const oldValue = data[name];
data[name] = value;
this.fire('set', name, oldValue, value);
}

/**
* @param {string} onOrOff - 'on' or 'off'.
* @private
*/
_toggleLifecycleListeners(onOrOff) {
this[onOrOff]('set_value', this._onSetValue, this);
this[onOrOff]('set_handleSize', this._onSetHandleSize, this);
this[onOrOff]('set_orientation', this._onSetOrientation, this);

// TODO Handle scrollwheel events
}

_handleEntitySubscribe() {
this._evtHandleEntityElementAdd = this._handleEntity.on('element:add', this._onHandleElementGain, this);

Expand Down Expand Up @@ -299,31 +267,10 @@ class ScrollbarComponent extends Component {
}
}

_onSetValue(name, oldValue, newValue) {
if (Math.abs(newValue - oldValue) > 1e-5) {
this.data.value = math.clamp(newValue, 0, 1);
this._updateHandlePositionAndSize();
this.fire('set:value', this.data.value);
}
}

_onSetHandleSize(name, oldValue, newValue) {
if (Math.abs(newValue - oldValue) > 1e-5) {
this.data.handleSize = math.clamp(newValue, 0, 1);
this._updateHandlePositionAndSize();
}
}

_onSetHandleAlignment() {
this._updateHandlePositionAndSize();
}

_onSetOrientation(name, oldValue, newValue) {
if (newValue !== oldValue && this._handleEntity?.element) {
this._handleEntity.element[this._getOppositeDimension()] = 0;
}
}

_updateHandlePositionAndSize() {
const handleEntity = this._handleEntity;
const handleElement = handleEntity?.element;
Expand Down Expand Up @@ -353,34 +300,34 @@ class ScrollbarComponent extends Component {

_getTrackLength() {
if (this.entity.element) {
return this.orientation === ORIENTATION_HORIZONTAL ? this.entity.element.calculatedWidth : this.entity.element.calculatedHeight;
return this._orientation === ORIENTATION_HORIZONTAL ? this.entity.element.calculatedWidth : this.entity.element.calculatedHeight;
}

return 0;
}

_getHandleLength() {
return this._getTrackLength() * this.handleSize;
return this._getTrackLength() * this._handleSize;
}

_getHandlePosition() {
return this._scrollValueToHandlePosition(this.value);
return this._scrollValueToHandlePosition(this._value);
}

_getSign() {
return this.orientation === ORIENTATION_HORIZONTAL ? 1 : -1;
return this._orientation === ORIENTATION_HORIZONTAL ? 1 : -1;
}

_getAxis() {
return this.orientation === ORIENTATION_HORIZONTAL ? 'x' : 'y';
return this._orientation === ORIENTATION_HORIZONTAL ? 'x' : 'y';
}

_getDimension() {
return this.orientation === ORIENTATION_HORIZONTAL ? 'width' : 'height';
return this._orientation === ORIENTATION_HORIZONTAL ? 'width' : 'height';
}

_getOppositeDimension() {
return this.orientation === ORIENTATION_HORIZONTAL ? 'height' : 'width';
return this._orientation === ORIENTATION_HORIZONTAL ? 'height' : 'width';
}

_destroyDragHelper() {
Expand All @@ -405,7 +352,6 @@ class ScrollbarComponent extends Component {

onRemove() {
this._destroyDragHelper();
this._toggleLifecycleListeners('off');
}

resolveDuplicatedEntityReferenceProperties(oldScrollbar, duplicatedIdsMap) {
Expand Down
16 changes: 0 additions & 16 deletions src/framework/components/scrollbar/data.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
import { ORIENTATION_HORIZONTAL } from '../../../scene/constants.js';

/**
* @import { Entity } from '../../../framework/entity'
*/

class ScrollbarComponentData {
enabled = true;

orientation = ORIENTATION_HORIZONTAL;

value = 0;

/** @type {number} */
handleSize = 0;

/** @type {Entity|null} */
handleEntity = null;
}

export { ScrollbarComponentData };
31 changes: 24 additions & 7 deletions src/framework/components/scrollbar/system.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Component } from '../component.js';
import { ComponentSystem } from '../system.js';
import { ScrollbarComponent } from './component.js';
import { ScrollbarComponentData } from './data.js';
Expand All @@ -6,12 +7,9 @@ import { ScrollbarComponentData } from './data.js';
* @import { AppBase } from '../../app-base.js'
*/

const _schema = [
{ name: 'enabled', type: 'boolean' },
{ name: 'orientation', type: 'number' },
{ name: 'value', type: 'number' },
{ name: 'handleSize', type: 'number' }
];
const _schema = ['enabled'];

const _properties = ['orientation', 'value', 'handleSize', 'handleEntity'];

/**
* Manages creation of {@link ScrollbarComponent}s.
Expand Down Expand Up @@ -40,8 +38,25 @@ class ScrollbarComponentSystem extends ComponentSystem {
}

initializeComponentData(component, data, properties) {
for (let i = 0; i < _properties.length; i++) {
const property = _properties[i];
if (data.hasOwnProperty(property)) {
component[property] = data[property];
}
}

super.initializeComponentData(component, data, _schema);
component.handleEntity = data.handleEntity;
}

cloneComponent(entity, clone) {
const c = entity.scrollbar;
return this.addComponent(clone, {
enabled: c.enabled,
orientation: c.orientation,
value: c.value,
handleSize: c.handleSize,
handleEntity: c.handleEntity
});
}

_onAddComponent(entity) {
Expand All @@ -53,4 +68,6 @@ class ScrollbarComponentSystem extends ComponentSystem {
}
}

Component._buildAccessors(ScrollbarComponent.prototype, _schema);

export { ScrollbarComponentSystem };
Loading