Skip to content

Commit

Permalink
util.getRectPoint: add utility to get a point on a rect from given ke…
Browse files Browse the repository at this point in the history
…yword (#1658)

* util.getRectPoint: add utility to get a point on a rect from given keyword

* add docs

* rename location to positionName
  • Loading branch information
kumilingus authored May 4, 2022
1 parent 2a24944 commit 1a77a9b
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 7 deletions.
19 changes: 19 additions & 0 deletions docs/src/joint/api/util/getRectPoint.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<pre class="docs-method-signature"><code>util.getRectPoint(rect, positionName)</code></pre>
<p>
Returns a <a href="geometry.html#g.Point.constructor">g.Point</a> on the rectangle specified by the keyword <code>positionName</code>.
<br>
The <code>rect</code> object has the form <code>{ x: Number, y: Number, width: Number, height: Number }</code>.
<br>
The <code>positionName</code> keyword can be one of the following:</p>
<ul>
<li><code>'top-left'</code></li>
<li><code>'top'</code></li>
<li><code>'top-right'</code></li>
<li><code>'bottom-left'</code></li>
<li><code>'bottom'</code></li>
<li><code>'bottom-right'</code></li>
<li><code>'left'</code></li>
<li><code>'right'</code></li>
<li><code>'center'</code></li>
</ul>
</p>
Empty file added src/V/annotation.mjs
Empty file.
2 changes: 1 addition & 1 deletion src/dia/Graph.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ export const Graph = Backbone.Model.extend({
const bbox = element.getBBox().rotateAroundCenter(element.angle());
const elements = (searchBy === 'bbox')
? this.findModelsInArea(bbox)
: this.findModelsFromPoint(bbox[searchBy]());
: this.findModelsFromPoint(util.getRectPoint(bbox, searchBy));
// don't account element itself or any of its descendants
return elements.filter(el => element.id !== el.id && !el.isEmbeddedIn(element));
},
Expand Down
65 changes: 65 additions & 0 deletions src/util/getRectPoint.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as g from '../g/index.mjs';

const Positions = {
TOP: 'top',
RIGHT: 'right',
BOTTOM: 'bottom',
LEFT: 'left',
TOP_LEFT: 'top-left',
TOP_RIGHT: 'top-right',
BOTTOM_LEFT: 'bottom-left',
BOTTOM_RIGHT: 'bottom-right',
CENTER: 'center',
};

export function getRectPoint(rect, position) {
const r = new g.Rect(rect);
switch (position) {
case undefined:
throw new Error('Position required');

// Middle Points
case Positions.LEFT:
case 'leftMiddle':
return r.leftMiddle();

case Positions.RIGHT:
case 'rightMiddle':
return r.rightMiddle();

case Positions.TOP:
case 'topMiddle':
return r.topMiddle();

case Positions.BOTTOM:
case 'bottomMiddle':
return r.bottomMiddle();

// Corners
case Positions.TOP_LEFT:
case 'topLeft':
case 'origin':
return r.topLeft();

case Positions.TOP_RIGHT:
case 'topRight':
return r.topRight();

case Positions.BOTTOM_LEFT:
case 'bottomLeft':
return r.bottomLeft();

case Positions.BOTTOM_RIGHT:
case 'bottomRight':
case 'corner':
return r.bottomRight();

// Center
case Positions.CENTER:
return r.center();

// TODO: calc(), percentage etc.
default:
throw new Error(`Unknown position: ${position}`);
}
}
1 change: 1 addition & 0 deletions src/util/index.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './wrappers.mjs';
export * from './util.mjs';
export * from './cloneCells.mjs';
export * from './getRectPoint.mjs';
40 changes: 40 additions & 0 deletions test/jointjs/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1216,4 +1216,44 @@ QUnit.module('util', function(hooks) {
});
});
});

