Skip to content

Added some constructors and swappers. Updated to version 0.0.14 #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ Note that this library is brand-new and lacks a lot of features; I'm heavily wor

Lots of neat features will follow soon!

Installation: `[clojurefx "0.0.12"]`
Installation: `[clojurefx "0.0.14"]`

### Short info about the state of the project
Right now I'm rather busy and have a few things to do on a deadline. That's why there's little activity right now. Expect more activity in about one to two months. *I will not abandon this project*. Feel free to add stuff (including tests) and send pull requests - I will review them in about two days and accept them if they're allright.
6 changes: 3 additions & 3 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
(defproject clojurefx "0.0.13-SNAPSHOT"
(defproject clojurefx "0.0.14"
:description "Helper functions and probably a wrapper to simplify usage of JavaFX in Clojure.

This is meant to be used with Java 8. If you add JavaFX 2.2 to your classpath it might still work, but that isn't tested.

[This Project On GitHub](https://www.github.com/zilti/clojurefx)

**Installation: `[clojurefx \"0.0.11\"]`**
**Installation: `[clojurefx \"0.0.14\"]`**

Navigation
----------
@@ -18,7 +18,7 @@ Navigation
:lein-release {:deploy-via :clojars}
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]]
:dependencies [[org.clojure/clojure "1.6.0"]]
:plugins [[lein-marginalia "0.7.1"]
[lein-midje "3.1.3-RC2"]
[lein-release "1.0.5"]]
47 changes: 44 additions & 3 deletions src/clojurefx/core.clj
Original file line number Diff line number Diff line change
@@ -100,6 +100,8 @@ Runs the code on the FX application thread and waits until the return value is d

;; ## Collection helpers
;; This probably isn't the ideal approach for mutable collections. Check back for better ones.
(defn list->observable [l]
(javafx.collections.FXCollections/observableArrayList l))
(defn seq->observable [s]
(javafx.collections.FXCollections/unmodifiableObservableList s))

@@ -153,6 +155,25 @@ args is a named-argument-list, where the key is the property name (e.g. :text) a
`(do ~@(for [entry# m#]
`(bind-property!* ~obj ~(key entry#) ~(val entry#))))))


(defn bind-simple-property! [property at]
(let [listeners (atom [])
inv-listeners (atom [])
observable (reify javafx.beans.value.ObservableValue
(^void addListener [this ^javafx.beans.value.ChangeListener l] (swap! listeners conj l))
(^void addListener [this ^javafx.beans.InvalidationListener l] (swap! inv-listeners conj l))
(^void removeListener [this ^javafx.beans.InvalidationListener l] (swap! inv-listeners #(remove #{l} %)))
(^void removeListener [this ^javafx.beans.value.ChangeListener l] (swap! listeners #(remove #{l} %)))
(getValue [this] @at))]
(add-watch at :simple-listener
(fn [_ r oldS newS]
(run-now (doseq [listener @inv-listeners] (.invalidated listener observable))
(doseq [listener @listeners] (.changed listener observable oldS newS)))))
(run-now (.bind property observable))
(run-now (doseq [listener @inv-listeners] (.invalidated listener observable)))
property))


;; ## <a name="events"></a> Events
(defn- prep-key-code [k]
{:keycode k
@@ -322,6 +343,8 @@ The listener gets a preprocessed event map as shown above.
(def-simple-swapper javafx.scene.control.ContextMenu .getItems .setAll)
(def-simple-swapper javafx.scene.control.ListView .getItems .setAll)
(def-simple-swapper javafx.scene.control.Menu .getItems .setAll)
(def-simple-swapper javafx.scene.control.MenuButton .getItems .setAll)
(def-simple-swapper javafx.scene.control.CustomMenuItem .getItems .setAll)
(def-simple-swapper javafx.scene.control.MenuBar .getMenus .setAll)
(def-simple-swapper javafx.scene.control.TableColumn .getColumns .setAll)
(def-simple-swapper javafx.scene.control.TabPane .getTabs .setAll)
@@ -330,6 +353,14 @@ The listener gets a preprocessed event map as shown above.
(def-simple-swapper javafx.scene.control.TreeItem .getChildren .setAll)
(def-simple-swapper javafx.scene.control.TreeTableColumn .getColumns .setAll)
(def-simple-swapper javafx.scene.shape.Path .getElements .setAll)
(def-simple-swapper javafx.scene.chart.PieChart .getData .setAll)
(def-simple-swapper javafx.scene.chart.XYChart .getData .setAll)
(def-simple-swapper javafx.scene.chart.LineChart .getData .setAll)
(def-simple-swapper javafx.scene.chart.BarChart .getData .setAll)
(def-simple-swapper javafx.scene.chart.AreaChart .getData .setAll)
(def-simple-swapper javafx.scene.chart.StackedAreaChart .getData .setAll)
(def-simple-swapper javafx.scene.chart.ScatterChart .getData .setAll)


(defmethod swap-content!* javafx.scene.control.SplitPane [obj fun]
(let [data {:items (into [] (.getItems obj))
@@ -340,6 +371,8 @@ The listener gets a preprocessed event map as shown above.

;; TODO TreeTableView

(defmethod swap-content!* javafx.scene.control.CustomMenuItem [obj fun]
(.setContent obj (fun (.getContent obj))))
(defmethod swap-content!* javafx.scene.control.ScrollPane [obj fun]
(.setContent obj (fun (.getContent obj))))
(defmethod swap-content!* javafx.scene.control.TitledPane [obj fun]
@@ -436,12 +469,19 @@ Don't use this yourself; See the macros \"fx\" and \"deffx\" below.
`(defmethod construct-node '~clazz [cl# ar#]
(apply constructor-helper cl# (for [k# ~keys] (get ar# k#)))))

(defmulti construct-node (fn [class args] (resolve class)))
(defmulti construct-node (fn [class args] class))
(defmethod construct-node :default [class _]
(run-now (eval `(new ~class)))
)

(construct javafx.scene.control.ColorPicker [:color])
(construct javafx.scene.control.TableColumn [:items])
(construct javafx.scene.control.cell.PropertyValueFactory [:property])
(construct javafx.scene.chart.AreaChart [:x-axis :y-axis :ser-list])
(construct javafx.scene.chart.StackedAreaChart [:x-axis :y-axis :ser-list])
(construct javafx.scene.chart.LineChart [:x-axis :y-axis :ser-list])
(construct javafx.scene.chart.BarChart [:x-axis :y-axis :ser-list])
(construct javafx.scene.chart.ScatterChart [:x-axis :y-axis :ser-list])
(construct javafx.scene.layout.BackgroundImage [:image :repeat-x :repeat-y :position :size])
(construct javafx.scene.layout.BorderImage [:image :widths :insets :slices :filled :repeat-x :repeat-y]) ;; TODO Wrapper for BorderWidths, BorderRepeat and Insets

@@ -461,7 +501,7 @@ Don't use this yourself; See the macros \"fx\" and \"deffx\" below.
;; ## <a name="contentcreation"></a> Content creation
(defn fx* [ctrl & args]
(let [args# (if-not (and (nil? (first args)) (map? (first args))) (apply hash-map args) (first args))
{:keys [bind listen content children]} args#
{:keys [bind listen content children style-classes]} args#
props# bind
listeners# listen
content# (if (or (seq? content) (seq? children))
@@ -482,7 +522,8 @@ Don't use this yourself; See the macros \"fx\" and \"deffx\" below.
(if (or (not (nil? content#))
(and (seq? content#) (not (empty? content#))))
(swap-content!* obj# (fn [_] content#)))
obj#)))
(if style-classes (.addAll (.getStyleClass obj#) (list->observable style-classes)))
obj#)))

(defmacro fx "
The central macro of ClojureFX. This takes the name of a node as declared in the pkgs atom and