Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dimensions2d class #54

Merged
merged 29 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
186a79a
Add Dimensions2d class
amacdonald-google Dec 15, 2020
03c524f
Port additional Toolbox components.
amacdonald-google Dec 15, 2020
eef4b7c
Consolidate and cull duplicated or similar functionality.
amacdonald-google Dec 17, 2020
7cb8ef4
Remove `getStyle`
amacdonald-google Dec 17, 2020
bb22936
Add comments, cull unnecessary code
amacdonald-google Dec 17, 2020
85d9b41
Handle 0 area canvases in WebGlImageSequence
amacdonald-google Dec 17, 2020
821fea8
Polish pass in response to review
amacdonald-google Dec 17, 2020
26c328d
Restore x
amacdonald-google Dec 18, 2020
1276663
Re-work Map classes
amacdonald-google Dec 18, 2020
f4a5c40
Cleanup arrayf
amacdonald-google Dec 18, 2020
4c353d0
Remove unused code
amacdonald-google Dec 18, 2020
6d5393f
Restore ArrayMap
amacdonald-google Dec 18, 2020
0569c8b
Remove unused code in CachedElementVector
amacdonald-google Dec 18, 2020
2731d26
Inline method ComputedStyleService
amacdonald-google Dec 18, 2020
93e665f
Extract duplicated code to ComputedStyleService
amacdonald-google Dec 18, 2020
c93396a
Remove unused Dimensions2dDom code
amacdonald-google Dec 18, 2020
f0bb5f9
Simplify Dimensions cached vector
amacdonald-google Dec 18, 2020
55e56b2
Simplify MatrixDom
amacdonald-google Dec 18, 2020
41c3a4f
Consolidate visible distance from root functions
amacdonald-google Dec 18, 2020
bbc0ccf
Inline single call init function
amacdonald-google Dec 18, 2020
6c394d7
Add comment explaining inspiration for DynamicDefaultMap
amacdonald-google Dec 19, 2020
de16706
Simplify visible-distance-from-root-service
amacdonald-google Dec 19, 2020
9624a3a
Yank abstract classes
amacdonald-google Dec 19, 2020
937735b
Remove a lot of caching classes.
amacdonald-google Dec 19, 2020
726a46e
Remove caching
amacdonald-google Dec 19, 2020
f65bd63
Correct comment
amacdonald-google Dec 19, 2020
2f16261
Remove now unused code
amacdonald-google Dec 19, 2020
c7bf8f5
Respond to review feedback with improvements
amacdonald-google Dec 19, 2020
5debf79
Address feedback from PR
amacdonald-google Jan 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions src/arrayf/arrayf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,6 @@ export class arrayf {
return output;
}

/**
* Zips arrays together. zip(['a', 'b'], [1, 2]) becomes
* [['a', 1], ['b', 2]]
*/
static zip<T>(...lists: T[][]): T[][] {
const result = [];
let i = 0;
let remainingLists = lists.filter((list) => list.length > i);
while (remainingLists.length) {
result[i] = remainingLists.map((list) => list[i]);
i++;
remainingLists = remainingLists.filter((list) => list.length > i);
}
return result;
}

/**
* Return value from array that generates the highest return value when
* passed as a parameter to the score function.
Expand All @@ -67,5 +51,4 @@ export class arrayf {
});
return maxValue;
}

}
21 changes: 21 additions & 0 deletions src/dom/dimensions-2d-dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export class Dimensions2dDom {
angusm marked this conversation as resolved.
Show resolved Hide resolved
static fromElementOffset(element: HTMLElement) {
return new Dimensions2dDom(element.offsetWidth, element.offsetHeight);
}
width: number;
height: number;

constructor(width: number, height: number) {
this.width = width;
this.height = height;
}

equals(candidate: Dimensions2dDom) {
return this.width === candidate.width &&
this.height === candidate.height;
}

getHypotenuseLength() {
return Math.sqrt(this.width * this.width + this.height * this.height);
}
}
15 changes: 15 additions & 0 deletions src/dom/dom-vectorf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { MatrixDom } from './matrix-dom';
import { Vector } from '../mathf/vector';

/**
* DOM version of Vector2d with various DOM-specific helper functions.
*/
export class domVectorf {
static fromMatrix<T extends Vector>(matrix: MatrixDom): T {
return <T>new Vector(matrix.getTranslateX(), matrix.getTranslateY());
}

static fromElementTransform<T extends Vector>(element: Element): T {
return this.fromMatrix(MatrixDom.fromElementTransform(element));
}
}
9 changes: 5 additions & 4 deletions src/dom/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,6 @@ export class dom {
return window.getComputedStyle(element);
}



