1 ! Copyright (C) 2006, 2008 Slava Pestov
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types arrays assocs cocoa kernel math
4 cocoa.messages cocoa.subclassing cocoa.classes cocoa.views
5 cocoa.application cocoa.pasteboard cocoa.types cocoa.windows sequences
6 ui ui.private ui.gadgets ui.gadgets.private ui.gadgets.worlds
7 ui.gestures core-foundation.strings core-graphics core-graphics.types
8 threads combinators math.rectangles ;
9 IN: ui.backend.cocoa.views
11 : send-mouse-moved ( view event -- )
12 [ mouse-location ] [ drop window ] 2bi move-hand fire-motion yield ;
14 : button ( event -- n )
15 #! Cocoa -> Factor UI button mapping
16 -> buttonNumber H{ { 0 1 } { 2 2 } { 1 3 } } at ;
53 : key-code ( event -- string ? )
54 dup -> keyCode key-codes at
55 [ t ] [ -> charactersIgnoringModifiers CF>string f ] ?if ;
57 : event-modifiers ( event -- modifiers )
58 -> modifierFlags modifiers modifier ;
60 : key-event>gesture ( event -- modifiers keycode action? )
61 [ event-modifiers ] [ key-code ] bi ;
63 : send-key-event ( view gesture -- )
64 swap window propagate-key-gesture ;
66 : interpret-key-event ( view event -- )
67 NSArray swap -> arrayWithObject: -> interpretKeyEvents: ;
69 : send-key-down-event ( view event -- )
70 [ key-event>gesture <key-down> send-key-event ]
71 [ interpret-key-event ]
74 : send-key-up-event ( view event -- )
75 key-event>gesture <key-up> send-key-event ;
77 : mouse-event>gesture ( event -- modifiers button )
78 [ event-modifiers ] [ button ] bi ;
80 : send-button-down$ ( view event -- )
81 [ nip mouse-event>gesture <button-down> ]
84 2tri send-button-down ;
86 : send-button-up$ ( view event -- )
87 [ nip mouse-event>gesture <button-up> ]
92 : send-wheel$ ( view event -- )
93 [ nip [ -> deltaX ] [ -> deltaY ] bi [ sgn neg ] bi@ 2array ]
98 : send-action$ ( view event gesture -- junk )
99 [ drop window ] dip send-action f ;
101 : add-resize-observer ( observer object -- )
103 "updateFactorGadgetSize:"
104 "NSViewFrameDidChangeNotification" <NSString>
107 : string-or-nil? ( NSString -- ? )
108 [ CF>string NSStringPboardType = ] [ t ] if* ;
110 : valid-service? ( gadget send-type return-type -- ? )
111 2dup [ string-or-nil? ] [ string-or-nil? ] bi* and
112 [ drop [ gadget-selection? ] [ drop t ] if ] [ 3drop f ] if ;
114 : NSRect>rect ( NSRect world -- rect )
115 [ [ [ CGRect-x ] [ CGRect-y ] bi ] [ dim>> second ] bi* swap - 2array ]
116 [ drop [ CGRect-w ] [ CGRect-h ] bi 2array ]
119 : rect>NSRect ( rect world -- NSRect )
120 [ [ loc>> first2 ] [ dim>> second ] bi* swap - ]
121 [ drop dim>> first2 ]
125 { +superclass+ "NSOpenGLView" }
126 { +name+ "FactorView" }
127 { +protocols+ { "NSTextInput" } }
131 { "drawRect:" "void" { "id" "SEL" "NSRect" }
132 [ 2drop window relayout-1 ]
136 { "acceptsFirstMouse:" "char" { "id" "SEL" "id" }
140 { "mouseEntered:" "void" { "id" "SEL" "id" }
141 [ nip send-mouse-moved ]
144 { "mouseExited:" "void" { "id" "SEL" "id" }
145 [ 3drop forget-rollover ]
148 { "mouseMoved:" "void" { "id" "SEL" "id" }
149 [ nip send-mouse-moved ]
152 { "mouseDragged:" "void" { "id" "SEL" "id" }
153 [ nip send-mouse-moved ]
156 { "rightMouseDragged:" "void" { "id" "SEL" "id" }
157 [ nip send-mouse-moved ]
160 { "otherMouseDragged:" "void" { "id" "SEL" "id" }
161 [ nip send-mouse-moved ]
164 { "mouseDown:" "void" { "id" "SEL" "id" }
165 [ nip send-button-down$ ]
168 { "mouseUp:" "void" { "id" "SEL" "id" }
169 [ nip send-button-up$ ]
172 { "rightMouseDown:" "void" { "id" "SEL" "id" }
173 [ nip send-button-down$ ]
176 { "rightMouseUp:" "void" { "id" "SEL" "id" }
177 [ nip send-button-up$ ]
180 { "otherMouseDown:" "void" { "id" "SEL" "id" }
181 [ nip send-button-down$ ]
184 { "otherMouseUp:" "void" { "id" "SEL" "id" }
185 [ nip send-button-up$ ]
188 { "scrollWheel:" "void" { "id" "SEL" "id" }
192 { "keyDown:" "void" { "id" "SEL" "id" }
193 [ nip send-key-down-event ]
196 { "keyUp:" "void" { "id" "SEL" "id" }
197 [ nip send-key-up-event ]
200 { "undo:" "id" { "id" "SEL" "id" }
201 [ nip undo-action send-action$ ]
204 { "redo:" "id" { "id" "SEL" "id" }
205 [ nip redo-action send-action$ ]
208 { "cut:" "id" { "id" "SEL" "id" }
209 [ nip cut-action send-action$ ]
212 { "copy:" "id" { "id" "SEL" "id" }
213 [ nip copy-action send-action$ ]
216 { "paste:" "id" { "id" "SEL" "id" }
217 [ nip paste-action send-action$ ]
220 { "delete:" "id" { "id" "SEL" "id" }
221 [ nip delete-action send-action$ ]
224 { "selectAll:" "id" { "id" "SEL" "id" }
225 [ nip select-all-action send-action$ ]
228 { "newDocument:" "id" { "id" "SEL" "id" }
229 [ nip new-action send-action$ ]
232 { "openDocument:" "id" { "id" "SEL" "id" }
233 [ nip open-action send-action$ ]
236 { "saveDocument:" "id" { "id" "SEL" "id" }
237 [ nip save-action send-action$ ]
240 { "saveDocumentAs:" "id" { "id" "SEL" "id" }
241 [ nip save-as-action send-action$ ]
244 { "revertDocumentToSaved:" "id" { "id" "SEL" "id" }
245 [ nip revert-action send-action$ ]
248 ! Multi-touch gestures: this is undocumented.
249 ! http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html
250 { "magnifyWithEvent:" "void" { "id" "SEL" "id" }
254 { 1 [ zoom-in-action send-action$ ] }
255 { -1 [ zoom-out-action send-action$ ] }
261 { "swipeWithEvent:" "void" { "id" "SEL" "id" }
265 { 1 [ left-action send-action$ ] }
266 { -1 [ right-action send-action$ ] }
270 { 1 [ up-action send-action$ ] }
271 { -1 [ down-action send-action$ ] }
280 ! "rotateWithEvent:" "void" { "id" "SEL" "id" }}
282 { "acceptsFirstResponder" "char" { "id" "SEL" }
287 { "validRequestorForSendType:returnType:" "id" { "id" "SEL" "id" "id" }
289 ! We return either self or nil
290 [ over window-focus ] 2dip
291 valid-service? [ drop ] [ 2drop f ] if
295 { "writeSelectionToPasteboard:types:" "char" { "id" "SEL" "id" "id" }
297 CF>string-array NSStringPboardType swap member? [
298 [ drop window-focus gadget-selection ] dip over
299 [ set-pasteboard-string 1 ] [ 2drop 0 ] if
304 { "readSelectionFromPasteboard:" "char" { "id" "SEL" "id" }
306 pasteboard-string dup [
307 [ drop window ] dip swap user-input 1
313 { "insertText:" "void" { "id" "SEL" "id" }
314 [ nip CF>string swap window user-input ]
317 { "hasMarkedText" "char" { "id" "SEL" }
321 { "markedRange" "NSRange" { "id" "SEL" }
322 [ 2drop 0 0 <NSRange> ]
325 { "selectedRange" "NSRange" { "id" "SEL" }
326 [ 2drop 0 0 <NSRange> ]
329 { "setMarkedText:selectedRange:" "void" { "id" "SEL" "id" "NSRange" }
333 { "unmarkText" "void" { "id" "SEL" }
337 { "validAttributesForMarkedText" "id" { "id" "SEL" }
338 [ 2drop NSArray -> array ]
341 { "attributedSubstringFromRange:" "id" { "id" "SEL" "NSRange" }
345 { "characterIndexForPoint:" "NSUInteger" { "id" "SEL" "NSPoint" }
349 { "firstRectForCharacterRange:" "NSRect" { "id" "SEL" "NSRange" }
350 [ 3drop 0 0 0 0 <CGRect> ]
353 { "conversationIdentifier" "NSInteger" { "id" "SEL" }
354 [ drop alien-address ]
358 { "updateFactorGadgetSize:" "void" { "id" "SEL" "id" }
359 [ 2drop [ window ] [ view-dim ] bi >>dim drop yield ]
362 { "doCommandBySelector:" "void" { "id" "SEL" "SEL" }
366 { "initWithFrame:pixelFormat:" "id" { "id" "SEL" "NSRect" "id" }
369 SUPER-> initWithFrame:pixelFormat:
370 dup dup add-resize-observer
374 { "dealloc" "void" { "id" "SEL" }
377 [ unregister-window ]
384 : sync-refresh-to-screen ( GLView -- )
385 -> openGLContext -> CGLContextObj NSOpenGLCPSwapInterval 1 <int>
386 CGLSetParameter drop ;
388 : <FactorView> ( dim pixel-format -- view )
389 [ FactorView ] 2dip <GLView> [ sync-refresh-to-screen ] keep ;
391 : save-position ( world window -- )
392 -> frame CGRect-top-left 2array >>window-loc drop ;
395 { +superclass+ "NSObject" }
396 { +name+ "FactorWindowDelegate" }
399 { "windowDidMove:" "void" { "id" "SEL" "id" }
401 2nip -> object [ -> contentView window ] keep save-position
405 { "windowDidBecomeKey:" "void" { "id" "SEL" "id" }
407 2nip -> object -> contentView window focus-world
411 { "windowDidResignKey:" "void" { "id" "SEL" "id" }
414 2nip -> object -> contentView
415 dup -> isInFullScreenMode zero?
416 [ window unfocus-world ]
421 { "windowShouldClose:" "char" { "id" "SEL" "id" }
427 { "windowWillClose:" "void" { "id" "SEL" "id" }
429 2nip -> object -> contentView window ungraft
433 : install-window-delegate ( window -- )
434 FactorWindowDelegate install-delegate ;