Skip to content

Commit

Permalink
Try to move item by pseudo dragging
Browse files Browse the repository at this point in the history
Enact-DCO-1.0-Signed-off-by: Seungcheon Baek (sc.baek@lge.com)
  • Loading branch information
0x64 committed Feb 21, 2022
1 parent b907a5b commit 1175ee0
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 30 deletions.
18 changes: 12 additions & 6 deletions packages/ui/VirtualList/VirtualList.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ const VirtualList = (props) => {
VirtualList.displayName = 'ui:VirtualList';

VirtualList.propTypes = /** @lends ui/VirtualList.VirtualList.prototype */ {
cbMoveItem: PropTypes.func,

/**
* A callback function that receives a reference to the `scrollTo` feature.
*
Expand Down Expand Up @@ -118,6 +116,8 @@ VirtualList.propTypes = /** @lends ui/VirtualList.VirtualList.prototype */ {
*/
direction: PropTypes.oneOf(['horizontal', 'vertical']),

editMode: PropTypes.bool,

/**
* Specifies how to show horizontal scrollbar.
*
Expand Down Expand Up @@ -228,6 +228,8 @@ VirtualList.propTypes = /** @lends ui/VirtualList.VirtualList.prototype */ {
*/
onScrollStop: PropTypes.func,

onUpdateItemsOrder: PropTypes.func,

/**
* Specifies overscroll effects shows on which type of inputs.
*
Expand Down Expand Up @@ -279,15 +281,16 @@ VirtualList.propTypes = /** @lends ui/VirtualList.VirtualList.prototype */ {
};

VirtualList.defaultProps = {
cbMoveItem: nop,
cbScrollTo: nop,
direction: 'vertical',
editMode: false,
horizontalScrollbar: 'auto',
noScrollByDrag: false,
noScrollByWheel: false,
onScroll: nop,
onScrollStart: nop,
onScrollStop: nop,
onUpdateItemsOrder: nop,
overscrollEffectOn: {
drag: false,
pageKey: false,
Expand Down Expand Up @@ -344,8 +347,6 @@ const VirtualGridList = (props) => {
VirtualGridList.displayName = 'ui:VirtualGridList';

VirtualGridList.propTypes = /** @lends ui/VirtualList.VirtualGridList.prototype */ {
cbMoveItem: PropTypes.func,

/**
* A callback function that receives a reference to the `scrollTo` feature.
*
Expand Down Expand Up @@ -391,6 +392,8 @@ VirtualGridList.propTypes = /** @lends ui/VirtualList.VirtualGridList.prototype
*/
direction: PropTypes.oneOf(['horizontal', 'vertical']),

editMode: PropTypes.bool,

/**
* Specifies how to show horizontal scrollbar.
*
Expand Down Expand Up @@ -501,6 +504,8 @@ VirtualGridList.propTypes = /** @lends ui/VirtualList.VirtualGridList.prototype
*/
onScrollStop: PropTypes.func,

onUpdateItemsOrder: PropTypes.func,

/**
* Specifies overscroll effects shows on which type of inputs.
*
Expand Down Expand Up @@ -552,15 +557,16 @@ VirtualGridList.propTypes = /** @lends ui/VirtualList.VirtualGridList.prototype
};

VirtualGridList.defaultProps = {
cbMoveItem: nop,
cbScrollTo: nop,
direction: 'vertical',
editMode: false,
horizontalScrollbar: 'auto',
noScrollByDrag: false,
noScrollByWheel: false,
onScroll: nop,
onScrollStart: nop,
onScrollStop: nop,
onUpdateItemsOrder: nop,
overscrollEffectOn: {
drag: false,
pageKey: false,
Expand Down
106 changes: 84 additions & 22 deletions packages/ui/VirtualList/VirtualListBasic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import EnactPropTypes from '@enact/core/internal/prop-types';
import {forward} from '@enact/core/handle';
import {platform} from '@enact/core/platform';
import {clamp} from '@enact/core/util';
import {utilDOM} from '@enact/ui/useScroll/utilDOM';
import PropTypes from 'prop-types';
import equals from 'ramda/src/equals';
import {createRef, Component} from 'react';
Expand Down Expand Up @@ -93,8 +94,6 @@ class VirtualListBasic extends Component {
gridListItemSizeShape
]).isRequired,

cbMoveItem: PropTypes.func,

/**
* Callback method of scrollTo.
* Normally, useScroll should set this value.
Expand Down Expand Up @@ -171,6 +170,8 @@ class VirtualListBasic extends Component {
*/
direction: PropTypes.oneOf(['horizontal', 'vertical']),

editMode: PropTypes.bool,

/**
* Called to get the scroll affordance from themed component.
*
Expand Down Expand Up @@ -203,6 +204,8 @@ class VirtualListBasic extends Component {
*/
itemSizes: PropTypes.arrayOf(PropTypes.number),

onUpdateItemsOrder: PropTypes.func,

/**
* Called when the range of items has updated.
*
Expand Down Expand Up @@ -299,10 +302,10 @@ class VirtualListBasic extends Component {
};

static defaultProps = {
cbMoveItem: nop,
cbScrollTo: nop,
dataSize: 0,
direction: 'vertical',
editMode: false,
getAffordance: () => (0),
overhang: 3,
pageScroll: false,
Expand Down Expand Up @@ -330,10 +333,11 @@ class VirtualListBasic extends Component {
prevFirstIndex: 0,
updateFrom: 0,
updateTo: 0,
editMode: props.editMode,
...nextState
};

props.cbMoveItem(this.moveItem);
this.emitUpdateItemsOrder = props.onUpdateItemsOrder;
window.moveItem = this.moveItem; // FIXME: for testing only
}

Expand Down Expand Up @@ -370,6 +374,13 @@ class VirtualListBasic extends Component {
} else {
this.setContainerSize();
}

if (this.props.scrollContentRef.current) {
const node = this.props.scrollContentRef.current;
node.addEventListener('mousedown', this.itemMovingBegin);
node.addEventListener('mousemove', this.itemMoving);
node.addEventListener('mouseup', this.itemMovingEnd);
}
}

componentDidUpdate (prevProps, prevState) {
Expand Down Expand Up @@ -511,6 +522,9 @@ class VirtualListBasic extends Component {
itemPositions = [];
indexToScrollIntoView = -1;

// Edit mode
editingIndex = null;

updateScrollPosition = ({x, y}, rtl = this.props.rtl) => {
if (this.props.scrollMode === 'native') {
this.scrollToPosition(x, y, rtl);
Expand All @@ -530,7 +544,7 @@ class VirtualListBasic extends Component {

getCenterItemIndexFromScrollPosition = (scrollPosition) => Math.floor((scrollPosition + (this.primary.clientSize / 2)) / this.primary.gridSize) * this.dimensionToExtent + Math.floor(this.dimensionToExtent / 2);

getGridPosition (index) {
getGridPosition (index) { // TBD
const
{dataSize, itemSizes} = this.props,
{dimensionToExtent, itemPositions, primary, secondary} = this,
Expand Down Expand Up @@ -561,7 +575,7 @@ class VirtualListBasic extends Component {
}

// For individually sized item
getItemBottomPosition = (index) => {
getItemBottomPosition = (index) => { // TBD
const
itemPosition = this.itemPositions[index],
itemSize = this.props.itemSizes[index];
Expand All @@ -574,11 +588,11 @@ class VirtualListBasic extends Component {
};

// For individually sized item
getItemTopPositionFromPreviousItemBottomPosition = (index, spacing) => {
getItemTopPositionFromPreviousItemBottomPosition = (index, spacing) => { // TBD
return index === 0 ? 0 : this.getItemBottomPosition(index - 1) + spacing;
};

getItemPosition = (index, stickTo = 'start', optionalOffset = 0) => {
getItemPosition = (index, stickTo = 'start', optionalOffset = 0) => { // TBD
const {isPrimaryDirectionVertical, primary, scrollBounds} = this;
const maxPos = isPrimaryDirectionVertical ? scrollBounds.maxTop : scrollBounds.maxLeft;
const position = this.getGridPosition(index);
Expand Down Expand Up @@ -688,7 +702,7 @@ class VirtualListBasic extends Component {
}
}

getStatesAndUpdateBounds = (props, firstIndex = 0) => {
getStatesAndUpdateBounds = (props, firstIndex = 0) => { // TBD
const
{dataSize, overhang, updateStatesAndBounds} = props,
{dimensionToExtent, primary, moreInfo, scrollPosition} = this,
Expand Down Expand Up @@ -727,7 +741,7 @@ class VirtualListBasic extends Component {
};
};

calculateFirstIndex (props, wasFirstIndexMax, dataSizeDiff, firstIndex) {
calculateFirstIndex (props, wasFirstIndexMax, dataSizeDiff, firstIndex) { // TBD
const
{overhang} = props,
{dimensionToExtent, isPrimaryDirectionVertical, maxFirstIndex, primary, scrollBounds, scrollPosition, threshold} = this,
Expand Down Expand Up @@ -981,7 +995,7 @@ class VirtualListBasic extends Component {
}

// For individually sized item
calculateAndCacheItemPosition (index) {
calculateAndCacheItemPosition (index) { // TBD
const {itemSizes} = this.props;

if (!this.itemPositions[index] && itemSizes[index]) {
Expand All @@ -994,7 +1008,7 @@ class VirtualListBasic extends Component {
}

// For individually sized item
applyItemPositionToDOMElement (index) {
applyItemPositionToDOMElement (index) { // TBD
const
{direction, rtl} = this.props,
{numOfItems} = this.state,
Expand Down Expand Up @@ -1096,39 +1110,40 @@ class VirtualListBasic extends Component {
return style;
}

applyStyleToNewNode = (index, ...rest) => {
applyStyleToNewNode = (index, ...rest) => { // TBD
const dataIndex = index;
const
{childProps, itemRefs, itemRenderer, getComponentProps} = this.props,
key = index % this.state.numOfItems,
componentProps = getComponentProps && getComponentProps(index) || {},
componentProps = getComponentProps && getComponentProps(dataIndex) || {},
itemContainerRef = (ref) => {
if (ref === null) {
itemRefs.current[key] = ref;
} else {
const itemNode = ref.children[0];

itemRefs.current[key] = (parseInt(itemNode.dataset.index) === index) ?
itemRefs.current[key] = (parseInt(itemNode.dataset.index) === dataIndex) ?
itemNode :
ref.querySelector(`[data-index="${index}"]`);
ref.querySelector(`[data-index="${dataIndex}"]`); // TBD

this.itemContainerRefs[key] = ref;
}
};

this.cc[key] = (
this.cc[key] = ( // TBD
<div className={css.listItem} key={key} ref={itemContainerRef} style={this.composeStyle(...rest)}>
{itemRenderer({...childProps, ...componentProps, index})}
{itemRenderer({...childProps, ...componentProps, index: dataIndex})}
</div>
);
};

applyStyleToHideNode = (index) => {
applyStyleToHideNode = (index) => { // TBD
const
{itemRefs} = this.props,
key = index % this.state.numOfItems,
itemContainerRef = () => (itemRefs.current[key] = null);

this.cc[key] = <div key={key} ref={itemContainerRef} style={{display: 'none'}} />;
this.cc[key] = <div key={key} ref={itemContainerRef} style={{display: 'none'}} />; // TBD
};

positionItems () {
Expand Down Expand Up @@ -1224,8 +1239,54 @@ class VirtualListBasic extends Component {
return false;
};

getCCNodeFromPosition = (x, y) => {
if (typeof window !== 'undefined') {
const contentNode = this.contentRef.current;
let node = document.elementFromPoint(x, y);
if (utilDOM.containsDangerously(contentNode, node)) {
while (node.parentNode !== contentNode) {
if (node === document) {
return null;
}
node = node.parentNode;
}

return node;
}
}

return null;
}

getIndexFromCCNode = (node) => (node ? parseInt(node.querySelector(`[data-index]`).dataset.index) : null)

itemMovingBegin = ({clientX, clientY}) => {
console.log('mousedown');
const node = this.getCCNodeFromPosition(clientX, clientY);
this.editingIndex = this.getIndexFromCCNode(node);
}

itemMoving = ({clientX, clientY}) => {
console.log('mousemove');
if (this.editingIndex !== null) {
const node = this.getCCNodeFromPosition(clientX, clientY);
const index = this.getIndexFromCCNode(node);
if (index !== null) {
this.moveItem(this.editingIndex, index);
this.editingIndex = index;
}
}
}

itemMovingEnd = () => {
console.log('mouseup');
this.editingIndex = null;
}

moveItem = (from, to) => {
console.log('moveItem', from, to);
const newItemsOrder = [...Array(this.props.dataSize).keys()];
newItemsOrder.splice(to, 0, newItemsOrder.splice(from, 1)[0]);
this.emitUpdateItemsOrder(newItemsOrder);
}

// render
Expand All @@ -1243,12 +1304,12 @@ class VirtualListBasic extends Component {
),
contentClasses = scrollModeNative ? null : css.content;

delete rest.cbMoveItem;
delete rest.cbScrollTo;
delete rest.childProps;
delete rest.clientSize;
delete rest.dataSize;
delete rest.direction;
delete rest.editMode;
delete rest.getAffordance;
delete rest.getComponentProps;
delete rest.isHorizontalScrollbarVisible;
Expand All @@ -1259,6 +1320,7 @@ class VirtualListBasic extends Component {
delete rest.itemSizes;
delete rest.onUpdate;
delete rest.onUpdateItems;
delete rest.onUpdateItemsOrder;
delete rest.overhang;
delete rest.pageScroll;
delete rest.rtl;
Expand Down
Loading

0 comments on commit 1175ee0

Please sign in to comment.