Mercurial > lasercutter
diff src/clojure/contrib/swing_utils.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/swing_utils.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,152 @@ 1.4 +;; Copyright (c) Stephen C. Gilardi. All rights reserved. The use and 1.5 +;; distribution terms for this software are covered by the Eclipse Public 1.6 +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can 1.7 +;; be found in the file epl-v10.html at the root of this distribution. By 1.8 +;; using this software in any fashion, you are agreeing to be bound by the 1.9 +;; terms of this license. You must not remove this notice, or any other, 1.10 +;; from this software. 1.11 +;; 1.12 +;; clojure.contrib.swing-utils 1.13 +;; 1.14 +;; Useful functions for interfacing Clojure to Swing 1.15 +;; 1.16 +;; scgilardi (gmail) 1.17 +;; Created 31 May 2009 1.18 + 1.19 +(ns clojure.contrib.swing-utils 1.20 + (:import (java.awt.event ActionListener KeyAdapter) 1.21 + (javax.swing AbstractAction Action 1.22 + JMenu JMenuBar JMenuItem 1.23 + SwingUtilities)) 1.24 + (:use [clojure.contrib.def :only (defvar)])) 1.25 + 1.26 +(defn add-action-listener 1.27 + "Adds an ActionLister to component. When the action fires, f will be 1.28 + invoked with the event as its first argument followed by args. 1.29 + Returns the listener." 1.30 + [component f & args] 1.31 + (let [listener (proxy [ActionListener] [] 1.32 + (actionPerformed [event] (apply f event args)))] 1.33 + (.addActionListener component listener) 1.34 + listener)) 1.35 + 1.36 +(defn add-key-typed-listener 1.37 + "Adds a KeyListener to component that only responds to KeyTyped events. 1.38 + When a key is typed, f is invoked with the KeyEvent as its first argument 1.39 + followed by args. Returns the listener." 1.40 + [component f & args] 1.41 + (let [listener (proxy [KeyAdapter] [] 1.42 + (keyTyped [event] (apply f event args)))] 1.43 + (.addKeyListener component listener) 1.44 + listener)) 1.45 + 1.46 +;; ---------------------------------------------------------------------- 1.47 +;; Meikel Brandmeyer 1.48 + 1.49 +(defn do-swing* 1.50 + "Runs thunk in the Swing event thread according to schedule: 1.51 + - :later => schedule the execution and return immediately 1.52 + - :now => wait until the execution completes." 1.53 + [schedule thunk] 1.54 + (cond 1.55 + (= schedule :later) (SwingUtilities/invokeLater thunk) 1.56 + (= schedule :now) (if (SwingUtilities/isEventDispatchThread) 1.57 + (thunk) 1.58 + (SwingUtilities/invokeAndWait thunk))) 1.59 + nil) 1.60 + 1.61 +(defmacro do-swing 1.62 + "Executes body in the Swing event thread asynchronously. Returns 1.63 + immediately after scheduling the execution." 1.64 + [& body] 1.65 + `(do-swing* :later (fn [] ~@body))) 1.66 + 1.67 +(defmacro do-swing-and-wait 1.68 + "Executes body in the Swing event thread synchronously. Returns 1.69 + after the execution is complete." 1.70 + [& body] 1.71 + `(do-swing* :now (fn [] ~@body))) 1.72 + 1.73 +(defvar action-translation-table 1.74 + (atom {:name Action/NAME 1.75 + :accelerator Action/ACCELERATOR_KEY 1.76 + :command-key Action/ACTION_COMMAND_KEY 1.77 + :long-desc Action/LONG_DESCRIPTION 1.78 + :short-desc Action/SHORT_DESCRIPTION 1.79 + :mnemonic Action/MNEMONIC_KEY 1.80 + :icon Action/SMALL_ICON}) 1.81 + "Translation table for the make-action constructor.") 1.82 + 1.83 +(defn make-action 1.84 + "Create an Action proxy from the given action spec. The standard keys 1.85 + recognised are: :name, :accelerator, :command-key, :long-desc, 1.86 + :short-desc, :mnemonic and :icon - corresponding to the similar named 1.87 + Action properties. The :handler value is used in the actionPerformed 1.88 + method of the proxy to pass on the event." 1.89 + [spec] 1.90 + (let [t-table @action-translation-table 1.91 + handler (:handler spec) 1.92 + spec (dissoc spec :handler) 1.93 + spec (map (fn [[k v]] [(t-table k) v]) spec) 1.94 + action (proxy [AbstractAction] [] 1.95 + (actionPerformed [evt] (handler evt)))] 1.96 + (doseq [[k v] spec] 1.97 + (.putValue action k v)) 1.98 + action)) 1.99 + 1.100 +(defvar menu-constructor-dispatch 1.101 + (atom #{:action :handler :items}) 1.102 + "An atom containing the dispatch set for the add-menu-item method.") 1.103 + 1.104 +(defmulti add-menu-item 1.105 + "Adds a menu item to the parent according to the item description. 1.106 + The item description is a map of the following structure. 1.107 + 1.108 + Either: 1.109 + - one single :action specifying a javax.swing.Action to be associated 1.110 + with the item. 1.111 + - a specification suitable for make-action 1.112 + - a set of :name, :mnemonic and :items keys, specifying a submenu with 1.113 + the given sequence of item entries. 1.114 + - an empty map specifying a separator." 1.115 + {:arglists '([parent item])} 1.116 + (fn add-menu-item-dispatch [_ item] 1.117 + (some @menu-constructor-dispatch (keys item)))) 1.118 + 1.119 +(defmethod add-menu-item :action 1.120 + add-menu-item-action 1.121 + [parent {:keys [action]}] 1.122 + (let [item (JMenuItem. action)] 1.123 + (.add parent item))) 1.124 + 1.125 +(defmethod add-menu-item :handler 1.126 + add-menu-item-handler 1.127 + [parent spec] 1.128 + (add-menu-item parent {:action (make-action spec)})) 1.129 + 1.130 +(defmethod add-menu-item :items 1.131 + add-menu-item-submenu 1.132 + [parent {:keys [items mnemonic name]}] 1.133 + (let [menu (JMenu. name)] 1.134 + (when mnemonic 1.135 + (.setMnemonic menu mnemonic)) 1.136 + (doseq [item items] 1.137 + (add-menu-item menu item)) 1.138 + (.add parent menu))) 1.139 + 1.140 +(defmethod add-menu-item nil ; nil meaning separator 1.141 + add-menu-item-separator 1.142 + [parent _] 1.143 + (.addSeparator parent)) 1.144 + 1.145 +(defn make-menubar 1.146 + "Create a menubar containing the given sequence of menu items. The menu 1.147 + items are described by a map as is detailed in the docstring of the 1.148 + add-menu-item function." 1.149 + [menubar-items] 1.150 + (let [menubar (JMenuBar.)] 1.151 + (doseq [item menubar-items] 1.152 + (add-menu-item menubar item)) 1.153 + menubar)) 1.154 + 1.155 +;; ----------------------------------------------------------------------