(ns clj-twitter-feelings.ui (:import [java.awt Dimension Color Font] [java.awt.event KeyEvent KeyAdapter] [javax.imageio ImageIO] [javax.swing JPanel JFrame JLabel JDialog JTextField JPasswordField JButton JOptionPane Timer WindowConstants UIManager] [org.jfree.chart ChartFactory ChartPanel] [org.jfree.chart.plot PiePlot] [org.jfree.chart.labels StandardPieSectionLabelGenerator] [org.jfree.data.general DefaultPieDataset] [org.jfree.data.time Millisecond TimeSeries TimeSeriesCollection] [org.jfree.ui RefineryUtilities]) (:use [clj-twitter-feelings.core] [clojure.java.io :only (resource)] [clojure.contrib [miglayout :only (miglayout)] [swing-utils :only (add-action-listener add-key-typed-listener do-swing)]]) (:gen-class)) (JFrame/setDefaultLookAndFeelDecorated true) (JDialog/setDefaultLookAndFeelDecorated true) (UIManager/setLookAndFeel "org.jvnet.substance.skin.SubstanceModerateLookAndFeel") (let [message-type { :error JOptionPane/ERROR_MESSAGE :info JOptionPane/INFORMATION_MESSAGE :warn JOptionPane/WARNING_MESSAGE :question JOptionPane/QUESTION_MESSAGE :plain JOptionPane/PLAIN_MESSAGE }] (defn show-message [frame message title type] (JOptionPane/showMessageDialog frame message title (type message-type)))) (defn exit-app [^JFrame frame] (doto frame (.setVisible false) (.dispose)) (System/exit 0)) (defn create-auth-input-dialog "Creates a JDialog to take the input of username and password from the user. Returns the dialog. Arguments are: parent: the parent frame dialog-title: the title of the dialog dialog-message: the message shown in the dialog dialog-width : the width of the dialog dialog-height: the height of the dialog username-lbl-text: the text shown on the username label password-lbl-text: the text shown on the password label input-field-size: the size of the username and password input fields ok-btn-text: the text shown on the ok button cancel-btn-text: the text shown on the cancel button validation-fn: a function which is called to validate the user input when the user presses the ok button. the function is called with arguments: username, password, this dialog. if the function return a string, it is shown on the dialog as the error message and the dialog remains visible. otherwise ok-fn is called. ok-fn: a function which is called when the user presses ok button and the input is valid as per the call to validation-fn. the function is called with arguments: username, password, this dialog. the dialog is hidden before the call. cancel-fn: a function which is called when the user presses cancel button. the function is called with arguments: this dialog. the dialog is hidden before the call. " [^JFrame parent ^String dialog-title ^String dialog-message dialog-width dialog-height ^String username-lbl-text ^String password-lbl-text input-field-size ^String ok-btn-text ^String cancel-btn-text validation-fn ok-fn cancel-fn] (let [username-input (JTextField. (int input-field-size)) password-input (JPasswordField. (int input-field-size)) validation-msg-lbl (JLabel. " ") ok-btn (JButton. ok-btn-text) cancel-btn (JButton. cancel-btn-text) dialog (JDialog. parent dialog-title true)] (doseq [^JTextField in [username-input password-input]] (.addKeyListener in (proxy [KeyAdapter] [] (keyTyped [^KeyEvent e] (when (= (.getKeyChar e) \newline) (.doClick ok-btn))) (keyPressed [^KeyEvent e] (when (= (.getKeyCode e) KeyEvent/VK_ESCAPE) (.doClick cancel-btn)))))) (doto dialog (.setDefaultCloseOperation JDialog/DO_NOTHING_ON_CLOSE) (.setContentPane (miglayout (JPanel.) :layout {:wrap 2} (JLabel. dialog-message) {:span 2} (JLabel. username-lbl-text) username-input (JLabel. password-lbl-text) password-input validation-msg-lbl {:span 2 :align "center"} (miglayout (JPanel.) (doto ok-btn (add-action-listener (fn [e] (let [username (.getText username-input) password (.getText password-input)] (if-let [validation-msg (validation-fn username password dialog)] (.setText validation-msg-lbl validation-msg) (do (.setText validation-msg-lbl " ") (.setVisible dialog false) (ok-fn username password dialog))))))) (doto cancel-btn (add-action-listener (fn [e] (.setVisible dialog false) (cancel-fn dialog))))) {:span 2 :align "center"})) (.setSize dialog-width dialog-height)))) (defn init-gui [adjective-map] (let [frame (JFrame. "Twitter Feelings") ^DefaultPieDataset pie-dataset (reduce #(do (.setValue ^DefaultPieDataset %1 ^String %2 0) %1) (DefaultPieDataset.) (sort (keys @adjective-type-count))) pie-chart (ChartFactory/createPieChart "Distribution" pie-dataset true false false) pie-chart-panel (doto (ChartPanel. pie-chart) (.setPreferredSize (Dimension. 500 400))) time-series-map (into (sorted-map) (map #(vector % (TimeSeries. % Millisecond)) (keys @adjective-type-count))) time-series-dataset (reduce #(do (.addSeries ^TimeSeriesCollection %1 %2) %1) (TimeSeriesCollection.) (vals time-series-map)) time-series-chart (ChartFactory/createTimeSeriesChart "History" "Time" "Percentage" time-series-dataset true false false) time-series-chart-panel (doto (ChartPanel. time-series-chart) (.setPreferredSize (Dimension. 550 400))) adjective-lbl (JLabel. "