1 | ;; http://java.sun.com/docs/books/tutorial/uiswing/components/passwordfield.html |
2 | (ns com.github.kyleburton.sandbox.swing |
3 | (:import (javax.swing JPanel JPasswordField JFrame JLabel JComponent |
4 | JButton SwingUtilities UIManager |
5 | JTable JScrollPane) |
6 | (java.awt GridLayout FlowLayout GridBagLayout BorderLayout GridLayout) |
7 | (java.awt.event ActionListener ActionEvent WindowAdapter) |
8 | (java.util.concurrent CountDownLatch TimeUnit)) |
9 | (:require [com.github.kyleburton.sandbox.landmark-parser :as lparse] |
10 | [com.github.kyleburton.sandbox.utils :as kutils] |
11 | [com.github.kyleburton.sandbox.sql :as ksql]) |
12 | (:use [clojure.contrib.str-utils :as str] |
13 | [clojure.contrib.fcase :only (case)])) |
14 |
|
15 | (def *ui-latch* (atom (CountDownLatch. 1))) |
16 |
|
17 | (defn ui-latch-reset! [& [count]] |
18 | (reset! *ui-latch* (CountDownLatch. (or count 1)))) |
19 |
|
20 | (defn ui-latch-relese! [] |
21 | (.countDown @*ui-latch*)) |
22 |
|
23 | (def *current-ui* (atom nil)) |
24 |
|
25 | (defn current-ui-set! [ui] |
26 | (reset! *current-ui* ui)) |
27 |
|
28 | (defn close-and-destroy-ui [] |
29 | (.setVisible @*current-ui* false) |
30 | (.dispose @*current-ui*) |
31 | (reset! *current-ui* nil) |
32 | (ui-latch-relese!)) |
33 |
|
34 | (defn get-password-dialog [& args] |
35 | (ui-latch-reset!) |
36 | (let [params (kutils/parse-paired-arglist args) |
37 | frame (JFrame. "Password") |
38 | password (atom nil) |
39 | pass-field (JPasswordField. 20) |
40 | ok-txt "Ok" |
41 | cancel-txt "Cancel" |
42 | panel (proxy |
43 | [JPanel ActionListener] |
44 | [] |
45 | (actionPerformed |
46 | [#^ActionEvent e] |
47 | (let [command (.getActionCommand e) |
48 | done (atom false)] |
49 | (prn (format "WindowAdapter.windowActivated, done=%s event=%s cmd=%s this=%s" |
50 | @done |
51 | e |
52 | command |
53 | this)) |
54 | (if (= ok-txt command) |
55 | (do |
56 | (reset! password (.getPassword pass-field)) |
57 | (reset! done true))) |
58 | (if (= cancel-txt command) |
59 | (do |
60 | (reset! done true))) |
61 | (if @done |
62 | (do |
63 | (close-and-destroy-ui)))))) |
64 | pass-label (JLabel. "Password: ") |
65 | button-panel (let [button-panel (JPanel. (GridLayout. 0 1)) |
66 | ok-button (JButton. "OK") |
67 | cancel-button (JButton. cancel-txt)] |
68 | (.setActionCommand ok-button ok-txt) |
69 | (.addActionListener ok-button panel) |
70 | (.add button-panel ok-button) |
71 | (.setActionCommand cancel-button cancel-txt) |
72 | (.addActionListener cancel-button panel) |
73 | (.add button-panel cancel-button) |
74 | button-panel) |
75 | text-pane (JPanel. (FlowLayout. FlowLayout/TRAILING))] |
76 | (current-ui-set! frame) |
77 | (SwingUtilities/invokeAndWait |
78 | (proxy [Runnable] [] |
79 | (run [] |
80 | (UIManager/put "swing.boldMetal" Boolean/FALSE) |
81 | (.setActionCommand pass-field ok-txt) |
82 | (.addActionListener pass-field panel) |
83 | (.setLabelFor pass-label pass-field) |
84 | |
85 | (.add text-pane pass-label) |
86 | (.add text-pane pass-field) |
87 | (.add panel text-pane) |
88 | (.add panel button-panel) |
89 | |
90 | (.setOpaque panel true) |
91 | (.setContentPane frame panel) |
92 | (.addWindowListener |
93 | frame |
94 | (proxy [WindowAdapter] [] |
95 | (windowActivated |
96 | [e] |
97 | (prn (format "WindowAdapter.windowActivated, this=%s event=%s" this e))))) |
98 | (.pack frame) |
99 | (.setVisible frame true)))) |
100 | (if (:timeout params) |
101 | (.await @*ui-latch* (:timeout params) TimeUnit/SECONDS) |
102 | (.await @*ui-latch*)) |
103 | @password)) |
104 |
|
105 | ;; (let [pass (get-password-dialog)] (prn (format "pass=%s/%s" (or pass "*null*") (String. (or pass "*null*"))))) |
106 | ;; |
107 | ;; (close-and-destroy-ui) |
108 |
|
109 |
|
110 | (defn display-table-data [title cols data] |
111 | (let [frame (JFrame. (str title)) |
112 | panel (JPanel.) |
113 | table (JTable. (to-array-2d data) |
114 | (to-array cols)) |
115 | scroller (JScrollPane. table)] |
116 | (.setResizingAllowed (.getTableHeader table) true) |
117 | (.setAutoResizeMode table JTable/AUTO_RESIZE_SUBSEQUENT_COLUMNS) |
118 | (.setLayout frame (GridLayout. 1 1)) |
119 | (.setContentPane frame panel) |
120 | (.setLayout panel (BorderLayout. 2 1)) |
121 | (.add panel scroller) |
122 | (.pack frame) |
123 | (.setVisible frame true) |
124 | frame)) |
125 |
|
126 | (defn display-table-data-from-map [title data] |
127 | (display-table-data title (keys (first data)) |
128 | (map (fn [m] |
129 | (map #(% m) (keys m))) |
130 | data))) |
131 |
|
132 | (defn sql-browse-db [db] |
133 | (display-table-data |
134 | "DATABASE" |
135 | ["SCHEMA_NAME"] |
136 | (map (fn [x] [x]) (ksql/db-schemas db)))) |
137 |
|
138 | ;; TODO: double-clicking on a name should either invoke sql-browse-table or sql-describe-table |
139 | (defn sql-browse-schema [db schema-name] |
140 | (display-table-data |
141 | schema-name |
142 | ["TABLE_NAME" "SCHEMA" "TYPE" "CATALOG"] |
143 | (map (fn [x] (map x [:name :schema :type :catalog])) (ksql/schema-tables db schema-name)))) |
144 |
|
145 | (defn sql-browse-table [db table-name] |
146 | (display-table-data |
147 | table-name |
148 | (map :name (ksql/describe-table db table-name)) |
149 | (ksql/sql->records db (ksql/select-all table-name)))) |
150 |
|
151 | (defn sql-describe-table [db table-name] |
152 | (let [columns [:name :type :size :scale :is-nullable :precision]] |
153 | (display-table-data |
154 | table-name |
155 | columns |
156 | (map |
157 | (fn [x] (map x columns)) |
158 | (ksql/describe-table db table-name))))) |