diff --git a/project.clj b/project.clj index 90f18f6..28e2f0f 100644 --- a/project.clj +++ b/project.clj @@ -3,16 +3,18 @@ :license "Like Clojure." :url "https://www.bitbucket.org/zilti/clojurefx" :signing {:gpg-key "68484437"} - :dependencies [[org.clojure/clojure "1.8.0"] + :dependencies [[org.clojure/clojure "1.9.0-beta1"] [swiss-arrows "1.0.0"] [camel-snake-kebab "0.4.0"] [org.controlsfx/controlsfx "8.40.13"] [com.taoensso/timbre "4.7.4" :exclusions [com.taoensso/carmine]] [net.openhft/compiler "2.3.0"] [org.ow2.asm/asm "6.0_BETA"] + [org.ow2.asm/asm-util "6.0_BETA"] [clojure-jsr-223 "0.1.0"]] :profiles {:test {:source-paths ["test"] :resource-paths ["test-resources"]} :uberjar {:aot :all}} + :aot :all :source-paths ["src"] :java-source-paths ["src"]) diff --git a/src/clojurefx/controllergen.clj b/src/clojurefx/controllergen.clj index 0219d80..cc27425 100644 --- a/src/clojurefx/controllergen.clj +++ b/src/clojurefx/controllergen.clj @@ -1,16 +1,16 @@ (ns clojurefx.controllergen - (:gen-class :name Controllergen - :implements [org.objectweb.asm.Opcodes] - :prefix "") + ;; (:gen-class :name Controllergen + ;; :implements [org.objectweb.asm.Opcodes]) ;; (:import (net.openhft.compiler CachedCompiler CompilerUtils)) - (:import org.objectweb.asm.ClassWriter) + (:import (org.objectweb.asm ClassWriter Opcodes)) (:use swiss.arrows) (:require [clojure.xml :as xml] [clojure.zip :as zip] [clojure.string :as str] [clojure.java.io :as io] [taoensso.timbre :as timbre] - [camel-snake-kebab.core :as csk])) + [camel-snake-kebab.core :as csk] + [clojure.spec.alpha :as s])) (timbre/refer-timbre) ;; (def xmlzip (zip/xml-zip (xml/parse "/home/zilti/projects/lizenztool/resources/fxml/mainwindow.fxml"))) @@ -42,41 +42,32 @@ (first (filter #(= class-str (last (str/split (pr-str %) #"\.")))))) (defn init-class [pkg classname] - (let [cw (new org.objectweb.asm.ClassWriter 0)] - (.. cw (visit V1_8 - (+ ACC_PUBLIC) - (str pkg "/" classname) - nil - "java/lang/Object" - nil) - (visitField ACC_PRIVATE - "resources" - (pr-str (qualify-class "ResourceBundle")) - null - null) - (visitField ACC_PRIVATE - "location" - (pr-str (qualify-class "URL")) - null - null)) + (let [cw (new org.objectweb.asm.ClassWriter 0) + clazz (.visit cw Opcodes/V1_8 + (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) + (str pkg "/" classname) + nil + "java/lang/Object" + nil) + resources_fv (.visitField cw Opcodes/ACC_PRIVATE + "resources" + (pr-str (qualify-class "ResourceBundle")) + nil + nil) + url_fv (.visitField cw Opcodes/ACC_PRIVATE + "location" + (pr-str (qualify-class "URL")) + nil + nil)] + (-> (.visitAnnotation resources_fv "Ljavafx/fxml/FXML;" true) + .visitEnd) + (.visitEnd resources_fv) + + (-> (.visitAnnotation url_fv "Ljavafx/fxml/FXML;" true) + .visitEnd) + (.visitEnd url_fv) cw)) -;; (def stockimports "import clojure.java.api.Clojure;\nimport clojure.lang.IFn;\nimport java.net.URL;\nimport java.util.ResourceBundle;\nimport javafx.event.ActionEvent;\nimport javafx.fxml.FXML;\n") - -;; (def stockprops " @FXML -;; private ResourceBundle resources; - -;; @FXML -;; private URL location;\n\n") - -;; (defn get-imports [filename] -;; (->> (slurp filename) -;; (str/split-lines) -;; (filter #(str/starts-with? % "" ";")) -;; (str/join "\n"))) - (defn zip-tree-seq [node] (tree-seq (complement string?) :content @@ -85,7 +76,8 @@ (defn get-handler-props [{:keys [attrs]}] (->> attrs (filter #(str/starts-with? (name (key %)) "on")) - (map val))) + (map val) + flatten)) (defn get-handler-fns [ziptree] (->> ziptree @@ -104,14 +96,40 @@ :attrs :fx:controller)) -;; (defn gen-props [coll] -;; (let [props-str -;; (->> (flatten coll) -;; (map #(format " @FXML\n public %s %s;\n\n" -;; (name (:tag %)) (get-in % [:attrs :fx:id]))) -;; (str/join ""))] -;; (debug (type props-str)) -;; props-str)) +(defn gen-props [cw [entry & coll]] + (if-not (empty? coll) + (let [fv (.visitField cw Opcodes/ACC_PUBLIC + (get-in entry [:attrs :fx:id]) + (pr-str (qualify-class (name (:tag entry)))) + nil nil)] + (-> (.visitAnnotation fv "Ljava/fxml/FXML;" true) + .visitEnd) + (.visitEnd fv) + (recur cw coll)) + cw)) + +(defn gen-handlers [cw [entry & coll] clj-ns] + (if-not (empty? coll) + (let [mv (.visitMethod cw 0 + (subs entry 1) + "(Ljavafx/event/ActionEvent;)V" + nil nil)] + (-> (.visitAnnotation mv "Ljava/fxml/FXML;" true) + .visitEnd) + (.. mv + visitCode + (visitLdcInsn clj-ns) + (visitLdcInsn (csk/->kebab-case (subs % 1))) + (visitMethodInsn Opcodes/INVOKESTATIC "clojure/java/api/Clojure" "var" "(Ljava/lang/Object;Ljava/lang/Object;)Lclojure/lang/IFn;" false) + (visitVarInsn Opcodes/ALOAD 0) + (visitVarInsn Opcodes/ALOAD 1) + (visitMethodInsn Opcodes/INVOKEINTERFACE "clojure/lang/IFn" "invoke" "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;" true) + (visitInsn Opcodes/POP) + (visitInsn Opcodes/RETURN) + (visitMaxs 3 2) + visitEnd) + (recur cw coll clj-ns)) + cw)) ;; (defn gen-handlers [coll clj-ns] ;; (->> (flatten coll) @@ -152,3 +170,5 @@ ;; [pkg classname] (reverse (map str/reverse (str/split (str/reverse clazz) #"\." 2))) ;; cljvec (str/split clj-fn #"/")] ;; (makeclass pkg classname (gen-fx-controller fxmlzip fxmlpath cljvec)))) + +(defn gen-fx-controller-class [fxmlpath clj-fn])