| 7 | |
| 8 | == Elementary Usage == |
| 9 | |
| 10 | Here's a very simple example of how to create a window and draw to it. |
| 11 | |
| 12 | {{{ |
| 13 | (in-package "CL-USER") |
| 14 | |
| 15 | (require "COCOA") |
| 16 | |
| 17 | (defclass red-view (ns:ns-view) |
| 18 | () |
| 19 | (:metaclass ns:+ns-object)) |
| 20 | |
| 21 | (objc:defmethod (#/drawRect: :void) ((self red-view) (rect :<NSR>ect)) |
| 22 | (#/set (#/redColor ns:ns-color)) |
| 23 | (#_NSRectFill (#/bounds self))) |
| 24 | |
| 25 | (defun show-red-window () |
| 26 | (ccl::with-autorelease-pool |
| 27 | (let* ((rect (ns:make-ns-rect 0 0 300 300)) |
| 28 | (w (make-instance 'ns:ns-window |
| 29 | :with-content-rect rect |
| 30 | :style-mask (logior #$NSTitledWindowMask |
| 31 | #$NSClosableWindowMask |
| 32 | #$NSMiniaturizableWindowMask) |
| 33 | :backing #$NSBackingStoreBuffered |
| 34 | :defer t))) |
| 35 | (#/setTitle: w "Red") |
| 36 | (#/setContentView: w (make-instance 'red-view)) |
| 37 | (#/center w) |
| 38 | (#/makeKeyAndOrderFront: w nil) |
| 39 | (#/contentView w)))) |
| 40 | }}} |
| 41 | |
| 42 | Load the file containing these forms, evaluate `(show-red-window)`, and you'll see a red window. |
| 43 | |
| 44 | === More drawing === |
| 45 | |
| 46 | The general assumption in Cocoa is that you will do your drawing in your custom |
| 47 | view's `drawRect:` method. It's often nice, though, to be able to draw by evaluating |
| 48 | forms at the lisp top-level. |
| 49 | |
| 50 | One problem with that, at least in OpenMCL, is that parts of Cocoa are not |
| 51 | thread-safe. Fortunately, creating windows on secondary threads is supported. |
| 52 | So is drawing to a view, provided that the drawing is bracketed with calls to |
| 53 | `lockFocusIfCanDraw` and `unlockFocus`. |
| 54 | |
| 55 | So, to keep from forgetting to `unlockFocus`, define this simple macro. |
| 56 | (If you forget to `unlockFocus`, you'll get a spinning beach ball and have |
| 57 | to kill the lisp.) |
| 58 | |
| 59 | {{{ |
| 60 | (defmacro with-focused-view (view &body forms) |
| 61 | `(when (#/lockFocusIfCanDraw ,view) |
| 62 | ,@forms |
| 63 | (#/unlockFocus ,view))) |
| 64 | }}} |
| 65 | |
| 66 | Now, you can draw. Notice that `show-red-view` returns a view instance. |
| 67 | |
| 68 | {{{ |
| 69 | (setf *v* (show-red-view)) |
| 70 | (with-focused-view *v* |
| 71 | (let* ((path (#/bezierPath ns:ns-bezier-path))) |
| 72 | (#/moveToPoint: path (ns:make-ns-point 10 10)) |
| 73 | (#/lineToPoint: path (ns:make-ns-point 100 100)) |
| 74 | (#/stroke path))) |
| 75 | }}} |
| 76 | |