Mercurial > lasercutter
view 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 source
1 ;; Copyright (c) Stephen C. Gilardi. All rights reserved. The use and2 ;; distribution terms for this software are covered by the Eclipse Public3 ;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can4 ;; be found in the file epl-v10.html at the root of this distribution. By5 ;; using this software in any fashion, you are agreeing to be bound by the6 ;; terms of this license. You must not remove this notice, or any other,7 ;; from this software.8 ;;9 ;; clojure.contrib.swing-utils10 ;;11 ;; Useful functions for interfacing Clojure to Swing12 ;;13 ;; scgilardi (gmail)14 ;; Created 31 May 200916 (ns clojure.contrib.swing-utils17 (:import (java.awt.event ActionListener KeyAdapter)18 (javax.swing AbstractAction Action19 JMenu JMenuBar JMenuItem20 SwingUtilities))21 (:use [clojure.contrib.def :only (defvar)]))23 (defn add-action-listener24 "Adds an ActionLister to component. When the action fires, f will be25 invoked with the event as its first argument followed by args.26 Returns the listener."27 [component f & args]28 (let [listener (proxy [ActionListener] []29 (actionPerformed [event] (apply f event args)))]30 (.addActionListener component listener)31 listener))33 (defn add-key-typed-listener34 "Adds a KeyListener to component that only responds to KeyTyped events.35 When a key is typed, f is invoked with the KeyEvent as its first argument36 followed by args. Returns the listener."37 [component f & args]38 (let [listener (proxy [KeyAdapter] []39 (keyTyped [event] (apply f event args)))]40 (.addKeyListener component listener)41 listener))43 ;; ----------------------------------------------------------------------44 ;; Meikel Brandmeyer46 (defn do-swing*47 "Runs thunk in the Swing event thread according to schedule:48 - :later => schedule the execution and return immediately49 - :now => wait until the execution completes."50 [schedule thunk]51 (cond52 (= schedule :later) (SwingUtilities/invokeLater thunk)53 (= schedule :now) (if (SwingUtilities/isEventDispatchThread)54 (thunk)55 (SwingUtilities/invokeAndWait thunk)))56 nil)58 (defmacro do-swing59 "Executes body in the Swing event thread asynchronously. Returns60 immediately after scheduling the execution."61 [& body]62 `(do-swing* :later (fn [] ~@body)))64 (defmacro do-swing-and-wait65 "Executes body in the Swing event thread synchronously. Returns66 after the execution is complete."67 [& body]68 `(do-swing* :now (fn [] ~@body)))70 (defvar action-translation-table71 (atom {:name Action/NAME72 :accelerator Action/ACCELERATOR_KEY73 :command-key Action/ACTION_COMMAND_KEY74 :long-desc Action/LONG_DESCRIPTION75 :short-desc Action/SHORT_DESCRIPTION76 :mnemonic Action/MNEMONIC_KEY77 :icon Action/SMALL_ICON})78 "Translation table for the make-action constructor.")80 (defn make-action81 "Create an Action proxy from the given action spec. The standard keys82 recognised are: :name, :accelerator, :command-key, :long-desc,83 :short-desc, :mnemonic and :icon - corresponding to the similar named84 Action properties. The :handler value is used in the actionPerformed85 method of the proxy to pass on the event."86 [spec]87 (let [t-table @action-translation-table88 handler (:handler spec)89 spec (dissoc spec :handler)90 spec (map (fn [[k v]] [(t-table k) v]) spec)91 action (proxy [AbstractAction] []92 (actionPerformed [evt] (handler evt)))]93 (doseq [[k v] spec]94 (.putValue action k v))95 action))97 (defvar menu-constructor-dispatch98 (atom #{:action :handler :items})99 "An atom containing the dispatch set for the add-menu-item method.")101 (defmulti add-menu-item102 "Adds a menu item to the parent according to the item description.103 The item description is a map of the following structure.105 Either:106 - one single :action specifying a javax.swing.Action to be associated107 with the item.108 - a specification suitable for make-action109 - a set of :name, :mnemonic and :items keys, specifying a submenu with110 the given sequence of item entries.111 - an empty map specifying a separator."112 {:arglists '([parent item])}113 (fn add-menu-item-dispatch [_ item]114 (some @menu-constructor-dispatch (keys item))))116 (defmethod add-menu-item :action117 add-menu-item-action118 [parent {:keys [action]}]119 (let [item (JMenuItem. action)]120 (.add parent item)))122 (defmethod add-menu-item :handler123 add-menu-item-handler124 [parent spec]125 (add-menu-item parent {:action (make-action spec)}))127 (defmethod add-menu-item :items128 add-menu-item-submenu129 [parent {:keys [items mnemonic name]}]130 (let [menu (JMenu. name)]131 (when mnemonic132 (.setMnemonic menu mnemonic))133 (doseq [item items]134 (add-menu-item menu item))135 (.add parent menu)))137 (defmethod add-menu-item nil ; nil meaning separator138 add-menu-item-separator139 [parent _]140 (.addSeparator parent))142 (defn make-menubar143 "Create a menubar containing the given sequence of menu items. The menu144 items are described by a map as is detailed in the docstring of the145 add-menu-item function."146 [menubar-items]147 (let [menubar (JMenuBar.)]148 (doseq [item menubar-items]149 (add-menu-item menubar item))150 menubar))152 ;; ----------------------------------------------------------------------