Skip to content

Commit 1b1b0ee

Browse files
committed
Implemented various NSRect-related functions from NSGeometry, that test geometric relationships.
1 parent 738eacd commit 1b1b0ee

File tree

2 files changed

+165
-8
lines changed

2 files changed

+165
-8
lines changed

Foundation/NSGeometry.swift

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ prefix public func -(x: CGFloat) -> CGFloat {
5757
return CGFloat(-x.native)
5858
}
5959

60+
public func +=(inout lhs: CGFloat, rhs: CGFloat) {
61+
lhs.native = lhs.native + rhs.native
62+
}
63+
6064
extension Double {
6165
public init(_ value: CGFloat) {
6266
self = Double(value.native)
@@ -283,14 +287,63 @@ public func NSInsetRect(aRect: NSRect, _ dX: CGFloat, _ dY: CGFloat) -> NSRect {
283287
public func NSIntegralRect(aRect: NSRect) -> NSRect { NSUnimplemented() }
284288
public func NSIntegralRectWithOptions(aRect: NSRect, _ opts: NSAlignmentOptions) -> NSRect { NSUnimplemented() }
285289

286-
public func NSUnionRect(aRect: NSRect, _ bRect: NSRect) -> NSRect { NSUnimplemented() }
287-
public func NSIntersectionRect(aRect: NSRect, _ bRect: NSRect) -> NSRect { NSUnimplemented() }
288-
public func NSOffsetRect(aRect: NSRect, _ dX: CGFloat, _ dY: CGFloat) -> NSRect { NSUnimplemented() }
290+
public func NSUnionRect(aRect: NSRect, _ bRect: NSRect) -> NSRect {
291+
let isEmptyFirstRect = NSIsEmptyRect(aRect)
292+
let isEmptySecondRect = NSIsEmptyRect(bRect)
293+
if isEmptyFirstRect && isEmptySecondRect {
294+
return NSZeroRect
295+
} else if isEmptyFirstRect {
296+
return bRect
297+
} else if isEmptySecondRect {
298+
return aRect
299+
}
300+
let x = min(NSMinX(aRect), NSMinX(bRect))
301+
let y = min(NSMinY(aRect), NSMinY(bRect))
302+
let width = max(NSMaxX(aRect), NSMaxX(bRect)) - x
303+
let height = max(NSMaxY(aRect), NSMaxY(bRect)) - y
304+
return NSMakeRect(x, y, width, height)
305+
}
306+
307+
public func NSIntersectionRect(aRect: NSRect, _ bRect: NSRect) -> NSRect {
308+
if NSMaxX(aRect) <= NSMinX(bRect) || NSMaxX(bRect) <= NSMinX(aRect) || NSMaxY(aRect) <= NSMinY(bRect) || NSMaxY(bRect) <= NSMinY(aRect) {
309+
return NSZeroRect
310+
}
311+
let x = max(NSMinX(aRect), NSMinX(bRect))
312+
let y = max(NSMinY(aRect), NSMinY(bRect))
313+
let width = min(NSMaxX(aRect), NSMaxX(bRect)) - x
314+
let height = min(NSMaxY(aRect), NSMaxY(bRect)) - y
315+
return NSMakeRect(x, y, width, height)
316+
}
317+
318+
public func NSOffsetRect(aRect: NSRect, _ dX: CGFloat, _ dY: CGFloat) -> NSRect {
319+
var result = aRect
320+
result.origin.x += dX
321+
result.origin.y += dY
322+
return result
323+
}
324+
289325
public func NSDivideRect(inRect: NSRect, _ slice: UnsafeMutablePointer<NSRect>, _ rem: UnsafeMutablePointer<NSRect>, _ amount: CGFloat, _ edge: NSRectEdge) { NSUnimplemented() }
290-
public func NSPointInRect(aPoint: NSPoint, _ aRect: NSRect) -> Bool { NSUnimplemented() }
291-
public func NSMouseInRect(aPoint: NSPoint, _ aRect: NSRect, _ flipped: Bool) -> Bool { NSUnimplemented() }
292-
public func NSContainsRect(aRect: NSRect, _ bRect: NSRect) -> Bool { NSUnimplemented() }
293-
public func NSIntersectsRect(aRect: NSRect, _ bRect: NSRect) -> Bool { NSUnimplemented() }
326+
327+
public func NSPointInRect(aPoint: NSPoint, _ aRect: NSRect) -> Bool {
328+
return NSMouseInRect(aPoint, aRect, true)
329+
}
330+
331+
public func NSMouseInRect(aPoint: NSPoint, _ aRect: NSRect, _ flipped: Bool) -> Bool {
332+
if flipped {
333+
return aPoint.x >= NSMinX(aRect) && aPoint.y >= NSMinX(aRect) && aPoint.x < NSMaxX(aRect) && aPoint.y < NSMaxY(aRect)
334+
}
335+
return aPoint.x >= NSMinX(aRect) && aPoint.y > NSMinY(aRect) && aPoint.x < NSMaxX(aRect) && aPoint.y <= NSMaxY(aRect)
336+
}
337+
338+
public func NSContainsRect(aRect: NSRect, _ bRect: NSRect) -> Bool {
339+
return !NSIsEmptyRect(bRect) && NSMaxX(bRect) <= NSMaxX(aRect) && NSMinX(bRect) >= NSMinX(aRect) &&
340+
NSMaxY(bRect) <= NSMaxY(aRect) && NSMinY(bRect) >= NSMinY(aRect)
341+
}
342+
343+
public func NSIntersectsRect(aRect: NSRect, _ bRect: NSRect) -> Bool {
344+
return !(NSIsEmptyRect(aRect) || NSIsEmptyRect(bRect) ||
345+
NSMaxX(aRect) <= NSMinX(bRect) || NSMaxX(bRect) <= NSMinX(aRect) || NSMaxY(aRect) <= NSMinY(bRect) || NSMaxY(bRect) <= NSMinY(aRect))
346+
}
294347

295348
public func NSStringFromPoint(aPoint: NSPoint) -> String { NSUnimplemented() }
296349
public func NSStringFromSize(aSize: NSSize) -> String { NSUnimplemented() }

TestFoundation/TestNSGeometry.swift

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ class TestNSGeometry : XCTestCase {
3131
("test_NSMakePoint", test_NSMakePoint),
3232
("test_NSMakeSize", test_NSMakeSize),
3333
("test_NSMakeRect", test_NSMakeRect),
34+
("test_NSUnionRect", test_NSUnionRect),
35+
("test_NSIntersectionRect", test_NSIntersectionRect),
36+
("test_NSOffsetRect", test_NSOffsetRect),
37+
("test_NSPointInRect", test_NSPointInRect),
38+
("test_NSMouseInRect", test_NSMouseInRect),
39+
("test_NSContainsRect", test_NSContainsRect),
40+
("test_NSIntersectsRect", test_NSIntersectsRect),
3441
]
3542
}
3643

@@ -138,4 +145,101 @@ class TestNSGeometry : XCTestCase {
138145
XCTAssertEqual(r2.size.width, CGFloat(5.0))
139146
XCTAssertEqual(r2.size.height, CGFloat(5.0))
140147
}
141-
}
148+
149+
func test_NSUnionRect() {
150+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
151+
let r2 = NSMakeRect(CGFloat(10.2), CGFloat(2.5), CGFloat(5.0), CGFloat(5.0))
152+
153+
XCTAssertTrue(NSIsEmptyRect(NSUnionRect(NSZeroRect, NSZeroRect)))
154+
XCTAssertTrue(NSEqualRects(r1, NSUnionRect(r1, NSZeroRect)))
155+
XCTAssertTrue(NSEqualRects(r2, NSUnionRect(NSZeroRect, r2)))
156+
157+
let r3 = NSUnionRect(r1, r2)
158+
XCTAssertEqual(r3.origin.x, CGFloat(1.2))
159+
XCTAssertEqual(r3.origin.y, CGFloat(2.5))
160+
XCTAssertEqual(r3.size.width, CGFloat(14.0))
161+
XCTAssertEqual(r3.size.height, CGFloat(10.6))
162+
}
163+
164+
func test_NSIntersectionRect() {
165+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
166+
let r2 = NSMakeRect(CGFloat(-2.3), CGFloat(-1.5), CGFloat(1.0), CGFloat(1.0))
167+
let r3 = NSMakeRect(CGFloat(10.2), CGFloat(2.5), CGFloat(5.0), CGFloat(5.0))
168+
169+
XCTAssertTrue(NSIsEmptyRect(NSIntersectionRect(r1, r2)))
170+
171+
let r4 = NSIntersectionRect(r1, r3)
172+
XCTAssertEqual(r4.origin.x, CGFloat(10.2))
173+
XCTAssertEqual(r4.origin.y, CGFloat(3.1))
174+
XCTAssertEqual(r4.size.width, CGFloat(1.0))
175+
XCTAssertEqual(r4.size.height, CGFloat(4.4))
176+
}
177+
178+
func test_NSOffsetRect() {
179+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
180+
let r2 = NSOffsetRect(r1, CGFloat(2.0), CGFloat(-5.0))
181+
let expectedRect = NSMakeRect(CGFloat(3.2), CGFloat(-1.9), CGFloat(10.0), CGFloat(10.0))
182+
183+
XCTAssertTrue(NSEqualRects(r2, expectedRect))
184+
}
185+
186+
func test_NSPointInRect() {
187+
let p1 = NSMakePoint(CGFloat(2.2), CGFloat(5.3))
188+
let p2 = NSMakePoint(CGFloat(1.2), CGFloat(3.1))
189+
let p3 = NSMakePoint(CGFloat(1.2), CGFloat(5.3))
190+
let p4 = NSMakePoint(CGFloat(5.2), CGFloat(3.1))
191+
let p5 = NSMakePoint(CGFloat(11.2), CGFloat(13.1))
192+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
193+
let r2 = NSMakeRect(CGFloat(-2.3), CGFloat(-1.5), CGFloat(1.0), CGFloat(1.0))
194+
195+
XCTAssertFalse(NSPointInRect(NSZeroPoint, NSZeroRect))
196+
XCTAssertFalse(NSPointInRect(p1, r2))
197+
XCTAssertTrue(NSPointInRect(p1, r1))
198+
XCTAssertTrue(NSPointInRect(p2, r1))
199+
XCTAssertTrue(NSPointInRect(p3, r1))
200+
XCTAssertTrue(NSPointInRect(p4, r1))
201+
XCTAssertFalse(NSPointInRect(p5, r1))
202+
}
203+
204+
func test_NSMouseInRect() {
205+
let p1 = NSMakePoint(CGFloat(2.2), CGFloat(5.3))
206+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
207+
let r2 = NSMakeRect(CGFloat(-2.3), CGFloat(-1.5), CGFloat(1.0), CGFloat(1.0))
208+
209+
XCTAssertFalse(NSMouseInRect(NSZeroPoint, NSZeroRect, true))
210+
XCTAssertFalse(NSMouseInRect(p1, r2, true))
211+
XCTAssertTrue(NSMouseInRect(p1, r1, true))
212+
213+
let p2 = NSMakePoint(NSMinX(r1), NSMaxY(r1))
214+
XCTAssertFalse(NSMouseInRect(p2, r1, true))
215+
XCTAssertTrue(NSMouseInRect(p2, r1, false))
216+
217+
let p3 = NSMakePoint(NSMinX(r1), NSMinY(r1))
218+
XCTAssertFalse(NSMouseInRect(p3, r1, false))
219+
XCTAssertTrue(NSMouseInRect(p3, r1, true))
220+
}
221+
222+
func test_NSContainsRect() {
223+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
224+
let r2 = NSMakeRect(CGFloat(-2.3), CGFloat(-1.5), CGFloat(1.0), CGFloat(1.0))
225+
let r3 = NSMakeRect(CGFloat(10.2), CGFloat(5.5), CGFloat(0.5), CGFloat(5.0))
226+
227+
XCTAssertFalse(NSContainsRect(r1, NSZeroRect))
228+
XCTAssertFalse(NSContainsRect(r1, r2))
229+
XCTAssertFalse(NSContainsRect(r2, r1))
230+
XCTAssertTrue(NSContainsRect(r1, r3))
231+
}
232+
233+
func test_NSIntersectsRect() {
234+
let r1 = NSMakeRect(CGFloat(1.2), CGFloat(3.1), CGFloat(10.0), CGFloat(10.0))
235+
let r2 = NSMakeRect(CGFloat(-2.3), CGFloat(-1.5), CGFloat(1.0), CGFloat(1.0))
236+
let r3 = NSMakeRect(CGFloat(10.2), CGFloat(2.5), CGFloat(5.0), CGFloat(5.0))
237+
238+
XCTAssertFalse(NSIntersectsRect(NSZeroRect, NSZeroRect))
239+
XCTAssertFalse(NSIntersectsRect(r1, NSZeroRect))
240+
XCTAssertFalse(NSIntersectsRect(NSZeroRect, r2))
241+
XCTAssertFalse(NSIntersectsRect(r1, r2))
242+
XCTAssertTrue(NSIntersectsRect(r1, r3))
243+
}
244+
245+
}

0 commit comments

Comments
 (0)