- 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:
Bruno Windels 2019-01-14 20:24:54 +01:00
parent 961e0d24df
commit 9ecb23ce71
7 changed files with 94 additions and 133 deletions

View file

@ -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",

View file

@ -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,
};

View file

@ -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,
}; };

View file

@ -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);
} }
} }
} }

View file

@ -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);

View file

@ -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,
};

View file

@ -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`;
}
}