Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'release/1.4.5'

  • Loading branch information...
commit 81cedcb6b6224550ef54978f2a32201429f8dd96 2 parents fd9e65d + 1363b6f
@daveray authored
View
4 project.clj
@@ -1,4 +1,4 @@
-(defproject seesaw "1.4.4"
+(defproject seesaw "1.4.5"
:description "A Swing wrapper/DSL for Clojure. You want seesaw.core, FYI. See http://seesaw-clj.org for more info."
:url "http://seesaw-clj.org"
@@ -25,7 +25,7 @@
[com.jgoodies/forms "1.2.1"]
[org.swinglabs.swingx/swingx-core "1.6.3"]
[j18n "1.0.2"]
- [org.fife.ui/rsyntaxtextarea "2.0.4.1"]]
+ [com.fifesoft/rsyntaxtextarea "2.5.6"]]
:profiles { :dev {:dependencies [[com.stuartsierra/lazytest "1.1.2"]
[lein-autodoc "0.9.0"]]}}
:repositories [["stuartsierra-releases" "http://stuartsierra.com/maven2"]]
View
2  src/seesaw/behave.clj
@@ -61,7 +61,7 @@
"
[w & opts]
(let [{:keys [start drag finish]
- :or { start (fn [e]) drag (fn [e]) finish (fn [e]) }} opts
+ :or { start (fn [e]) drag (fn [e [x y]]) finish (fn [e]) }} opts
last-point (java.awt.Point.)]
(listen w
:mouse-pressed
View
9 src/seesaw/bind.clj
@@ -148,6 +148,15 @@
(fn [] (remove-watch this key))))
(notify [this v] (throw (IllegalStateException. "Can't notify an agent!")))
+ clojure.lang.Ref
+ (subscribe [this handler]
+ (let [key (keyword (gensym "bindable-ref-watcher"))]
+ (add-watch this key
+ (fn bindable-ref-watcher
+ [k r o n] (when-not (= o n) (handler n))))
+ (fn [] (remove-watch this key))))
+ (notify [this v] (dosync (ref-set this v)))
+
javax.swing.text.Document
(subscribe [this handler]
(ssc/listen this :document
View
12 src/seesaw/border.clj
@@ -29,9 +29,9 @@
is only used if :top, :bottom, etc are omitted. Defaults to 1.
:top Thickness of the top border in pixels. Defaults to 0.
- :left Thickness of the left border in pixels. Defaluts to 0.
- :bottom Thickness of the bottom border in pixels. Defaluts to 0.
- :right Thickness of the right border in pixels. Defaluts to 0.
+ :left Thickness of the left border in pixels. Defaults to 0.
+ :bottom Thickness of the bottom border in pixels. Defaults to 0.
+ :right Thickness of the right border in pixels. Defaults to 0.
Examples:
@@ -54,9 +54,9 @@
:thickness The thickness of the border in pixels. This property is only used
if :top, :bottom, etc are omitted. Defaults to 1.
:top Thickness of the top border in pixels. Defaults to 0.
- :left Thickness of the left border in pixels. Defaluts to 0.
- :bottom Thickness of the bottom border in pixels. Defaluts to 0.
- :right Thickness of the right border in pixels. Defaluts to 0.
+ :left Thickness of the left border in pixels. Defaults to 0.
+ :bottom Thickness of the bottom border in pixels. Defaults to 0.
+ :right Thickness of the right border in pixels. Defaults to 0.
Examples:
View
68 src/seesaw/chooser.clj
@@ -118,14 +118,25 @@
:selection-mode The file selection mode: :files-only, :dirs-only and :files-and-dirs.
Defaults to :files-only
:filters A seq of either:
-
- A seq that contains a filter name and a seq of
- extensions as strings for that filter.
-
- A seq that contains a filter name and a function
- to be used as accept function. (see file-filter)
- A FileFilter. (see file-filter)
+ a seq that contains a filter name and a seq of
+ extensions as strings for that filter;
+
+ a seq that contains a filter name and a function
+ to be used as accept function (see file-filter);
+
+ a FileFilter (see file-filter).
+
+ The filters appear in the dialog's filter selection in the same
+ order as in the seq.
+ :all-files? If true, a filter matching all file extensions and files
+ without an extension will appear in the filter selection
+ of the dialog additionally to the filters specified
+ through :filters. The filter usually appears last in the
+ selection. If this is not desired set this option to
+ false and include an equivalent filter manually at the
+ desired position as shown in the examples below. Defaults
+ to true.
:remember-directory? Flag specifying whether to remember the directory for future
file-input invocations in case of successful exit. Default: true.
@@ -141,10 +152,12 @@
; ask & return single file
(choose-file)
- ; ask & return including a filter for image files
- (choose-file :filters [[\"Images\" [\"png\" \"jpeg\"]
- [\"Folders\" #(.isDirectory %)]
- (file-filter \"All files\" (constantly true))]])
+ ; ask & return including a filter for image files and an \"all files\"
+ ; filter appearing at the beginning
+ (choose-file :all-files? false
+ :filters [(file-filter \"All files\" (constantly true))
+ [\"Images\" [\"png\" \"jpeg\"]]
+ [\"Folders\" #(.isDirectory %)]])
; ask & return absolute file path as string
(choose-file :success-fn (fn [fc file] (.getAbsolutePath file)))
@@ -162,16 +175,29 @@
cancel-fn (fn [fc])}
:as opts}] (if (keyword? (first args)) (cons nil args) args)
parent (if (keyword? parent) nil parent)
- ^JFileChooser chooser (configure-file-chooser (JFileChooser.) (dissoc opts :type :remember-directory? :success-fn :cancel-fn))
- multi? (.isMultiSelectionEnabled chooser)
- result (show-file-chooser chooser parent type)]
- (cond
- (= result JFileChooser/APPROVE_OPTION)
- (do
- (when remember-directory?
- (remember-chooser-dir chooser))
- (success-fn chooser (if multi? (.getSelectedFiles chooser) (.getSelectedFile chooser))))
- :else (cancel-fn chooser))))
+ ^JFileChooser chooser (configure-file-chooser
+ (JFileChooser.)
+ (dissoc
+ opts
+ :type
+ :remember-directory?
+ :success-fn
+ :cancel-fn))]
+ (when-let [[filter _] (seq (.getChoosableFileFilters chooser))]
+ (.setFileFilter chooser filter))
+ (let [result (show-file-chooser chooser parent type)
+ multi? (.isMultiSelectionEnabled chooser)]
+ (cond
+ (= result JFileChooser/APPROVE_OPTION)
+ (do
+ (when remember-directory?
+ (remember-chooser-dir chooser))
+ (success-fn
+ chooser
+ (if multi?
+ (.getSelectedFiles chooser)
+ (.getSelectedFile chooser))))
+ :else (cancel-fn chooser)))))
(defn choose-color
"Choose a color with a color chooser dialog. The optional first argument is the
View
4 src/seesaw/clipboard.clj
@@ -37,9 +37,9 @@
(let [cb (system)]
(cond
(string? transferable)
- (contents! (dnd/default-transferable [dnd/string-flavor transferable]))
+ (contents! (dnd/default-transferable [dnd/string-flavor transferable]) owner)
:else
- (.setContents (system) ^java.awt.datatransfer.Tranferable transferable owner))
+ (.setContents (system) ^java.awt.datatransfer.Transferable transferable owner))
cb)))
(comment
View
79 src/seesaw/core.clj
@@ -216,8 +216,8 @@
A macro that returns a proxied instance of the given class. This is
used by Seesaw to construct widgets that can be fiddled with later,
e.g. installing a paint handler, etc."
- ([factory-class]
- `(proxy [~factory-class seesaw.selector.Tag] []
+ ([factory-class & opts]
+ `(proxy [~factory-class seesaw.selector.Tag] [~@opts]
(tag_name [] (.getSimpleName ~factory-class)))))
@@ -813,7 +813,7 @@
(def ^{:private true} boolean-examples 'boolean)
(def ^{:private true} dimension-examples [[640 :by 480] 'java.awt.Dimension])
-(def ^{:private true} base-resource-options [:text :foreground :background :font :icon :tip])
+(def base-resource-options [:text :foreground :background :font :icon :tip])
(def default-options
(option-map
@@ -952,7 +952,7 @@
Examples:
; Create a panel with a label positions at (10, 10) with width 200 and height 40.
- (xyz-panel :items [(label :text \"The Black Lodge\" :bounds [10 10 200 40]))
+ (xyz-panel :items [(label :text \"The Black Lodge\" :bounds [10 10 200 40])])
; Move a widget up 50 pixels and right 25 pixels
(move! my-label :by [25 -50])
@@ -3035,9 +3035,45 @@
;*******************************************************************************
; Alert
+(def ^{:private true} message-type-map {
+ :error JOptionPane/ERROR_MESSAGE
+ :info JOptionPane/INFORMATION_MESSAGE
+ :warning JOptionPane/WARNING_MESSAGE
+ :question JOptionPane/QUESTION_MESSAGE
+ :plain JOptionPane/PLAIN_MESSAGE
+})
+
+(defn- alert-impl
+ "
+ showMessageDialog(Component parentComponent,
+ Object message,
+ String title,
+ int messageType,
+ Icon icon)
+ "
+ [source message {:keys [title type icon] :or {type :plain}}]
+ (let [source (to-widget source)
+ message (if (coll? message) (object-array message) (resource message))]
+ (JOptionPane/showMessageDialog ^java.awt.Component source
+ message
+ (resource title)
+ (message-type-map type)
+ (make-icon icon))))
+
(defn alert
- "Show a simple message alert dialog. Take an optional parent component, source,
- used for dialog placement, and a message which is passed through (resource).
+ "Show a simple message alert dialog:
+
+ (alert [source] message & options)
+
+ source - optional parent component
+ message - The message to show the user. May be a string, or list of strings, widgets, etc.
+ options - additional options
+
+ Additional options:
+
+ :title The dialog title
+ :type :warning, :error, :info, :plain, or :question
+ :icon Icon to display (Icon, URL, etc)
Examples:
@@ -3045,22 +3081,22 @@
(alert e \"Hello!\")
See:
- http://download.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html#showMessageDialog%28java.awt.Component,%20java.lang.Object%29
+ http://download.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html#showMessageDialog%28java.awt.Component,%20java.lang.Object,%20java.lang.String,%20int%29
"
- ([source message]
- (JOptionPane/showMessageDialog (to-widget source) (resource message)))
- ([message] (alert nil message)))
+ [& args]
+ (let [n (count args)
+ f (first args)
+ s (second args)]
+ (cond
+ (or (= n 0) (keyword? f))
+ (illegal-argument "alert requires at least one non-keyword arg")
+ (= n 1) (alert-impl nil f {})
+ (= n 2) (alert-impl f s {})
+ (keyword? s) (alert-impl nil f (drop 1 args))
+ :else (alert-impl f s (drop 2 args)))))
;*******************************************************************************
; Input
-(def ^{:private true} input-type-map {
- :error JOptionPane/ERROR_MESSAGE
- :info JOptionPane/INFORMATION_MESSAGE
- :warning JOptionPane/WARNING_MESSAGE
- :question JOptionPane/QUESTION_MESSAGE
- :plain JOptionPane/PLAIN_MESSAGE
-})
-
(defrecord InputChoice [value to-string]
Object
(toString [this] (to-string value)))
@@ -3083,7 +3119,7 @@
result (JOptionPane/showInputDialog ^java.awt.Component source
message
(resource title)
- (input-type-map type)
+ (message-type-map type)
(make-icon icon)
choices value)]
(if (and result choices)
@@ -3155,7 +3191,6 @@
})
(def ^:private dialog-defaults {
- :parent nil
:content "Please set the :content option."
:option-type :default
:type :plain
@@ -3239,7 +3274,7 @@
options default-option success-fn cancel-fn no-fn]} (merge dialog-defaults opts)
pane (JOptionPane.
content
- (input-type-map type)
+ (message-type-map type)
(dialog-option-type-map option-type)
nil ;icon
(when options
@@ -3284,7 +3319,7 @@
message
(resource title)
(dialog-option-type-map option-type)
- (input-type-map type)
+ (message-type-map type)
(make-icon icon))]
(condp = result
JOptionPane/NO_OPTION false
View
20 src/seesaw/cursor.clj
@@ -2,7 +2,7 @@
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-; which can be found in the file epl-v10.html at the root of this
+; which can be found in the file epl-v10.html at the root of this
; distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
@@ -14,18 +14,18 @@
(:use [seesaw.util :only [constant-map illegal-argument]])
(:import [java.awt Cursor Toolkit]))
-(def ^{:private true} built-in-cursor-map
- (constant-map Cursor {:suffix "_CURSOR"}
+(def ^{:private true} built-in-cursor-map
+ (constant-map Cursor {:suffix "_CURSOR"}
:crosshair :custom :default :hand :move :text :wait
:e-resize :n-resize :ne-resize :nw-resize :s-resize :se-resize :sw-resize :w-resize))
(defn- custom-cursor
[^java.awt.Image image & [point]]
(let [[x y] point]
- (.. (Toolkit/getDefaultToolkit) (createCustomCursor image
- (java.awt.Point. (or x 0) (or y 0))
+ (.. (Toolkit/getDefaultToolkit) (createCustomCursor image
+ (java.awt.Point. (or x 0) (or y 0))
(str (gensym "seesaw-cursor"))))))
-(defn cursor
+(defn cursor
"Create a built-in or custom cursor. Take one of two forms:
(cursor :name-of-built-in-cursor)
@@ -33,7 +33,7 @@
Creates a built-in cursor of the given type. Valid types are:
:crosshair :custom :default :hand :move :text :wait
- :e-resize :n-resize :ne-resize :nw-resize
+ :e-resize :n-resize :ne-resize :nw-resize
:s-resize :se-resize :sw-resize :w-resize
To create custom cursor:
@@ -54,7 +54,7 @@
Notes:
This function is used implicitly by the :cursor option on most widget
- constructor functions. So
+ constructor functions. So
(label :cursor (cursor :hand))
@@ -69,10 +69,10 @@
See:
- http://download.oracle.com/javase/6/docs/api/java/awt/Cursor.html
+ http://download.oracle.com/javase/6/docs/api/java/awt/Cursor.html
http://download.oracle.com/javase/6/docs/api/java/awt/Toolkit.html#createCustomCursor%28java.awt.Image,%20java.awt.Point,%20java.lang.String%29
"
- ^Cursor
+ ^java.awt.Cursor
[type & args]
(cond
; TODO protocol if this gets any more nasty
View
3  src/seesaw/graphics.clj
@@ -306,7 +306,7 @@
(when (seq dashes) (float-array dashes))
dash-phase))
-(defn to-stroke [v]
+(defn to-stroke
"Convert v to a stroke. As follows depending on v:
nil - returns nil
@@ -314,6 +314,7 @@
Throws IllegalArgumentException if it can't figure out what to do.
"
+ [v]
(cond
(nil? v) nil
(number? v) (stroke :width v)
View
5 src/seesaw/layout.clj
@@ -26,8 +26,9 @@
(add!* [layout target widget constraint])
(get-constraint* [layout container widget]))
-(defn handle-structure-change [^javax.swing.JComponent container]
+(defn handle-structure-change
"Helper. Revalidate and repaint a container after structure change"
+ [^java.awt.Component container]
(doto container
.revalidate
.repaint))
@@ -277,7 +278,7 @@
(add-widget target widget (border-layout-dirs constraint)))
(get-constraint* [layout container widget]
(.getConstraints layout widget))
-
+
java.awt.CardLayout
(add!* [layout target widget constraint]
(add-widget target widget (name constraint)))
View
2  src/seesaw/selection.clj
@@ -84,6 +84,8 @@
(extend-protocol Selection
javax.swing.JList
+ ; TODO #165 getSelectedValues() is deprecated in JDK 7 in favor of getSelectedValuesList()
+ ; replace if people ever stop using JDK 6.
(get-selection [target] (seq (.getSelectedValues target)))
(set-selection [target args] (jlist-set-selection target args)))
View
5 src/seesaw/selector.clj
@@ -43,8 +43,9 @@
; TODO should we enforce unique ids?
(id-of!* w id)))
-(defn class-of [w]
+(defn class-of
"Retrieve the classes of a widget as a set of strings"
+ [w]
(class-of* w))
(defn class-of!
@@ -275,7 +276,7 @@
[accepts (when (seq chains) (comp next-states ps))]))
(defn cacheable [selector] (vary-meta selector assoc ::cacheable true))
-(defn cacheable? [selector] false (-> selector meta ::cacheable))
+(defn cacheable? [selector] (-> selector meta ::cacheable))
(defn- automaton* [selector]
(make-state (-> selector (selector-chains 0) set)))
View
1  src/seesaw/table.clj
@@ -197,6 +197,7 @@
(let [target (to-table-model target)
col-key-map (get-column-key-map target)]
(cond
+ (nil? rows) nil
(integer? rows) (single-value-at target col-key-map rows)
:else (map #(single-value-at target col-key-map %) rows))))
View
70 src/seesaw/util.clj
@@ -2,23 +2,23 @@
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-; which can be found in the file epl-v10.html at the root of this
+; which can be found in the file epl-v10.html at the root of this
; distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns seesaw.util
- (:require clojure.string
+ (:require clojure.string
[j18n.core :as j18n])
(:import [java.net URL URI MalformedURLException URISyntaxException]))
-(defn illegal-argument
+(defn illegal-argument
"Throw an illegal argument exception formatted as with (clojure.core/format)"
[fmt & args]
(throw (IllegalArgumentException. ^String (apply format fmt args))))
-(defn check-args
+(defn check-args
[condition message]
(if-not condition
(throw (IllegalArgumentException. ^String message))
@@ -34,10 +34,10 @@
"Spawn of (cond) and (doto). Works like (doto), but each form has a condition
which controls whether it is executed. Returns x.
- (doto (new java.util.HashMap)
- true (.put \"a\" 1)
+ (doto (new java.util.HashMap)
+ true (.put \"a\" 1)
(< 2 1) (.put \"b\" 2))
-
+
Here, only (.put \"a\" 1) is executed.
"
[x & forms]
@@ -50,9 +50,10 @@
(partition 2 forms))
~gx)))
-(defn to-seq [v]
+(defn to-seq
"Stupid helper to turn possibly single values into seqs"
- (cond
+ [v]
+ (cond
(nil? v) v
(seq? v) v
(coll? v) (seq v)
@@ -63,13 +64,13 @@
(.. (name k) (toUpperCase) (replace "-" "_")))
(defn constant-map
- "Given a class and a list of keywordized constant names returns the
+ "Given a class and a list of keywordized constant names returns the
values of those fields in a map. The name mapping upper-cases and replaces
hyphens with underscore, e.g.
-
+
:above-baseline --> ABOVE_BASELINE
- Note that the fields must be static and declared *in* the class, not a
+ Note that the fields must be static and declared *in* the class, not a
supertype.
"
[^Class klass & fields]
@@ -78,45 +79,50 @@
(reduce
(fn [m [k v]] (assoc m k v))
{}
- (map
- #(vector %1 (.. klass
- (getDeclaredField (str (constantize-keyword %1) suffix))
+ (map
+ #(vector %1 (.. klass
+ (getDeclaredField (str (constantize-keyword %1) suffix))
(get nil)))
fields))))
-
-
+
+
(defn camelize
"Convert input string to camelCase from hyphen-case"
[s]
(clojure.string/replace s #"-(.)" #(.toUpperCase ^String (%1 1))))
-(defn boolean? [b]
+(defn boolean?
"Return true if b is exactly true or false. Useful for handling optional
- boolean properties where we want to do nothing if the property isn't
+ boolean properties where we want to do nothing if the property isn't
provided."
+ [b]
(or (true? b) (false? b)))
-(defn atom? [a]
+(defn atom?
"Return true if a is an atom"
+ [a]
(isa? (type a) clojure.lang.Atom))
-(defn try-cast [c x]
+(defn try-cast
"Just like clojure.core/cast, but returns nil on failure rather than throwing ClassCastException"
+ [c x]
(try
(cast c x)
(catch ClassCastException e nil)))
-(defn ^URL to-url [s]
- "Try to parse (str s) as a URL. Returns new java.net.URL on success, nil
+(defn ^URL to-url
+ "Try to parse (str s) as a URL. Returns new java.net.URL on success, nil
otherwise. This is different from clojure.java.io/as-url in that it doesn't
throw an exception and it uses (str) on the input."
+ [s]
(if (instance? URL s) s
(try
(URL. (str s))
(catch MalformedURLException e nil))))
-(defn ^URI to-uri [s]
+(defn ^URI to-uri
"Try to make a java.net.URI from s"
+ [s]
(cond
(instance? URI s) s
(instance? URL s) (.toURI ^URL s)
@@ -141,8 +147,8 @@
(java.awt.Insets. top left (or bottom top) (or right left)))
:else (illegal-argument "Don't know how to create insets from %s" v)))
-(defprotocol Children
- "A protocol for retrieving the children of a widget as a seq.
+(defprotocol Children
+ "A protocol for retrieving the children of a widget as a seq.
This takes care of idiosyncracies of frame vs. menus, etc."
(children [c] "Returns a seq of the children of the given widget"))
@@ -158,12 +164,12 @@
(defn collect
"Given a root widget or frame, returns a depth-fist seq of all the widgets
in the hierarchy. For example to disable everything:
-
+
(config (collect (.getContentPane my-frame)) :enabled? false)
"
[root]
- (tree-seq
- (constantly true)
+ (tree-seq
+ (constantly true)
children
root))
@@ -180,19 +186,19 @@
(defn ^Integer to-mnemonic-keycode
"Convert a character to integer to a mnemonic keycode. In the case of char
- input, generates the correct keycode even if it's lower case. Input argument
+ input, generates the correct keycode even if it's lower case. Input argument
can be:
* i18n resource keyword - only first char is used
* string - only first char is used
* char - lower or upper case
* int - key event code
-
+
See:
java.awt.event.KeyEvent for list of keycodes
http://download.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html"
[v]
- (cond
+ (cond
(resource-key? v) (to-mnemonic-keycode (resource v))
(string? v) (to-mnemonic-keycode (.charAt ^String v 0))
(char? v) (int (Character/toUpperCase ^Character v))
View
19 test/seesaw/test/bind.clj
@@ -172,7 +172,24 @@
true)
; Unfortunately, in Clojure 1.2, IllegalStateException gets wrapped by reset!
(catch RuntimeException e
- (= IllegalStateException (class (.getCause e))))))))))
+ (= IllegalStateException (class (.getCause e)))))))))
+
+ (testing "given a Ref"
+ (it "should pass along changes to the ref's value"
+ (let [start (ref nil)
+ end (atom nil)]
+ (bind start end)
+ (dosync
+ (alter start (constantly "foo")))
+ (expect (= "foo" @start))
+ (expect (= "foo" @end))))
+ (it "should pass update the ref's value when the source changes"
+ (let [start (atom nil)
+ end (ref nil)]
+ (bind start end)
+ (reset! start "foo")
+ (expect (= "foo" @start))
+ (expect (= "foo" @end))))) )
(describe b-do*
(it "executes a function with a single argument and ends a chain"
View
4 test/seesaw/test/core.clj
@@ -850,8 +850,8 @@
(let [render-fn (fn [renderer info] nil)
renderer (default-list-cell-renderer render-fn)
lb (combobox :renderer renderer)]
- (= renderer (.getRenderer lb))
- (= renderer (config lb :renderer))))
+ (expect (= renderer (.getRenderer lb)))
+ (expect (= renderer (config lb :renderer)))))
(it "should create a JComboBox using a seq as its model"
(let [lb (combobox :model [1 2 3 4])
model (.getModel lb)]
View
21 test/seesaw/test/examples/clock.clj
@@ -2,7 +2,7 @@
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-; which can be found in the file epl-v10.html at the root of this
+; which can be found in the file epl-v10.html at the root of this
; distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
@@ -38,14 +38,15 @@
(def tick-style (style :foreground java.awt.Color/DARK_GRAY
:stroke (stroke :width 3 :cap :round)))
-(defn second-so-far []
- (let [d (java.util.Date.)]
- (+
- (* (.getHours d) 60 60)
- (* (.getMinutes d) 60)
- (.getSeconds d))))
+(defn second-so-far []
-(defn paint-clock [c g]
+ (let [c (java.util.Calendar/getInstance)]
+ (+
+ (* (.get c java.util.Calendar/HOUR_OF_DAY) 60 60)
+ (* (.get c java.util.Calendar/MINUTE) 60)
+ (.get c java.util.Calendar/SECOND))))
+
+(defn paint-clock [^javax.swing.JComponent c ^java.awt.Graphics2D g]
(let [width (.getWidth c)
height (.getHeight c)
m (- (min width height) 15)
@@ -78,8 +79,8 @@
(defexample []
(let [cvs (canvas :id :canvas :background "#BBBBBB" :paint paint-clock)
t (timer (fn [e] (repaint! cvs)) :delay 1000)]
- (frame
- :title "Seesaw Canvas Clock"
+ (frame
+ :title "Seesaw Canvas Clock"
:width 400 :height 400
:content cvs)))
View
12 test/seesaw/test/examples/example.clj
@@ -1,21 +1,21 @@
(ns seesaw.test.examples.example
(:use [seesaw.core :only [config! pack! show! invoke-now]]))
-(defmacro defexample
- "Does the boilerplate for an example.
+(defmacro defexample
+ "Does the boilerplate for an example.
arg-vec is a binding vector of arguments for the example, usually command-line
args. body is code which must return an instance of javax.swing.JFrame. If the
frame's size has not been set at all, pack! is called. Then show! is called.
-
+
Defines two functions:
-
+
run : takes an on-close keyword and trailing args and runs
the example.
-main : calls (run :exit & args). i.e. runs the example and exits when
closed
-
- See the plethora of examples in this directory for usage examples.
+
+ See the plethora of examples in this directory for usage examples.
"
[arg-vec & body]
`(do
View
28 test/seesaw/test/examples/hotpotatoes.clj
@@ -2,7 +2,7 @@
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-; which can be found in the file epl-v10.html at the root of this
+; which can be found in the file epl-v10.html at the root of this
; distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
@@ -13,16 +13,16 @@
seesaw.test.examples.example)
(:require [clojure.java.io :only reader]))
-; A simple HTTP request app. Enter a URL and click "Go". It does the request in
+; A simple HTTP request app. Enter a URL and click "Go". It does the request in
; the background and displays the response.
(defn do-request [url-str f]
- (future
+ (future
(let [result (if-let [url (to-url url-str)]
(slurp url)
- ("Invalid URL"))]
+ "Invalid URL")]
(invoke-later (f result)))))
-
+
(defexample []
(let [exit-action (action :handler dispose! :name "Exit")
url-text (text "http://google.com")
@@ -31,29 +31,29 @@
result-handler (fn [s]
(text! result-text s)
(text! status "Ready"))
- go-handler (fn [e]
+ go-handler (fn [e]
(text! status "Busy")
- (do-request
+ (do-request
(text url-text)
result-handler))]
- (frame
+ (frame
:id :frame
:title "Hot Potatoes!"
:menubar (menubar :items [(menu :text "File" :items [exit-action])])
:width 500 :height 600
- :content
+ :content
(border-panel
:border 5
:north (toolbar :items [exit-action])
- :center
+ :center
(border-panel
- :north
- (horizontal-panel
+ :north
+ (horizontal-panel
:border [5 "Configure Request"]
- :items ["URL" url-text
+ :items ["URL" url-text
(action :handler go-handler :name "Go")])
:center
- (horizontal-panel
+ (horizontal-panel
:border [5 "Request Result"]
:items [(scrollable result-text)]))
:south status))))
View
4 test/seesaw/test/layout.clj
@@ -13,6 +13,10 @@
(:use [lazytest.describe :only (describe it testing)]
[lazytest.expect :only (expect)]))
+(describe handle-structure-change
+ (it "should successfully handle all kinds of components"
+ (handle-structure-change (proxy [java.awt.Component] []))))
+
(describe realize-grid-bag-constraints
(it "should return a vector of widget/constraint pairs"
(let [[[w0 c0] [w1 c1] & more] (realize-grid-bag-constraints [[:first :weightx 99 :weighty 555 :gridx :relative] [:second :weightx 100 :anchor :baseline]])]
View
4 test/seesaw/test/selection.clj
@@ -107,8 +107,8 @@
(it "returns a seq of selected model row indices when selection is non-empty"
(let [jtable (javax.swing.JTable. 5 3)]
(.setRowSelectionInterval jtable 1 3)
- (= [1 2 3] (selection jtable {:multi? true}))
- (= 1 (selection jtable))))))
+ (expect (= [1 2 3] (selection jtable {:multi? true})))
+ (expect (= 1 (selection jtable)))))))
(describe selection!
View
4 test/seesaw/test/table.clj
@@ -85,6 +85,10 @@
(let [t (table-model :columns [{:key :a :text "a"} {:key :b :text "b"}]
:rows [[:a "bee" :b "cee"] [:a "tree" :b "four"]])]
(expect (nil? (value-at t 9)))))
+ (it "returns nil for a nil rows parameter"
+ (let [t (table-model :columns [{:key :a :text "a"} {:key :b :text "b"}]
+ :rows [[:a "bee" :b "cee"] [:a "tree" :b "four"]])]
+ (expect (nil? (value-at t nil)))))
(it "survives an out-of-bounds value-at call"
(let [t (table-model :columns [{:key :a :text "a"} {:key :b :text "b"}]
:rows [{:a "bee" :b "cee"} {:a "tree" :b "four"}])]
Please sign in to comment.
Something went wrong with that request. Please try again.