QUnit.test('getRectPoint', function(assert) {

var x = 7;
var y = 11;
var width = 13;
var height = 17;
var rect = new g.Rect(x, y, width, height);
var util = joint.util;

assert.throws(function() {
util.getRectPoint(rect);
}, /Position required/);

assert.throws(function() {
util.getRectPoint(rect, 'unknown');
}, /Unknown position: unknown/);

assert.equal(util.getRectPoint(rect, 'center').toString(), '13.5@19.5');
assert.equal(util.getRectPoint(rect, 'top').toString(), '13.5@11');
assert.equal(util.getRectPoint(rect, 'left').toString(), '7@19.5');
assert.equal(util.getRectPoint(rect, 'right').toString(), '20@19.5');
assert.equal(util.getRectPoint(rect, 'bottom').toString(), '13.5@28');
assert.equal(util.getRectPoint(rect, 'top-left').toString(), '7@11');
assert.equal(util.getRectPoint(rect, 'top-right').toString(), '20@11');
assert.equal(util.getRectPoint(rect, 'bottom-left').toString(), '7@28');
assert.equal(util.getRectPoint(rect, 'bottom-right').toString(), '20@28');

// Legacy keywords
assert.equal(util.getRectPoint(rect, 'topLeft').toString(), '7@11');
assert.equal(util.getRectPoint(rect, 'topRight').toString(), '20@11');
assert.equal(util.getRectPoint(rect, 'bottomLeft').toString(), '7@28');
assert.equal(util.getRectPoint(rect, 'bottomRight').toString(), '20@28');
assert.equal(util.getRectPoint(rect, 'origin').toString(), '7@11');
assert.equal(util.getRectPoint(rect, 'corner').toString(), '20@28');
assert.equal(util.getRectPoint(rect, 'topMiddle').toString(), '13.5@11');
assert.equal(util.getRectPoint(rect, 'leftMiddle').toString(), '7@19.5');
assert.equal(util.getRectPoint(rect, 'rightMiddle').toString(), '20@19.5');
assert.equal(util.getRectPoint(rect, 'bottomMiddle').toString(), '13.5@28');
});
});
18 changes: 12 additions & 6 deletions types/joint.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ export namespace dia {
vertical?: number;
};

type LegacyPositionName = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' |
'topMiddle' | 'bottomMiddle' | 'leftMiddle' | 'rightMiddle' |
'corner' | 'origin';

type PositionName = 'top' | 'left' | 'bottom' | 'right' | 'center' |
'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' |
LegacyPositionName;

type Sides = number | SidesJSON;

type OrthogonalDirection =
Expand Down Expand Up @@ -223,11 +231,7 @@ export namespace dia {

findModelsInArea(rect: BBox, opt?: { strict?: boolean }): Element[];

findModelsUnderElement(element: Element, opt?: {
searchBy?: 'bottomLeft' | 'bottomMiddle' | 'center' |
'corner' | 'leftMiddle' | 'origin' | 'rightMiddle' |
'topMiddle' | 'topRight' | 'bbox';
}): Element[];
findModelsUnderElement(element: Element, opt?: { searchBy?: 'bbox' | PositionName }): Element[];

getBBox(): g.Rect | null;

Expand Down Expand Up @@ -1205,7 +1209,7 @@ export namespace dia {

type PointConstraintCallback = (x: number, y: number, opt: any) => Point;
type RestrictTranslateCallback = (elementView: ElementView, x0: number, y0: number) => BBox | boolean | PointConstraintCallback;
type FindParentByType = 'bbox' | 'center' | 'origin' | 'corner' | 'topRight' | 'bottomLeft' | 'pointer';
type FindParentByType = 'bbox' | 'pointer' | PositionName;
type FindParentByCallback = ((this: dia.Graph, elementView: ElementView, evt: dia.Event, x: number, y: number) => Cell[]);

interface Options extends mvc.ViewOptions<Graph> {
Expand Down Expand Up @@ -3056,6 +3060,8 @@ export namespace util {

export function uniqueId(prefix?: string): string;

export function getRectPoint(rect: dia.BBox, position: dia.PositionName): g.Point;

// `merge` has a weird signature
// typescript cannot express "any number of objects optionally followed by CustomizerFunction"
export function merge(destinationObject: object, sourceObject: object, customizer?: CustomizerFunction): object;
Expand Down

0 comments on commit 1a77a9b

Please sign in to comment.