-
Notifications
You must be signed in to change notification settings - Fork 3
/
inspector.lisp
145 lines (127 loc) · 5.34 KB
/
inspector.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
(defun get-class (class-or-name)
"Obtain the class designed by the name, if it's a string,
otherwise return the java object"
(etypecase class-or-name
(string (jclass class-or-name))
(java-object class-or-name))) ;TODO: how to specialize?
(defun get-constructors (class-name)
"Obtain list of constructors defined by the class itself."
(loop with x = (get-class class-name)
for c across (java:jclass-constructors x)
when (equal (#"getName" (#"getDeclaringClass" c))
(java:jclass-name x))
collect (to-list c)))
(defun get-methods (class-name &key (only-local T))
"Obtain list of methods defined by the class itself.
Unless only-local = NIL, in which case gets all available methods."
(loop with x = (get-class class-name)
for c across (java:jclass-methods x)
when (if only-local (equal (#"getName" (#"getDeclaringClass" c))
(java:jclass-name x))
T)
collect (to-list c)))
;; pretty print classes and other java objects
(defgeneric to-list (c))
(defmethod to-list ((c (java:jclass "java.lang.Class")))
(list :name (#"getName" c)
:interfaces (#"getInterfaces" c)
:classes (#"getClasses" c)
:genericsuperclass (#"getGenericSuperclass" c)
:methods (get-methods c)
:constructors (get-methods c)
))
(defmethod to-list ((c (java:jclass "java.lang.reflect.Method")))
(list :name (#"getName" c)
:parameter-types (#"getParameterTypes" c)
:return-type (#"getReturnType" c)
:parameters (#"getParameters" c)))
(defmethod to-list ((c (java:jclass "java.lang.reflect.Constructor")))
(list :parameter-types (#"getParameterTypes" c)
:parameters (#"getParameters" c)))
;; list to swing List
;; can only show String values...
(defun k-v-to-string (param value)
(format nil "~40A: ~80A" param value))
(defun plist-to-listmodel (plist)
(let ((lm (defaultlistmodel)))
(alexandria:doplist (key val plist)
(defaultlistmodel-add lm (k-v-to-string key val)))
lm))
(defmacro list-listener (list jl f)
`(listselectionlistener (lambda (e)
(declare (ignore e))
(let* ((selected-i
(#"getSelectedIndex" ,jl))
(selected-list
(elt ,list selected-i)))
;; show inspector for list or plist or etc.
(cond
((typep selected-list 'cons)
(if (keywordp (car selected-list))
(display-plist selected-list)
(display-list selected-list)))
((typep selected-list 'string)
(show-message-dialog
,f
(format nil "String: ~A" selected-list)))
(t
(show-warning-message ,f "Can't inspect!")))
))))
(defun display-list (list)
(let* ((lm (defaultlistmodel))
(f (frame "Inspecting list" 640 480))
(jl (jlist lm)))
(#"addListSelectionListener"
jl
(list-listener list jl f))
(loop for item in list
do (defaultlistmodel-add lm (format nil "~80A" item)))
(add-using-borderlayout f
:center (scrollpane jl))))
(defun plist-to-jarray (plist)
"Convert PLIST into jarray of jarray<string>"
(let (x)
(alexandria:doplist (key val plist)
(push
(list (format nil "~A" key)
(format nil "~A" val))
x))
(java:jnew-array-from-list "java.lang.String" (nreverse x))))
(defun display-plist (plist)
"As JTable"
(let* ((dtm (defaulttablemodel '("Key" "Value")))
(jt (jtable dtm))
(f (frame "Inspecting plist" 640 480)))
;; add data...
(alexandria:doplist
(key val plist)
(#"addRow" dtm (list-to-jarray (list
(format nil "~A" key)
(format nil "~A" val)))))
(add-using-borderlayout f
:center (scrollpane jt))))
(defun display-table (list &key (title ""))
"Display table (list of plists with same length)"
(let ((column-names nil)
;(width nil)
)
(alexandria:doplist (k v (car list))
(push (format nil "~10A" k) column-names))
(nreverse column-names)
;(setf width (length column-names))
(let* ((dtm (defaulttablemodel column-names))
(jt (jtable dtm))
(f (frame title 640 480)))
(loop for row in list ;for each row
do
(let ((row2))
(alexandria:doplist (k v row)
(push (format nil "~10A" v) row2))
(nreverse row2)
(#"addRow" dtm (list-to-jarray row2))))
(add-using-borderlayout f
:center (scrollpane jt)))))
(defun display-methods (class-name &optional (only-local T))
(display-table (get-methods class-name :only-local only-local)
:title (format nil "Methods of ~A" class-name)
))