membrane

https://github.com/phronmophobic/membrane
genekim 2020-08-27T04:22:48.028Z

@smith.adriane Thank you!!! Wow, trying it right now!

šŸ¤ž 1
phronmophobic 2020-08-27T04:28:36.028700Z

I forgot to mention you'll need to update you membrane dependency to [com.phronemophobic/membrane "0.9.12-beta"]

genekim 2020-08-27T04:37:44.030400Z

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. šŸ™‚

genekim 2020-08-27T04:40:07.032Z

@smith.adriane So funny — it’s so autonomic, it’s difficult to remember which way textboxes are ā€œsupposedā€ to scroll! šŸ˜†

phronmophobic 2020-08-27T04:40:26.032200Z

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

phronmophobic 2020-08-27T04:40:45.032800Z

mac books switched it at some point

genekim 2020-08-27T04:41:45.033700Z

That’s super funny — so this bypasses all the native widget mouse handling… far out. šŸ™‚ Stand by…. hopefully will have positive result shortly!

phronmophobic 2020-08-27T04:46:26.034600Z

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))))])

genekim 2020-08-27T04:58:19.037400Z

@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…)

phronmophobic 2020-08-27T05:00:45.037600Z

that's a good question

phronmophobic 2020-08-27T05:06:36.042300Z

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?)))

phronmophobic 2020-08-27T05:07:55.043100Z

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]])

phronmophobic 2020-08-27T05:10:07.044600Z

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

phronmophobic 2020-08-27T05:12:09.045600Z

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?]])

🤯 1
phronmophobic 2020-08-27T05:13:05.046500Z

that's what the dollar sign prefix does. the proposed effect says to toggle the path [ATOM :done?]

phronmophobic 2020-08-27T05:13:35.047200Z

the path is similar to a keypath like you use in get-in or assoc-in.

phronmophobic 2020-08-27T05:15:01.048800Z

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

🤯 1
phronmophobic 2020-08-27T05:16:55.050700Z

i'm not sure I'm making any sense

phronmophobic 2020-08-27T05:19:46.052300Z

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])]

genekim 2020-08-27T05:21:30.054900Z

🤯 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!!!

🦜 1
phronmophobic 2020-08-27T05:21:48.055300Z

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]))

genekim 2020-08-27T05:26:19.058300Z

…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!!!

phronmophobic 2020-08-27T05:26:48.058700Z

the membrane.component is a little offbeat and deserves its own longer/better explanation which is in the works.

phronmophobic 2020-08-27T05:27:07.059100Z

have a great night!

genekim 2020-08-27T05:52:42.060500Z

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

phronmophobic 2020-08-27T05:53:22.060800Z

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))))])

phronmophobic 2020-08-27T05:53:43.061300Z

and just replace lorem-ipsum with whatever text you're trying to display

phronmophobic 2020-08-27T05:54:07.061900Z

or maybe i'm missing some other requirement

genekim 2020-08-27T05:54:58.062700Z

…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…

phronmophobic 2020-08-27T05:56:47.063200Z

right, you can word wrap before passing to the label. I think I have some code that does that. one sec..

genekim 2020-08-27T05:57:09.063300Z

genekim 2020-08-27T05:59:59.065700Z

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!

phronmophobic 2020-08-27T06:03:35.066600Z

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

phronmophobic 2020-08-27T06:04:57.067800Z

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

genekim 2020-08-27T06:06:17.068300Z

Roger that! I’ll come up with something in the short term — will keep you posted! Catch you soon!!!

phronmophobic 2020-08-27T06:08:55.068900Z

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)))))])

phronmophobic 2020-08-27T06:10:05.069800Z

it's not perfect since it doesn't it will only necessarily work for non monospaced fonts

genekim 2020-08-27T06:12:49.072500Z

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!

🤘 1