Vuo 2.4.4
Loading...
Searching...
No Matches
VuoGraphicsView.m
Go to the documentation of this file.
1
10#import "VuoGraphicsView.h"
11#import "VuoGraphicsLayer.h"
12
13#ifdef VUO_COMPILER
15 "title" : "VuoGraphicsView",
16 "dependencies" : [
17 "VuoGraphicsLayer",
18 ]
19});
20#endif
21
25@interface VuoGraphicsView ()
26@property(retain) NSImage *circleImage;
27@property NSRect circleRect;
28
29@property NSMutableSet *touchTriggers;
30@property NSMutableSet *zoomedTriggers;
31@property NSMutableSet *swipedLeftTriggers;
32@property NSMutableSet *swipedRightTriggers;
33@end
34
35@implementation VuoGraphicsView
36
42- (instancetype)init
43{
44 if (self = [super init])
45 {
46 self.wantsLayer = true;
47
48 self.allowedTouchTypes = NSTouchTypeMaskIndirect;
49 self.wantsRestingTouches = YES;
50 _touchTriggers = [NSMutableSet new];
51 _zoomedTriggers = [NSMutableSet new];
52 _swipedLeftTriggers = [NSMutableSet new];
53 _swipedRightTriggers = [NSMutableSet new];
54
55 // Prepare the circle mouse cursor.
56 {
57 _circleRect = NSMakeRect(0,0,48,48);
58 _circleImage = [[NSImage alloc] initWithSize:_circleRect.size];
59 [_circleImage lockFocus];
60 {
61 [[NSColor colorWithDeviceWhite:1 alpha:0.75] setFill];
62 [[NSColor colorWithDeviceWhite:0 alpha:0.15] setStroke];
63 NSBezierPath *circlePath = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(_circleRect, 1, 1)];
64 [circlePath fill];
65 [circlePath stroke];
66 }
67 [_circleImage unlockFocus];
68 }
69 }
70 return self;
71}
72
79- (void)viewDidMoveToWindow
80{
81 if (!self.window)
82 return;
83
84 _viewport = self.frame;
85}
86
93- (void)viewDidChangeBackingProperties
94{
95 VuoGraphicsLayer *l = (VuoGraphicsLayer *)self.layer;
97 [l setNeedsDisplay];
98}
99
104- (void)resetCursorRects
105{
106 VuoGraphicsWindow *gw = (VuoGraphicsWindow *)self.window;
107 VuoCursor cursor = gw.cursor;
108 NSCursor *nsCursor = nil;
109
110 if (cursor == VuoCursor_None)
111 {
112 NSImage *im = [[NSImage alloc] initWithSize:NSMakeSize(1,1)];
113 nsCursor = [[[NSCursor alloc] initWithImage:im hotSpot:NSMakePoint(0,0)] autorelease];
114 [im release];
115 }
116 else if (cursor == VuoCursor_Pointer)
117 nsCursor = [NSCursor arrowCursor];
118 else if (cursor == VuoCursor_Crosshair)
119 nsCursor = [NSCursor crosshairCursor];
120 else if (cursor == VuoCursor_HandOpen)
121 nsCursor = [NSCursor openHandCursor];
122 else if (cursor == VuoCursor_HandClosed)
123 nsCursor = [NSCursor closedHandCursor];
124 else if (cursor == VuoCursor_IBeam)
125 nsCursor = [NSCursor IBeamCursor];
126 else if (cursor == VuoCursor_Circle)
127 nsCursor = [[[NSCursor alloc] initWithImage:_circleImage hotSpot:NSMakePoint(NSMidX(_circleRect),NSMidY(_circleRect))] autorelease];
128
129 if (nsCursor)
130 [self addCursorRect:[self visibleRect] cursor:nsCursor];
131}
132
139- (BOOL)acceptsFirstResponder
140{
141 return YES;
142}
143
155- (BOOL)mouseDownCanMoveWindow
156{
157 return NO;
158}
159
163- (void)dealloc
164{
165 [_circleImage release];
166 [super dealloc];
167}
168
169static NSInteger VuoGraphicsView_touchComparator(NSTouch *a, NSTouch *b, void *p)
170{
171 float ax = a.normalizedPosition.x;
172 float bx = b.normalizedPosition.x;
173 if (ax < bx)
174 return -1;
175 else if (ax > bx)
176 return 1;
177 else
178 return 0;
179}
180
181- (void)fireTouches:(NSEvent *)e
182{
183 NSSet *touchesSet = [e touchesMatchingPhase:NSTouchPhaseAny inView:nil];
184 NSArray *orderedTouches = [touchesSet.allObjects sortedArrayUsingFunction:VuoGraphicsView_touchComparator context:nil];
185
186 VuoList_VuoPoint2d touches = VuoListCreateWithCount_VuoPoint2d(orderedTouches.count, (VuoPoint2d){0,0});
187 VuoPoint2d *touchPoints = VuoListGetData_VuoPoint2d(touches);
188 int i = 0;
189 for (NSTouch *t in orderedTouches)
190 touchPoints[i++] = (VuoPoint2d){
191 t.normalizedPosition.x * 2 - 1,
192 (t.normalizedPosition.y * 2 - 1) * (t.deviceSize.height / t.deviceSize.width)
193 };
194
195 dispatch_async(dispatch_get_main_queue(), ^{
196 for (NSValue *v in self.touchTriggers)
197 {
198 void (*touchesMoved)(VuoList_VuoPoint2d) = v.pointerValue;
199 if (touchesMoved)
200 touchesMoved(touches);
201 }
202 });
203}
204- (void)touchesBeganWithEvent:(NSEvent *)event
205{
206 [self fireTouches:event];
207}
208- (void)touchesMovedWithEvent:(NSEvent *)event
209{
210 [self fireTouches:event];
211}
212- (void)touchesEndedWithEvent:(NSEvent *)event
213{
214 [self fireTouches:event];
215}
216- (void)touchesCancelledWithEvent:(NSEvent *)event
217{
218 [self fireTouches:event];
219}
220
221- (void)magnifyWithEvent:(NSEvent *)event
222{
223 if (event.magnification != 0)
224 dispatch_async(dispatch_get_main_queue(), ^{
225 for (NSValue *v in self.zoomedTriggers)
226 {
227 void (*zoomed)(VuoReal) = v.pointerValue;
228 if (zoomed)
229 zoomed(event.magnification);
230 }
231 });
232}
233
234- (void)swipeWithEvent:(NSEvent *)event
235{
236 if (event.deltaX > 0)
237 dispatch_async(dispatch_get_main_queue(), ^{
238 for (NSValue *v in self.swipedLeftTriggers)
239 {
240 void (*swipedLeft)(void) = v.pointerValue;
241 if (swipedLeft)
242 swipedLeft();
243 }
244 });
245 else if (event.deltaX < 0)
246 dispatch_async(dispatch_get_main_queue(), ^{
247 for (NSValue *v in self.swipedRightTriggers)
248 {
249 void (*swipedRight)(void) = v.pointerValue;
250 if (swipedRight)
251 swipedRight();
252 }
253 });
254}
255
262- (void)addTouchesMovedTrigger:(void (*)(VuoList_VuoPoint2d))touchesMoved
263 zoomed:(void (*)(VuoReal))zoomed
264 swipedLeft:(void (*)(void))swipedLeft
265 swipedRight:(void (*)(void))swipedRight
266{
267 dispatch_async(dispatch_get_main_queue(), ^{
268 [self.touchTriggers addObject:[NSValue valueWithPointer:touchesMoved]];
269 [self.zoomedTriggers addObject:[NSValue valueWithPointer:zoomed]];
270 [self.swipedLeftTriggers addObject:[NSValue valueWithPointer:swipedLeft]];
271 [self.swipedRightTriggers addObject:[NSValue valueWithPointer:swipedRight]];
272 });
273}
274
281- (void)removeTouchesMovedTrigger:(void (*)(VuoList_VuoPoint2d))touchesMoved
282 zoomed:(void (*)(VuoReal))zoomed
283 swipedLeft:(void (*)(void))swipedLeft
284 swipedRight:(void (*)(void))swipedRight
285{
286 dispatch_async(dispatch_get_main_queue(), ^{
287 for (NSValue *v in self.touchTriggers)
288 if (v.pointerValue == touchesMoved)
289 [self.touchTriggers removeObject:v];
290 for (NSValue *v in self.zoomedTriggers)
291 if (v.pointerValue == zoomed)
292 [self.zoomedTriggers removeObject:v];
293 for (NSValue *v in self.swipedLeftTriggers)
294 if (v.pointerValue == swipedLeft)
295 [self.swipedLeftTriggers removeObject:v];
296 for (NSValue *v in self.swipedRightTriggers)
297 if (v.pointerValue == swipedRight)
298 [self.swipedRightTriggers removeObject:v];
299 });
300}
301@end