piling.js
Version:
A WebGL-based Library for Visual Piling/Stacking
980 lines (844 loc) • 25.3 kB
JavaScript
import {
pipe,
camelToConst,
deepClone,
cubicInOut,
update,
withForwardedMethod,
withReadOnlyProperty,
withStaticProperty,
} from '@flekschas/utils';
import deepEqual from 'deep-equal';
import { createStore as createReduxStore, combineReducers } from 'redux';
import { enableBatching } from 'redux-batched-actions';
import { version } from '../package.json';
import createOrderer from './orderer';
import {
DEFAULT_DARK_MODE,
DEFAULT_LASSO_FILL_OPACITY,
DEFAULT_LASSO_SHOW_START_INDICATOR,
DEFAULT_LASSO_START_INDICATOR_OPACITY,
DEFAULT_LASSO_STROKE_OPACITY,
DEFAULT_LASSO_STROKE_SIZE,
DEFAULT_PILE_COVER_SCALE,
DEFAULT_PILE_ITEM_BRIGHTNESS,
DEFAULT_PILE_ITEM_TINT,
DEFAULT_PILE_SIZE_BADGE_ALIGN,
DEFAULT_POPUP_BACKGROUND_OPACITY,
DEFAULT_PREVIEW_BACKGROUND_COLOR,
DEFAULT_PREVIEW_BACKGROUND_OPACITY,
NAVIGATION_MODE_AUTO,
NAVIGATION_MODES,
} from './defaults';
const clone = (value, state) => {
switch (typeof value) {
case 'object': {
if (!deepEqual(value, state)) {
return deepClone(value);
}
return state;
}
default:
return value;
}
};
const setReducer = (key, defaultValue = null) => {
const actionType = `SET_${camelToConst(key)}`;
return (state = defaultValue, action) => {
switch (action.type) {
case actionType:
return clone(action.payload[key], state);
default:
return state;
}
};
};
const setOptionsReducer = (key, options, defaultValue = null) => {
// eslint-disable-next-line no-param-reassign
options = new Set(options);
const actionType = `SET_${camelToConst(key)}`;
return (state = defaultValue, action) => {
switch (action.type) {
case actionType:
if (options.has(action.payload[key])) {
return clone(action.payload[key], state);
}
return state;
default:
return state;
}
};
};
const setAction = (key) => {
const type = `SET_${camelToConst(key)}`;
return (newValue) => ({ type, payload: { [key]: newValue } });
};
const setter = (key, defaultValue = null) => [
setReducer(key, defaultValue),
setAction(key),
];
const setterOptions = (key, options, defaultValue = null) => [
setOptionsReducer(key, options, defaultValue),
setAction(key),
];
export const reset = () => ({
type: 'RESET',
payload: {},
});
export const overwrite = (newState, debug) => ({
type: 'OVERWRITE',
payload: { newState, debug },
});
export const softOverwrite = (newState, debug) => ({
type: 'SOFT_OVERWRITE',
payload: { newState, debug },
});
const [arrangementType, setArrangementType] = setter('arrangementType');
const [arrangementObjective, setArrangementObjective] = setter(
'arrangementObjective'
);
const [arrangeOnGrouping, setArrangeOnGrouping] = setter(
'arrangeOnGrouping',
false
);
const [arrangementOptions, setArrangementOptions] = setter(
'arrangementOptions',
{}
);
const [groupingType, setGroupingType] = setter('groupingType');
const [groupingObjective, setGroupingObjective] = setter('groupingObjective');
const [groupingOptions, setGroupingOptions] = setter('groupingOptions', {});
const [splittingType, setSplittingType] = setter('splittingType');
const [splittingObjective, setSplittingObjective] = setter(
'splittingObjective'
);
const [splittingOptions, setSplittingOptions] = setter('splittingOptions', {});
const [backgroundColor, setBackgroundColor] = setter(
'backgroundColor',
0x000000
);
const [darkMode, setDarkMode] = setter('darkMode', DEFAULT_DARK_MODE);
const [dimensionalityReducer, setDimensionalityReducer] = setter(
'dimensionalityReducer'
);
const [gridColor, setGridColor] = setter('gridColor', 0x787878);
const [gridOpacity, setGridOpacity] = setter('gridOpacity', 1);
const [showGrid, setShowGrid] = setter('showGrid', false);
const [popupBackgroundOpacity, setPopupBackgroundOpacity] = setter(
'popupBackgroundOpacity',
DEFAULT_POPUP_BACKGROUND_OPACITY
);
const [lassoFillColor, setLassoFillColor] = setter('lassoFillColor');
const [lassoFillOpacity, setLassoFillOpacity] = setter(
'lassoFillOpacity',
DEFAULT_LASSO_FILL_OPACITY
);
const [lassoShowStartIndicator, setLassoShowStartIndicator] = setter(
'lassoShowStartIndicator',
DEFAULT_LASSO_SHOW_START_INDICATOR
);
const [lassoStartIndicatorOpacity, setLassoStartIndicatorOpacity] = setter(
'lassoStartIndicatorOpacity',
DEFAULT_LASSO_START_INDICATOR_OPACITY
);
const [lassoStrokeColor, setLassoStrokeColor] = setter('lassoStrokeColor');
const [lassoStrokeOpacity, setLassoStrokeOpacity] = setter(
'lassoStrokeOpacity',
DEFAULT_LASSO_STROKE_OPACITY
);
const [lassoStrokeSize, setLassoStrokeSize] = setter(
'lassoStrokeSize',
DEFAULT_LASSO_STROKE_SIZE
);
const [itemRenderer, setItemRenderer] = setter('itemRenderer');
const [previewRenderer, setPreviewRenderer] = setter('previewRenderer');
const [coverRenderer, setCoverRenderer] = setter('coverRenderer');
const [previewAggregator, setPreviewAggregator] = setter('previewAggregator');
const [coverAggregator, setCoverAggregator] = setter('coverAggregator');
const [orderer, setOrderer] = setter('orderer', createOrderer().rowMajor);
// Grid
const [itemSize, setItemSize] = setter('itemSize');
const [itemSizeRange, setItemSizeRange] = setter('itemSizeRange', [0.5, 1.0]);
const [columns, setColumns] = setter('columns', 10);
const [rowHeight, setRowHeight] = setter('rowHeight');
const [cellAspectRatio, setCellAspectRatio] = setter('cellAspectRatio', 1);
const [cellPadding, setCellPadding] = setter('cellPadding', 12);
const [cellSize, setCellSize] = setter('cellSize');
const [pileCoverScale, setPileCoverScale] = setter(
'pileCoverScale',
DEFAULT_PILE_COVER_SCALE
);
const [pileCoverInvert, setPileCoverInvert] = setter('pileCoverInvert', false);
const [pileItemBrightness, setPileItemBrightness] = setter(
'pileItemBrightness',
DEFAULT_PILE_ITEM_BRIGHTNESS
);
const [pileItemInvert, setPileItemInvert] = setter('pileItemInvert', false);
const [pileItemOffset, setPileItemOffset] = setter('pileItemOffset', [5, 5]);
const [pileItemOpacity, setPileItemOpacity] = setter('pileItemOpacity', 1.0);
const [pileOrderItems, setPileOrderItems] = setter('pileOrderItems');
const [pileItemRotation, setPileItemRotation] = setter('pileItemRotation', 0);
const [pileItemTint, setPileItemTint] = setter(
'pileItemTint',
DEFAULT_PILE_ITEM_TINT
);
const [focusedPiles, setFocusedPiles] = setter('focusedPiles', []);
const [magnifiedPiles, setMagnifiedPiles] = setter('magnifiedPiles', []);
// 'originalPos' and 'closestPos'
const [depileMethod, setDepileMethod] = setter('depileMethod', 'originalPos');
const [depiledPile, setDepiledPile] = setter('depiledPile', []);
const [temporaryDepiledPiles, setTemporaryDepiledPiles] = setter(
'temporaryDepiledPiles',
[]
);
// 'horizontal' or 'vertical'
const [tempDepileDirection, setTempDepileDirection] = setter(
'tempDepileDirection',
'horizontal'
);
const [tempDepileOneDNum, setTempDepileOneDNum] = setter(
'tempDepileOneDNum',
6
);
const [easing, setEasing] = setter('easing', cubicInOut);
const [navigationMode, setNavigationMode] = setterOptions(
'navigationMode',
NAVIGATION_MODES,
NAVIGATION_MODE_AUTO
);
const [previewItemOffset, setPreviewItemOffset] = setter('previewItemOffset');
const [previewAlignment, setPreviewAlignment] = setter(
'previewAlignment',
'top'
);
const [previewPadding, setPreviewPadding] = setter('previewPadding', 2);
const [previewScaling, setPreviewScaling] = setter('previewScaling', [1, 1]);
const [
previewScaleToCover,
setPreviewScaleToCover,
] = setter('previewScaleToCover', [false, false]);
const [previewSpacing, setPreviewSpacing] = setter('previewSpacing', 2);
const [previewOffset, setPreviewOffset] = setter('previewOffset', 2);
const [previewBackgroundColor, setPreviewBackgroundColor] = setter(
'previewBackgroundColor',
DEFAULT_PREVIEW_BACKGROUND_COLOR
);
const [previewBackgroundOpacity, setPreviewBackgroundOpacity] = setter(
'previewBackgroundOpacity',
DEFAULT_PREVIEW_BACKGROUND_OPACITY
);
const [previewBorderColor, setPreviewBorderColor] = setter(
'previewBorderColor'
);
const [previewBorderOpacity, setPreviewBorderOpacity] = setter(
'previewBorderOpacity',
0.85
);
const [pileBackgroundColor, setPileBackgroundColor] = setter(
'pileBackgroundColor'
);
const [pileBackgroundOpacity, setPileBackgroundOpacity] = setter(
'pileBackgroundOpacity',
0
);
const [pileBackgroundColorHover, setPileBackgroundColorHover] = setter(
'pileBackgroundColorHover'
);
const [pileBackgroundOpacityHover, setPileBackgroundOpacityHover] = setter(
'pileBackgroundOpacityHover',
0.85
);
const [pileBackgroundColorFocus, setPileBackgroundColorFocus] = setter(
'pileBackgroundColorFocus'
);
const [pileBackgroundOpacityFocus, setPileBackgroundOpacityFocus] = setter(
'pileBackgroundOpacityFocus'
);
const [pileBackgroundColorActive, setPileBackgroundColorActive] = setter(
'pileBackgroundColorActive'
);
const [pileBackgroundOpacityActive, setPileBackgroundOpacityActive] = setter(
'pileBackgroundOpacityActive'
);
const [pileBorderColor, setPileBorderColor] = setter(
'pileBorderColor',
0x808080
);
const [pileBorderOpacity, setPileBorderOpacity] = setter(
'pileBorderOpacity',
1.0
);
const [pileBorderColorHover, setPileBorderColorHover] = setter(
'pileBorderColorHover',
0x808080
);
const [pileBorderOpacityHover, setPileBorderOpacityHover] = setter(
'pileBorderOpacityHover',
1.0
);
const [pileBorderColorFocus, setPileBorderColorFocus] = setter(
'pileBorderColorFocus',
0xeee462
);
const [pileBorderOpacityFocus, setPileBorderOpacityFocus] = setter(
'pileBorderOpacityFocus',
1.0
);
const [pileBorderColorActive, setPileBorderColorActive] = setter(
'pileBorderColorActive',
0xffa5da
);
const [pileBorderOpacityActive, setPileBorderOpacityActive] = setter(
'pileBorderOpacityActive',
1.0
);
const [pileBorderSize, setPileBorderSize] = setter('pileBorderSize', 0);
// 'topLeft', 'topRight', 'bottomLeft', 'bottomRight', 'center'
const [pileCellAlignment, setPileCellAlignment] = setter(
'pileCellAlignment',
'topLeft'
);
const [pileContextMenuItems, setPileContextMenuItems] = setter(
'pileContextMenuItems',
[]
);
const [pileSizeBadge, setPileSizeBadge] = setter('pileSizeBadge', false);
const [pileSizeBadgeAlign, setPileSizeBadgeAlign] = setter(
'pileSizeBadgeAlign',
DEFAULT_PILE_SIZE_BADGE_ALIGN
);
const [pileVisibilityItems, setPileVisibilityItems] = setter(
'pileVisibilityItems',
true
);
const [pileOpacity, setPileOpacity] = setter('pileOpacity', 1.0);
const [pileScale, setPileScale] = setter('pileScale', 1.0);
const [zoomScale, setZoomScale] = setter('zoomScale', 1.0);
// Label
const [pileLabel, setPileLabel] = setter('pileLabel');
const [pileLabelColor, setPileLabelColor] = setter('pileLabelColor');
const [pileLabelText, setPileLabelText] = setter('pileLabelText', false);
const [pileLabelTextMapping, setPileLabelTextMapping] = setter(
'pileLabelTextMapping',
false
);
const [pileLabelTextColor, setPileLabelTextColor] = setter(
'pileLabelTextColor',
0x000000
);
const [pileLabelTextOpacity, setPileLabelTextOpacity] = setter(
'pileLabelTextOpacity',
1
);
const [pileLabelTextStyle, setPileLabelTextStyle] = setter(
'pileLabelTextDropShadow',
{}
);
const [pileLabelAlign, setPileLabelAlign] = setter('pileLabelAlign', 'bottom');
const [pileLabelStackAlign, setPileLabelStackAlign] = setter(
'pileLabelStackAlign',
'horizontal'
);
const [pileLabelFontSize, setPileLabelFontSize] = setter(
'pileLabelFontSize',
7
);
const [pileLabelHeight, setPileLabelHeight] = setter('pileLabelHeight', 2);
const [pileLabelSizeTransform, setPileLabelSizeTransform] = setter(
'pileLabelSizeTransform'
);
const [projector, setProjector] = setter('projector');
const [zoomBounds, setZoomBounds] = setter('zoomBounds', [-Infinity, Infinity]);
const items = (previousState = {}, action) => {
switch (action.type) {
case 'SET_ITEMS': {
const useCustomId = action.payload.items.length
? typeof action.payload.items[0].id !== 'undefined'
: false;
return action.payload.items.reduce((newState, item, index) => {
const id = useCustomId ? item.id : index;
newState[id] = {
id,
index,
...item,
};
return newState;
}, {});
}
default:
return previousState;
}
};
const setItems = (newItems) => ({
type: 'SET_ITEMS',
payload: { items: newItems },
});
const piles = (previousState = {}, action) => {
switch (action.type) {
case 'SET_PILES': {
return Object.entries(action.payload.piles).reduce(
(newState, [pileId, pileState], index) => {
newState[pileId] = {
...pileState,
id: pileId,
index: Number.isNaN(+pileState.index) ? index : +pileState.index,
};
return newState;
},
{}
);
}
case 'INIT_PILES': {
const useCustomItemId = action.payload.newItems.length
? typeof action.payload.newItems[0].id !== 'undefined'
: false;
const newItemIds = action.payload.newItems.reduce(
(itemIds, item, index) => {
const id = item.id === undefined ? index.toString() : item.id;
itemIds.add(id);
return itemIds;
},
new Set()
);
return action.payload.newItems.reduce((newState, item, index) => {
const itemId = useCustomItemId ? item.id : index.toString();
const previousPileState = previousState[itemId];
const newPileState = {
id: itemId,
index,
items: [itemId],
x: null,
y: null,
...previousPileState,
};
if (previousPileState) {
if (previousPileState.items.length) {
newPileState.items = previousPileState.items.filter((id) =>
newItemIds.has(id)
);
} else if (newItemIds.has(itemId)) {
const isItemOnPile = Object.values(previousState).filter(
(pile) => pile.items.includes(itemId) && newItemIds.has(pile.id)
).length;
if (!isItemOnPile) newPileState.items = [itemId];
}
}
newState[itemId] = newPileState;
return newState;
}, {});
}
case 'MERGE_PILES': {
const newState = { ...previousState };
let target;
if (
action.payload.targetPileId === undefined &&
// eslint-disable-next-line no-restricted-globals
isNaN(action.payload.pileIds[0])
) {
target = action.payload.pileIds[0];
} else {
target =
action.payload.targetPileId !== undefined
? action.payload.targetPileId
: Math.min.apply([], action.payload.pileIds).toString();
}
const sourcePileIds = action.payload.pileIds.filter(
(id) => id !== target
);
const [x, y] = action.payload.targetPos;
newState[target] = {
...newState[target],
items: [...newState[target].items],
x,
y,
};
sourcePileIds.forEach((id) => {
newState[target].items.push(...newState[id].items);
newState[id] = {
...newState[id],
items: [],
x: null,
y: null,
};
});
return newState;
}
case 'MOVE_PILES': {
const newState = { ...previousState };
action.payload.movingPiles.forEach(({ id, x, y }) => {
newState[id] = {
...newState[id],
x,
y,
};
});
return newState;
}
case 'SCATTER_PILES': {
const scatterPiles = action.payload.piles.filter(
(pile) => pile.items.length > 1
);
if (!scatterPiles.length) return previousState;
const newState = { ...previousState };
scatterPiles.forEach((pile) => {
pile.items.forEach((itemId) => {
newState[itemId] = {
...newState[itemId],
items: [itemId],
x: pile.x,
y: pile.y,
};
});
});
return newState;
}
case 'SPLIT_PILES': {
if (!Object.values(action.payload.piles).length) return previousState;
const newState = { ...previousState };
// The 0th index represents the groups that is kept on the source pile
Object.entries(action.payload.piles)
// If there is only one split group we don't have to do anything
.filter((splittedPiles) => splittedPiles[1].length > 1)
.forEach(([source, splits]) => {
splits.forEach((itemIds) => {
newState[itemIds[0]] = {
...newState[itemIds[0]],
x: newState[source].x,
y: newState[source].y,
items: [...itemIds],
};
});
});
return newState;
}
default:
return previousState;
}
};
// action
const initPiles = (newItems) => ({
type: 'INIT_PILES',
payload: { newItems },
});
const mergePiles = (pileIds, targetPos, targetPileId) => ({
type: 'MERGE_PILES',
payload: { pileIds, targetPos, targetPileId },
});
const movePiles = (movingPiles) => ({
type: 'MOVE_PILES',
payload: { movingPiles },
});
const scatterPiles = (pilesToBeScattered) => ({
type: 'SCATTER_PILES',
payload: { piles: pilesToBeScattered },
});
const splitPiles = (pilesToBeSplit) => ({
type: 'SPLIT_PILES',
payload: { piles: pilesToBeSplit },
});
const setPiles = (newPiles) => ({
type: 'SET_PILES',
payload: { piles: newPiles },
});
const [showSpatialIndex, setShowSpatialIndex] = setter(
'showSpatialIndex',
false
);
const createStore = () => {
let lastAction = null;
const reducers = {
arrangementObjective,
arrangementOptions,
arrangementType,
arrangeOnGrouping,
backgroundColor,
coverRenderer,
cellAspectRatio,
cellPadding,
cellSize,
columns,
coverAggregator,
depiledPile,
depileMethod,
dimensionalityReducer,
easing,
focusedPiles,
gridColor,
gridOpacity,
groupingObjective,
groupingOptions,
groupingType,
darkMode,
popupBackgroundOpacity,
itemRenderer,
items,
itemSize,
itemSizeRange,
lassoFillColor,
lassoFillOpacity,
lassoShowStartIndicator,
lassoStartIndicatorOpacity,
lassoStrokeColor,
lassoStrokeOpacity,
lassoStrokeSize,
magnifiedPiles,
navigationMode,
orderer,
pileBackgroundColor,
pileBackgroundColorActive,
pileBackgroundColorFocus,
pileBackgroundColorHover,
pileBackgroundOpacity,
pileBackgroundOpacityActive,
pileBackgroundOpacityFocus,
pileBackgroundOpacityHover,
pileBorderColor,
pileBorderColorActive,
pileBorderColorFocus,
pileBorderColorHover,
pileBorderOpacity,
pileBorderOpacityActive,
pileBorderOpacityFocus,
pileBorderOpacityHover,
pileBorderSize,
pileCellAlignment,
pileContextMenuItems,
pileCoverInvert,
pileCoverScale,
pileItemOffset,
pileItemBrightness,
pileItemInvert,
pileItemOpacity,
pileOrderItems,
pileItemRotation,
pileItemTint,
pileLabel,
pileLabelAlign,
pileLabelColor,
pileLabelFontSize,
pileLabelHeight,
pileLabelStackAlign,
pileLabelSizeTransform,
pileLabelText,
pileLabelTextColor,
pileLabelTextMapping,
pileLabelTextOpacity,
pileLabelTextStyle,
pileOpacity,
piles,
pileScale,
pileSizeBadge,
pileSizeBadgeAlign,
pileVisibilityItems,
previewAggregator,
previewAlignment,
previewBackgroundColor,
previewBackgroundOpacity,
previewBorderColor,
previewBorderOpacity,
previewItemOffset,
previewOffset,
previewPadding,
previewRenderer,
previewScaleToCover,
previewScaling,
previewSpacing,
projector,
rowHeight,
splittingObjective,
splittingOptions,
splittingType,
showGrid,
showSpatialIndex,
tempDepileDirection,
tempDepileOneDNum,
temporaryDepiledPiles,
zoomBounds,
zoomScale,
};
const appReducer = combineReducers(reducers);
const warnForUnknownImportProps = (newState) => {
const unknownProps = Object.keys(newState)
.reduce((unknown, prop) => {
if (reducers[prop] === undefined) {
unknown.push(`"${prop}"`);
}
return unknown;
}, [])
.join(', ');
if (unknownProps) {
console.warn(
`The following state properties are not understood and will not imported: ${unknownProps}`
);
}
};
const rootReducer = (state, action) => {
lastAction = action;
if (action.type === 'RESET') {
state = undefined; // eslint-disable-line no-param-reassign
} else if (action.type === 'OVERWRITE') {
if (action.payload.debug)
warnForUnknownImportProps(action.payload.newState);
state = action.payload.newState; // eslint-disable-line no-param-reassign
} else if (action.type === 'SOFT_OVERWRITE') {
if (action.payload.debug)
warnForUnknownImportProps(action.payload.newState);
// eslint-disable-next-line no-param-reassign
state = update(state, action.payload.newState, true);
}
return appReducer(state, action);
};
const reduxStore = createReduxStore(enableBatching(rootReducer));
reduxStore.lastAction = () => lastAction;
Object.defineProperty(reduxStore, 'lastAction', {
get: () => lastAction,
});
const exportState = () => {
const clonedState = deepClone(reduxStore.getState());
clonedState.version = version;
return clonedState;
};
const importState = (
newState,
{ overwriteState = false, debug = false } = {}
) => {
if (newState.version !== version) {
console.warn(
`The version of the imported state "${newState.version}" doesn't match the library version "${version}". Use at your own risk!`
);
}
if (newState.version) delete newState.version;
if (overwriteState) reduxStore.dispatch(overwrite(newState, debug));
else reduxStore.dispatch(softOverwrite(newState, debug));
};
const resetState = () => {
reduxStore.dispatch(reset());
};
return pipe(
withStaticProperty('reduxStore', reduxStore),
withReadOnlyProperty('lastAction', () => lastAction),
withReadOnlyProperty('state', reduxStore.getState),
withForwardedMethod('dispatch', reduxStore.dispatch),
withForwardedMethod('subscribe', reduxStore.subscribe)
)({
export: exportState,
import: importState,
reset: resetState,
});
};
export default createStore;
export const createAction = {
initPiles,
mergePiles,
movePiles,
scatterPiles,
setPiles,
setCoverRenderer,
setArrangementObjective,
setArrangeOnGrouping,
setArrangementOptions,
setArrangementType,
setBackgroundColor,
setCellAspectRatio,
setCellPadding,
setCellSize,
setColumns,
setCoverAggregator,
setDepiledPile,
setDepileMethod,
setDimensionalityReducer,
setEasing,
setFocusedPiles,
setGridColor,
setGridOpacity,
setGroupingObjective,
setGroupingOptions,
setGroupingType,
setDarkMode,
setPopupBackgroundOpacity,
setItemRenderer,
setItems,
setItemSize,
setItemSizeRange,
setLassoFillColor,
setLassoFillOpacity,
setLassoShowStartIndicator,
setLassoStartIndicatorOpacity,
setLassoStrokeColor,
setLassoStrokeOpacity,
setLassoStrokeSize,
setMagnifiedPiles,
setNavigationMode,
setOrderer,
setPileBackgroundColor,
setPileBackgroundColorActive,
setPileBackgroundColorFocus,
setPileBackgroundColorHover,
setPileBackgroundOpacity,
setPileBackgroundOpacityActive,
setPileBackgroundOpacityFocus,
setPileBackgroundOpacityHover,
setPileBorderColor,
setPileBorderColorActive,
setPileBorderColorFocus,
setPileBorderColorHover,
setPileBorderOpacity,
setPileBorderOpacityActive,
setPileBorderOpacityFocus,
setPileBorderOpacityHover,
setPileBorderSize,
setPileCellAlignment,
setPileContextMenuItems,
setPileCoverInvert,
setPileCoverScale,
setPileItemOffset,
setPileOrderItems,
setPileItemBrightness,
setPileItemInvert,
setPileItemOpacity,
setPileItemRotation,
setPileItemTint,
setPileLabel,
setPileLabelAlign,
setPileLabelColor,
setPileLabelFontSize,
setPileLabelHeight,
setPileLabelStackAlign,
setPileLabelSizeTransform,
setPileLabelText,
setPileLabelTextColor,
setPileLabelTextMapping,
setPileLabelTextOpacity,
setPileLabelTextStyle,
setPileVisibilityItems,
setPileOpacity,
setPileScale,
setPileSizeBadge,
setPileSizeBadgeAlign,
setPreviewAggregator,
setPreviewAlignment,
setPreviewBackgroundColor,
setPreviewBackgroundOpacity,
setPreviewBorderColor,
setPreviewBorderOpacity,
setPreviewItemOffset,
setPreviewOffset,
setPreviewPadding,
setPreviewRenderer,
setPreviewScaleToCover,
setPreviewScaling,
setPreviewSpacing,
setProjector,
setRowHeight,
setSplittingObjective,
setSplittingOptions,
setSplittingType,
setShowGrid,
setShowSpatialIndex,
setTempDepileDirection,
setTempDepileOneDNum,
setTemporaryDepiledPiles,
setZoomBounds,
setZoomScale,
splitPiles,
};