@smith.adriane Thank you!!! Wow, trying it right now!
I forgot to mention you'll need to update you membrane
dependency to [com.phronemophobic/membrane "0.9.12-beta"]
Wow!!! It works!!! Not quite sure I understand how this magic worksā¦ Amazing! Mouse scrolling is reversed āĀ on mac trackpad, text scrolls opposite way expectedā¦. Trying to flip some signs to see if it fixes it. š
@smith.adriane So funny āĀ itās so autonomic, itās difficult to remember which way textboxes are āsupposedā to scroll! š
I think that's because I got used to the wrong way a long time ago and probably coded it to work the wrong way
mac books switched it at some point
Thatās super funny āĀ so this bypasses all the native widget mouse handlingā¦ far out. š Stand byā¦. hopefully will have positive result shortly!
it's not a great fix, but you can change the scroll direction by wrapping the scrollview with:
(defn fix-scroll [elem]
(ui/on-scroll (fn [[sx sy]]
(ui/scroll elem [(- sx) (- sy)]))
elem))
eg:
(defn test-scrollview []
[(ui/translate 10 10
(fix-scroll
(get-scrollview :my-scrollview [300 300]
(ui/label lorem-ipsum))))])
@smith.adriane Holy cow, thatās so helpful. I was studying how get-scrollview
worksā¦.
Do I understand that youāre putting EDN s-expressions into the event dispatch? e.g., (list 'nil->val [0 0])
. Just curious: why do this instead of putting.. I dunno.. anonymous functions instead? (LISPs are amazingā¦)
that's a good question
the way events work is that each events are a pure function like (fn [elem event] effects)
. as the simplest example, here's the checkbox code:
(defui checkbox
"Checkbox component."
[& {:keys [checked?]}]
(on
:mouse-down
(fn [_]
[[::toggle $checked?]])
(ui/checkbox checked?)))
mouse-down
is a pure function that says returns what effects the checkbox proposes given a mouse-down event:
> (ui/mouse-down (membrane.basic-components/checkbox :checked true ) [0 0])
([:membrane.basic-components/toggle [:membrane.component/unknown]])
to make checkbox a pure function, it not only needs to know the value of checked, but it needs an identifier for the checked?
property. for membrane.component
, I use lenses
there's a bunch of macrology in membrane.component
that automatically tracks where property values are derived from so you don't have to worry about it, but you can also pass those values directly:
> (ui/mouse-down (membrane.basic-components/checkbox :checked? true :$checked? ['ATOM :done?] ) [0 0])
([:membrane.basic-components/toggle [ATOM :done?]])
that's what the dollar sign prefix does. the proposed effect says to toggle the path [ATOM :done?]
the path is similar to a keypath like you use in get-in
or assoc-in
.
lenses give you a little more power than keypaths. if you're familiar with specter, that's what I use under the hood lenses give you a little more power than just walking an associative structure. if you're familiar with
i'm not sure I'm making any sense
regarding the (list 'nil->val [0 0])
. it's part of specifying the identity of the :offset
property of the scroll view
:$offset [(list 'get sid) :offset (list 'nil->val [0 0])]
š¤Æ Very coolā¦. It all works! Thanks so much for all this help ā I will create a new sample program, using all of these constructs, and put in a couple of suggestions for the docs in a pull request. Super fun!!!
so it's saying if you want to update the :offset
state, tell me this path back. when I get this back, I'll do the equivalent of (-> state (get sid) :offset (or [0 0]))
ā¦okay, wow, never thought Iād actually see Haskell-like lenses in real life, let alone in something UI-related. Iām copying this off to study more tomorrow! In the meantime, Iām going to hack away at the app for a bit! (Note to self: investigate potentially strange behavior around changing subscriptions, which seem to require a REPL restartā¦) Have a great night!!!
the membrane.component
is a little offbeat and deserves its own longer/better explanation which is in the works.
have a great night!
Iām making some great progress now! Another question, which hopefully has much shorter answer āĀ if I want a scrollview, but wraps text, is there an easy way to do that? (Iām using to print out paragraphs of textā¦) @smith.adriane
I thought that's what the example did:
(defn test-scrollview []
[(ui/translate 10 10
(fix-scroll
(get-scrollview :my-scrollview [300 300]
(ui/label lorem-ipsum))))])
and just replace lorem-ipsum with whatever text you're trying to display
or maybe i'm missing some other requirement
ā¦hang onā¦ let me post a screenshotā¦ text that exceeds screen width is clipped, so you have to scroll right. Would love it if it wraps the text to the next lineā¦
right, you can word wrap before passing to the label. I think I have some code that does that. one sec..
Hahaha. You already have code for that? Thatās super! PS: it occurs to me that youāre having to re-implement the functionality of almost all of the native windowing elements. Iām not sure whether to keep asking for these changes (which Iām super grateful for!!), or if this signals that youāre doomed to endlessly have to rebuild the wheel that every window manager/window framework has already builtā¦ But this is very gratifying to see come together!
I thought I had that, but it uses an apache lang library that's not included and I don't remember what the maven dependency is
I think right now, there's some creature comforts missing, but I think(hope) that eventually you get to the a place where you have 80-90% of what people expect out of the box
Roger that! Iāll come up with something in the short term āĀ will keep you posted! Catch you soon!!!
I found this old code as well:
(defn line-wrap [s n]
(loop [s (seq s)
current-line []
lines []
i 0]
(if s
(let [c (first s)]
(cond
(= c \newline)
(do
(recur (next s)
[]
(conj lines current-line)
0))
(>= i n)
(recur s
[]
(conj lines current-line)
0)
:else
(recur (next s)
(conj current-line c)
lines
(inc i)))
)
(clojure.string/join "\n" (map (partial apply str) lines)))))
(def line-wrap-memo (memoize line-wrap))
(defn test-scrollview []
[(ui/translate 10 10
(fix-scroll
(get-scrollview :my-scrollview [300 300]
(ui/label (line-wrap-memo lorem-ipsum 20)))))])
it's not perfect since it doesn't it will only necessarily work for non monospaced fonts
Yep! I will either use yours or the WordUtils.wrap() in org.apache.commons.textā¦. tomorrow. Have a great night!!! PS: hopefully Iāll have my toy app done tomorrow, and I may redo it in cljfx, and compare/contrast, and write it up. I really love the feeling of doing everything without using clojurescript for once!