-
Notifications
You must be signed in to change notification settings - Fork 0
/
display_results.clj
82 lines (72 loc) · 2.81 KB
/
display_results.clj
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
(ns ^{:doc "Display a graphical table of results using Swing."
:author "Paul Landes"}
zensols.tabres.display-results
(:import (com.zensols.gui.tabres ResultsFrame))
(:require [clojure.test :as test]))
(def ^:dynamic *data-limit*
"The limit of data presented in the GUI, which defaults
to [[Integer/MAX_VALUE]]."
Integer/MAX_VALUE)
(def ^:private result-frame-data (atom nil))
(def ^:dynamic frame-factory-fn
"A function that takes no args used to create the results frame."
(fn []
(let [frame (ResultsFrame. "mainframe")]
(.init frame)
frame)))
(def ^:dynamic frame-config-fn
"A function that configures a frame either after being created or orphaned.
It takes three arguments: the frame, the title to set if not nil, and a
boolean if it is being orphaned."
(fn [frame title orphaned?]
(if title (.setTitle frame title))))
(defn- new-frame [title]
(swap! result-frame-data
(fn [frame]
(when frame
(.dispose frame))
(let [nf (frame-factory-fn)]
(frame-config-fn nf title false)
nf))))
(defn- result-frame
[title]
(swap! result-frame-data #(or % (new-frame title))))
(defn orphan-frame
"Making a results frame orphaned means it will detach from any new result
sets on any subsquent calls to [[display-results]] and dispose all resources
next time the frame is closed."
([]
(orphan-frame nil))
([title]
(swap! result-frame-data
(fn [frame]
(when frame
(.setDefaultCloseOperation frame
javax.swing.JFrame/DISPOSE_ON_CLOSE)
(.setEnabled (.getPrefSupport frame) false)
(frame-config-fn frame title true))
nil))))
(defn display-results
"Display the results of **data-or-fn**.
**data** is a two dimension seq or a function. If it is a two dimension seq
the first dimension are the rows and the second the respective colum data.
If it is a function, it takes the frame input and what it returns is returned
from this function.
Keys:
**title:** the title set on the (maybe new) frame
**column-names:** seq of the names of the column headers"
[data-or-fn & {:keys [title column-names] :or {title "Results"}}]
(let [frame (result-frame title)]
(.setTitle frame title)
(when (instance? ResultsFrame frame)
(.setHeightFudge frame (if column-names ResultsFrame/HEIGHT_FUDGE 10)))
(let [res (if (test/function? data-or-fn)
(data-or-fn frame)
(let [data (take *data-limit* data-or-fn)]
(.displayResults frame data column-names)
(if (= title "Results")
(.setTitle frame (format "Results (%d)" (count data))))
frame))]
(.pack frame)
(.setVisible frame true)
res)))