/**
* Creates an image in memory that is later deletable so it can
* be released from native memory AND image cache.
Expand Down Expand Up @@ -853,12 +851,11 @@ export class dom {
return el['currentStyle'] || window.getComputedStyle(el);
}


/**
* Tests whether the provided element is set to display none.
*/
static isDisplayNone(el: Element): boolean {
let style = window.getComputedStyle(el, null).display;
let style = window.getComputedStyle(el).display;
return style == 'none';
}

Expand Down Expand Up @@ -985,4 +982,8 @@ export class dom {
})

}

static getScrollElement(): Element {
return document.scrollingElement || document.documentElement;
}
}
45 changes: 45 additions & 0 deletions src/dom/get-visible-y-from-root.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { dom } from '../';
import { domVectorf } from './dom-vectorf';

function isFixed(element: HTMLElement) {
return dom.getStyle(element).position === 'fixed';
}

function getTransformedOffset(candidateElement: HTMLElement): number {
return candidateElement.offsetTop +
domVectorf.fromElementTransform(candidateElement).y;
}

function getVisibleDistanceFromRoot(
angusm marked this conversation as resolved.
Show resolved Hide resolved
angusm marked this conversation as resolved.
Show resolved Hide resolved
element: HTMLElement,
getOffsetFn: (e: HTMLElement) => number
): number {
// Short circuit for fixed elements.
if (isFixed(element)) {
return element.offsetTop;
}

// Loop through offset parents and tally the distance
let candidateElement: HTMLElement = <HTMLElement>element.offsetParent;
let y = 0;
while (candidateElement && candidateElement !== document.body) {
// Special case for fixed elements
if (isFixed(candidateElement)) {
return y + candidateElement.offsetTop;
} else {
// Factor in the offset and the scroll
y += getOffsetFn(candidateElement) - candidateElement.scrollTop;
}
candidateElement = <HTMLElement>candidateElement.offsetParent;
}

return getOffsetFn(element) + y - dom.getScrollElement().scrollTop;
}

/**
* Returns the visible distance between the top of the given element and the
* top of the viewport.
*/
export function getVisibleYFromRoot(element: HTMLElement) {
return getVisibleDistanceFromRoot(element, getTransformedOffset);
}
60 changes: 60 additions & 0 deletions src/dom/matrix-dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Class for dealing with CSS Transform matrices.
* Supports relative updates being made to a matrix from multiple pieces of
* code without them over-riding each other (unless explicitly desired).
*/
import { dom } from './dom';

export class MatrixDom {
static parseFromString(str: string): MatrixDom {
if (str === 'none' || !str.length) {
return new MatrixDom();
}
const values =
str.slice('matrix('.length, -1)
.split(',')
.map((value) => parseFloat(value));
if (values.length !== 6 || values.some((value) => isNaN((value)))) {
throw new Error('Invalid matrix passed to MatrixDom.parseFromString');
}
return new MatrixDom(...values);
}

static fromElementTransform(element: Element): MatrixDom {
const transform = dom.getStyle(element).transform;
return MatrixDom.parseFromString(transform);
}

// Values a, b, c, d, tx, ty as per CSS transforms
readonly a: number;
readonly b: number;
readonly c: number;
readonly d: number;
readonly tx: number;
readonly ty: number;

// Use numeric to allow strings or numbers
constructor(
a: number = 1,
b: number = 0,
c: number = 0,
d: number = 1,
tx: number = 0,
ty: number = 0
) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.tx = tx;
this.ty = ty;
}

getTranslateX(): number {
return this.tx;
}

getTranslateY(): number {
return this.ty;
}
}
13 changes: 8 additions & 5 deletions src/dom/webgl-image-sequence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,6 @@ export class WebGlImageSequence {


private async draw(imageSource: string | null) {

// Prevent invalid draws
if (!imageSource || this.disposed) {
return;
Expand All @@ -991,6 +990,12 @@ export class WebGlImageSequence {
if (imageSource == this.lastDrawSource) {
return;
}

// Can't draw on a 0 area canvas
if (!this.canvasWidth || !this.canvasHeight) {
return;
}

this.lastDrawSource = imageSource;


Expand All @@ -1001,7 +1006,7 @@ export class WebGlImageSequence {
// the very last draw call is always rendered.
this.lastDrawSource = null;
this.draw(imageSource);
})
});
return;
}

