UNPKG

uicore-ts

Version:

UICore is a library to build native-like user interfaces using pure Typescript. No HTML is needed at all. Components are described as TS classes and all user interactions are handled explicitly. This library is strongly inspired by the UIKit framework tha

461 lines (460 loc) 15.6 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var UIRectangle_exports = {}; __export(UIRectangle_exports, { UIRectangle: () => UIRectangle }); module.exports = __toCommonJS(UIRectangle_exports); var import_UIObject = require("./UIObject"); var import_UIPoint = require("./UIPoint"); class UIRectangle extends import_UIObject.UIObject { constructor(x = 0, y = 0, height = 0, width = 0) { super(); this.min = new import_UIPoint.UIPoint(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); this.max = new import_UIPoint.UIPoint(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); this.min.didChange = (point) => { var _a; (_a = this.rectanglePointDidChange) == null ? void 0 : _a.call(this, point); this._rectanglePointDidChange(); }; this.max.didChange = (point) => { var _a; (_a = this.rectanglePointDidChange) == null ? void 0 : _a.call(this, point); this._rectanglePointDidChange(); }; this._isBeingUpdated = import_UIObject.NO; this.min = new import_UIPoint.UIPoint(x, y); this.max = new import_UIPoint.UIPoint(x + width, y + height); if ((0, import_UIObject.IS_NIL)(height)) { this.max.y = height; } if ((0, import_UIObject.IS_NIL)(width)) { this.max.x = width; } } copy() { return new UIRectangle(this.x, this.y, this.height, this.width); } isEqualTo(rectangle) { return (0, import_UIObject.IS)(rectangle) && this.min.isEqualTo(rectangle.min) && this.max.isEqualTo(rectangle.max); } static zero() { return new UIRectangle(0, 0, 0, 0); } containsPoint(point) { return this.min.x <= point.x && this.min.y <= point.y && point.x <= this.max.x && point.y <= this.max.y; } updateByAddingPoint(point) { if (!point) { point = new import_UIPoint.UIPoint(0, 0); } this.beginUpdates(); const min = this.min.copy(); if (min.x === import_UIObject.nil) { min.x = this.max.x; } if (min.y === import_UIObject.nil) { min.y = this.max.y; } const max = this.max.copy(); if (max.x === import_UIObject.nil) { max.x = this.min.x; } if (max.y === import_UIObject.nil) { max.y = this.min.y; } this.min.x = Math.min(min.x, point.x); this.min.y = Math.min(min.y, point.y); this.max.x = Math.max(max.x, point.x); this.max.y = Math.max(max.y, point.y); this.finishUpdates(); } scale(scale) { if ((0, import_UIObject.IS_NOT_NIL)(this.max.y)) { this.height = this.height * scale; } if ((0, import_UIObject.IS_NOT_NIL)(this.max.x)) { this.width = this.width * scale; } } get height() { if (this.max.y === import_UIObject.nil) { return import_UIObject.nil; } return this.max.y - this.min.y; } set height(height) { this.max.y = this.min.y + height; } get width() { if (this.max.x === import_UIObject.nil) { return import_UIObject.nil; } return this.max.x - this.min.x; } set width(width) { this.max.x = this.min.x + width; } get x() { return this.min.x; } set x(x) { this.beginUpdates(); const width = this.width; this.min.x = x; this.max.x = this.min.x + width; this.finishUpdates(); } get y() { return this.min.y; } set y(y) { this.beginUpdates(); const height = this.height; this.min.y = y; this.max.y = this.min.y + height; this.finishUpdates(); } get topLeft() { return this.min.copy(); } get topRight() { return new import_UIPoint.UIPoint(this.max.x, this.y); } get bottomLeft() { return new import_UIPoint.UIPoint(this.x, this.max.y); } get bottomRight() { return this.max.copy(); } get center() { return this.min.copy().add(this.min.to(this.max).scale(0.5)); } set center(center) { const offset = this.center.to(center); this.offsetByPoint(offset); } offsetByPoint(offset) { this.min.add(offset); this.max.add(offset); return this; } concatenateWithRectangle(rectangle) { this.updateByAddingPoint(rectangle.bottomRight); this.updateByAddingPoint(rectangle.topLeft); return this; } intersectionRectangleWithRectangle(rectangle) { const result = this.copy(); result.beginUpdates(); const min = result.min; if (min.x === import_UIObject.nil) { min.x = rectangle.max.x - Math.min(result.width, rectangle.width); } if (min.y === import_UIObject.nil) { min.y = rectangle.max.y - Math.min(result.height, rectangle.height); } const max = result.max; if (max.x === import_UIObject.nil) { max.x = rectangle.min.x + Math.min(result.width, rectangle.width); } if (max.y === import_UIObject.nil) { max.y = rectangle.min.y + Math.min(result.height, rectangle.height); } result.min.x = Math.max(result.min.x, rectangle.min.x); result.min.y = Math.max(result.min.y, rectangle.min.y); result.max.x = Math.min(result.max.x, rectangle.max.x); result.max.y = Math.min(result.max.y, rectangle.max.y); if (result.height < 0) { const averageY = (this.center.y + rectangle.center.y) * 0.5; result.min.y = averageY; result.max.y = averageY; } if (result.width < 0) { const averageX = (this.center.x + rectangle.center.x) * 0.5; result.min.x = averageX; result.max.x = averageX; } result.finishUpdates(); return result; } get area() { return this.height * this.width; } intersectsWithRectangle(rectangle) { return this.intersectionRectangleWithRectangle(rectangle).area != 0; } rectangleWithInsets(left, right, bottom, top) { const result = this.copy(); result.min.x = this.min.x + left; result.max.x = this.max.x - right; result.min.y = this.min.y + top; result.max.y = this.max.y - bottom; return result; } rectangleWithInset(inset) { return this.rectangleWithInsets(inset, inset, inset, inset); } rectangleWithHeight(height, centeredOnPosition = import_UIObject.nil) { if (isNaN(centeredOnPosition)) { centeredOnPosition = import_UIObject.nil; } const result = this.copy(); result.height = height; if (centeredOnPosition != import_UIObject.nil) { const change = height - this.height; result.offsetByPoint(new import_UIPoint.UIPoint(0, change * centeredOnPosition).scale(-1)); } return result; } rectangleWithWidth(width, centeredOnPosition = import_UIObject.nil) { if (isNaN(centeredOnPosition)) { centeredOnPosition = import_UIObject.nil; } const result = this.copy(); result.width = width; if (centeredOnPosition != import_UIObject.nil) { const change = width - this.width; result.offsetByPoint(new import_UIPoint.UIPoint(change * centeredOnPosition, 0).scale(-1)); } return result; } rectangleWithHeightRelativeToWidth(heightRatio = 1, centeredOnPosition = import_UIObject.nil) { return this.rectangleWithHeight(this.width * heightRatio, centeredOnPosition); } rectangleWithWidthRelativeToHeight(widthRatio = 1, centeredOnPosition = import_UIObject.nil) { return this.rectangleWithWidth(this.height * widthRatio, centeredOnPosition); } rectangleWithX(x, centeredOnPosition = 0) { const result = this.copy(); result.x = x - result.width * centeredOnPosition; return result; } rectangleWithY(y, centeredOnPosition = 0) { const result = this.copy(); result.y = y - result.height * centeredOnPosition; return result; } rectangleByAddingX(x) { const result = this.copy(); result.x = this.x + x; return result; } rectangleByAddingY(y) { const result = this.copy(); result.y = this.y + y; return result; } rectangleWithRelativeValues(relativeXPosition, widthMultiplier, relativeYPosition, heightMultiplier) { const result = this.copy(); const width = result.width; const height = result.height; result.width = widthMultiplier * width; result.height = heightMultiplier * height; result.center = new import_UIPoint.UIPoint( relativeXPosition * width, relativeYPosition * height ); return result; } rectanglesBySplittingWidth(weights, paddings = 0, absoluteWidths = import_UIObject.nil) { if ((0, import_UIObject.IS_NIL)(paddings)) { paddings = 1; } if (!(paddings instanceof Array)) { paddings = [paddings].arrayByRepeating(weights.length - 1); } paddings = paddings.arrayByTrimmingToLengthIfLonger(weights.length - 1); if (!(absoluteWidths instanceof Array) && (0, import_UIObject.IS_NOT_NIL)(absoluteWidths)) { absoluteWidths = [absoluteWidths].arrayByRepeating(weights.length); } const result = []; const sumOfWeights = weights.reduce( (a, b, index) => { if ((0, import_UIObject.IS_NOT_NIL)(absoluteWidths[index])) { b = 0; } return a + b; }, 0 ); const sumOfPaddings = paddings.summedValue; const sumOfAbsoluteWidths = absoluteWidths.summedValue; const totalRelativeWidth = this.width - sumOfPaddings - sumOfAbsoluteWidths; let previousCellMaxX = this.x; for (let i = 0; i < weights.length; i++) { let resultWidth; if ((0, import_UIObject.IS_NOT_NIL)(absoluteWidths[i])) { resultWidth = absoluteWidths[i] || 0; } else { resultWidth = totalRelativeWidth * (weights[i] / sumOfWeights); } const rectangle = this.rectangleWithWidth(resultWidth); let padding = 0; if (paddings.length > i && paddings[i]) { padding = paddings[i]; } rectangle.x = previousCellMaxX; previousCellMaxX = rectangle.max.x + padding; result.push(rectangle); } return result; } rectanglesBySplittingHeight(weights, paddings = 0, absoluteHeights = import_UIObject.nil) { if ((0, import_UIObject.IS_NIL)(paddings)) { paddings = 1; } if (!(paddings instanceof Array)) { paddings = [paddings].arrayByRepeating(weights.length - 1); } paddings = paddings.arrayByTrimmingToLengthIfLonger(weights.length - 1); if (!(absoluteHeights instanceof Array) && (0, import_UIObject.IS_NOT_NIL)(absoluteHeights)) { absoluteHeights = [absoluteHeights].arrayByRepeating(weights.length); } const result = []; const sumOfWeights = weights.reduce( (a, b, index) => { if ((0, import_UIObject.IS_NOT_NIL)(absoluteHeights[index])) { b = 0; } return a + b; }, 0 ); const sumOfPaddings = paddings.summedValue; const sumOfAbsoluteHeights = absoluteHeights.summedValue; const totalRelativeHeight = this.height - sumOfPaddings - sumOfAbsoluteHeights; var previousCellMaxY = this.y; for (var i = 0; i < weights.length; i++) { var resultHeight; if ((0, import_UIObject.IS_NOT_NIL)(absoluteHeights[i])) { resultHeight = absoluteHeights[i] || 0; } else { resultHeight = totalRelativeHeight * (weights[i] / sumOfWeights); } const rectangle = this.rectangleWithHeight(resultHeight); var padding = 0; if (paddings.length > i && paddings[i]) { padding = paddings[i]; } rectangle.y = previousCellMaxY; previousCellMaxY = rectangle.max.y + padding; result.push(rectangle); } return result; } rectanglesByEquallySplittingWidth(numberOfFrames, padding = 0) { const result = []; const totalPadding = padding * (numberOfFrames - 1); const resultWidth = (this.width - totalPadding) / numberOfFrames; for (var i = 0; i < numberOfFrames; i++) { const rectangle = this.rectangleWithWidth(resultWidth, i / (numberOfFrames - 1)); result.push(rectangle); } return result; } rectanglesByEquallySplittingHeight(numberOfFrames, padding = 0) { const result = []; const totalPadding = padding * (numberOfFrames - 1); const resultHeight = (this.height - totalPadding) / numberOfFrames; for (var i = 0; i < numberOfFrames; i++) { const rectangle = this.rectangleWithHeight(resultHeight, i / (numberOfFrames - 1)); result.push(rectangle); } return result; } distributeViewsAlongWidth(views, weights = 1, paddings, absoluteWidths) { if (!(weights instanceof Array)) { weights = [weights].arrayByRepeating(views.length); } const frames = this.rectanglesBySplittingWidth(weights, paddings, absoluteWidths); frames.forEach((frame, index) => (0, import_UIObject.FIRST_OR_NIL)(views[index]).frame = frame); return this; } distributeViewsAlongHeight(views, weights = 1, paddings, absoluteHeights) { if (!(weights instanceof Array)) { weights = [weights].arrayByRepeating(views.length); } const frames = this.rectanglesBySplittingHeight(weights, paddings, absoluteHeights); frames.forEach((frame, index) => (0, import_UIObject.FIRST_OR_NIL)(views[index]).frame = frame); return this; } distributeViewsEquallyAlongWidth(views, padding) { const frames = this.rectanglesByEquallySplittingWidth(views.length, padding); frames.forEach((frame, index) => views[index].frame = frame); return this; } distributeViewsEquallyAlongHeight(views, padding) { const frames = this.rectanglesByEquallySplittingHeight(views.length, padding); frames.forEach((frame, index) => views[index].frame = frame); return this; } rectangleForNextRow(padding = 0, height = this.height) { if (height instanceof Function) { height = height(this.width); } const result = this.rectangleWithY(this.max.y + padding); if (height != this.height) { result.height = height; } return result; } rectangleForNextColumn(padding = 0, width = this.width) { if (width instanceof Function) { width = width(this.height); } const result = this.rectangleWithX(this.max.x + padding); if (width != this.width) { result.width = width; } return result; } rectangleForPreviousRow(padding = 0) { return this.rectangleWithY(this.min.y - this.height - padding); } rectangleForPreviousColumn(padding = 0) { return this.rectangleWithX(this.min.x - this.width - padding); } static boundingBoxForPoints(points) { const result = new UIRectangle(); for (let i = 0; i < points.length; i++) { result.updateByAddingPoint(points[i]); } return result; } beginUpdates() { this._isBeingUpdated = import_UIObject.YES; } finishUpdates() { this._isBeingUpdated = import_UIObject.NO; this.didChange(); } didChange() { } _rectanglePointDidChange() { if (!this._isBeingUpdated) { this.didChange(); } } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { UIRectangle }); //# sourceMappingURL=UIRectangle.js.map