Why does web-view scale with its parent container, but image-view doe not? I am having a hard time understanding how the child components get the width and height passed to them. This component scales with the parent:
(defn instance-tab [{:keys [instance-id svg-id display-name svg]}]
{:fx/type :tab
:text (format "[%d] %s" instance-id display-name)
:closable false
:on-selection-changed {:event/type ::set-active-instance :instance-id instance-id}
:content {:fx/type fx.ext.web-view/with-engine-props
:desc {:fx/type :web-view
:pref-width 1341
:pref-height 948}
:props {:content svg
:on-status-changed {:event/type ::set-status}}}})
This one does not:
(defn instance-tab [{:keys [instance-id svg-id display-name svg]}]
{:fx/type :tab
:text (format "[%d] %s" instance-id display-name)
:closable false
:on-selection-changed {:event/type ::set-active-instance :instance-id instance-id}
:content {:fx/type :stack-pane
:children [{:fx/type :image-view
:image {:is (io/input-stream "resources/images/vpc_panel_1.png")}
:preserve-ratio true
:smooth true
:stack-pane/alignment :center}]}})
I have tried many combinations of containers for the ImageView, all of them do not scale the image size.
I know that I could put the window width and height in my state atom, and just update the scale of the image-view manually, but I am curious to understand how other components are able to tap into the state of their parents. Do I need to make an extension for this component to handle fitting to the size of the parent?When you say scale, do you mean resize?
javafx defines nodes as either resizable or unresizable, and image views are unresizable
I implemented resizable image view for Defold’s markdown renderer: https://github.com/defold/defold/blob/c02db1513ffda8f5c12401d0cf44464c99db0fb7/editor/src/java/com/defold/control/ResizableImageView.java#L21
And here is how it’s used in cljfx context: https://github.com/defold/defold/blob/c02db1513ffda8f5c12401d0cf44464c99db0fb7/editor/src/clj/editor/markdown.clj#L391-L410
@vlaaad Yes resizing is what I meant. Thank you for your explanation! This makes a lot of sense. I got something working. I am confused though, the image-view is MUCH faster at rendering the image compared to the web-view loading a simple svg with an image href inside of it. I remember reading about memoizing and contexts in your README. Is this a case where I should be controlling the context more tightly? Or is web-view just less performant? Also, is this okay to do? I based it on your defold code, but pulled it up into Clojureland.
(def ^:private ext-with-image-view-props
(fx/make-ext-with-props fx.image-view/props))
(defn resizable-image-view
[{:keys [image]}]
(letfn [(aspect-ratio [img]
(let [h (some-> img .getHeight)]
(if (and h (pos? h))
(/ (.getWidth img) h)
1.0)))
(img-width [img] (or (some-> img .getWidth)
0.0))
(img-height [img] (or (some-> img .getHeight)
0.0))
(pref [constraint img scale-fn fallback]
(if (pos? constraint)
(scale-fn constraint (aspect-ratio img))
(fallback img)))]
{:fx/type ext-with-image-view-props
:desc {:fx/type fx/ext-instance-factory
:create (fn []
(proxy [ImageView] []
(minWidth [_] 0.0)
(minHeight [_] 0.0)
(prefWidth [h]
(let [img (.getImage this)]
(pref h img * img-width)))
(prefHeight [w]
(let [img (.getImage this)]
(pref w img (fn [x ar] (/ x ar)) img-height)))
(isResizable [] true)
(resize [w h]
(.setFitWidth this w)
(.setFitHeight this h))
(getContentBias [] Orientation/HORIZONTAL)))}
:props {:preserve-ratio true
:image image}}))Proxy is fine if you don't want to bother with java compilation
I use java for such things in Defold because the compilation is configured there
And proxy is "slow", though I didn't really try to measure using it.. ever... But I heard it's slow
Proxy is faster than web view so far 🤣... by a lot. I don't think I saved the benchmarks, but it's the difference between smooth Image-view 60fps and Webview was herky jerky 15fps. I will re-run them later this weekend. I could use gen-class to improve performance? Normally, I would just import your defold code, but I don't need a whole markdown editor in this system. I am also open to other suggestions. I am kinda just experimenting with every possible thing right now.