cleanup
- move some methods to ResizeItem subclass - allow distributor to instanciate sizer and resizeitem it needs through static factory methods, instead of passing in another ctor a distributor can only function with the right item and sizer anyways. - use consistent import/export style - remove obsolete code
This commit is contained in:
parent
961e0d24df
commit
9ecb23ce71
7 changed files with 94 additions and 133 deletions
|
@ -167,7 +167,7 @@ module.exports = React.createClass({
|
||||||
const cfg = {
|
const cfg = {
|
||||||
onResized: this._onSubListResize,
|
onResized: this._onSubListResize,
|
||||||
};
|
};
|
||||||
this.resizer = new Resizer(this.resizeContainer, RoomDistributor, cfg, RoomSizer);
|
this.resizer = new Resizer(this.resizeContainer, RoomDistributor, cfg);
|
||||||
this.resizer.setClassNames({
|
this.resizer.setClassNames({
|
||||||
handle: "mx_ResizeHandle",
|
handle: "mx_ResizeHandle",
|
||||||
vertical: "mx_ResizeHandle_vertical",
|
vertical: "mx_ResizeHandle_vertical",
|
||||||
|
|
|
@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ResizeItem from "./item";
|
||||||
|
import Sizer from "./sizer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
distributors translate a moving cursor into
|
distributors translate a moving cursor into
|
||||||
CSS/DOM changes by calling the sizer
|
CSS/DOM changes by calling the sizer
|
||||||
|
@ -26,7 +29,15 @@ they have two methods:
|
||||||
the offset from the container edge of where
|
the offset from the container edge of where
|
||||||
the mouse cursor is.
|
the mouse cursor is.
|
||||||
*/
|
*/
|
||||||
class FixedDistributor {
|
export class FixedDistributor {
|
||||||
|
static createItem(resizeHandle, resizer, sizer) {
|
||||||
|
return new ResizeItem(resizeHandle, resizer, sizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static createSizer(containerElement, vertical, reverse) {
|
||||||
|
return new Sizer(containerElement, vertical, reverse);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(item) {
|
constructor(item) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
this.beforeOffset = item.offset();
|
this.beforeOffset = item.offset();
|
||||||
|
@ -45,12 +56,23 @@ class FixedDistributor {
|
||||||
finish() {}
|
finish() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CollapseItem extends ResizeItem {
|
||||||
|
notifyCollapsed(collapsed) {
|
||||||
|
const callback = this.resizer.config.onCollapsed;
|
||||||
|
if (callback) {
|
||||||
|
callback(collapsed, this.id, this.domNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CollapseDistributor extends FixedDistributor {
|
export class CollapseDistributor extends FixedDistributor {
|
||||||
constructor(item, sizer, _container, config) {
|
static createItem(resizeHandle, resizer, sizer) {
|
||||||
|
return new CollapseItem(resizeHandle, resizer, sizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(item, config) {
|
||||||
super(item);
|
super(item);
|
||||||
this.toggleSize = config && config.toggleSize;
|
this.toggleSize = config && config.toggleSize;
|
||||||
this.onCollapsed = config && config.onCollapsed;
|
|
||||||
this.isCollapsed = false;
|
this.isCollapsed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,13 +80,9 @@ class CollapseDistributor extends FixedDistributor {
|
||||||
const isCollapsedSize = newSize < this.toggleSize;
|
const isCollapsedSize = newSize < this.toggleSize;
|
||||||
if (isCollapsedSize && !this.isCollapsed) {
|
if (isCollapsedSize && !this.isCollapsed) {
|
||||||
this.isCollapsed = true;
|
this.isCollapsed = true;
|
||||||
if (this.onCollapsed) {
|
this.item.notifyCollapsed(true);
|
||||||
this.onCollapsed(true, this.item);
|
|
||||||
}
|
|
||||||
} else if (!isCollapsedSize && this.isCollapsed) {
|
} else if (!isCollapsedSize && this.isCollapsed) {
|
||||||
if (this.onCollapsed) {
|
this.item.notifyCollapsed(false);
|
||||||
this.onCollapsed(false, this.item);
|
|
||||||
}
|
|
||||||
this.isCollapsed = false;
|
this.isCollapsed = false;
|
||||||
}
|
}
|
||||||
if (!isCollapsedSize) {
|
if (!isCollapsedSize) {
|
||||||
|
@ -72,8 +90,3 @@ class CollapseDistributor extends FixedDistributor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
FixedDistributor,
|
|
||||||
CollapseDistributor,
|
|
||||||
};
|
|
||||||
|
|
|
@ -14,17 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Sizer, FlexSizer} from "./sizer";
|
|
||||||
import {FixedDistributor, CollapseDistributor} from "./distributors";
|
import {FixedDistributor, CollapseDistributor} from "./distributors";
|
||||||
import {Resizer} from "./resizer";
|
import Resizer from "./resizer";
|
||||||
import {RoomSizer, RoomDistributor} from "./room";
|
import RoomDistributor from "./room";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Resizer,
|
Resizer,
|
||||||
Sizer,
|
|
||||||
FlexSizer,
|
|
||||||
FixedDistributor,
|
FixedDistributor,
|
||||||
CollapseDistributor,
|
CollapseDistributor,
|
||||||
RoomSizer,
|
|
||||||
RoomDistributor,
|
RoomDistributor,
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,11 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class ResizeItem {
|
export default class ResizeItem {
|
||||||
constructor(domNode, id, reverse, resizer, sizer) {
|
constructor(handle, resizer, sizer) {
|
||||||
|
const id = handle.getAttribute("data-id");
|
||||||
|
const reverse = resizer.isReverseResizeHandle(handle);
|
||||||
|
const domNode = reverse ? handle.nextElementSibling : handle.previousElementSibling;
|
||||||
|
|
||||||
this.domNode = domNode;
|
this.domNode = domNode;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.reverse = reverse;
|
this.reverse = reverse;
|
||||||
|
@ -23,11 +27,9 @@ export default class ResizeItem {
|
||||||
this.sizer = sizer;
|
this.sizer = sizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromResizeHandle(handle, resizer, sizer) {
|
_copyWith(handle, resizer, sizer) {
|
||||||
const id = handle.getAttribute("data-id");
|
const Ctor = this.constructor;
|
||||||
const reverse = resizer.isReverseResizeHandle(handle);
|
return new Ctor(handle, resizer, sizer);
|
||||||
const domNode = reverse ? handle.nextElementSibling : handle.previousElementSibling;
|
|
||||||
return new ResizeItem(domNode, id, reverse, resizer, sizer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_advance(forwards) {
|
_advance(forwards) {
|
||||||
|
@ -43,9 +45,10 @@ export default class ResizeItem {
|
||||||
} else {
|
} else {
|
||||||
handle = handle.previousElementSibling;
|
handle = handle.previousElementSibling;
|
||||||
}
|
}
|
||||||
} while(handle && !this.resizer.isResizeHandle(handle));
|
} while (handle && !this.resizer.isResizeHandle(handle));
|
||||||
|
|
||||||
if (handle) {
|
if (handle) {
|
||||||
const nextHandle = ResizeItem.fromResizeHandle(handle, this.resizer, this.sizer);
|
const nextHandle = this._copyWith(handle, this.resizer, this.sizer);
|
||||||
nextHandle.reverse = this.reverse;
|
nextHandle.reverse = this.reverse;
|
||||||
return nextHandle;
|
return nextHandle;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +72,7 @@ export default class ResizeItem {
|
||||||
|
|
||||||
setSize(size) {
|
setSize(size) {
|
||||||
this.sizer.setItemSize(this.domNode, size);
|
this.sizer.setItemSize(this.domNode, size);
|
||||||
const callback = this.resizer.distributorCfg.onResized;
|
const callback = this.resizer.config.onResized;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(size, this.id, this.domNode);
|
callback(size, this.id, this.domNode);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +80,7 @@ export default class ResizeItem {
|
||||||
|
|
||||||
clearSize() {
|
clearSize() {
|
||||||
this.sizer.clearItemSize(this.domNode);
|
this.sizer.clearItemSize(this.domNode);
|
||||||
const callback = this.resizer.distributorCfg.onResized;
|
const callback = this.resizer.config.onResized;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(null, this.id, this.domNode);
|
callback(null, this.id, this.domNode);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +92,7 @@ export default class ResizeItem {
|
||||||
return this.resizer.isResizeHandle(el);
|
return this.resizer.isResizeHandle(el);
|
||||||
});
|
});
|
||||||
if (firstHandle) {
|
if (firstHandle) {
|
||||||
return ResizeItem.fromResizeHandle(firstHandle, this.resizer, this.sizer);
|
return this._copyWith(firstHandle, this.resizer, this.sizer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ export default class ResizeItem {
|
||||||
return this.resizer.isResizeHandle(el);
|
return this.resizer.isResizeHandle(el);
|
||||||
});
|
});
|
||||||
if (lastHandle) {
|
if (lastHandle) {
|
||||||
return ResizeItem.fromResizeHandle(lastHandle, this.resizer, this.sizer);
|
return this._copyWith(lastHandle, this.resizer, this.sizer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,6 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Sizer} from "./sizer";
|
|
||||||
import ResizeItem from "./item";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
classNames:
|
classNames:
|
||||||
// class on resize-handle
|
// class on resize-handle
|
||||||
|
@ -30,14 +27,13 @@ classNames:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
export class Resizer {
|
export default class Resizer {
|
||||||
// TODO move vertical/horizontal to config option/container class
|
// TODO move vertical/horizontal to config option/container class
|
||||||
// as it doesn't make sense to mix them within one container/Resizer
|
// as it doesn't make sense to mix them within one container/Resizer
|
||||||
constructor(container, distributorCtor, distributorCfg, sizerCtor = Sizer) {
|
constructor(container, distributorCtor, config) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.distributorCtor = distributorCtor;
|
this.distributorCtor = distributorCtor;
|
||||||
this.distributorCfg = distributorCfg;
|
this.config = config;
|
||||||
this.sizerCtor = sizerCtor;
|
|
||||||
this.classNames = {
|
this.classNames = {
|
||||||
handle: "resizer-handle",
|
handle: "resizer-handle",
|
||||||
reverse: "resizer-reverse",
|
reverse: "resizer-reverse",
|
||||||
|
@ -132,25 +128,13 @@ export class Resizer {
|
||||||
_createSizerAndDistributor(resizeHandle) {
|
_createSizerAndDistributor(resizeHandle) {
|
||||||
const vertical = resizeHandle.classList.contains(this.classNames.vertical);
|
const vertical = resizeHandle.classList.contains(this.classNames.vertical);
|
||||||
const reverse = this.isReverseResizeHandle(resizeHandle);
|
const reverse = this.isReverseResizeHandle(resizeHandle);
|
||||||
// eslint-disable-next-line new-cap
|
const Distributor = this.distributorCtor;
|
||||||
const sizer = new this.sizerCtor(this.container, vertical, reverse);
|
const sizer = Distributor.createSizer(this.container, vertical, reverse);
|
||||||
const item = ResizeItem.fromResizeHandle(resizeHandle, this, sizer);
|
const item = Distributor.createItem(resizeHandle, this, sizer);
|
||||||
// eslint-disable-next-line new-cap
|
const distributor = new Distributor(item, this.config);
|
||||||
const distributor = new this.distributorCtor(
|
|
||||||
item,
|
|
||||||
sizer,
|
|
||||||
this.container,
|
|
||||||
this.distributorCfg
|
|
||||||
);
|
|
||||||
return {sizer, distributor};
|
return {sizer, distributor};
|
||||||
}
|
}
|
||||||
|
|
||||||
_getResizableItems(reverse) {
|
|
||||||
return this._getResizeHandles().map((handle) => {
|
|
||||||
return ResizeItem.fromResizeHandle(handle);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_getResizeHandles() {
|
_getResizeHandles() {
|
||||||
return Array.from(this.container.children).filter(el => {
|
return Array.from(this.container.children).filter(el => {
|
||||||
return this.isResizeHandle(el);
|
return this.isResizeHandle(el);
|
||||||
|
|
|
@ -14,16 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Sizer} from "./sizer";
|
import Sizer from "./sizer";
|
||||||
|
import ResizeItem from "./item";
|
||||||
|
|
||||||
class RoomSizer extends Sizer {
|
class RoomSizer extends Sizer {
|
||||||
setItemSize(item, size) {
|
setItemSize(item, size) {
|
||||||
item.style.maxHeight = `${Math.round(size)}px`;
|
item.style.maxHeight = `${Math.round(size)}px`;
|
||||||
item.classList.add("resized-sized");
|
item.classList.add("resized-sized");
|
||||||
// const total = this.getTotalSize();
|
|
||||||
// const percent = size / total;
|
|
||||||
// const growFactor = Math.round(1 + (percent * 100));
|
|
||||||
// item.style.flexGrow = `${growFactor}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearItemSize(item) {
|
clearItemSize(item) {
|
||||||
|
@ -32,38 +29,36 @@ class RoomSizer extends Sizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
class RoomSubListItem extends ResizeItem {
|
||||||
class RoomSubList extends ResizeItem {
|
isCollapsed() {
|
||||||
collapsed() {
|
return this.domNode.classList.contains("mx_RoomSubList_hidden");
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
id() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maxSize() {
|
maxSize() {
|
||||||
|
const scrollItem = this.domNode.querySelector(".mx_RoomSubList_scroll");
|
||||||
|
const header = this.domNode.querySelector(".mx_RoomSubList_labelContainer");
|
||||||
|
const headerHeight = this.sizer.getItemSize(header);
|
||||||
|
return headerHeight + scrollItem.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
minSize() {
|
minSize() {
|
||||||
|
return 74; //size of header + 1 room tile
|
||||||
|
}
|
||||||
|
|
||||||
|
isSized() {
|
||||||
|
return this.domNode.classList.contains("resized-sized");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
const MIN_SIZE = 74;
|
export default class RoomDistributor {
|
||||||
// would be good to have a way in here to know if the item can be resized
|
static createItem(resizeHandle, resizer, sizer) {
|
||||||
// - collapsed items can't be resized (.mx_RoomSubList_hidden)
|
return new RoomSubListItem(resizeHandle, resizer, sizer);
|
||||||
// - items at MIN_SIZE can't be resized smaller
|
}
|
||||||
// - items at maxContentHeight can't be resized larger
|
|
||||||
|
static createSizer(containerElement, vertical, reverse) {
|
||||||
|
return new RoomSizer(containerElement, vertical, reverse);
|
||||||
|
}
|
||||||
|
|
||||||
// if you shrink the predecesor, and start dragging down again afterwards, which item has to grow?
|
|
||||||
/*
|
|
||||||
either items before (starting from first or last)
|
|
||||||
or
|
|
||||||
*/
|
|
||||||
class RoomDistributor {
|
|
||||||
constructor(item) {
|
constructor(item) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
}
|
}
|
||||||
|
@ -72,57 +67,40 @@ class RoomDistributor {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isCollapsed(item) {
|
|
||||||
return item.domNode.classList.contains("mx_RoomSubList_hidden");
|
|
||||||
}
|
|
||||||
|
|
||||||
_contentSize(item) {
|
|
||||||
const scrollItem = item.domNode.querySelector(".mx_RoomSubList_scroll");
|
|
||||||
const header = item.domNode.querySelector(".mx_RoomSubList_labelContainer");
|
|
||||||
const headerHeight = item.sizer.getItemSize(header);
|
|
||||||
return headerHeight + scrollItem.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isSized(item) {
|
|
||||||
return item.domNode.classList.contains("resized-sized");
|
|
||||||
}
|
|
||||||
|
|
||||||
resize(size) {
|
resize(size) {
|
||||||
console.log("*** starting resize session with size", size);
|
//console.log("*** starting resize session with size", size);
|
||||||
let item = this.item;
|
let item = this.item;
|
||||||
while (item) {
|
while (item) {
|
||||||
if (this._isCollapsed(item)) {
|
const minSize = item.minSize();
|
||||||
|
if (item.isCollapsed()) {
|
||||||
item = item.previous();
|
item = item.previous();
|
||||||
}
|
} else if (size <= minSize) {
|
||||||
else if (size <= MIN_SIZE) {
|
//console.log(" - resizing", item.id, "to min size", minSize);
|
||||||
console.log(" - resizing", item.id, "to min size", MIN_SIZE);
|
item.setSize(minSize);
|
||||||
item.setSize(MIN_SIZE);
|
const remainder = minSize - size;
|
||||||
const remainder = MIN_SIZE - size;
|
|
||||||
item = item.previous();
|
item = item.previous();
|
||||||
if (item) {
|
if (item) {
|
||||||
size = item.size() - remainder - this._handleSize();
|
size = item.size() - remainder - this._handleSize();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
const maxSize = item.maxSize();
|
||||||
const contentSize = this._contentSize(item);
|
if (size > maxSize) {
|
||||||
if (size > contentSize) {
|
// console.log(" - resizing", item.id, "to maxSize", maxSize);
|
||||||
// console.log(" - resizing", item.id, "to contentSize", contentSize);
|
item.setSize(maxSize);
|
||||||
item.setSize(contentSize);
|
const remainder = size - maxSize;
|
||||||
const remainder = size - contentSize;
|
|
||||||
item = item.previous();
|
item = item.previous();
|
||||||
if (item) {
|
if (item) {
|
||||||
size = item.size() + remainder; // todo: handle size here?
|
size = item.size() + remainder; // todo: handle size here?
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
//console.log(" - resizing", item.id, "to size", size);
|
||||||
console.log(" - resizing", item.id, "to size", size);
|
|
||||||
item.setSize(size);
|
item.setSize(size);
|
||||||
item = null;
|
item = null;
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("*** ending resize session");
|
//console.log("*** ending resize session");
|
||||||
}
|
}
|
||||||
|
|
||||||
resizeFromContainerOffset(containerOffset) {
|
resizeFromContainerOffset(containerOffset) {
|
||||||
|
@ -130,10 +108,10 @@ class RoomDistributor {
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
console.log("RoomDistributor::start: setting all items to their actual size in pixels");
|
// set all max-height props to the actual height.
|
||||||
let item = this.item.first();
|
let item = this.item.first();
|
||||||
while(item) {
|
while (item) {
|
||||||
if (!this._isCollapsed(item)) {
|
if (!item.isCollapsed() && item.isSized()) {
|
||||||
item.setSize(item.size());
|
item.setSize(item.size());
|
||||||
}
|
}
|
||||||
item = item.next();
|
item = item.next();
|
||||||
|
@ -141,11 +119,5 @@ class RoomDistributor {
|
||||||
}
|
}
|
||||||
|
|
||||||
finish() {
|
finish() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
RoomSizer,
|
|
||||||
RoomDistributor,
|
|
||||||
};
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
||||||
implements DOM/CSS operations for resizing.
|
implements DOM/CSS operations for resizing.
|
||||||
The sizer determines what CSS mechanism is used for sizing items, like flexbox, ...
|
The sizer determines what CSS mechanism is used for sizing items, like flexbox, ...
|
||||||
*/
|
*/
|
||||||
export class Sizer {
|
export default class Sizer {
|
||||||
constructor(container, vertical, reverse) {
|
constructor(container, vertical, reverse) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.reverse = reverse;
|
this.reverse = reverse;
|
||||||
|
@ -86,10 +86,3 @@ export class Sizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FlexSizer extends Sizer {
|
|
||||||
setItemSize(item, size) {
|
|
||||||
item.style.flexGrow = `0`;
|
|
||||||
item.style.flexBasis = `${Math.round(size)}px`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue