sku-pg
Version:
Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!
402 lines (336 loc) • 14.1 kB
HTML
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by an Apache 2.0 License.
See the COPYING file for details.
-->
<!--
Author: eae@google.com (Emil A Eklund)
Author: dgajda@google.com (Damian Gajda)
-->
<head>
<title>Closure Unit Tests - goog.fx.AbstractDragDrop</title>
<script src="../base.js"></script>
<script>
goog.require('goog.fx.AbstractDragDrop');
goog.require('goog.math.Box');
goog.require('goog.testing.jsunit');
</script>
<style>
#cont {
position: relative;
border: 1px solid black;
height: 100px;
width: 100px;
}
#cont div {
position: absolute;
overflow: hidden;
}
</style>
</head>
<body>
<div id="cont" style=""></div>
<button onclick="drawTargets(targets, 10)">draw targets 1</button><br>
<button onclick="drawTargets(targets2, 1)">draw targets 2</button><br>
<button onclick="drawTargets(targets3, 10)">draw targets 3</button>
<script>
var targets = [
{ box_: new goog.math.Box(0, 3, 1, 1) },
{ box_: new goog.math.Box(0, 7, 2, 6) },
{ box_: new goog.math.Box(2, 2, 3, 1) },
{ box_: new goog.math.Box(4, 1, 6, 1) },
{ box_: new goog.math.Box(4, 9, 7, 6) },
{ box_: new goog.math.Box(9, 9, 10, 1) }
];
var targets2 = [
{ box_: new goog.math.Box(10, 50, 20, 10) },
{ box_: new goog.math.Box(20, 50, 30, 10) },
{ box_: new goog.math.Box(60, 50, 70, 10) },
{ box_: new goog.math.Box(70, 50, 80, 10) }
];
var targets3 = [
{ box_: new goog.math.Box(0, 4, 1, 1) },
{ box_: new goog.math.Box(1, 6, 4, 5) },
{ box_: new goog.math.Box(5, 5, 6, 2) },
{ box_: new goog.math.Box(2, 1, 5, 0) }
];
/**
* Test the utility function which tells how two one dimensional ranges
* overlap.
*/
function testRangeOverlap() {
assertEquals(RangeOverlap.LEFT, rangeOverlap(1, 2, 3, 4));
assertEquals(RangeOverlap.LEFT, rangeOverlap(2, 3, 3, 4));
assertEquals(RangeOverlap.LEFT_IN, rangeOverlap(1, 3, 2, 4));
assertEquals(RangeOverlap.IN, rangeOverlap(1, 3, 1, 4));
assertEquals(RangeOverlap.IN, rangeOverlap(2, 3, 1, 4));
assertEquals(RangeOverlap.IN, rangeOverlap(3, 4, 1, 4));
assertEquals(RangeOverlap.RIGHT_IN, rangeOverlap(2, 4, 1, 3));
assertEquals(RangeOverlap.RIGHT, rangeOverlap(2, 3, 1, 2));
assertEquals(RangeOverlap.RIGHT, rangeOverlap(3, 4, 1, 2));
assertEquals(RangeOverlap.CONTAINS, rangeOverlap(1, 4, 2, 3));
}
/**
* An enum describing how two ranges overlap (non-symmetrical relation).
* @enum {number}
*/
RangeOverlap = {
LEFT: 1, // First range is placed to the left of the second.
LEFT_IN: 2, // First range overlaps on the left side of the second.
IN: 3, // First range is completely contained in the second.
RIGHT_IN: 4, // First range overlaps on the right side of the second.
RIGHT: 5, // First range is placed to the right side of the second.
CONTAINS: 6 // First range contains the second.
};
/**
* Computes how two one dimentional ranges overlap.
*
* @param {number} left1 Left inclusive bound of the first range.
* @param {number} right1 Right exclusive bound of the first range.
* @param {number} left2 Left inclusive bound of the second range.
* @param {number} right2 Right exclusive bound of the second range.
* @return {RangeOverlap} The enum value describing the type of the overlap.
*/
function rangeOverlap(left1, right1, left2, right2) {
if (right1 <= left2) return RangeOverlap.LEFT;
if (left1 >= right2) return RangeOverlap.RIGHT;
var leftIn = left1 >= left2;
var rightIn = right1 <= right2;
if (leftIn && rightIn) return RangeOverlap.IN;
if (leftIn) return RangeOverlap.RIGHT_IN;
if (rightIn) return RangeOverlap.LEFT_IN;
return RangeOverlap.CONTAINS;
}
/**
* Tells whether two boxes overlap.
*
* @param {goog.math.Box} box1 First box in question.
* @param {goog.math.Box} box2 Second box in question.
* @return {boolean} Whether boxes overlap in any way.
*/
function boxOverlaps(box1, box2) {
var horizontalOverlap = rangeOverlap(
box1.left, box1.right, box2.left, box2.right);
var verticalOverlap = rangeOverlap(
box1.top, box1.bottom, box2.top, box2.bottom);
return horizontalOverlap != RangeOverlap.LEFT &&
horizontalOverlap != RangeOverlap.RIGHT &&
verticalOverlap != RangeOverlap.LEFT &&
verticalOverlap != RangeOverlap.RIGHT;
}
/**
* Tests if the utility function to compute box overlapping functions properly.
*/
function testBoxOverlaps() {
// Overlapping tests.
var box2 = new goog.math.Box(1, 4, 4, 1);
// Corner overlaps.
assertTrue('NW overlap', boxOverlaps(new goog.math.Box(0, 2, 2, 0), box2));
assertTrue('NE overlap', boxOverlaps(new goog.math.Box(0, 5, 2, 3), box2));
assertTrue('SE overlap', boxOverlaps(new goog.math.Box(3, 5, 5, 3), box2));
assertTrue('SW overlap', boxOverlaps(new goog.math.Box(3, 2, 5, 0), box2));
// Inside.
assertTrue('Inside overlap',
boxOverlaps(new goog.math.Box(2, 3, 3, 2), box2));
// Around.
assertTrue('Outside overlap',
boxOverlaps(new goog.math.Box(0, 5, 5, 0), box2));
// Edge overlaps.
assertTrue('N overlap', boxOverlaps(new goog.math.Box(0, 3, 2, 2), box2));
assertTrue('E overlap', boxOverlaps(new goog.math.Box(2, 5, 3, 3), box2));
assertTrue('S overlap', boxOverlaps(new goog.math.Box(3, 3, 5, 2), box2));
assertTrue('W overlap', boxOverlaps(new goog.math.Box(2, 2, 3, 0), box2));
assertTrue('N-in overlap', boxOverlaps(new goog.math.Box(0, 5, 2, 0), box2));
assertTrue('E-in overlap', boxOverlaps(new goog.math.Box(0, 5, 5, 3), box2));
assertTrue('S-in overlap', boxOverlaps(new goog.math.Box(3, 5, 5, 0), box2));
assertTrue('W-in overlap', boxOverlaps(new goog.math.Box(0, 2, 5, 0), box2));
// Does not overlap.
var box2 = new goog.math.Box(3, 6, 6, 3);
// Along the edge - shorter.
assertFalse('N-in no overlap',
boxOverlaps(new goog.math.Box(1, 5, 2, 4), box2));
assertFalse('E-in no overlap',
boxOverlaps(new goog.math.Box(4, 8, 5, 7), box2));
assertFalse('S-in no overlap',
boxOverlaps(new goog.math.Box(7, 5, 8, 4), box2));
assertFalse('N-in no overlap',
boxOverlaps(new goog.math.Box(4, 2, 5, 1), box2));
// By the corner.
assertFalse('NE no overlap',
boxOverlaps(new goog.math.Box(1, 8, 2, 7), box2));
assertFalse('SE no overlap',
boxOverlaps(new goog.math.Box(7, 8, 8, 7), box2));
assertFalse('SW no overlap',
boxOverlaps(new goog.math.Box(7, 2, 8, 1), box2));
assertFalse('NW no overlap',
boxOverlaps(new goog.math.Box(1, 2, 2, 1), box2));
// Perpendicular to an edge.
assertFalse('NNE no overlap',
boxOverlaps(new goog.math.Box(1, 7, 2, 5), box2));
assertFalse('NEE no overlap',
boxOverlaps(new goog.math.Box(2, 8, 4, 7), box2));
assertFalse('SEE no overlap',
boxOverlaps(new goog.math.Box(5, 8, 7, 7), box2));
assertFalse('SSE no overlap',
boxOverlaps(new goog.math.Box(7, 7, 8, 5), box2));
assertFalse('SSW no overlap',
boxOverlaps(new goog.math.Box(7, 4, 8, 2), box2));
assertFalse('SWW no overlap',
boxOverlaps(new goog.math.Box(5, 2, 7, 1), box2));
assertFalse('NWW no overlap',
boxOverlaps(new goog.math.Box(2, 2, 4, 1), box2));
assertFalse('NNW no overlap',
boxOverlaps(new goog.math.Box(1, 4, 2, 2), box2));
// Along the edge - longer.
assertFalse('N no overlap',
boxOverlaps(new goog.math.Box(0, 7, 1, 2), box2));
assertFalse('E no overlap',
boxOverlaps(new goog.math.Box(2, 9, 7, 8), box2));
assertFalse('S no overlap',
boxOverlaps(new goog.math.Box(8, 7, 9, 2), box2));
assertFalse('W no overlap',
boxOverlaps(new goog.math.Box(2, 1, 7, 0), box2));
}
/**
* Checks whether a given box overlaps any of given DnD target boxes.
*
* @param {goog.math.Box} box The box to check.
* @param {Array.<Object>} targets The array of targets with boxes to check
* if they overlap with the given box.
* @return {boolean} Whether the box overlaps any of the target boxes.
*/
function boxOverlapsTargets(box, targets) {
return goog.array.some(targets, function(target) {
return boxOverlaps(box, target.box_);
});
}
function testMaybeCreateDummyTargetForPosition() {
var testGroup = new goog.fx.AbstractDragDrop();
testGroup.targetList_ = targets;
testGroup.targetBox_ = new goog.math.Box(0, 9, 10, 1);
var target = testGroup.maybeCreateDummyTargetForPosition_(3, 3);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(3, 3, target.box_));
target = testGroup.maybeCreateDummyTargetForPosition_(2, 4);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(2, 4, target.box_));
target = testGroup.maybeCreateDummyTargetForPosition_(2, 7);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(2, 7, target.box_));
testGroup.targetList_.push({ box_: new goog.math.Box(5, 6, 6, 0) });
target = testGroup.maybeCreateDummyTargetForPosition_(3, 3);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(3, 3, target.box_));
target = testGroup.maybeCreateDummyTargetForPosition_(2, 7);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(2, 7, target.box_));
target = testGroup.maybeCreateDummyTargetForPosition_(6, 3);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(6, 3, target.box_));
target = testGroup.maybeCreateDummyTargetForPosition_(0, 3);
assertNull(target);
target = testGroup.maybeCreateDummyTargetForPosition_(9, 0);
assertNull(target);
}
function testMaybeCreateDummyTargetForPosition2() {
var testGroup = new goog.fx.AbstractDragDrop();
testGroup.targetList_ = targets2;
testGroup.targetBox_ = new goog.math.Box(10, 50, 80, 10);
var target = testGroup.maybeCreateDummyTargetForPosition_(30, 40);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(30, 40, target.box_));
target = testGroup.maybeCreateDummyTargetForPosition_(45, 40);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(45, 40, target.box_));
testGroup.targetList_.push({ box_: new goog.math.Box(40, 50, 50, 40) });
target = testGroup.maybeCreateDummyTargetForPosition_(30, 40);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
target = testGroup.maybeCreateDummyTargetForPosition_(45, 35);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
}
function testMaybeCreateDummyTargetForPosition3BoxHasDecentSize() {
var testGroup = new goog.fx.AbstractDragDrop();
testGroup.targetList_ = targets3;
testGroup.targetBox_ = new goog.math.Box(0, 6, 6, 0);
var target = testGroup.maybeCreateDummyTargetForPosition_(3, 3);
assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(3, 3, target.box_));
assertEquals('(1t, 5r, 5b, 1l)', target.box_.toString());
}
function testMaybeCreateDummyTargetForPosition4() {
var testGroup = new goog.fx.AbstractDragDrop();
testGroup.targetList_ = targets;
testGroup.targetBox_ = new goog.math.Box(0, 9, 10, 1);
for (var x = testGroup.targetBox_.left;
x < testGroup.targetBox_.right;
x++) {
for (var y = testGroup.targetBox_.top;
y < testGroup.targetBox_.bottom;
y++) {
var inRealTarget = false;
for (var i = 0; i < testGroup.targetList_.length; i++) {
if (testGroup.isInside_(x, y, testGroup.targetList_[i].box_)) {
inRealTarget = true;
break;
}
}
if (!inRealTarget) {
var target = testGroup.maybeCreateDummyTargetForPosition_(x, y);
if (target) {
assertFalse('Fake target for point(' + x + ',' + y + ') should ' +
'not overlap any real targets.',
boxOverlapsTargets(target.box_, testGroup.targetList_));
assertTrue(testGroup.isInside_(x, y, target.box_));
}
}
}
}
}
function testIsInside() {
var add = new goog.fx.AbstractDragDrop();
// The box in question.
// 10,20+++++20,20
// + |
// 10,30-----20,30
var box = new goog.math.Box(20, 20, 30, 10);
assertTrue('A point somewhere in the middle of the box should be inside.',
add.isInside_(15, 25, box));
assertTrue('A point in top-left corner should be inside the box.',
add.isInside_(10, 20, box));
assertTrue('A point on top border should be inside the box.',
add.isInside_(15, 20, box));
assertFalse('A point in top-right corner should be outside the box.',
add.isInside_(20, 20, box));
assertFalse('A point on right border should be outside the box.',
add.isInside_(20, 25, box));
assertFalse('A point in bottom-right corner should be outside the box.',
add.isInside_(20, 30, box));
assertFalse('A point on bottom border should be outside the box.',
add.isInside_(15, 30, box));
assertFalse('A point in bottom-left corner should be outside the box.',
add.isInside_(10, 30, box));
assertTrue('A point on left border should be inside the box.',
add.isInside_(10, 25, box));
add.dispose();
}
// Helper function for manual debugging.
function drawTargets(targets, multiplier) {
var colors = ['green', 'blue', 'red', 'lime', 'pink', 'silver', 'orange'];
var cont = document.getElementById('cont');
cont.innerHTML = '';
for (var i = 0; i < targets.length; i++) {
var box = targets[i].box_;
var el = document.createElement('div');
el.style.top = (box.top * multiplier) + 'px';
el.style.left = (box.left * multiplier) + 'px';
el.style.width = ((box.right - box.left) * multiplier) + 'px';
el.style.height = ((box.bottom - box.top) * multiplier) + 'px';
el.style.backgroundColor = colors[i];
cont.appendChild(el);
}
}
</script>
</body>
</html>