Expand Down Expand Up @@ -1204,8 +1209,6 @@ export class WebGlImageSequence {
this.lastRenderSource = imageSource;
}



/**
* Updates the internal sizing options.
* @param options
Expand Down Expand Up @@ -1296,4 +1299,4 @@ export class WebGlImageSequence {
this.gl = null;
}

}
}
2 changes: 1 addition & 1 deletion src/map/array.spec.ts → src/map/array-map.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ArrayMap } from './array';
import { ArrayMap } from './array-map';
import test from 'ava';

test('ArrayMap should always return an array', async t => {
Expand Down
11 changes: 11 additions & 0 deletions src/map/array-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DefaultMap } from './default-map';

/**
* A map where the values in the map are all expected to be arrays.
* When calling get(K) for an unset key K, we are returned and empty array.
*/
export class ArrayMap<K, V> extends DefaultMap<K, V[]> {
constructor(iterable: Array<[K, V[]]> = []) {
super(iterable, () => []);
}
}
18 changes: 0 additions & 18 deletions src/map/array.ts

This file was deleted.

18 changes: 9 additions & 9 deletions src/map/dynamic-default.spec.ts → src/map/default-map.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DynamicDefaultMap } from './dynamic-default';
import { DefaultMap } from './default-map';
import test from 'ava';

const testDefaultFns = [
Expand All @@ -7,38 +7,38 @@ const testDefaultFns = [
(x: number) => `${x}!`
];

test('DynamicDefaultMap should generate default values', async t => {
test('DefaultMap should generate default values', async t => {
testDefaultFns.forEach((defaultFn) => {
const map = new DynamicDefaultMap<number, any>([], Map, defaultFn);
const map = new DefaultMap<number, any>([], defaultFn);
for (let i = -1; i < 2; i++) {
t.is(map.get(i), defaultFn(i));
}
});
});

test('DynamicDefaultMap should not generate defaults over set values', async t => {
test('DefaultMap should not generate defaults over set values', async t => {
testDefaultFns.forEach((defaultFn) => {
const map = new DynamicDefaultMap<number, any>([], Map, defaultFn);
const map = new DefaultMap<number, any>([], defaultFn);
for (let i = -1; i < 2; i++) {
map.set(i, i);
t.is(map.get(i), i);
}
});
});

test('DynamicDefaultMap should not generate defaults over initialized values', async t => {
test('DefaultMap should not generate defaults over initialized values', async t => {
testDefaultFns.forEach((defaultFn) => {
const testValues: Array<[number, any]> = [[-1, -1], [0, 0], [1, 1]];
const map = new DynamicDefaultMap<number, any>(testValues, Map, defaultFn);
const map = new DefaultMap<number, any>(testValues, defaultFn);
for (let i = -1; i < 2; i++) {
t.is(map.get(i), i);
}
});
});

test('DynamicDefaultMap usingFunction should return an empty map using the given function to generate defaults', async t => {
test('DefaultMap usingFunction should return an empty map using the given function to generate defaults', async t => {
testDefaultFns.forEach((defaultFn) => {
const map = DynamicDefaultMap.usingFunction<number, any>(defaultFn);
const map = DefaultMap.usingFunction<number, any>(defaultFn);
for (let i = -1; i < 2; i++) {
map.set(i, i);
t.is(map.get(i), i);
Expand Down
40 changes: 40 additions & 0 deletions src/map/default-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { noop } from '../func/noop';

type DefaultFunction<K, V> = (key: K) => V;
/**
* Allows for returning generated defaults for unknown keys.
* Useful as a quick and dirty way to cache results of functions.
*
* This is intended to behave similarly to the defaultdict structure in python.
*
* ```
* const sqrRts =
* DefaultMap.usingFunction<number, number>((x) => Math.sqrt(x));
* sqrRts.get(9); // Returns 3
* ```
*/
export class DefaultMap<K, V> extends Map<K, V> {
static usingFunction<K, V>(
defaultFunction: DefaultFunction<K, V>
): DefaultMap<K, V> {
return new this([], defaultFunction);
}

private readonly defaultFunction: DefaultFunction<K, V>;

constructor(iterable: Array<[K, V]> = [],
defaultFunction: DefaultFunction<K, V> = noop) {
super(iterable);
this.defaultFunction = defaultFunction;
}

get(key: K): V {
if (!this.has(key)) {
const defaultValue = this.defaultFunction(key);
this.set(key, defaultValue);
return defaultValue;
} else {
return super.get(key);
}
}
}
Loading