-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathclim-objc-browser.lisp
103 lines (91 loc) · 4.55 KB
/
clim-objc-browser.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
(defpackage :clim-objc-browser
(:use :clim-lisp :clim))
(in-package :clim-objc-browser)
(define-application-frame class-browser ()
((classes :initarg :classes :reader classes)
(visible-classes :initform nil :accessor visible-classes)
(current-class :initform nil :accessor current-class))
(:panes (classes :application
:incremental-redisplay t
:display-function 'display-classes
#+nil(:double-buffering t)
)
(methods :application
:incremental-redisplay t
:display-function 'display-methods)
(int :interactor))
(:pointer-documentation t)
(:layouts (default (vertically ()
(horizontally ()
classes methods)
int)))
(:default-initargs
:classes (sort (remove-if (serapeum:op
(alexandria:starts-with #\_
(objc-runtime::objc-class-get-name _)))
(objc-runtime::get-classes))
#'string-lessp
:key 'objc-runtime::objc-class-get-name)))
(defun reset-application-frame ()
(setf (visible-classes clim:*application-frame*) nil
(current-class clim:*application-frame*) nil
(slot-value clim:*application-frame* 'classes)
(sort (remove-if (serapeum:op (alexandria:starts-with #\_
(objc-runtime::objc-class-get-name _)))
(objc-runtime::get-classes))
#'string-lessp
:key 'objc-runtime::objc-class-get-name)))
(define-presentation-type objc-class ())
(define-presentation-method present (object (type objc-class) stream view &key)
(declare (ignore view))
(format stream "#[OBJC Class: ~a]"
(objc-runtime::objc-class-get-name object)))
(define-presentation-type objc-method ())
(define-presentation-method present (object (type objc-method) stream view &key)
(declare (ignore view))
(format stream "@(~a)"
(objc-runtime::get-method-name object)))
(define-presentation-translator string-to-objc-class (string objc-class class-browser
:tester ((inp) (objc-runtime:ensure-class inp))
:tester-definitive t)
(inp)
(format *terminal-io* "~&translating ~s to an objc-class" inp)
(objc-runtime:ensure-class inp))
(defun display-classes (frame pane)
(updating-output (pane :unique-id (or (visible-classes frame)
(classes frame))
:id-test 'eq)
(loop for class in (or (visible-classes frame)
(classes frame))
do
(updating-output (pane :unique-id (cffi:pointer-address class)
:id-test 'eql
:cache-value class
:cache-test 'eql)
(with-output-as-presentation (pane class 'objc-class)
(format pane "~& ~a~%" (objc-runtime::objc-class-get-name class)))))))
(defun display-methods (frame pane)
(updating-output (pane :unique-id (current-class frame)
:id-test 'eq)
(when (current-class frame)
(loop for method in (sort (objc-runtime::get-methods (current-class frame))
'string<
:key 'objc-runtime::get-method-name)
do
(with-output-as-presentation (pane method 'objc-method)
(format pane " Method: ~a~%" (objc-runtime::get-method-name method)))))))
(define-class-browser-command (com-get-methods :name t :menu t) ((the-class objc-class :gesture :select))
(if (cffi:pointerp the-class)
(setf (current-class *application-frame*) the-class)
(format *terminal-io* "~&The value ~s is not a pointer to a class, but a ~s" the-class (type-of the-class))))
(define-class-browser-command (com-refresh-classes :name t :menu t) ()
(reset-application-frame))
(define-class-browser-command (com-filter-classes :name t :menu t) ((prefix string))
(setf (visible-classes *application-frame*)
(remove-if-not (serapeum:op
(alexandria:starts-with-subseq prefix _ :test #'char-equal))
(classes *application-frame*)
:key 'objc-runtime::objc-class-get-name)))
(defun main ()
(clim:run-frame-top-level
(clim:make-application-frame 'class-browser)))