annotate src/clojure/inspector.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 ; Copyright (c) Rich Hickey. All rights reserved.
rlm@10 2 ; The use and distribution terms for this software are covered by the
rlm@10 3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
rlm@10 4 ; which can be found in the file epl-v10.html at the root of this distribution.
rlm@10 5 ; By using this software in any fashion, you are agreeing to be bound by
rlm@10 6 ; the terms of this license.
rlm@10 7 ; You must not remove this notice, or any other, from this software.
rlm@10 8
rlm@10 9 (ns ^{:doc "Graphical object inspector for Clojure data structures."
rlm@10 10 :author "Rich Hickey"}
rlm@10 11 clojure.inspector
rlm@10 12 (:import
rlm@10 13 (java.awt BorderLayout)
rlm@10 14 (java.awt.event ActionEvent ActionListener)
rlm@10 15 (javax.swing.tree TreeModel)
rlm@10 16 (javax.swing.table TableModel AbstractTableModel)
rlm@10 17 (javax.swing JPanel JTree JTable JScrollPane JFrame JToolBar JButton SwingUtilities)))
rlm@10 18
rlm@10 19 (defn atom? [x]
rlm@10 20 (not (coll? x)))
rlm@10 21
rlm@10 22 (defn collection-tag [x]
rlm@10 23 (cond
rlm@10 24 (instance? java.util.Map$Entry x) :entry
rlm@10 25 (instance? java.util.Map x) :map
rlm@10 26 (sequential? x) :seq
rlm@10 27 :else :atom))
rlm@10 28
rlm@10 29 (defmulti is-leaf collection-tag)
rlm@10 30 (defmulti get-child (fn [parent index] (collection-tag parent)))
rlm@10 31 (defmulti get-child-count collection-tag)
rlm@10 32
rlm@10 33 (defmethod is-leaf :default [node]
rlm@10 34 (atom? node))
rlm@10 35 (defmethod get-child :default [parent index]
rlm@10 36 (nth parent index))
rlm@10 37 (defmethod get-child-count :default [parent]
rlm@10 38 (count parent))
rlm@10 39
rlm@10 40 (defmethod is-leaf :entry [e]
rlm@10 41 (is-leaf (val e)))
rlm@10 42 (defmethod get-child :entry [e index]
rlm@10 43 (get-child (val e) index))
rlm@10 44 (defmethod get-child-count :entry [e]
rlm@10 45 (count (val e)))
rlm@10 46
rlm@10 47 (defmethod is-leaf :map [m]
rlm@10 48 false)
rlm@10 49 (defmethod get-child :map [m index]
rlm@10 50 (nth (seq m) index))
rlm@10 51
rlm@10 52 (defn tree-model [data]
rlm@10 53 (proxy [TreeModel] []
rlm@10 54 (getRoot [] data)
rlm@10 55 (addTreeModelListener [treeModelListener])
rlm@10 56 (getChild [parent index]
rlm@10 57 (get-child parent index))
rlm@10 58 (getChildCount [parent]
rlm@10 59 (get-child-count parent))
rlm@10 60 (isLeaf [node]
rlm@10 61 (is-leaf node))
rlm@10 62 (valueForPathChanged [path newValue])
rlm@10 63 (getIndexOfChild [parent child]
rlm@10 64 -1)
rlm@10 65 (removeTreeModelListener [treeModelListener])))
rlm@10 66
rlm@10 67
rlm@10 68 (defn old-table-model [data]
rlm@10 69 (let [row1 (first data)
rlm@10 70 colcnt (count row1)
rlm@10 71 cnt (count data)
rlm@10 72 vals (if (map? row1) vals identity)]
rlm@10 73 (proxy [TableModel] []
rlm@10 74 (addTableModelListener [tableModelListener])
rlm@10 75 (getColumnClass [columnIndex] Object)
rlm@10 76 (getColumnCount [] colcnt)
rlm@10 77 (getColumnName [columnIndex]
rlm@10 78 (if (map? row1)
rlm@10 79 (name (nth (keys row1) columnIndex))
rlm@10 80 (str columnIndex)))
rlm@10 81 (getRowCount [] cnt)
rlm@10 82 (getValueAt [rowIndex columnIndex]
rlm@10 83 (nth (vals (nth data rowIndex)) columnIndex))
rlm@10 84 (isCellEditable [rowIndex columnIndex] false)
rlm@10 85 (removeTableModelListener [tableModelListener]))))
rlm@10 86
rlm@10 87 (defn inspect-tree
rlm@10 88 "creates a graphical (Swing) inspector on the supplied hierarchical data"
rlm@10 89 {:added "1.0"}
rlm@10 90 [data]
rlm@10 91 (doto (JFrame. "Clojure Inspector")
rlm@10 92 (.add (JScrollPane. (JTree. (tree-model data))))
rlm@10 93 (.setSize 400 600)
rlm@10 94 (.setVisible true)))
rlm@10 95
rlm@10 96 (defn inspect-table
rlm@10 97 "creates a graphical (Swing) inspector on the supplied regular
rlm@10 98 data, which must be a sequential data structure of data structures
rlm@10 99 of equal length"
rlm@10 100 {:added "1.0"}
rlm@10 101 [data]
rlm@10 102 (doto (JFrame. "Clojure Inspector")
rlm@10 103 (.add (JScrollPane. (JTable. (old-table-model data))))
rlm@10 104 (.setSize 400 600)
rlm@10 105 (.setVisible true)))
rlm@10 106
rlm@10 107
rlm@10 108 (defmulti list-provider class)
rlm@10 109
rlm@10 110 (defmethod list-provider :default [x]
rlm@10 111 {:nrows 1 :get-value (fn [i] x) :get-label (fn [i] (.getName (class x)))})
rlm@10 112
rlm@10 113 (defmethod list-provider java.util.List [c]
rlm@10 114 (let [v (if (vector? c) c (vec c))]
rlm@10 115 {:nrows (count v)
rlm@10 116 :get-value (fn [i] (v i))
rlm@10 117 :get-label (fn [i] i)}))
rlm@10 118
rlm@10 119 (defmethod list-provider java.util.Map [c]
rlm@10 120 (let [v (vec (sort (map (fn [[k v]] (vector k v)) c)))]
rlm@10 121 {:nrows (count v)
rlm@10 122 :get-value (fn [i] ((v i) 1))
rlm@10 123 :get-label (fn [i] ((v i) 0))}))
rlm@10 124
rlm@10 125 (defn list-model [provider]
rlm@10 126 (let [{:keys [nrows get-value get-label]} provider]
rlm@10 127 (proxy [AbstractTableModel] []
rlm@10 128 (getColumnCount [] 2)
rlm@10 129 (getRowCount [] nrows)
rlm@10 130 (getValueAt [rowIndex columnIndex]
rlm@10 131 (cond
rlm@10 132 (= 0 columnIndex) (get-label rowIndex)
rlm@10 133 (= 1 columnIndex) (print-str (get-value rowIndex)))))))
rlm@10 134
rlm@10 135 (defmulti table-model class)
rlm@10 136
rlm@10 137 (defmethod table-model :default [x]
rlm@10 138 (proxy [AbstractTableModel] []
rlm@10 139 (getColumnCount [] 2)
rlm@10 140 (getRowCount [] 1)
rlm@10 141 (getValueAt [rowIndex columnIndex]
rlm@10 142 (if (zero? columnIndex)
rlm@10 143 (class x)
rlm@10 144 x))))
rlm@10 145
rlm@10 146 ;(defn make-inspector [x]
rlm@10 147 ; (agent {:frame frame :data x :parent nil :index 0}))
rlm@10 148
rlm@10 149
rlm@10 150 (defn inspect
rlm@10 151 "creates a graphical (Swing) inspector on the supplied object"
rlm@10 152 {:added "1.0"}
rlm@10 153 [x]
rlm@10 154 (doto (JFrame. "Clojure Inspector")
rlm@10 155 (.add
rlm@10 156 (doto (JPanel. (BorderLayout.))
rlm@10 157 (.add (doto (JToolBar.)
rlm@10 158 (.add (JButton. "Back"))
rlm@10 159 (.addSeparator)
rlm@10 160 (.add (JButton. "List"))
rlm@10 161 (.add (JButton. "Table"))
rlm@10 162 (.add (JButton. "Bean"))
rlm@10 163 (.add (JButton. "Line"))
rlm@10 164 (.add (JButton. "Bar"))
rlm@10 165 (.addSeparator)
rlm@10 166 (.add (JButton. "Prev"))
rlm@10 167 (.add (JButton. "Next")))
rlm@10 168 BorderLayout/NORTH)
rlm@10 169 (.add
rlm@10 170 (JScrollPane.
rlm@10 171 (doto (JTable. (list-model (list-provider x)))
rlm@10 172 (.setAutoResizeMode JTable/AUTO_RESIZE_LAST_COLUMN)))
rlm@10 173 BorderLayout/CENTER)))
rlm@10 174 (.setSize 400 400)
rlm@10 175 (.setVisible true)))
rlm@10 176
rlm@10 177
rlm@10 178 (comment
rlm@10 179
rlm@10 180 (load-file "src/inspector.clj")
rlm@10 181 (refer 'inspector)
rlm@10 182 (inspect-tree {:a 1 :b 2 :c [1 2 3 {:d 4 :e 5 :f [6 7 8]}]})
rlm@10 183 (inspect-table [[1 2 3][4 5 6][7 8 9][10 11 12]])
rlm@10 184
rlm@10 185 )