cljfx

https://github.com/cljfx/cljfx
EmmanuelOga 2020-02-25T00:27:07.005600Z

I this an alternative to REBL ?

EmmanuelOga 2020-02-25T00:28:06.005800Z

> Where datafy-and-nav based tools like REBL pretend that atoms are single-element vectors, Reveal never obscures evaluation results, even the metadata.

EmmanuelOga 2020-02-25T00:34:53.008300Z

I've only been using REBL for a few days but I found the "kiler" feature so far was support for tap>s. It is quite nice to put a tap> anywhere to see intermediate results (previously I'd litter the code with print statements). Also the tap allowing you to navigate the object is amazing. But yeah, it takes a while to recognize one is dealing with a datafied thing as opposed to the actual thing. I'm still learning how to read datafications.

vlaaad 2020-02-25T06:19:58.008600Z

Yeah, it's can be seen as alternative to REBL. Yes, tap> is great! It's pretty well supported in Reveal

2020-02-25T18:53:22.010700Z

hi everybody! is there a way of adding a callback that gets called after a component render so I can check the dimensions it got? something like componentDidMount in react?

vlaaad 2020-02-25T18:54:34.010800Z

Hi! I haven't implemented it, and haven't had a need for that so far. What is your use case?

2020-02-25T18:57:28.013200Z

I'm migrating a diagram application I created in reagent/re-frame to cljfx. I'm rendering different dynamic in content nodes so I don't know the bounding box before the render (imagine they have text with different lengths)

2020-02-25T18:57:51.013600Z

it would be great to know the bounding boxes after the nodes had been rendered, so I can update the state with that info

2020-02-25T19:00:12.014Z

does it make sense?

vlaaad 2020-02-25T19:01:28.014100Z

Not sure I understand, what do you mean by different dynamic in content nodes?

2020-02-25T19:02:16.015100Z

like when you add content to a div, you don't know the final size until it has been rendered (unless your are fixing it's with and height)

2020-02-25T19:03:37.015400Z

as an example I'm currently rendering a bunch of

(defn node-cmp [{:keys [fx/context node]}]
  {:fx/type :text
   :translate-x (:x node)
   :translate-y (:y node)
   :wrapping-width (:w node)
   :text (str node)})

2020-02-25T19:04:08.016100Z

since text length is different for every node I don't know the height until it gets rendered

2020-02-25T19:05:47.017Z

so with dynamic nodes I mean they are going to take the size of their contents, in this case they are text but they are going to be groups

vlaaad 2020-02-25T19:10:54.017100Z

Hmm, but why do you need text height? Why is it not enough using javafx layouts like v-box or grid-pane?

vlaaad 2020-02-25T19:11:18.017200Z

@jpmonettas ^

2020-02-25T19:17:11.018Z

but even using a pane, if I put a bunch of text inside it how do I know the final box size after render?

2020-02-25T19:20:02.019200Z

I need width and height of whatever nodes I rendered because I need to draw lines that link different nodes, so I need the boxes dimensions

vlaaad 2020-02-25T19:20:31.019600Z

Ah, I see, so it's a non-standard layout. Hmm, let me think...

2020-02-25T19:20:38.019800Z

https://github.com/jpmonettas/clograms

2020-02-25T19:20:48.020300Z

that is the re-frame app, you can look at the screenshots to have an idea

vlaaad 2020-02-25T19:36:20.021400Z

@jpmonettas

(fx/on-fx-thread
  (fx/create-component
    {:fx/type :stage
     :showing true
     :scene {:fx/type :scene
             :root {:fx/type :v-box
                    :children [{:fx/type fx/ext-on-instance-lifecycle
                                :on-created #(prn (.getHeight (.getLayoutBounds %)))
                                :desc {:fx/type :text
                                       :wrapping-width 100
                                       :text (str (range 100))}}]}}}))
every node has layout bounds, you can observe it in on-created

vlaaad 2020-02-25T19:36:47.021900Z

but you probably need to save it to app context as well?

2020-02-25T19:37:18.022800Z

oh I think that will work! that on-created is just what I was looking for

2020-02-25T19:37:20.023Z

thanks a lot!

vlaaad 2020-02-25T19:37:36.023400Z

can your text change?

vlaaad 2020-02-25T19:37:54.023800Z

for a given node

2020-02-25T19:38:01.024Z

yeah I will probably also need a on-updated

vlaaad 2020-02-25T19:39:27.025300Z

no, on updated won't work: it's for instance changes — when component described by :desc starts returning different node

2020-02-25T19:40:40.026Z

oh ok, any ideas if there is something for that purpose?

2020-02-25T19:41:07.026300Z

sorry I'm just learning my way around javafx

vlaaad 2020-02-25T19:44:50.027700Z

usually for getters there are observable properties, so you can use them as well:

(fx/on-fx-thread
  (fx/create-component
    {:fx/type :stage
     :showing true
     :scene {:fx/type :scene
             :root {:fx/type :v-box
                    :children [{:fx/type fx/ext-on-instance-lifecycle
                                :on-created (fn [^javafx.scene.text.Text text]
                                              (prn (.getLayoutBounds text))
                                              (.addListener (.layoutBoundsProperty text)
                                                            (reify javafx.beans.value.ChangeListener
                                                              (changed [_ _ _ v]
                                                                (prn v)))))
                                :desc {:fx/type :text
                                       :wrapping-width 100
                                       :text (str (range 100))}}]}}}))

vlaaad 2020-02-25T19:46:31.029500Z

the problem is, you'll probably want to dispatch events updating db from this callback, which might introduce unnecessary coupling with event handler, so ideally you'd want to have a prop observing layout bounds

2020-02-25T19:49:17.031300Z

I think for my case it will work, I'll give it a try, I will leave some notes and will came later and see if I can figure out the prop creation

2020-02-25T19:49:31.031700Z

thanks again @vlaaad!

vlaaad 2020-02-25T19:49:40.031900Z

you are welcome!

vlaaad 2020-02-25T19:52:35.034400Z

@jpmonettas FYI, I tried creating :on-layout-bounds-changed prop:

(def text
  (cljfx.composite/describe javafx.scene.text.Text
    :ctor []
    :props (merge cljfx.fx.text/props
                  (cljfx.composite/props javafx.scene.text.Text
                    :on-layout-bounds-changed [:property-change-listener cljfx.lifecycle/change-listener]))))

(fx/on-fx-thread
  (fx/create-component
    {:fx/type :stage
     :showing true
     :scene {:fx/type :scene
             :root {:fx/type :v-box
                    :children [{:fx/type text ;; notice: text, not :text
                                :on-layout-bounds-changed {::event ::bounds-changed}
                                :wrapping-width 100
                                :text (str (range 100))}]}}}))
Unfortunately, it'll be invoked only when bounds change, so you'll still need to invoke event handler manually when text is created. I don't have a complete solution so far.

2020-02-25T19:54:19.035Z

I think that is enough for what I'm trying to do, thx!

2020-02-25T20:32:47.035900Z

is there a function for dispatching a event from a component when not using the map solution? calling directly the ev handler function will not send the context

vlaaad 2020-02-25T20:33:35.036200Z

that's what I was worried about 🙂

vlaaad 2020-02-25T20:34:00.036500Z

do you use fx/create-app?

2020-02-25T20:36:10.036700Z

yes

vlaaad 2020-02-25T20:37:19.037700Z

it returns map with renderer and handler. That handler will send the context

2020-02-25T20:38:16.038300Z

oh ok, will work around it like that, thx!