Added ways to search the scenegraph

This commit is contained in:
zilti 2018-10-24 15:55:13 +00:00
parent 02a2c6aca2
commit 04b7e79d35
4 changed files with 99 additions and 40 deletions

View file

@ -90,7 +90,7 @@ This macro runs the code given on the JavaFX thread and immediately returns. Pre
@node Coding a scenegraph @node Coding a scenegraph
@chapter Coding a scenegraph @chapter Coding a scenegraph
@strong{This part of the library has not been tested for a long time; I will get to it eventually, but expect things to be somewhat broken.} @strong{This part of the library is not yet completed; mainly, the problem is that some objects can have children while not being a Parent.}
@lisp @lisp
(require '[clojurefx.clojure :refer [compile]]) (require '[clojurefx.clojure :refer [compile]])

View file

@ -10,9 +10,9 @@
[swiss-arrows "1.0.0"] [swiss-arrows "1.0.0"]
[camel-snake-kebab "0.4.0"] [camel-snake-kebab "0.4.0"]
[com.taoensso/timbre "4.10.0" :exclusions [com.taoensso/carmine]] [com.taoensso/timbre "4.10.0" :exclusions [com.taoensso/carmine]]
[net.openhft/compiler "2.3.0"] [net.openhft/compiler "2.3.1"]
[org.ow2.asm/asm "6.0"] [org.ow2.asm/asm "6.2.1"]
[org.ow2.asm/asm-util "6.0"] [org.ow2.asm/asm-util "6.2.1"]
[clojure-jsr-223 "0.1.0"] [clojure-jsr-223 "0.1.0"]
] ]
:profiles {:test {:source-paths ["test"] :profiles {:test {:source-paths ["test"]

View file

@ -4,13 +4,17 @@
[clojure.zip :as zip] [clojure.zip :as zip]
[clojure.reflect :as reflect] [clojure.reflect :as reflect]
[clojure.string :as str] [clojure.string :as str]
[swiss.arrows :refer :all]) [swiss.arrows :refer :all]
[clojure.spec.alpha :as s])
(:import (javafx.scene.layout Region) (:import (javafx.scene.layout Region)
(javafx.scene.shape Rectangle) (javafx.scene.shape Rectangle)
(clojurefx.ApplicationInitializer))) (clojurefx.ApplicationInitializer)))
(timbre/refer-timbre) (timbre/refer-timbre)
;; ## Specs
(s/def ::node (partial instance? javafx.scene.Node))
;; ## Functional interfaces ;; ## Functional interfaces
(defmacro fi (defmacro fi
@ -138,6 +142,61 @@
(info "Constructing" clazz "with" (first args)) (info "Constructing" clazz "with" (first args))
(clojure.lang.Reflector/invokeConstructor clazz (into-array args))) (clojure.lang.Reflector/invokeConstructor clazz (into-array args)))
;; ## Scene graph walker
(defn- has-method? [node method]
(not (empty? (clojure.lang.Reflector/getMethods (class node) 0 method false))))
(defn- graph-node-has-children? [node]
{:pre [(s/valid? ::node node)]
:post [boolean?]}
(or (has-method? node "getChildren")
(has-method? node "getGraphic")
(has-method? node "getMenus")
(has-method? node "getColumns")
(has-method? node "getContent")
(has-method? node "getTabs")
(has-method? node "getItems"))
)
(defn- graph-node-get-children [node]
{:pre [(s/valid? ::node node)]
:post [coll?]}
(cond (has-method? node "getChildren") (.getChildren node)
(has-method? node "getGraphic") (.getGraphic node)
(has-method? node "getMenus") (.getMenus node)
(has-method? node "getContent") (.getContent node)
(has-method? node "getTabs") (.getTabs node)
(has-method? node "getColumns") (.getColumns node)
(has-method? node "getItems") (.getItems node))
)
(defn scenegraph-zipper [node]
(zip/zipper graph-node-has-children? graph-node-get-children nil node))
(defn- flat-zipper [zipper]
(let [next (zip/next zipper)]
(if (zip/end? next)
(node next)
(lazy-seq (cons (node next) next)))))
(defn find-child-by-id [node id]
{:pre [(s/valid? ::node node)
(string? id)]
:post [#(or (s/valid? ::node node) nil?)]}
(let [zipper (scenegraph-zipper node)]
(filter #(= id (.getId %)) (flat-zipper zipper))))
(defn- contains-class? [coll clazz]
(> 0 (count (filter #(= % clazz) coll))))
(defn find-child-by-class [node clazz]
{:pre [(s/valid? ::node node)
(string? id)]
:post [#(or (s/valid? ::node node) nil?)]}
(let [zipper (scenegraph-zipper node)]
(filter #(contains-class? (.getStyleClass %) clazz) (flat-zipper zipper))))
;; ## Properties ;; ## Properties
(defn find-property [obj prop] (defn find-property [obj prop]

View file

@ -4,38 +4,38 @@
[clojure.test :as t] [clojure.test :as t]
[clojure.java.io :as io] [clojure.java.io :as io]
[taoensso.timbre :as timbre])) [taoensso.timbre :as timbre]))
(timbre/refer-timbre) ;(timbre/refer-timbre)
;
(defonce force-toolkit-init (javafx.embed.swing.JFXPanel.)) ;(defonce force-toolkit-init (javafx.embed.swing.JFXPanel.))
;
(def test1-fxml (io/resource "fxml/exampleWindow.fxml")) ;(def test1-fxml (io/resource "fxml/exampleWindow.fxml"))
;
(t/deftest fxml-loading ;(t/deftest fxml-loading
(debug "FXML loading") ; (debug "FXML loading")
(t/is (instance? javafx.scene.Node (sut/load-fxml test1-fxml)))) ; (t/is (instance? javafx.scene.Node (sut/load-fxml test1-fxml))))
;
(def test2-fxml (io/resource "fxml/exampleControllerWindow.fxml")) ;(def test2-fxml (io/resource "fxml/exampleControllerWindow.fxml"))
;
(t/deftest controller-generation ;(t/deftest controller-generation
(t/is (instance? java.lang.Class (sut/generate-controller test2-fxml "a.b/c")))) ; (t/is (instance? java.lang.Class (sut/generate-controller test2-fxml "a.b/c"))))
;
;
;
(def instance (atom nil)) ;(def instance (atom nil))
(def clicked (atom false)) ;(def clicked (atom false))
;
(defn initialize [inst] ;(defn initialize [inst]
(reset! instance inst)) ; (reset! instance inst))
;
(defn test-1-click [_ e] ;(defn test-1-click [_ e]
(reset! clicked true)) ; (reset! clicked true))
;
(sut/load-fxml-with-controller test2-fxml "clojurefx.fxml-test/initialize") ;(sut/load-fxml-with-controller test2-fxml "clojurefx.fxml-test/initialize")
;
(t/deftest proper-init ;(t/deftest proper-init
(t/is (instance? ch.lyrion.Test1 @instance))) ; (t/is (instance? ch.lyrion.Test1 @instance)))
;
(.fire (.simpleButton @instance)) ;(.fire (.simpleButton @instance))
;
(t/deftest testfire-result ;(t/deftest testfire-result
(t/is @clicked)) ; (t/is @clicked))