| 1 | ;; lisp-doc-controller.lisp
|
|---|
| 2 |
|
|---|
| 3 | #|
|
|---|
| 4 | The MIT license.
|
|---|
| 5 |
|
|---|
| 6 | Copyright (c) 2010 Paul L. Krueger
|
|---|
| 7 |
|
|---|
| 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|---|
| 9 | and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|---|
| 10 | including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|---|
| 11 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|---|
| 12 | furnished to do so, subject to the following conditions:
|
|---|
| 13 |
|
|---|
| 14 | The above copyright notice and this permission notice shall be included in all copies or substantial
|
|---|
| 15 | portions of the Software.
|
|---|
| 16 |
|
|---|
| 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|---|
| 18 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|---|
| 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|---|
| 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|---|
| 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|---|
| 22 |
|
|---|
| 23 | |#
|
|---|
| 24 |
|
|---|
| 25 | (eval-when (:compile-toplevel :load-toplevel :execute)
|
|---|
| 26 | (require :menu-utils))
|
|---|
| 27 |
|
|---|
| 28 | (defpackage :interface-utilities
|
|---|
| 29 | (:nicknames :iu)
|
|---|
| 30 | (:export lisp-doc-controller))
|
|---|
| 31 |
|
|---|
| 32 | (in-package :iu)
|
|---|
| 33 |
|
|---|
| 34 | ;; demonstration code for creating a Cocoa document class in lisp that can be required
|
|---|
| 35 | ;; and loaded into a standard running CCL IDE (i.e. does not require a stand-alone program).
|
|---|
| 36 |
|
|---|
| 37 | ;; lisp-doc-controller class
|
|---|
| 38 | ;; This class does some of the same things that the shared NSDocumentController instance
|
|---|
| 39 | ;; does for stand-alone application programs. We use it so that we don't have to mess
|
|---|
| 40 | ;; with CCL's existing interfaces to or its NSApplication delegate objects et. We will
|
|---|
| 41 | ;; create specific menu-items that target an instance of this class to create new documents
|
|---|
| 42 | ;; of a specified type that the CCL IDE knows nothing about. We will tell the shared
|
|---|
| 43 | ;; NSDocumentController about our documents so that it can manage things like saving and
|
|---|
| 44 | ;; closing them. This class will also handle opening files of a specified type.
|
|---|
| 45 | ;; The creator of one of these objects can also specify a name to use for inserting
|
|---|
| 46 | ;; "New <menu-class>" and "Open <menu-class>" menuitems which will target this instance.
|
|---|
| 47 |
|
|---|
| 48 | (defclass lisp-doc-controller (ns:ns-object)
|
|---|
| 49 | ((document-class :accessor document-class :initarg :doc-class)
|
|---|
| 50 | (menu-class-name :accessor menu-class-name :initarg :menu-class)
|
|---|
| 51 | (file-ext :accessor file-ext :initarg :file-ext)
|
|---|
| 52 | (doc-ctrlr :accessor doc-ctrlr)
|
|---|
| 53 | (open-panel :accessor open-panel)
|
|---|
| 54 | (type-ns-str :accessor type-ns-str)
|
|---|
| 55 | (ext-ns-str :accessor ext-ns-str)
|
|---|
| 56 | (type-array :accessor type-array)
|
|---|
| 57 | (documents :accessor documents :initform nil))
|
|---|
| 58 | (:default-initargs
|
|---|
| 59 | :doc-class nil
|
|---|
| 60 | :menu-class nil
|
|---|
| 61 | :file-ext nil)
|
|---|
| 62 | (:metaclass ns:+ns-object))
|
|---|
| 63 |
|
|---|
| 64 | (defmethod initialize-instance :after ((self lisp-doc-controller)
|
|---|
| 65 | &key menu-class file-ext &allow-other-keys)
|
|---|
| 66 | (ccl:terminate-when-unreachable self)
|
|---|
| 67 | (when menu-class
|
|---|
| 68 | (setf (type-ns-str self) (ccl::%make-nsstring menu-class))
|
|---|
| 69 | (setf (ext-ns-str self) (ccl::%make-nsstring file-ext))
|
|---|
| 70 | (setf (doc-ctrlr self) (#/sharedDocumentController ns:ns-document-controller))
|
|---|
| 71 | (setf (open-panel self) (make-instance ns:ns-open-panel))
|
|---|
| 72 | (#/retain (open-panel self))
|
|---|
| 73 | (setf (type-array self)
|
|---|
| 74 | (#/arrayByAddingObject: (make-instance ns:ns-array) (ext-ns-str self)))
|
|---|
| 75 | (make-and-install-menuitems-after "File" "New"
|
|---|
| 76 | (list (concatenate 'string "New " menu-class)
|
|---|
| 77 | "newDoc"
|
|---|
| 78 | nil
|
|---|
| 79 | self))
|
|---|
| 80 | (make-and-install-menuitems-after "File" "Open..."
|
|---|
| 81 | (list (concatenate 'string "Open " menu-class "...")
|
|---|
| 82 | "openDoc"
|
|---|
| 83 | nil
|
|---|
| 84 | self))
|
|---|
| 85 | (make-and-install-menuitems-after "File" "Print..."
|
|---|
| 86 | (list (concatenate 'string "Print " menu-class "...")
|
|---|
| 87 | (concatenate 'string "print" menu-class ":")
|
|---|
| 88 | nil
|
|---|
| 89 | nil))))
|
|---|
| 90 |
|
|---|
| 91 | (defmethod ccl:terminate ((self lisp-doc-controller))
|
|---|
| 92 | (#/release (type-ns-str self))
|
|---|
| 93 | (#/release (ext-ns-str self))
|
|---|
| 94 | (#/release (type-array self))
|
|---|
| 95 | (#/release (open-panel self)))
|
|---|
| 96 |
|
|---|
| 97 | (objc:defmethod (#/newDoc :void)
|
|---|
| 98 | ((self lisp-doc-controller))
|
|---|
| 99 | (let ((new-doc (make-instance (document-class self))))
|
|---|
| 100 | (push new-doc (documents self))
|
|---|
| 101 | ;; register the document with the shared controller so that things like
|
|---|
| 102 | ;; "save" and "close" will work properly
|
|---|
| 103 | (#/addDocument: (doc-ctrlr self) new-doc)
|
|---|
| 104 | (#/makeWindowControllers new-doc)
|
|---|
| 105 | (#/showWindows new-doc)))
|
|---|
| 106 |
|
|---|
| 107 | (objc:defmethod (#/openDoc :void)
|
|---|
| 108 | ((self lisp-doc-controller))
|
|---|
| 109 | (let ((result (#/runModalForTypes: (open-panel self) (type-array self))))
|
|---|
| 110 | (when (eql result 1)
|
|---|
| 111 | (let ((urls (#/URLs (open-panel self))))
|
|---|
| 112 | (dotimes (i (#/count urls))
|
|---|
| 113 | (let ((doc (make-instance (document-class self))))
|
|---|
| 114 | (setf doc (#/initWithContentsOfURL:ofType:error:
|
|---|
| 115 | doc
|
|---|
| 116 | (#/objectAtIndex: urls i)
|
|---|
| 117 | (type-ns-str self)
|
|---|
| 118 | (%null-ptr)))
|
|---|
| 119 | (if doc
|
|---|
| 120 | (progn
|
|---|
| 121 | (pushnew doc (documents self))
|
|---|
| 122 | (#/addDocument: (doc-ctrlr self) doc)
|
|---|
| 123 | (#/makeWindowControllers doc)
|
|---|
| 124 | (#/showWindows doc))
|
|---|
| 125 | (#_NSRunAlertPanel #@"ALERT"
|
|---|
| 126 | #@"Could not open specified file ... ignoring it."
|
|---|
| 127 | #@"OK"
|
|---|
| 128 | (%null-ptr)
|
|---|
| 129 | (%null-ptr)))))))))
|
|---|
| 130 |
|
|---|
| 131 | (provide :lisp-doc-controller)
|
|---|