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
Show file tree
Hide file tree
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
Expand Up @@ -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.
Expand Down
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
----------
Expand All @@ -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"]]
Expand Down
47 changes: 44 additions & 3 deletions src/clojurefx/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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))
Expand All @@ -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]
Expand Down Expand Up @@ -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

Expand All @@ -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))
Expand All @@ -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
Expand Down